Coverage Report - org.kuali.rice.kim.service.impl.GroupUpdateServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
GroupUpdateServiceImpl
4%
6/143
2%
2/76
4.667
GroupUpdateServiceImpl$1
0%
0/3
0%
0/4
4.667
 
 1  
 /*
 2  
  * Copyright 2007-2010 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.kim.service.impl;
 17  
 
 18  
 import org.apache.commons.collections.CollectionUtils;
 19  
 import org.apache.commons.collections.Predicate;
 20  
 import org.apache.commons.lang.StringUtils;
 21  
 import org.apache.log4j.Logger;
 22  
 import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
 23  
 import org.kuali.rice.core.api.exception.RiceIllegalStateException;
 24  
 import org.kuali.rice.core.api.exception.RiceRuntimeException;
 25  
 import org.kuali.rice.kim.api.group.Group;
 26  
 import org.kuali.rice.kim.api.group.GroupService;
 27  
 import org.kuali.rice.kim.api.group.GroupUpdateService;
 28  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 29  
 import org.kuali.rice.kim.bo.entity.impl.KimEntityAffiliationImpl;
 30  
 import org.kuali.rice.kim.impl.common.attribute.KimAttributeDataBo;
 31  
 import org.kuali.rice.kim.impl.group.GroupAttributeBo;
 32  
 import org.kuali.rice.kim.impl.group.GroupBo;
 33  
 import org.kuali.rice.kim.impl.group.GroupMemberBo;
 34  
 import org.kuali.rice.kim.impl.group.GroupServiceBase;
 35  
 import org.kuali.rice.kim.service.IdentityManagementNotificationService;
 36  
 import org.kuali.rice.kim.service.KIMServiceLocatorInternal;
 37  
 import org.kuali.rice.kim.util.KIMPropertyConstants;
 38  
 import org.kuali.rice.kim.util.KIMWebServiceConstants;
 39  
 import org.kuali.rice.kim.util.KimConstants.KimGroupMemberTypes;
 40  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 41  
 import org.kuali.rice.kns.service.SequenceAccessorService;
 42  
 import org.kuali.rice.ksb.api.KsbApiServiceLocator;
 43  
 
 44  
 import javax.jws.WebService;
 45  
 import javax.xml.namespace.QName;
 46  
 import java.util.ArrayList;
 47  
 import java.util.Collection;
 48  
 import java.util.HashMap;
 49  
 import java.util.List;
 50  
 import java.util.Map;
 51  
 
 52  
 /**
 53  
  * This is the default implementation for the {@link GroupUpdateService}, where the write methods for KIM groups are located.
 54  
  *
 55  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 56  
  *
 57  
  */
 58  
 @WebService(endpointInterface = KIMWebServiceConstants.GroupUpdateService.INTERFACE_CLASS, serviceName = KIMWebServiceConstants.GroupUpdateService.WEB_SERVICE_NAME, portName = KIMWebServiceConstants.GroupUpdateService.WEB_SERVICE_PORT, targetNamespace = KIMWebServiceConstants.MODULE_TARGET_NAMESPACE)
 59  2
 public class GroupUpdateServiceImpl extends GroupServiceBase implements GroupUpdateService {
 60  
         
 61  1
         private static final Logger LOG = Logger.getLogger(GroupUpdateServiceImpl.class);
 62  
         
 63  
         private SequenceAccessorService sequenceAccessorService;
 64  
 
 65  
         /**
 66  
      * @see org.kuali.rice.kim.api.group.GroupUpdateService#addGroupToGroup(java.lang.String, java.lang.String)
 67  
      */
 68  
     public boolean addGroupToGroup(String childId, String parentId) {
 69  0
         if(childId.equals(parentId)) {
 70  0
             throw new IllegalArgumentException("Can't add group to itself.");
 71  
         }
 72  
 
 73  0
         if(isGroupMemberOfGroup(parentId, childId)) {
 74  0
             throw new IllegalArgumentException("Circular group reference.");
 75  
         }
 76  
 
 77  0
         GroupMemberBo groupMember = new GroupMemberBo();
 78  0
         groupMember.setGroupId(parentId);
 79  0
         groupMember.setTypeCode(KimGroupMemberTypes.GROUP_MEMBER_TYPE);
 80  0
         groupMember.setMemberId(childId);
 81  
 
 82  0
         this.businessObjectService.save(groupMember);
 83  0
         getIdentityManagementNotificationService().groupUpdated();
 84  
 
 85  0
         return true;
 86  
     }
 87  
 
 88  
     /**
 89  
      * @see org.kuali.rice.kim.api.group.GroupUpdateService#addPrincipalToGroup(java.lang.String, java.lang.String)
 90  
      */
 91  
     public boolean addPrincipalToGroup(String principalId, String groupId) {
 92  0
         GroupMemberBo groupMember = new GroupMemberBo();
 93  0
         groupMember.setGroupId(groupId);
 94  0
         groupMember.setTypeCode(KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE);
 95  0
         groupMember.setMemberId(principalId);
 96  
 
 97  0
         groupMember = (GroupMemberBo)this.businessObjectService.save(groupMember);
 98  0
         KIMServiceLocatorInternal.getGroupInternalService().updateForUserAddedToGroup(groupMember.getMemberId(), groupMember.getGroupId());
 99  0
         getIdentityManagementNotificationService().groupUpdated();
 100  0
         return true;
 101  
     }
 102  
 
 103  
     public Group createGroup(Group group) {
 104  1
         if (group == null) {
 105  1
             throw new RiceIllegalArgumentException(("group is null"));
 106  
         }
 107  0
         if (StringUtils.isNotBlank(group.getId()) && getGroup(group.getId()) != null) {
 108  0
             throw new RiceIllegalStateException("the group to create already exists: " + group);
 109  
         }
 110  0
         List<GroupAttributeBo> attrBos = KimAttributeDataBo.createFrom(GroupAttributeBo.class, group.getAttributes(), group.getKimTypeId());
 111  0
         if (StringUtils.isNotEmpty(group.getId())) {
 112  0
             for (GroupAttributeBo attr : attrBos) {
 113  0
                 attr.setAssignedToId(group.getId());
 114  
             }
 115  
         }
 116  0
         GroupBo bo = GroupBo.from(group);
 117  0
         bo.setAttributeDetails(attrBos);
 118  
 
 119  0
         bo = saveGroup(bo);
 120  
 
 121  0
         return GroupBo.to(bo);
 122  
     }
 123  
 
 124  
     public Group updateGroup(Group group) {
 125  0
         if (group == null) {
 126  0
             throw new RiceIllegalArgumentException(("group is null"));
 127  
         }
 128  0
         GroupBo origGroup = getGroupBo(group.getId());
 129  0
         if (StringUtils.isBlank(group.getId()) || origGroup == null) {
 130  0
             throw new RiceIllegalStateException("the group does not exist: " + group);
 131  
         }
 132  0
         List<GroupAttributeBo> attrBos = KimAttributeDataBo.createFrom(GroupAttributeBo.class, group.getAttributes(), group.getKimTypeId());
 133  0
         GroupBo bo = GroupBo.from(group);
 134  0
         bo.setMembers(origGroup.getMembers());
 135  0
         bo.setAttributeDetails(attrBos);
 136  
 
 137  0
         bo = saveGroup(bo);
 138  
 
 139  0
         return GroupBo.to(bo);
 140  
     }
 141  
 
 142  
             /**
 143  
          *
 144  
          * @see org.kuali.rice.kim.api.group.GroupUpdateService#updateGroup(java.lang.String, org.kuali.rice.kim.api.group.Group)
 145  
          */
 146  
         public Group updateGroup(String groupId, Group group) {
 147  1
         if (group == null) {
 148  1
             throw new RiceIllegalArgumentException(("group is null"));
 149  
         }
 150  0
         if (StringUtils.isEmpty(groupId)) {
 151  0
             throw new RiceIllegalArgumentException(("groupId is empty"));
 152  
         }
 153  
 
 154  0
         if (StringUtils.equals(groupId, group.getId())) {
 155  0
             return updateGroup(group);
 156  
         }
 157  
 
 158  
         //if group Ids are different, inactivate old group, and create new with new id based off old
 159  0
         GroupBo groupBo = getGroupBo(groupId);
 160  
 
 161  0
         if (StringUtils.isBlank(group.getId()) || groupBo == null) {
 162  0
             throw new RiceIllegalStateException("the group does not exist: " + group);
 163  
         }
 164  
 
 165  
         //create and save new group
 166  0
         GroupBo newGroup = GroupBo.from(group);
 167  0
         newGroup.setMembers(groupBo.getMembers());
 168  0
         List<GroupAttributeBo> attrBos = KimAttributeDataBo.createFrom(GroupAttributeBo.class, group.getAttributes(), group.getKimTypeId());
 169  0
         newGroup.setAttributeDetails(attrBos);
 170  0
         newGroup = saveGroup(newGroup);
 171  
 
 172  
         //inactivate and save old group
 173  0
         groupBo.setActive(false);
 174  0
         saveGroup(groupBo);
 175  
 
 176  0
         return GroupBo.to(newGroup);
 177  
     }
 178  
 
 179  
     /**
 180  
     *
 181  
     * @see org.kuali.rice.kim.api.group.GroupUpdateService#removeAllMembers(java.lang.String)
 182  
     */
 183  
    public void removeAllMembers(String groupId) {
 184  0
            GroupService groupService = KimApiServiceLocator.getGroupService();
 185  0
        List<String> memberPrincipalsBefore = groupService.getMemberPrincipalIds(groupId);
 186  
 
 187  0
        Collection<GroupMemberBo> toDeactivate = getActiveGroupMembers(groupId, null, null);
 188  0
        java.sql.Timestamp today = new java.sql.Timestamp(System.currentTimeMillis());
 189  
 
 190  
        // Set principals as inactive
 191  0
         for (GroupMemberBo aToDeactivate : toDeactivate) {
 192  0
             aToDeactivate.setActiveToDate(today);
 193  
         }
 194  
 
 195  
        // Save
 196  0
        this.businessObjectService.save(new ArrayList<GroupMemberBo>(toDeactivate));
 197  0
        List<String> memberPrincipalsAfter = groupService.getMemberPrincipalIds(groupId);
 198  
 
 199  0
        if (!CollectionUtils.isEmpty(memberPrincipalsAfter)) {
 200  
                // should never happen!
 201  0
                LOG.warn("after attempting removal of all members, group with id '" + groupId + "' still has principal members");
 202  
        }
 203  
 
 204  
        // do updates
 205  0
        KIMServiceLocatorInternal.getGroupInternalService().updateForWorkgroupChange(groupId, memberPrincipalsBefore, memberPrincipalsAfter);
 206  0
        getIdentityManagementNotificationService().groupUpdated();
 207  0
    }
 208  
 
 209  
         /**
 210  
      * @see org.kuali.rice.kim.api.group.GroupUpdateService#removeGroupFromGroup(java.lang.String, java.lang.String)
 211  
      */
 212  
     public boolean removeGroupFromGroup(String childId, String parentId) {
 213  0
             java.sql.Timestamp today = new java.sql.Timestamp(System.currentTimeMillis());
 214  
 
 215  0
             List<GroupMemberBo> groupMembers =
 216  
                     getActiveGroupMembers(parentId, childId, KimGroupMemberTypes.GROUP_MEMBER_TYPE);
 217  
 
 218  0
         if(groupMembers.size() == 1) {
 219  0
                 GroupMemberBo groupMember = groupMembers.get(0);
 220  0
                 groupMember.setActiveToDate(today);
 221  0
             this.businessObjectService.save(groupMember);
 222  0
             getIdentityManagementNotificationService().groupUpdated();
 223  0
             return true;
 224  
         }
 225  
 
 226  0
         return false;
 227  
     }
 228  
 
 229  
         /**
 230  
      * @see org.kuali.rice.kim.api.group.GroupUpdateService#removePrincipalFromGroup(java.lang.String, java.lang.String)
 231  
      */
 232  
     @SuppressWarnings("unchecked")
 233  
     public boolean removePrincipalFromGroup(String principalId, String groupId) {
 234  0
             List<GroupMemberBo> groupMembers =
 235  
                     getActiveGroupMembers(groupId, principalId, KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE);
 236  
 
 237  0
         if(groupMembers.size() == 1) {
 238  0
                 GroupMemberBo member = groupMembers.iterator().next();
 239  0
                 member.setActiveToDate(new java.sql.Timestamp(System.currentTimeMillis()));
 240  0
                 this.businessObjectService.save(member);
 241  0
             KIMServiceLocatorInternal.getGroupInternalService().updateForUserRemovedFromGroup(member.getMemberId(), member.getGroupId());
 242  0
             getIdentityManagementNotificationService().groupUpdated();
 243  0
             return true;
 244  
         }
 245  
 
 246  0
         return false;
 247  
     }
 248  
 
 249  
         protected GroupBo saveGroup(GroupBo group) {
 250  0
                 if ( group == null ) {
 251  0
                         return null;
 252  0
                 } else if (group.getId() != null) {
 253  
                         // Get the version of the group that is in the DB
 254  0
                         GroupBo oldGroup = getGroupBo(group.getId());
 255  
 
 256  0
                         if (oldGroup != null) {
 257  
                                 // Inactivate and re-add members no longer in the group (in order to preserve history).
 258  0
                                 java.sql.Timestamp activeTo = new java.sql.Timestamp(System.currentTimeMillis());
 259  0
                                 List<GroupMemberBo> toReAdd = null;
 260  
 
 261  0
                                 if (oldGroup.getMembers() != null) {
 262  0
                     for (GroupMemberBo member : oldGroup.getMembers()) {
 263  
                         // if the old member isn't in the new group
 264  0
                         if (group.getMembers() == null || !group.getMembers().contains(member)) {
 265  
                             // inactivate the member
 266  0
                             member.setActiveToDate(activeTo);
 267  0
                             if (toReAdd == null) {
 268  0
                                 toReAdd = new ArrayList<GroupMemberBo>();
 269  
                             }
 270  
                             // queue it up for re-adding
 271  0
                             toReAdd.add(member);
 272  
                         }
 273  
                     }
 274  
                                 }
 275  
 
 276  
                                 // do the re-adding
 277  0
                                 if (toReAdd != null) {
 278  0
                                         List<GroupMemberBo> groupMembers = group.getMembers();
 279  0
                                         if (groupMembers == null) {
 280  0
                         groupMembers = new ArrayList<GroupMemberBo>(toReAdd.size());
 281  
                     }
 282  0
                                         group.setMembers(groupMembers);
 283  
                                 }
 284  
                         }
 285  
                 }
 286  
 
 287  
                 // GroupInternalService handles KEW update duties
 288  
                 
 289  0
                 SequenceAccessorService sas = getSequenceAccessorService();
 290  0
             if (group.getId() == null) {
 291  0
                     group.setId(sas.getNextAvailableSequenceNumber(
 292  
                     "KRIM_GRP_ID_S", GroupBo.class).toString());
 293  
             }
 294  0
                 GroupBo savedGroup = KIMServiceLocatorInternal.getGroupInternalService().saveWorkgroup(group);
 295  0
                 getIdentityManagementNotificationService().groupUpdated();
 296  0
                 return savedGroup;
 297  
         }
 298  
 
 299  
         protected void saveGroupAttributes(List<GroupAttributeBo> groupAttributes) {
 300  0
         if ( groupAttributes == null ) {
 301  0
             return;
 302  
         }
 303  0
         SequenceAccessorService sas = getSequenceAccessorService();
 304  0
         for (GroupAttributeBo groupAttribute : groupAttributes) {
 305  0
                 if (groupAttribute.getId() == null) {
 306  0
                         groupAttribute.setId(sas.getNextAvailableSequenceNumber(
 307  
                         "KRIM_GRP_ATTR_DATA_ID_S", KimEntityAffiliationImpl.class).toString());
 308  
                 }
 309  
         }
 310  0
         this.businessObjectService.save( groupAttributes );
 311  0
     }
 312  
 
 313  
         protected void deleteGroupAttribute(GroupAttributeBo groupAttribute) {
 314  0
         if ( groupAttribute == null ) {
 315  0
             return;
 316  
         }
 317  0
         this.businessObjectService.delete( groupAttribute );
 318  0
     }
 319  
 
 320  
         /**
 321  
          * This helper method gets the active group members of the specified type (see {@link KimGroupMemberTypes}).
 322  
          * If the optional params are null, it will return all active members for the specified group regardless
 323  
          * of type.
 324  
          *
 325  
          * @param parentId
 326  
          * @param childId optional, but if provided then memberType must be too
 327  
          * @param memberType optional, but must be provided if childId is
 328  
      * @return a list of group members
 329  
          */
 330  
         private List<GroupMemberBo> getActiveGroupMembers(String parentId,
 331  
                         String childId, String memberType) {
 332  0
             final java.sql.Date today = new java.sql.Date(System.currentTimeMillis());
 333  
 
 334  0
             if (childId != null && memberType == null) throw new RiceRuntimeException("memberType must be non-null if childId is non-null");
 335  
 
 336  0
                 Map<String,Object> criteria = new HashMap<String,Object>(4);
 337  0
         criteria.put(KIMPropertyConstants.GroupMember.GROUP_ID, parentId);
 338  
 
 339  0
         if (childId != null) {
 340  0
                 criteria.put(KIMPropertyConstants.GroupMember.MEMBER_ID, childId);
 341  0
                 criteria.put(KIMPropertyConstants.GroupMember.MEMBER_TYPE_CODE, memberType);
 342  
         }
 343  
 
 344  0
         Collection<GroupMemberBo> groupMembers = this.businessObjectService.findMatching(GroupMemberBo.class, criteria);
 345  
 
 346  0
         CollectionUtils.filter(groupMembers, new Predicate() {
 347  
                         public boolean evaluate(Object object) {
 348  0
                                 GroupMemberBo member = (GroupMemberBo) object;
 349  
                                 // keep in the collection (return true) if the activeToDate is null, or if it is set to a future date
 350  0
                                 return member.getActiveToDate() == null || today.before(member.getActiveToDate());
 351  
                         }
 352  
                 });
 353  
 
 354  0
         return new ArrayList<GroupMemberBo>(groupMembers);
 355  
         }
 356  
 
 357  
         protected SequenceAccessorService getSequenceAccessorService() {
 358  0
                 if ( sequenceAccessorService == null ) {
 359  0
                         sequenceAccessorService = KNSServiceLocator.getSequenceAccessorService();
 360  
                 }
 361  0
                 return sequenceAccessorService;
 362  
         }
 363  
 
 364  
     protected IdentityManagementNotificationService getIdentityManagementNotificationService() {
 365  0
         return (IdentityManagementNotificationService) KsbApiServiceLocator.getMessageHelper().getServiceAsynchronously(new QName("KIM", "kimIdentityManagementNotificationService"));
 366  
     }
 367  
         
 368  
 }