1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.service.impl;
24  
25  import com.liferay.portal.DuplicateOrganizationException;
26  import com.liferay.portal.OrganizationNameException;
27  import com.liferay.portal.OrganizationParentException;
28  import com.liferay.portal.PortalException;
29  import com.liferay.portal.RequiredOrganizationException;
30  import com.liferay.portal.SystemException;
31  import com.liferay.portal.kernel.configuration.Filter;
32  import com.liferay.portal.kernel.util.ArrayUtil;
33  import com.liferay.portal.kernel.util.GetterUtil;
34  import com.liferay.portal.kernel.util.OrderByComparator;
35  import com.liferay.portal.kernel.util.StringPool;
36  import com.liferay.portal.kernel.util.Validator;
37  import com.liferay.portal.model.Group;
38  import com.liferay.portal.model.Organization;
39  import com.liferay.portal.model.OrganizationConstants;
40  import com.liferay.portal.model.ResourceConstants;
41  import com.liferay.portal.model.Role;
42  import com.liferay.portal.model.RoleConstants;
43  import com.liferay.portal.model.User;
44  import com.liferay.portal.model.impl.ListTypeImpl;
45  import com.liferay.portal.model.impl.OrganizationImpl;
46  import com.liferay.portal.security.permission.PermissionCacheUtil;
47  import com.liferay.portal.service.ServiceContext;
48  import com.liferay.portal.service.base.OrganizationLocalServiceBaseImpl;
49  import com.liferay.portal.util.PropsKeys;
50  import com.liferay.portal.util.PropsUtil;
51  import com.liferay.portal.util.PropsValues;
52  import com.liferay.portal.util.comparator.OrganizationNameComparator;
53  import com.liferay.portlet.expando.model.ExpandoBridge;
54  import com.liferay.util.UniqueList;
55  
56  import java.util.ArrayList;
57  import java.util.Iterator;
58  import java.util.LinkedHashMap;
59  import java.util.List;
60  
61  /**
62   * <a href="OrganizationLocalServiceImpl.java.html"><b><i>View Source</i></b>
63   * </a>
64   *
65   * @author Brian Wing Shun Chan
66   * @author Jorge Ferrer
67   *
68   */
69  public class OrganizationLocalServiceImpl
70      extends OrganizationLocalServiceBaseImpl {
71  
72      public void addGroupOrganizations(long groupId, long[] organizationIds)
73          throws SystemException {
74  
75          groupPersistence.addOrganizations(groupId, organizationIds);
76  
77          PermissionCacheUtil.clearCache();
78      }
79  
80      public Organization addOrganization(
81              long userId, long parentOrganizationId, String name,
82              String type, boolean recursable, long regionId, long countryId,
83              int statusId, String comments, ServiceContext serviceContext)
84          throws PortalException, SystemException {
85  
86          // Organization
87  
88          User user = userPersistence.findByPrimaryKey(userId);
89          parentOrganizationId = getParentOrganizationId(
90              user.getCompanyId(), parentOrganizationId);
91          recursable = true;
92  
93          validate(
94              user.getCompanyId(), parentOrganizationId, name, type, countryId,
95              statusId);
96  
97          long organizationId = counterLocalService.increment();
98  
99          Organization organization = organizationPersistence.create(
100             organizationId);
101 
102         organization.setCompanyId(user.getCompanyId());
103         organization.setParentOrganizationId(parentOrganizationId);
104         organization.setName(name);
105         organization.setType(type);
106         organization.setRecursable(recursable);
107         organization.setRegionId(regionId);
108         organization.setCountryId(countryId);
109         organization.setStatusId(statusId);
110         organization.setComments(comments);
111 
112         organizationPersistence.update(organization, false);
113 
114         // Group
115 
116         Group group = groupLocalService.addGroup(
117             userId, Organization.class.getName(), organizationId, null, null, 0,
118             null, true);
119 
120         if (PropsValues.ORGANIZATIONS_ASSIGNMENT_AUTO) {
121 
122             // Role
123 
124             Role role = roleLocalService.getRole(
125                 organization.getCompanyId(), RoleConstants.ORGANIZATION_OWNER);
126 
127             userGroupRoleLocalService.addUserGroupRoles(
128                 userId, group.getGroupId(), new long[] {role.getRoleId()});
129 
130             // User
131 
132             userPersistence.addOrganization(userId, organizationId);
133         }
134 
135         // Resources
136 
137         addOrganizationResources(userId, organization);
138 
139         // Expando
140 
141         ExpandoBridge expandoBridge = organization.getExpandoBridge();
142 
143         expandoBridge.setAttributes(serviceContext);
144 
145         return organization;
146     }
147 
148     public void addOrganizationResources(long userId, Organization organization)
149         throws PortalException, SystemException {
150 
151         String name = Organization.class.getName();
152 
153         resourceLocalService.addResources(
154             organization.getCompanyId(), 0, userId, name,
155             organization.getOrganizationId(), false, false, false);
156     }
157 
158     public void addPasswordPolicyOrganizations(
159             long passwordPolicyId, long[] organizationIds)
160         throws SystemException {
161 
162         passwordPolicyRelLocalService.addPasswordPolicyRels(
163             passwordPolicyId, Organization.class.getName(), organizationIds);
164     }
165 
166     public void deleteOrganization(long organizationId)
167         throws PortalException, SystemException {
168 
169         Organization organization = organizationPersistence.findByPrimaryKey(
170             organizationId);
171 
172         if ((userLocalService.getOrganizationUsersCount(
173                 organization.getOrganizationId(), true) > 0) ||
174             (organizationPersistence.countByC_P(
175                 organization.getCompanyId(),
176                 organization.getOrganizationId()) > 0)) {
177 
178             throw new RequiredOrganizationException();
179         }
180 
181         // Addresses
182 
183         addressLocalService.deleteAddresses(
184             organization.getCompanyId(), Organization.class.getName(),
185             organization.getOrganizationId());
186 
187         // Email addresses
188 
189         emailAddressLocalService.deleteEmailAddresses(
190             organization.getCompanyId(), Organization.class.getName(),
191             organization.getOrganizationId());
192 
193         // Password policy relation
194 
195         passwordPolicyRelLocalService.deletePasswordPolicyRel(
196             Organization.class.getName(), organization.getOrganizationId());
197 
198         // Phone
199 
200         phoneLocalService.deletePhones(
201             organization.getCompanyId(), Organization.class.getName(),
202             organization.getOrganizationId());
203 
204         // Website
205 
206         websiteLocalService.deleteWebsites(
207             organization.getCompanyId(), Organization.class.getName(),
208             organization.getOrganizationId());
209 
210         // Group
211 
212         Group group = organization.getGroup();
213 
214         groupLocalService.deleteGroup(group.getGroupId());
215 
216         // Resources
217 
218         String name = Organization.class.getName();
219 
220         resourceLocalService.deleteResource(
221             organization.getCompanyId(), name,
222             ResourceConstants.SCOPE_INDIVIDUAL,
223             organization.getOrganizationId());
224 
225         // Organization
226 
227         organizationPersistence.remove(organization);
228 
229         // Permission cache
230 
231         PermissionCacheUtil.clearCache();
232     }
233 
234     public List<Organization> getGroupOrganizations(long groupId)
235         throws SystemException {
236 
237         return groupPersistence.getOrganizations(groupId);
238     }
239 
240     /**
241      * Gets a list of organizations that a user has access to administrate. This
242      * includes organizations that a user belongs to and all suborganizations of
243      * those organizations.
244      *
245      * @param       userId the user id of the user
246      * @return      a list of organizations
247      */
248     public List<Organization> getManageableOrganizations(long userId)
249         throws SystemException {
250 
251         List<Organization> manageableOrganizations =
252             new UniqueList<Organization>();
253 
254         List<Organization> userOrganizations = userPersistence.getOrganizations(
255             userId);
256 
257         manageableOrganizations.addAll(userOrganizations);
258         manageableOrganizations.addAll(getSuborganizations(userOrganizations));
259 
260         return manageableOrganizations;
261     }
262 
263     public Organization getOrganization(long organizationId)
264         throws PortalException, SystemException {
265 
266         return organizationPersistence.findByPrimaryKey(organizationId);
267     }
268 
269     public Organization getOrganization(long companyId, String name)
270         throws PortalException, SystemException {
271 
272         return organizationPersistence.findByC_N(companyId, name);
273     }
274 
275     public long getOrganizationId(long companyId, String name)
276         throws SystemException {
277 
278         Organization organization = organizationPersistence.fetchByC_N(
279             companyId, name);
280 
281         if (organization != null) {
282             return organization.getOrganizationId();
283         }
284         else {
285             return 0;
286         }
287     }
288 
289     public List<Organization> getOrganizations(long[] organizationIds)
290         throws PortalException, SystemException {
291 
292         List<Organization> organizations = new ArrayList<Organization>(
293             organizationIds.length);
294 
295         for (long organizationId : organizationIds) {
296             Organization organization = getOrganization(organizationId);
297 
298             organizations.add(organization);
299         }
300 
301         return organizations;
302     }
303 
304     public List<Organization> getParentOrganizations(long organizationId)
305         throws PortalException, SystemException {
306 
307         if (organizationId ==
308                 OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) {
309 
310             return new ArrayList<Organization>();
311         }
312 
313         Organization organization =
314             organizationPersistence.findByPrimaryKey(organizationId);
315 
316         return getParentOrganizations(organization, true);
317     }
318 
319     public List<Organization> getSuborganizations(
320             List<Organization> organizations)
321         throws SystemException {
322 
323         List<Organization> allSuborganizations = new ArrayList<Organization>();
324 
325         for (int i = 0; i < organizations.size(); i++) {
326             Organization organization = organizations.get(i);
327 
328             List<Organization> suborganizations =
329                 organizationPersistence.findByC_P(
330                     organization.getCompanyId(),
331                     organization.getOrganizationId());
332 
333             addSuborganizations(allSuborganizations, suborganizations);
334         }
335 
336         return allSuborganizations;
337     }
338 
339     public List<Organization> getSubsetOrganizations(
340         List<Organization> allOrganizations,
341         List<Organization> availableOrganizations) {
342 
343         List<Organization> subsetOrganizations = new ArrayList<Organization>();
344 
345         Iterator<Organization> itr = allOrganizations.iterator();
346 
347         while (itr.hasNext()) {
348             Organization organization = itr.next();
349 
350             if (availableOrganizations.contains(organization)) {
351                 subsetOrganizations.add(organization);
352             }
353         }
354 
355         return subsetOrganizations;
356     }
357 
358     public List<Organization> getUserOrganizations(long userId)
359         throws SystemException {
360 
361         return userPersistence.getOrganizations(userId);
362     }
363 
364     public List<Organization> getUserOrganizations(
365             long userId, int start, int end)
366         throws SystemException {
367 
368         return userPersistence.getOrganizations(userId, start, end);
369     }
370 
371     public int getUserOrganizationsCount(long userId) throws SystemException {
372         return userPersistence.getOrganizationsSize(userId);
373     }
374 
375     public boolean hasGroupOrganization(long groupId, long organizationId)
376         throws SystemException {
377 
378         return groupPersistence.containsOrganization(groupId, organizationId);
379     }
380 
381     public boolean hasUserOrganization(long userId, long organizationId)
382         throws SystemException {
383 
384         return userPersistence.containsOrganization(userId, organizationId);
385     }
386 
387     public boolean hasPasswordPolicyOrganization(
388             long passwordPolicyId, long organizationId)
389         throws SystemException {
390 
391         return passwordPolicyRelLocalService.hasPasswordPolicyRel(
392             passwordPolicyId, Organization.class.getName(), organizationId);
393     }
394 
395     public List<Organization> search(
396             long companyId, long parentOrganizationId, String keywords,
397             String type, Long regionId, Long countryId,
398             LinkedHashMap<String, Object> params,
399             int start, int end)
400         throws SystemException {
401 
402         return search(
403             companyId, parentOrganizationId, keywords, type, regionId,
404             countryId, params, start, end,
405             new OrganizationNameComparator(true));
406     }
407 
408     public List<Organization> search(
409             long companyId, long parentOrganizationId, String keywords,
410             String type, Long regionId, Long countryId,
411             LinkedHashMap<String, Object> params,
412             int start, int end, OrderByComparator obc)
413         throws SystemException {
414 
415         String parentOrganizationIdComparator = StringPool.EQUAL;
416 
417         if (parentOrganizationId ==
418                 OrganizationConstants.ANY_PARENT_ORGANIZATION_ID) {
419 
420             parentOrganizationIdComparator = StringPool.NOT_EQUAL;
421         }
422 
423         return organizationFinder.findByKeywords(
424             companyId, parentOrganizationId, parentOrganizationIdComparator,
425             keywords, type, regionId, countryId, params, start, end,
426             obc);
427     }
428 
429     public List<Organization> search(
430             long companyId, long parentOrganizationId, String name, String type,
431             String street, String city, String zip,
432             Long regionId, Long countryId,
433             LinkedHashMap<String, Object> params, boolean andOperator,
434             int start, int end)
435         throws SystemException {
436 
437         return search(
438             companyId, parentOrganizationId, name, type, street, city, zip,
439             regionId, countryId, params, andOperator, start, end,
440             new OrganizationNameComparator(true));
441     }
442 
443     public List<Organization> search(
444             long companyId, long parentOrganizationId, String name, String type,
445             String street, String city, String zip,
446             Long regionId, Long countryId, LinkedHashMap<String, Object> params,
447             boolean andOperator, int start, int end, OrderByComparator obc)
448         throws SystemException {
449 
450         String parentOrganizationIdComparator = StringPool.EQUAL;
451 
452         if (parentOrganizationId ==
453                 OrganizationConstants.ANY_PARENT_ORGANIZATION_ID) {
454 
455             parentOrganizationIdComparator = StringPool.NOT_EQUAL;
456         }
457 
458         return organizationFinder.findByC_PO_N_T_S_C_Z_R_C(
459             companyId, parentOrganizationId, parentOrganizationIdComparator,
460             name, type, street, city, zip, regionId, countryId, params,
461             andOperator, start, end, obc);
462     }
463 
464     public int searchCount(
465             long companyId, long parentOrganizationId, String keywords,
466             String type, Long regionId, Long countryId,
467             LinkedHashMap<String, Object> params)
468         throws SystemException {
469 
470         String parentOrganizationIdComparator = StringPool.EQUAL;
471 
472         if (parentOrganizationId ==
473                 OrganizationConstants.ANY_PARENT_ORGANIZATION_ID) {
474 
475             parentOrganizationIdComparator = StringPool.NOT_EQUAL;
476         }
477 
478         return organizationFinder.countByKeywords(
479             companyId, parentOrganizationId, parentOrganizationIdComparator,
480             keywords, type, regionId, countryId, params);
481     }
482 
483     public int searchCount(
484             long companyId, long parentOrganizationId, String name, String type,
485             String street, String city, String zip,
486             Long regionId, Long countryId, LinkedHashMap<String, Object> params,
487             boolean andOperator)
488         throws SystemException {
489 
490         String parentOrganizationIdComparator = StringPool.EQUAL;
491 
492         if (parentOrganizationId ==
493                 OrganizationConstants.ANY_PARENT_ORGANIZATION_ID) {
494 
495             parentOrganizationIdComparator = StringPool.NOT_EQUAL;
496         }
497 
498         return organizationFinder.countByC_PO_N_T_S_C_Z_R_C(
499             companyId, parentOrganizationId, parentOrganizationIdComparator,
500             name, type, street, city, zip, regionId, countryId, params,
501             andOperator);
502     }
503 
504     public void setGroupOrganizations(long groupId, long[] organizationIds)
505         throws SystemException {
506 
507         groupPersistence.setOrganizations(groupId, organizationIds);
508 
509         PermissionCacheUtil.clearCache();
510     }
511 
512     public void unsetGroupOrganizations(long groupId, long[] organizationIds)
513         throws SystemException {
514 
515         groupPersistence.removeOrganizations(groupId, organizationIds);
516 
517         PermissionCacheUtil.clearCache();
518     }
519 
520     public void unsetPasswordPolicyOrganizations(
521             long passwordPolicyId, long[] organizationIds)
522         throws SystemException {
523 
524         passwordPolicyRelLocalService.deletePasswordPolicyRels(
525             passwordPolicyId, Organization.class.getName(), organizationIds);
526     }
527 
528     public Organization updateOrganization(
529             long companyId, long organizationId, long parentOrganizationId,
530             String name, String type, boolean recursable, long regionId,
531             long countryId, int statusId, String comments,
532             ServiceContext serviceContext)
533         throws PortalException, SystemException {
534 
535         // Organization
536 
537         parentOrganizationId = getParentOrganizationId(
538             companyId, parentOrganizationId);
539         recursable = true;
540 
541         validate(
542             companyId, organizationId, parentOrganizationId, name, type,
543             countryId, statusId);
544 
545         Organization organization = organizationPersistence.findByPrimaryKey(
546             organizationId);
547 
548         organization.setParentOrganizationId(parentOrganizationId);
549         organization.setName(name);
550         organization.setType(type);
551         organization.setRecursable(recursable);
552         organization.setRegionId(regionId);
553         organization.setCountryId(countryId);
554         organization.setStatusId(statusId);
555         organization.setComments(comments);
556 
557         organizationPersistence.update(organization, false);
558 
559         // Expando
560 
561         ExpandoBridge expandoBridge = organization.getExpandoBridge();
562 
563         expandoBridge.setAttributes(serviceContext);
564 
565         return organization;
566     }
567 
568     protected void addSuborganizations(
569             List<Organization> allSuborganizations,
570             List<Organization> organizations)
571         throws SystemException {
572 
573         for (Organization organization : organizations) {
574             if (!allSuborganizations.contains(organization)) {
575                 allSuborganizations.add(organization);
576 
577                 List<Organization> suborganizations =
578                     organizationPersistence.findByC_P(
579                         organization.getCompanyId(),
580                         organization.getOrganizationId());
581 
582                 addSuborganizations(allSuborganizations, suborganizations);
583             }
584         }
585     }
586 
587     protected long getParentOrganizationId(
588             long companyId, long parentOrganizationId)
589         throws SystemException {
590 
591         if (parentOrganizationId !=
592                 OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) {
593 
594             // Ensure parent organization exists and belongs to the proper
595             // company
596 
597             Organization parentOrganization =
598                 organizationPersistence.fetchByPrimaryKey(parentOrganizationId);
599 
600             if ((parentOrganization == null) ||
601                 (companyId != parentOrganization.getCompanyId())) {
602 
603                 parentOrganizationId =
604                     OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID;
605             }
606         }
607 
608         return parentOrganizationId;
609     }
610 
611     protected List<Organization> getParentOrganizations(
612             Organization organization, boolean lastOrganization)
613         throws PortalException, SystemException {
614 
615         List<Organization> organizations = new ArrayList<Organization>();
616 
617         if (!lastOrganization) {
618             organizations.add(organization);
619         }
620 
621         long parentOrganizationId = organization.getParentOrganizationId();
622 
623         if (parentOrganizationId ==
624                 OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID) {
625 
626             return organizations;
627         }
628 
629         Organization parentOrganization =
630             organizationPersistence.findByPrimaryKey(parentOrganizationId);
631 
632         List<Organization> parentOrganizatons = getParentOrganizations(
633             parentOrganization, false);
634 
635         organizations.addAll(parentOrganizatons);
636 
637         return organizations;
638     }
639 
640     protected boolean isParentOrganization(
641             long parentOrganizationId, long organizationId)
642         throws PortalException, SystemException {
643 
644         // Return true if parentOrganizationId is among the parent organizatons
645         // of organizationId
646 
647         Organization parentOrganization =
648             organizationPersistence.findByPrimaryKey(
649                 parentOrganizationId);
650 
651         List<Organization> parentOrganizations = getParentOrganizations(
652             organizationId);
653 
654         if (parentOrganizations.contains(parentOrganization)) {
655             return true;
656         }
657         else {
658             return false;
659         }
660     }
661 
662     protected void validate(
663             long companyId, long parentOrganizationId, String name, String type,
664             long countryId, int statusId)
665         throws PortalException, SystemException {
666 
667         validate(
668             companyId, 0, parentOrganizationId, name, type, countryId,
669             statusId);
670     }
671 
672     protected void validate(
673             long companyId, long organizationId, long parentOrganizationId,
674             String name, String type, long countryId, int statusId)
675         throws PortalException, SystemException {
676 
677         if ((parentOrganizationId ==
678                 OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID)) {
679 
680             if (!OrganizationImpl.isRootable(type)) {
681                 throw new OrganizationParentException(
682                     "Organization of type " + type + " cannot be a root");
683             }
684         }
685         else {
686             Organization parentOrganization =
687                 organizationPersistence.fetchByPrimaryKey(
688                     parentOrganizationId);
689 
690             if (parentOrganization == null) {
691                 throw new OrganizationParentException(
692                     "Organization " + parentOrganizationId + " doesn't exist");
693             }
694 
695             String[] childrenTypes = OrganizationImpl.getChildrenTypes(
696                 parentOrganization.getType());
697 
698             if (childrenTypes.length == 0) {
699                 throw new OrganizationParentException(
700                     "Organization of type " + type + " cannot have children");
701             }
702 
703             if ((companyId != parentOrganization.getCompanyId()) ||
704                 (parentOrganizationId == organizationId)) {
705 
706                 throw new OrganizationParentException();
707             }
708 
709             if (!ArrayUtil.contains(childrenTypes, type)) {
710                 throw new OrganizationParentException(
711                     "Type " + type + " not allowed as child of " +
712                         parentOrganization.getType());
713             }
714         }
715 
716         if ((organizationId > 0) &&
717             (parentOrganizationId !=
718                 OrganizationConstants.DEFAULT_PARENT_ORGANIZATION_ID)) {
719 
720             // Prevent circular organizational references
721 
722             if (isParentOrganization(organizationId, parentOrganizationId)) {
723                 throw new OrganizationParentException();
724             }
725         }
726 
727         if (Validator.isNull(name)) {
728             throw new OrganizationNameException();
729         }
730         else {
731             Organization organization = organizationPersistence.fetchByC_N(
732                 companyId, name);
733 
734             if ((organization != null) &&
735                 (organization.getName().equalsIgnoreCase(name))) {
736 
737                 if ((organizationId <= 0) ||
738                     (organization.getOrganizationId() != organizationId)) {
739 
740                     throw new DuplicateOrganizationException();
741                 }
742             }
743         }
744 
745         boolean countryRequired = GetterUtil.getBoolean(
746             PropsUtil.get(
747                 PropsKeys.ORGANIZATIONS_COUNTRY_REQUIRED, new Filter(type)));
748 
749         if (countryRequired || (countryId > 0)) {
750             countryPersistence.findByPrimaryKey(countryId);
751         }
752 
753         listTypeService.validate(statusId, ListTypeImpl.ORGANIZATION_STATUS);
754     }
755 
756 }