001    /*
002     * Copyright 2007-2009 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.kim.service.impl;
017    
018    import java.util.ArrayList;
019    import java.util.Collections;
020    import java.util.HashSet;
021    import java.util.List;
022    import java.util.Set;
023    
024    import javax.xml.namespace.QName;
025    
026    import org.apache.commons.collections.ListUtils;
027    import org.apache.commons.lang.StringUtils;
028    import org.kuali.rice.kew.api.WorkflowRuntimeException;
029    import org.kuali.rice.kew.messaging.MessageServiceNames;
030    import org.kuali.rice.kew.util.KEWConstants;
031    import org.kuali.rice.kew.workgroup.WorkgroupMembershipChangeProcessor;
032    import org.kuali.rice.kim.api.services.KimApiServiceLocator;
033    import org.kuali.rice.kim.impl.group.GroupBo;
034    import org.kuali.rice.kim.api.group.GroupService;
035    import org.kuali.rice.kim.service.GroupInternalService;
036    import org.kuali.rice.krad.service.BusinessObjectService;
037    import org.kuali.rice.krad.service.KRADServiceLocator;
038    import org.kuali.rice.ksb.api.KsbApiServiceLocator;
039    import org.kuali.rice.ksb.messaging.service.KSBXMLService;
040    
041    /**
042     * Concrete Implementation of {@link GroupInternalService}
043     *
044     * @author Kuali Rice Team (rice.collab@kuali.org)
045     *
046     */
047    public class GroupInternalServiceImpl implements GroupInternalService {
048        protected BusinessObjectService getBusinessObjectService() {
049            return KRADServiceLocator.getBusinessObjectService();
050        }
051    
052    
053        public GroupService getGroupService(){
054            return KimApiServiceLocator.getGroupService();
055        }
056    
057        public GroupBo saveWorkgroup(GroupBo group) {
058            GroupService ims = getGroupService();
059            List<String> oldIds = Collections.EMPTY_LIST;
060            if (StringUtils.isNotEmpty(group.getId())) {
061                oldIds = ims.getMemberPrincipalIds(group.getId());
062            }
063            group = (GroupBo)getBusinessObjectService().save( group );
064            List<String> newIds = ims.getMemberPrincipalIds(group.getId());
065            updateForWorkgroupChange(group.getId(), oldIds, newIds);
066            return group;
067        }
068    
069        public void updateForWorkgroupChange(String groupId,
070                    List<String> oldPrincipalIds, List<String> newPrincipalIds) {
071            MembersDiff membersDiff = getMembersDiff(oldPrincipalIds, newPrincipalIds);
072            for (String removedPrincipalId : membersDiff.getRemovedPrincipalIds()) {
073                    updateForUserRemovedFromGroup(removedPrincipalId, groupId);
074            }
075            for (String addedPrincipalId : membersDiff.getAddedPrincipalIds()) {
076                    updateForUserAddedToGroup(addedPrincipalId, groupId);
077            }
078        }
079    
080        public void updateForUserAddedToGroup(String principalId, String groupId) {
081            // first verify that the user is still a member of the workgroup
082            if(getGroupService().isMemberOfGroup(principalId, groupId))
083            {
084                KSBXMLService workgroupMembershipChangeProcessor = (KSBXMLService) KsbApiServiceLocator.getMessageHelper()
085                .getServiceAsynchronously(new QName(KEWConstants.KEW_MODULE_NAMESPACE, MessageServiceNames.WORKGROUP_MEMBERSHIP_CHANGE_SERVICE));
086                try {
087                    workgroupMembershipChangeProcessor.invoke(WorkgroupMembershipChangeProcessor
088                            .getMemberAddedMessageContents(principalId, groupId));
089                } catch (Exception e) {
090                    throw new WorkflowRuntimeException(e);
091                }
092            }
093        }
094    
095        public void updateForUserRemovedFromGroup(String principalId, String groupId) {
096            // first verify that the user is no longer a member of the workgroup
097            if(!getGroupService().isMemberOfGroup(principalId, groupId))
098            {
099                KSBXMLService workgroupMembershipChangeProcessor = (KSBXMLService) KsbApiServiceLocator.getMessageHelper()
100                .getServiceAsynchronously(new QName(KEWConstants.KEW_MODULE_NAMESPACE, MessageServiceNames.WORKGROUP_MEMBERSHIP_CHANGE_SERVICE));
101                try {
102                    workgroupMembershipChangeProcessor.invoke(WorkgroupMembershipChangeProcessor
103                            .getMemberRemovedMessageContents(principalId, groupId));
104                } catch (Exception e) {
105                    throw new WorkflowRuntimeException(e);
106                }
107            }
108    
109        }
110    
111        private MembersDiff getMembersDiff(List<String> oldMemberPrincipalIds, List<String> newMemberPrincipalIds) {
112    
113            // ListUtils does not check the null case.  Which can happen when adding a new group
114            // so, if they're null make them empty lists.
115            if(oldMemberPrincipalIds == null) oldMemberPrincipalIds = new ArrayList<String>();
116            if(newMemberPrincipalIds == null) newMemberPrincipalIds = new ArrayList<String>();
117    
118            Set<String> addedPrincipalIds = new HashSet<String>(ListUtils.subtract(newMemberPrincipalIds, oldMemberPrincipalIds));
119            Set<String> removedPrincipalIds = new HashSet<String>(ListUtils.subtract(oldMemberPrincipalIds, newMemberPrincipalIds));
120            return new MembersDiff(addedPrincipalIds, removedPrincipalIds);
121        }
122    
123        private class MembersDiff {
124            private final Set<String> addedPrincipalIds;
125    
126            private final Set<String> removedPrincipalIds;
127    
128            public MembersDiff(Set<String> addedPrincipalIds, Set<String>removedPrincipalIds) {
129                this.addedPrincipalIds = addedPrincipalIds;
130                this.removedPrincipalIds = removedPrincipalIds;
131            }
132    
133            public Set<String> getAddedPrincipalIds() {
134                return addedPrincipalIds;
135            }
136    
137            public Set<String> getRemovedPrincipalIds() {
138                return removedPrincipalIds;
139            }
140        }
141    
142    }