Coverage Report - org.kuali.rice.kim.impl.group.GroupServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
GroupServiceImpl
0%
0/402
0%
0/216
3.679
GroupServiceImpl$1
0%
0/3
0%
0/4
3.679
 
 1  
 /**
 2  
  * Copyright 2005-2011 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.impl.group;
 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.criteria.CriteriaLookupService;
 23  
 import org.kuali.rice.core.api.criteria.GenericQueryResults;
 24  
 import org.kuali.rice.core.api.criteria.LookupCustomizer;
 25  
 import org.kuali.rice.core.api.criteria.QueryByCriteria;
 26  
 import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
 27  
 import org.kuali.rice.core.api.exception.RiceRuntimeException;
 28  
 import org.kuali.rice.core.api.membership.MemberType;
 29  
 import org.kuali.rice.kim.api.KimConstants;
 30  
 import org.kuali.rice.kim.api.group.Group;
 31  
 import org.kuali.rice.kim.api.group.GroupMember;
 32  
 import org.kuali.rice.kim.api.group.GroupMemberQueryResults;
 33  
 import org.kuali.rice.kim.api.group.GroupQueryResults;
 34  
 import org.kuali.rice.kim.api.group.GroupService;
 35  
 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
 36  
 import org.kuali.rice.kim.impl.KIMPropertyConstants;
 37  
 import org.kuali.rice.kim.impl.common.attribute.AttributeTransform;
 38  
 import org.kuali.rice.kim.impl.common.attribute.KimAttributeDataBo;
 39  
 import org.kuali.rice.kim.impl.services.KimImplServiceLocator;
 40  
 import org.kuali.rice.krad.service.BusinessObjectService;
 41  
 
 42  
 import javax.jws.WebParam;
 43  
 import java.sql.Timestamp;
 44  
 import java.util.ArrayList;
 45  
 import java.util.Collection;
 46  
 import java.util.Collections;
 47  
 import java.util.HashMap;
 48  
 import java.util.HashSet;
 49  
 import java.util.List;
 50  
 import java.util.Map;
 51  
 import java.util.Set;
 52  
 
 53  
 import static org.kuali.rice.core.api.criteria.PredicateFactory.*;
 54  
 
 55  0
 public class GroupServiceImpl extends GroupServiceBase implements GroupService {
 56  0
     private static final Logger LOG = Logger.getLogger(GroupServiceImpl.class);
 57  
 
 58  
     protected BusinessObjectService businessObjectService;
 59  
     private CriteriaLookupService criteriaLookupService;
 60  
 
 61  
     @Override
 62  
     public Group getGroup(String groupId) throws RiceIllegalArgumentException {
 63  0
         incomingParamCheck(groupId, "groupId");
 64  0
                 return GroupBo.to(getGroupBo(groupId));
 65  
     }
 66  
 
 67  
     @Override
 68  
     public List<Group> getGroupsByPrincipalId(String principalId) throws RiceIllegalArgumentException {
 69  0
         incomingParamCheck(principalId,  "principalId");
 70  0
         return getGroupsByPrincipalIdAndNamespaceCodeInternal(principalId, null);
 71  
     }
 72  
 
 73  
     @Override
 74  
     public List<Group> getGroupsByPrincipalIdAndNamespaceCode(String principalId, String namespaceCode) throws RiceIllegalArgumentException {
 75  0
         incomingParamCheck(principalId, "principalId");
 76  0
         incomingParamCheck(namespaceCode, "namespaceCode");
 77  
 
 78  0
                 return getGroupsByPrincipalIdAndNamespaceCodeInternal(principalId, namespaceCode);
 79  
     }
 80  
 
 81  
     protected List<Group> getGroupsByPrincipalIdAndNamespaceCodeInternal(String principalId, String namespaceCode) throws RiceIllegalArgumentException {
 82  
 
 83  0
         Collection<Group> directGroups = getDirectGroupsForPrincipal( principalId, namespaceCode );
 84  0
                 Set<Group> groups = new HashSet<Group>();
 85  0
         groups.addAll(directGroups);
 86  0
                 for ( Group group : directGroups ) {
 87  0
                         groups.add( group );
 88  0
                         groups.addAll( getParentGroups( group.getId() ) );
 89  
                 }
 90  0
                 return Collections.unmodifiableList(new ArrayList<Group>( groups ));
 91  
     }
 92  
 
 93  
     @Override
 94  
     public List<String> findGroupIds(final QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
 95  0
         incomingParamCheck(queryByCriteria, "queryByCriteria");
 96  
 
 97  0
         GroupQueryResults results = this.findGroups(queryByCriteria);
 98  0
         List<String> result = new ArrayList<String>();
 99  
 
 100  0
         for (Group group : results.getResults()) {
 101  0
             result.add(group.getId());
 102  
         }
 103  
 
 104  0
         return Collections.unmodifiableList(result);
 105  
     }
 106  
 
 107  
     @Override
 108  
     public boolean isDirectMemberOfGroup(String principalId, String groupId) throws RiceIllegalArgumentException {
 109  0
         incomingParamCheck(principalId, "principalId");
 110  0
         incomingParamCheck(groupId, "groupId");
 111  
 
 112  0
                 Map<String,String> criteria = new HashMap<String,String>();
 113  0
                 criteria.put(KIMPropertyConstants.GroupMember.MEMBER_ID, principalId);
 114  0
                 criteria.put(KIMPropertyConstants.GroupMember.MEMBER_TYPE_CODE, KimConstants.KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE.getCode());
 115  0
                 criteria.put(KIMPropertyConstants.GroupMember.GROUP_ID, groupId);
 116  
 
 117  0
                 Collection<GroupMemberBo> groupMembers = businessObjectService.findMatching(GroupMemberBo.class, criteria);
 118  0
                 for ( GroupMemberBo gm : groupMembers ) {
 119  0
                         if ( gm.isActive(new Timestamp(System.currentTimeMillis())) ) {
 120  0
                                 return true;
 121  
                         }
 122  
                 }
 123  0
                 return false;
 124  
     }
 125  
 
 126  
     @Override
 127  
     public List<String> getGroupIdsByPrincipalId(String principalId) throws RiceIllegalArgumentException {
 128  0
         incomingParamCheck(principalId, "principalId");
 129  0
         return getGroupIdsByPrincipalIdAndNamespaceCodeInternal(principalId, null);
 130  
     }
 131  
 
 132  
     @Override
 133  
     public List<String> getGroupIdsByPrincipalIdAndNamespaceCode(String principalId, String namespaceCode) throws RiceIllegalArgumentException {
 134  0
         incomingParamCheck(principalId, "principalId");
 135  0
         incomingParamCheck(namespaceCode, "namespaceCode");
 136  
 
 137  0
         List<String> result = new ArrayList<String>();
 138  
 
 139  0
         if (principalId != null) {
 140  0
             List<Group> groupList = getGroupsByPrincipalIdAndNamespaceCode(principalId, namespaceCode);
 141  
 
 142  0
             for (Group group : groupList) {
 143  0
                 result.add(group.getId());
 144  
             }
 145  
         }
 146  
 
 147  0
         return Collections.unmodifiableList(result);
 148  
     }
 149  
 
 150  
     protected List<String> getGroupIdsByPrincipalIdAndNamespaceCodeInternal(String principalId, String namespaceCode) throws RiceIllegalArgumentException {
 151  
 
 152  0
         List<String> result = new ArrayList<String>();
 153  
 
 154  0
         if (principalId != null) {
 155  0
             List<Group> groupList = getGroupsByPrincipalIdAndNamespaceCodeInternal(principalId, namespaceCode);
 156  
 
 157  0
             for (Group group : groupList) {
 158  0
                 result.add(group.getId());
 159  
             }
 160  
         }
 161  
 
 162  0
         return Collections.unmodifiableList(result);
 163  
     }
 164  
 
 165  
     @Override
 166  
     public List<String> getDirectGroupIdsByPrincipalId(String principalId) throws RiceIllegalArgumentException {
 167  0
         incomingParamCheck(principalId, "principalId");
 168  
 
 169  0
         List<String> result = new ArrayList<String>();
 170  
 
 171  0
         if (principalId != null) {
 172  0
                 Collection<Group> groupList = getDirectGroupsForPrincipal(principalId);
 173  
 
 174  0
             for (Group g : groupList) {
 175  0
                 result.add(g.getId());
 176  
             }
 177  
         }
 178  
 
 179  0
         return Collections.unmodifiableList(result);
 180  
     }
 181  
 
 182  
     @Override
 183  
     public List<String> getMemberPrincipalIds(String groupId) throws RiceIllegalArgumentException {
 184  0
         incomingParamCheck(groupId, "groupId");
 185  
 
 186  0
                 return getMemberPrincipalIdsInternal(groupId, new HashSet<String>());
 187  
     }
 188  
 
 189  
     @Override
 190  
     public List<String> getDirectMemberPrincipalIds(String groupId) throws RiceIllegalArgumentException {
 191  0
         incomingParamCheck(groupId, "groupId");
 192  
 
 193  0
         return this.getMemberIdsByType(getMembersOfGroup(groupId), KimConstants.KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE);
 194  
     }
 195  
 
 196  
     @Override
 197  
     public List<String> getMemberGroupIds(String groupId) throws RiceIllegalArgumentException {
 198  0
         incomingParamCheck(groupId, "groupId");
 199  
 
 200  0
                 List<GroupBo> groups = getMemberGroupBos( groupId );
 201  0
                 ArrayList<String> groupIds = new ArrayList<String>( groups.size() );
 202  0
                 for ( GroupBo group : groups ) {
 203  0
                         if ( group.isActive() ) {
 204  0
                                 groupIds.add( group.getId() );
 205  
                         }
 206  
                 }
 207  0
                 return Collections.unmodifiableList(groupIds);
 208  
     }
 209  
 
 210  
 
 211  
         protected List<GroupBo> getMemberGroupBos(String groupId) {
 212  0
                 if ( groupId == null ) {
 213  0
                         return Collections.emptyList();
 214  
                 }
 215  0
                 Set<GroupBo> groups = new HashSet<GroupBo>();
 216  
 
 217  0
                 GroupBo group = getGroupBo(groupId);
 218  0
                 getMemberGroupsInternal(group, groups);
 219  
 
 220  0
                 return new ArrayList<GroupBo>(groups);
 221  
         }
 222  
 
 223  
     protected void getMemberGroupsInternal( GroupBo group, Set<GroupBo> groups ) {
 224  0
                 if ( group == null ) {
 225  0
                         return;
 226  
                 }
 227  0
                 List<String> groupIds = group.getMemberGroupIds();
 228  
 
 229  0
                 for (String id : groupIds) {
 230  0
                         GroupBo memberGroup = getGroupBo(id);
 231  
                         // if we've already seen that group, don't recurse into it
 232  0
                         if ( memberGroup.isActive() && !groups.contains( memberGroup ) ) {
 233  0
                                 groups.add(memberGroup);
 234  0
                                 getMemberGroupsInternal(memberGroup,groups);
 235  
                         }
 236  0
                 }
 237  
 
 238  0
         }
 239  
 
 240  
     @Override
 241  
         public boolean isGroupMemberOfGroup(String groupMemberId, String groupId) throws RiceIllegalArgumentException {
 242  0
         incomingParamCheck(groupMemberId, "groupMemberId");
 243  0
         incomingParamCheck(groupId, "groupId");
 244  
 
 245  0
                 return isMemberOfGroupInternal(groupMemberId, groupId, new HashSet<String>(), KimConstants.KimGroupMemberTypes.GROUP_MEMBER_TYPE);
 246  
         }
 247  
 
 248  
     @Override
 249  
     public boolean isMemberOfGroup(String principalId, String groupId) throws RiceIllegalArgumentException{
 250  0
         incomingParamCheck(principalId, "principalId");
 251  0
         incomingParamCheck(groupId, "groupId");
 252  
 
 253  0
                 Set<String> visitedGroupIds = new HashSet<String>();
 254  0
                 return isMemberOfGroupInternal(principalId, groupId, visitedGroupIds, KimConstants.KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE);
 255  
     }
 256  
 
 257  
     @Override
 258  
     public List<String> getDirectMemberGroupIds(String groupId) throws RiceIllegalArgumentException{
 259  0
         incomingParamCheck(groupId, "groupId");
 260  
 
 261  0
         return this.getMemberIdsByType(getMembersOfGroup(groupId), KimConstants.KimGroupMemberTypes.GROUP_MEMBER_TYPE);
 262  
     }
 263  
 
 264  
     @Override
 265  
     public List<String> getParentGroupIds(String groupId) throws RiceIllegalArgumentException {
 266  0
         incomingParamCheck(groupId, "groupId");
 267  
 
 268  0
         List<String> result = new ArrayList<String>();
 269  0
         if (groupId != null) {
 270  0
             List<Group> groupList = getParentGroups(groupId);
 271  
 
 272  0
             for (Group group : groupList) {
 273  0
                 result.add(group.getId());
 274  
             }
 275  
         }
 276  
 
 277  0
         return Collections.unmodifiableList(result);
 278  
     }
 279  
 
 280  
     @Override
 281  
     public List<String> getDirectParentGroupIds(String groupId) throws RiceIllegalArgumentException {
 282  0
         incomingParamCheck(groupId, "groupId");
 283  
 
 284  0
         List<String> result = new ArrayList<String>();
 285  0
         if (groupId != null) {
 286  0
             List<Group> groupList = getDirectParentGroups(groupId);
 287  0
             for (Group group : groupList) {
 288  0
                 result.add(group.getId());
 289  
             }
 290  
         }
 291  
 
 292  0
         return Collections.unmodifiableList(result);
 293  
     }
 294  
 
 295  
     @Override
 296  
     public Map<String, String> getAttributes(String groupId) throws RiceIllegalArgumentException {
 297  0
         incomingParamCheck(groupId, "groupId");
 298  
 
 299  0
         Group group = getGroup(groupId);
 300  0
         if (group != null) {
 301  0
             return group.getAttributes();
 302  
         }
 303  0
         return Collections.emptyMap();
 304  
     }
 305  
 
 306  
     @Override
 307  
     public List<GroupMember> getMembers(List<String> groupIds) throws RiceIllegalArgumentException{
 308  0
         if (CollectionUtils.isEmpty(groupIds)) {
 309  0
             throw new RiceIllegalArgumentException("groupIds is empty");
 310  
                 }
 311  
 
 312  
         //TODO: PRIME example of something for new Criteria API
 313  0
         List<GroupMember> groupMembers = new ArrayList<GroupMember>();
 314  0
         for (String groupId : groupIds) {
 315  0
               groupMembers.addAll(getMembersOfGroup(groupId));
 316  
         }
 317  0
         return Collections.unmodifiableList(groupMembers);
 318  
     }
 319  
 
 320  
     @Override
 321  
     public List<Group> getGroups(Collection<String> groupIds) throws RiceIllegalArgumentException {
 322  0
         incomingParamCheck(groupIds, "groupIds");
 323  0
         if (groupIds.isEmpty()) {
 324  0
             return Collections.emptyList();
 325  
         }
 326  0
         final QueryByCriteria.Builder builder = QueryByCriteria.Builder.create();
 327  0
         builder.setPredicates(and(in("id", groupIds.toArray()), equal("active", "Y")));
 328  0
         GroupQueryResults qr = findGroups(builder.build());
 329  
 
 330  0
         return qr.getResults();
 331  
     }
 332  
 
 333  
     @Override
 334  
     public Group getGroupByNameAndNamespaceCode(String namespaceCode, String groupName) throws RiceIllegalArgumentException{
 335  0
         incomingParamCheck(namespaceCode, "namespaceCode");
 336  0
         incomingParamCheck(groupName, "groupName");
 337  
 
 338  0
                 Map<String,String> criteria = new HashMap<String,String>();
 339  0
                 criteria.put(KimConstants.UniqueKeyConstants.NAMESPACE_CODE, namespaceCode);
 340  0
                 criteria.put(KimConstants.UniqueKeyConstants.GROUP_NAME, groupName);
 341  0
                 Collection<GroupBo> groups = businessObjectService.findMatching(GroupBo.class, criteria);
 342  0
                 if ( !groups.isEmpty() ) {
 343  0
                         return GroupBo.to(groups.iterator().next());
 344  
                 }
 345  0
                 return null;
 346  
     }
 347  
 
 348  
     @Override
 349  
     public GroupQueryResults findGroups(final QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
 350  0
         incomingParamCheck(queryByCriteria, "queryByCriteria");
 351  
 
 352  0
         LookupCustomizer.Builder<GroupBo> lc = LookupCustomizer.Builder.create();
 353  0
         lc.setPredicateTransform(AttributeTransform.getInstance());
 354  
 
 355  0
         GenericQueryResults<GroupBo> results = criteriaLookupService.lookup(GroupBo.class, queryByCriteria, lc.build());
 356  
 
 357  0
         GroupQueryResults.Builder builder = GroupQueryResults.Builder.create();
 358  0
         builder.setMoreResultsAvailable(results.isMoreResultsAvailable());
 359  0
         builder.setTotalRowCount(results.getTotalRowCount());
 360  
 
 361  0
         final List<Group.Builder> ims = new ArrayList<Group.Builder>();
 362  0
         for (GroupBo bo : results.getResults()) {
 363  0
             ims.add(Group.Builder.create(bo));
 364  
         }
 365  
 
 366  0
         builder.setResults(ims);
 367  0
         return builder.build();
 368  
     }
 369  
 
 370  
     @Override
 371  
     public GroupMemberQueryResults findGroupMembers(final QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
 372  0
         incomingParamCheck(queryByCriteria, "queryByCriteria");
 373  
 
 374  0
         GenericQueryResults<GroupMemberBo> results = criteriaLookupService.lookup(GroupMemberBo.class, queryByCriteria);
 375  
 
 376  0
         GroupMemberQueryResults.Builder builder = GroupMemberQueryResults.Builder.create();
 377  0
         builder.setMoreResultsAvailable(results.isMoreResultsAvailable());
 378  0
         builder.setTotalRowCount(results.getTotalRowCount());
 379  
 
 380  0
         final List<GroupMember.Builder> ims = new ArrayList<GroupMember.Builder>();
 381  0
         for (GroupMemberBo bo : results.getResults()) {
 382  0
             ims.add(GroupMember.Builder.create(bo));
 383  
         }
 384  
 
 385  0
         builder.setResults(ims);
 386  0
         return builder.build();
 387  
     }
 388  
 
 389  
 
 390  
     protected boolean isMemberOfGroupInternal(String memberId, String groupId, Set<String> visitedGroupIds, MemberType memberType) {
 391  0
                 if ( memberId == null || groupId == null ) {
 392  0
                         return false;
 393  
                 }
 394  
 
 395  
                 // when group traversal is not needed
 396  0
                 Group group = getGroup(groupId);
 397  0
                 if ( group == null || !group.isActive() ) {
 398  0
                         return false;
 399  
                 }
 400  
 
 401  0
         List<GroupMember> members = getMembersOfGroup(group.getId());
 402  
                 // check the immediate group
 403  0
                 for (String groupMemberId : getMemberIdsByType(members, memberType)) {
 404  0
                         if (groupMemberId.equals(memberId)) {
 405  0
                                 return true;
 406  
                         }
 407  
                 }
 408  
 
 409  
                 // check each contained group, returning as soon as a match is found
 410  0
                 for ( String memberGroupId : getMemberIdsByType(members, KimConstants.KimGroupMemberTypes.GROUP_MEMBER_TYPE) ) {
 411  0
                         if (!visitedGroupIds.contains(memberGroupId)){
 412  0
                                 visitedGroupIds.add(memberGroupId);
 413  0
                                 if ( isMemberOfGroupInternal( memberId, memberGroupId, visitedGroupIds, memberType ) ) {
 414  0
                                         return true;
 415  
                                 }
 416  
                         }
 417  
                 }
 418  
 
 419  
                 // no match found, return false
 420  0
                 return false;
 421  
         }
 422  
 
 423  
     protected void getParentGroupsInternal( String groupId, Set<Group> groups ) {
 424  0
                 List<Group> parentGroups = getDirectParentGroups( groupId );
 425  0
                 for ( Group group : parentGroups ) {
 426  0
                         if ( !groups.contains( group ) ) {
 427  0
                                 groups.add( group );
 428  0
                                 getParentGroupsInternal( group.getId(), groups );
 429  
                         }
 430  
                 }
 431  0
         }
 432  
 
 433  
     protected List<Group> getDirectParentGroups(String groupId) {
 434  0
                 if ( groupId == null ) {
 435  0
                         return Collections.emptyList();
 436  
                 }
 437  0
                 Map<String,String> criteria = new HashMap<String,String>();
 438  0
                 criteria.put(KIMPropertyConstants.GroupMember.MEMBER_ID, groupId);
 439  0
                 criteria.put(KIMPropertyConstants.GroupMember.MEMBER_TYPE_CODE, KimConstants.KimGroupMemberTypes.GROUP_MEMBER_TYPE.getCode());
 440  
 
 441  0
                 List<GroupMemberBo> groupMembers = (List<GroupMemberBo>)businessObjectService.findMatching(GroupMemberBo.class, criteria);
 442  0
                 Set<String> matchingGroupIds = new HashSet<String>();
 443  
                 // filter to active groups
 444  0
                 for ( GroupMemberBo gm : groupMembers ) {
 445  0
                         if ( gm.isActive(new Timestamp(System.currentTimeMillis())) ) {
 446  0
                                 matchingGroupIds.add(gm.getGroupId());
 447  
                         }
 448  
                 }
 449  0
                 if (CollectionUtils.isNotEmpty(matchingGroupIds)) {
 450  0
             return getGroups(matchingGroupIds);
 451  
         }
 452  0
         return Collections.emptyList();
 453  
         }
 454  
 
 455  
     @Override
 456  
     public List<GroupMember> getMembersOfGroup(String groupId) throws RiceIllegalArgumentException {
 457  0
         incomingParamCheck(groupId, "groupId");
 458  0
         Map<String,String> criteria = new HashMap<String,String>();
 459  0
                 criteria.put(KIMPropertyConstants.GroupMember.GROUP_ID, groupId);
 460  
 
 461  0
                 Collection<GroupMemberBo> groupMembersBos = businessObjectService.findMatching(GroupMemberBo.class, criteria);
 462  0
         List<GroupMember> groupMembers = new ArrayList<GroupMember>();
 463  0
         for (GroupMemberBo groupBo : groupMembersBos) {
 464  0
             if (groupBo.isActive(new Timestamp(System.currentTimeMillis()))){
 465  0
                 groupMembers.add(GroupMemberBo.to(groupBo));
 466  
             }
 467  
         }
 468  0
         return Collections.unmodifiableList(groupMembers);
 469  
     }
 470  
 
 471  
     protected List<String> getMemberIdsByType(Collection<GroupMember> members, MemberType memberType) {
 472  0
         List<String> membersIds = new ArrayList<String>();
 473  0
         if (members != null) {
 474  0
             for (GroupMember member : members) {
 475  0
                 if (member.getType().equals(memberType)) {
 476  0
                     membersIds.add(member.getMemberId());
 477  
                 }
 478  
             }
 479  
         }
 480  0
         return Collections.unmodifiableList(membersIds);
 481  
     }
 482  
 
 483  
     protected GroupBo getGroupBo(String groupId) {
 484  0
         incomingParamCheck(groupId, "groupId");
 485  0
         return businessObjectService.findByPrimaryKey(GroupBo.class, Collections.singletonMap("id", groupId));
 486  
     }
 487  
 
 488  
     protected GroupMemberBo getGroupMemberBo(String id) {
 489  0
         incomingParamCheck(id, "id");
 490  0
         return businessObjectService.findByPrimaryKey(GroupMemberBo.class, Collections.singletonMap("id", id));
 491  
     }
 492  
 
 493  
         protected List<Group> getParentGroups(String groupId) throws RiceIllegalArgumentException {
 494  0
                 if ( StringUtils.isEmpty(groupId) ) {
 495  0
                         throw new RiceIllegalArgumentException("groupId is blank");
 496  
                 }
 497  0
                 Set<Group> groups = new HashSet<Group>();
 498  0
                 getParentGroupsInternal( groupId, groups );
 499  0
                 return new ArrayList<Group>( groups );
 500  
         }
 501  
 
 502  
     protected List<String> getMemberPrincipalIdsInternal(String groupId, Set<String> visitedGroupIds) {
 503  0
                 if ( groupId == null ) {
 504  0
                         return Collections.emptyList();
 505  
                 }
 506  0
                 Set<String> ids = new HashSet<String>();
 507  0
                 GroupBo group = getGroupBo(groupId);
 508  0
                 if ( group == null || !group.isActive()) {
 509  0
                         return Collections.emptyList();
 510  
                 }
 511  
 
 512  
         //List<String> memberIds = getMemberIdsByType(group, memberType);
 513  
         //List<GroupMember> members = new ArrayList<GroupMember>(getMembersOfGroup(group.getId()));
 514  0
                 ids.addAll( group.getMemberPrincipalIds());
 515  0
                 visitedGroupIds.add(group.getId());
 516  
 
 517  0
                 for (String memberGroupId : group.getMemberGroupIds()) {
 518  0
                         if (!visitedGroupIds.contains(memberGroupId)){
 519  0
                                 ids.addAll(getMemberPrincipalIdsInternal(memberGroupId, visitedGroupIds));
 520  
                         }
 521  
                 }
 522  
 
 523  0
                 return Collections.unmodifiableList(new ArrayList<String>(ids));
 524  
         }
 525  
 
 526  
     protected Collection<Group> getDirectGroupsForPrincipal( String principalId ) {
 527  0
                 return getDirectGroupsForPrincipal( principalId, null );
 528  
         }
 529  
 
 530  
         protected Collection<Group> getDirectGroupsForPrincipal( String principalId, String namespaceCode ) {
 531  0
                 if ( principalId == null ) {
 532  0
                         return Collections.emptyList();
 533  
                 }
 534  0
                 Map<String,Object> criteria = new HashMap<String,Object>();
 535  0
                 criteria.put(KIMPropertyConstants.GroupMember.MEMBER_ID, principalId);
 536  0
                 criteria.put(KIMPropertyConstants.GroupMember.MEMBER_TYPE_CODE, KimConstants.KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE.getCode());
 537  0
                 Collection<GroupMemberBo> groupMembers = businessObjectService.findMatching(GroupMemberBo.class, criteria);
 538  0
                 Set<String> groupIds = new HashSet<String>( groupMembers.size() );
 539  
                 // only return the active members
 540  0
                 for ( GroupMemberBo gm : groupMembers ) {
 541  0
                         if ( gm.isActive(new Timestamp(System.currentTimeMillis())) ) {
 542  0
                                 groupIds.add( gm.getGroupId() );
 543  
                         }
 544  
                 }
 545  
                 // pull all the group information for the matching members
 546  0
                 List<Group> groups = CollectionUtils.isEmpty(groupIds) ? Collections.<Group>emptyList() : getGroups(groupIds);
 547  0
                 List<Group> result = new ArrayList<Group>( groups.size() );
 548  
                 // filter by namespace if necessary
 549  0
                 for ( Group group : groups ) {
 550  0
                         if ( group.isActive() ) {
 551  0
                                 if ( StringUtils.isBlank(namespaceCode) || StringUtils.equals(namespaceCode, group.getNamespaceCode() ) ) {
 552  0
                                         result.add(group);
 553  
                                 }
 554  
                         }
 555  
                 }
 556  0
                 return result;
 557  
         }
 558  
 
 559  
     @Override
 560  
     public boolean addGroupToGroup(String childId, String parentId)  throws RiceIllegalArgumentException {
 561  0
         incomingParamCheck(childId, "childId");
 562  0
         incomingParamCheck(parentId, "parentId");
 563  
 
 564  0
         if(childId.equals(parentId)) {
 565  0
             throw new RiceIllegalArgumentException("Can't add group to itself.");
 566  
         }
 567  0
         if(isGroupMemberOfGroup(parentId, childId)) {
 568  0
             throw new RiceIllegalArgumentException("Circular group reference.");
 569  
         }
 570  
 
 571  0
         GroupMemberBo groupMember = new GroupMemberBo();
 572  0
         groupMember.setGroupId(parentId);
 573  0
         groupMember.setType(KimConstants.KimGroupMemberTypes.GROUP_MEMBER_TYPE);
 574  0
         groupMember.setMemberId(childId);
 575  
 
 576  0
         this.businessObjectService.save(groupMember);
 577  0
         return true;
 578  
     }
 579  
 
 580  
     @Override
 581  
     public boolean addPrincipalToGroup(String principalId, String groupId) throws RiceIllegalArgumentException {
 582  0
         incomingParamCheck(principalId, "principalId");
 583  0
         incomingParamCheck(groupId, "groupId");
 584  
 
 585  0
         GroupMemberBo groupMember = new GroupMemberBo();
 586  0
         groupMember.setGroupId(groupId);
 587  0
         groupMember.setType(KimConstants.KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE);
 588  0
         groupMember.setMemberId(principalId);
 589  
 
 590  0
         groupMember = this.businessObjectService.save(groupMember);
 591  0
         KimImplServiceLocator.getGroupInternalService().updateForUserAddedToGroup(groupMember.getMemberId(),
 592  
                 groupMember.getGroupId());
 593  0
         return true;
 594  
     }
 595  
 
 596  
     @Override
 597  
     public Group createGroup(Group group) throws RiceIllegalArgumentException {
 598  0
         incomingParamCheck(group, "group");
 599  0
         if (StringUtils.isNotBlank(group.getId()) && getGroup(group.getId()) != null) {
 600  0
             throw new RiceIllegalArgumentException("the group to create already exists: " + group);
 601  
         }
 602  0
         List<GroupAttributeBo> attrBos = KimAttributeDataBo
 603  
                 .createFrom(GroupAttributeBo.class, group.getAttributes(), group.getKimTypeId());
 604  0
         if (StringUtils.isNotEmpty(group.getId())) {
 605  0
             for (GroupAttributeBo attr : attrBos) {
 606  0
                 attr.setAssignedToId(group.getId());
 607  
             }
 608  
         }
 609  0
         GroupBo bo = GroupBo.from(group);
 610  0
         bo.setAttributeDetails(attrBos);
 611  
 
 612  0
         bo = saveGroup(bo);
 613  
 
 614  0
         return GroupBo.to(bo);
 615  
     }
 616  
 
 617  
     @Override
 618  
     public Group updateGroup(Group group) throws RiceIllegalArgumentException{
 619  0
         incomingParamCheck(group, "group");
 620  0
         GroupBo origGroup = getGroupBo(group.getId());
 621  0
         if (StringUtils.isBlank(group.getId()) || origGroup == null) {
 622  0
             throw new RiceIllegalArgumentException("the group does not exist: " + group);
 623  
         }
 624  0
         List<GroupAttributeBo> attrBos = KimAttributeDataBo.createFrom(GroupAttributeBo.class, group.getAttributes(), group.getKimTypeId());
 625  0
         GroupBo bo = GroupBo.from(group);
 626  0
         bo.setMembers(origGroup.getMembers());
 627  0
         bo.setAttributeDetails(attrBos);
 628  
 
 629  0
         bo = saveGroup(bo);
 630  0
         if (origGroup.isActive()
 631  
                 && !bo.isActive()) {
 632  0
             KimImplServiceLocator.getRoleInternalService().groupInactivated(bo.getId());
 633  
         }
 634  
 
 635  0
         return GroupBo.to(bo);
 636  
     }
 637  
 
 638  
     @Override
 639  
         public Group updateGroup(String groupId, Group group) throws RiceIllegalArgumentException{
 640  0
         incomingParamCheck(group, "group");
 641  0
         incomingParamCheck(groupId, "groupId");
 642  
 
 643  0
         if (StringUtils.equals(groupId, group.getId())) {
 644  0
             return updateGroup(group);
 645  
         }
 646  
 
 647  
         //if group Ids are different, inactivate old group, and create new with new id based off old
 648  0
         GroupBo groupBo = getGroupBo(groupId);
 649  
 
 650  0
         if (StringUtils.isBlank(group.getId()) || groupBo == null) {
 651  0
             throw new RiceIllegalArgumentException("the group does not exist: " + group);
 652  
         }
 653  
 
 654  
         //create and save new group
 655  0
         GroupBo newGroup = GroupBo.from(group);
 656  0
         newGroup.setMembers(groupBo.getMembers());
 657  0
         List<GroupAttributeBo> attrBos = KimAttributeDataBo.createFrom(GroupAttributeBo.class, group.getAttributes(), group.getKimTypeId());
 658  0
         newGroup.setAttributeDetails(attrBos);
 659  0
         newGroup = saveGroup(newGroup);
 660  
 
 661  
         //inactivate and save old group
 662  0
         groupBo.setActive(false);
 663  0
         saveGroup(groupBo);
 664  
 
 665  0
         return GroupBo.to(newGroup);
 666  
     }
 667  
 
 668  
     @Override
 669  
     public GroupMember createGroupMember(GroupMember groupMember) throws RiceIllegalArgumentException {
 670  0
         incomingParamCheck(groupMember, "groupMember");
 671  0
         if (StringUtils.isNotBlank(groupMember.getId()) && getGroupMemberBo(groupMember.getId()) != null) {
 672  0
             throw new RiceIllegalArgumentException("the groupMember to create already exists: " + groupMember);
 673  
         }
 674  
 
 675  0
         GroupMemberBo bo = GroupMemberBo.from(groupMember);
 676  0
         GroupBo groupBo = getGroupBo(groupMember.getGroupId());
 677  0
         groupBo.getMembers().add(bo);
 678  0
         groupBo = saveGroup(groupBo);
 679  
 
 680  
         //get new groupMember from saved group
 681  0
         for (GroupMemberBo member : groupBo.getMembers()) {
 682  0
             if (member.getMemberId().equals(groupMember.getMemberId())
 683  
                     && member.getType().equals(groupMember.getType())
 684  
                     && member.getActiveFromDate().equals(groupMember.getActiveFromDate())
 685  
                     && member.getActiveToDate().equals(groupMember.getActiveToDate())) {
 686  0
                 return GroupMemberBo.to(member);
 687  
             }
 688  
         }
 689  0
         return GroupMemberBo.to(bo);
 690  
     }
 691  
 
 692  
     @Override
 693  
     public GroupMember updateGroupMember(
 694  
             @WebParam(name = "groupMember") GroupMember groupMember) throws RiceIllegalArgumentException {
 695  0
         incomingParamCheck(groupMember, "groupMember");
 696  0
         if (StringUtils.isBlank(groupMember.getId()) || getGroupMemberBo(groupMember.getId()) == null) {
 697  0
             throw new RiceIllegalArgumentException("the groupMember to update does not exist: " + groupMember);
 698  
         }
 699  
 
 700  0
         GroupMemberBo bo = GroupMemberBo.from(groupMember);
 701  0
         GroupBo groupBo = getGroupBo(groupMember.getGroupId());
 702  
         //find and replace the existing member
 703  
 
 704  0
         List<GroupMemberBo> memberList = new ArrayList<GroupMemberBo>();
 705  0
         for (GroupMemberBo member : groupBo.getMembers()) {
 706  0
             if (member.getId().equals(bo.getId())) {
 707  0
                 memberList.add(bo);
 708  
             } else {
 709  0
                 memberList.add(member);
 710  
             }
 711  
 
 712  
         }
 713  0
         groupBo.setMembers(memberList);
 714  0
         groupBo = saveGroup(groupBo);
 715  
 
 716  
         //get new groupMember from saved group
 717  0
         for (GroupMemberBo member : groupBo.getMembers()) {
 718  0
             if (member.getId().equals(groupMember.getId())) {
 719  0
                 return GroupMemberBo.to(member);
 720  
             }
 721  
         }
 722  0
         return GroupMemberBo.to(bo);
 723  
     }
 724  
 
 725  
     @Override
 726  
     public void removeAllMembers(String groupId) throws RiceIllegalArgumentException{
 727  0
         incomingParamCheck(groupId, "groupId");
 728  
 
 729  
 
 730  0
         GroupService groupService = KimApiServiceLocator.getGroupService();
 731  0
         List<String> memberPrincipalsBefore = groupService.getMemberPrincipalIds(groupId);
 732  
 
 733  0
         Collection<GroupMemberBo> toDeactivate = getActiveGroupMembers(groupId, null, null);
 734  0
         java.sql.Timestamp today = new java.sql.Timestamp(System.currentTimeMillis());
 735  
 
 736  
         // Set principals as inactive
 737  0
         for (GroupMemberBo aToDeactivate : toDeactivate) {
 738  0
             aToDeactivate.setActiveToDateValue(today);
 739  
         }
 740  
 
 741  
         // Save
 742  0
         this.businessObjectService.save(new ArrayList<GroupMemberBo>(toDeactivate));
 743  0
         List<String> memberPrincipalsAfter = groupService.getMemberPrincipalIds(groupId);
 744  
 
 745  0
         if (!CollectionUtils.isEmpty(memberPrincipalsAfter)) {
 746  
                 // should never happen!
 747  0
                 LOG.warn("after attempting removal of all members, group with id '" + groupId + "' still has principal members");
 748  
         }
 749  
 
 750  
         // do updates
 751  0
         KimImplServiceLocator.getGroupInternalService().updateForWorkgroupChange(groupId, memberPrincipalsBefore,
 752  
                memberPrincipalsAfter);
 753  0
     }
 754  
 
 755  
     @Override
 756  
     public boolean removeGroupFromGroup(String childId, String parentId) throws RiceIllegalArgumentException {
 757  0
             incomingParamCheck(childId, "childId");
 758  0
         incomingParamCheck(parentId, "parentId");
 759  
 
 760  0
         java.sql.Timestamp today = new java.sql.Timestamp(System.currentTimeMillis());
 761  
 
 762  0
             List<GroupMemberBo> groupMembers =
 763  
                     getActiveGroupMembers(parentId, childId, KimConstants.KimGroupMemberTypes.GROUP_MEMBER_TYPE);
 764  
 
 765  0
         if(groupMembers.size() == 1) {
 766  0
                 GroupMemberBo groupMember = groupMembers.get(0);
 767  0
                 groupMember.setActiveToDateValue(today);
 768  0
             this.businessObjectService.save(groupMember);
 769  0
             return true;
 770  
         }
 771  
 
 772  0
         return false;
 773  
     }
 774  
 
 775  
     @Override
 776  
     public boolean removePrincipalFromGroup(String principalId, String groupId) throws RiceIllegalArgumentException {
 777  0
             incomingParamCheck(principalId, "principalId");
 778  0
         incomingParamCheck(groupId, "groupId");
 779  
 
 780  0
         List<GroupMemberBo> groupMembers =
 781  
                     getActiveGroupMembers(groupId, principalId, KimConstants.KimGroupMemberTypes.PRINCIPAL_MEMBER_TYPE);
 782  
 
 783  0
         if(groupMembers.size() == 1) {
 784  0
                 GroupMemberBo member = groupMembers.iterator().next();
 785  0
                 member.setActiveToDateValue(new java.sql.Timestamp(System.currentTimeMillis()));
 786  0
                 this.businessObjectService.save(member);
 787  0
             KimImplServiceLocator.getGroupInternalService().updateForUserRemovedFromGroup(member.getMemberId(),
 788  
                     member.getGroupId());
 789  0
             return true;
 790  
         }
 791  
 
 792  0
         return false;
 793  
     }
 794  
 
 795  
         protected GroupBo saveGroup(GroupBo group) {
 796  0
                 if ( group == null ) {
 797  0
                         return null;
 798  0
                 } else if (group.getId() != null) {
 799  
                         // Get the version of the group that is in the DB
 800  0
                         GroupBo oldGroup = getGroupBo(group.getId());
 801  
 
 802  0
                         if (oldGroup != null) {
 803  
                                 // Inactivate and re-add members no longer in the group (in order to preserve history).
 804  0
                                 java.sql.Timestamp activeTo = new java.sql.Timestamp(System.currentTimeMillis());
 805  0
                                 List<GroupMemberBo> toReAdd = null;
 806  
 
 807  0
                                 if (oldGroup.getMembers() != null) {
 808  0
                     for (GroupMemberBo member : oldGroup.getMembers()) {
 809  
                         // if the old member isn't in the new group
 810  0
                         if (group.getMembers() == null || !group.getMembers().contains(member)) {
 811  
                             // inactivate the member
 812  0
                             member.setActiveToDateValue(activeTo);
 813  0
                             if (toReAdd == null) {
 814  0
                                 toReAdd = new ArrayList<GroupMemberBo>();
 815  
                             }
 816  
                             // queue it up for re-adding
 817  0
                             toReAdd.add(member);
 818  
                         }
 819  
                     }
 820  
                                 }
 821  
 
 822  
                                 // do the re-adding
 823  0
                                 if (toReAdd != null) {
 824  0
                                         List<GroupMemberBo> groupMembers = group.getMembers();
 825  0
                                         if (groupMembers == null) {
 826  0
                         groupMembers = new ArrayList<GroupMemberBo>(toReAdd.size());
 827  
                     }
 828  0
                                         group.setMembers(groupMembers);
 829  
                                 }
 830  
                         }
 831  
                 }
 832  
 
 833  0
                 return KimImplServiceLocator.getGroupInternalService().saveWorkgroup(group);
 834  
         }
 835  
 
 836  
 
 837  
         /**
 838  
          * This helper method gets the active group members of the specified type (see {@link org.kuali.rice.kim.api.KimConstants.KimGroupMemberTypes}).
 839  
          * If the optional params are null, it will return all active members for the specified group regardless
 840  
          * of type.
 841  
          *
 842  
          * @param parentId
 843  
          * @param childId optional, but if provided then memberType must be too
 844  
          * @param memberType optional, but must be provided if childId is
 845  
      * @return a list of group members
 846  
          */
 847  
         private List<GroupMemberBo> getActiveGroupMembers(String parentId, String childId, MemberType memberType) {
 848  0
             final java.sql.Date today = new java.sql.Date(System.currentTimeMillis());
 849  
 
 850  0
             if (childId != null && memberType == null) {
 851  0
             throw new RiceRuntimeException("memberType must be non-null if childId is non-null");
 852  
         }
 853  
 
 854  0
                 Map<String,Object> criteria = new HashMap<String,Object>(4);
 855  0
         criteria.put(KIMPropertyConstants.GroupMember.GROUP_ID, parentId);
 856  
 
 857  0
         if (childId != null) {
 858  0
                 criteria.put(KIMPropertyConstants.GroupMember.MEMBER_ID, childId);
 859  0
                 criteria.put(KIMPropertyConstants.GroupMember.MEMBER_TYPE_CODE, memberType.getCode());
 860  
         }
 861  
 
 862  0
         Collection<GroupMemberBo> groupMembers = this.businessObjectService.findMatching(GroupMemberBo.class, criteria);
 863  
 
 864  0
         CollectionUtils.filter(groupMembers, new Predicate() {
 865  
                         @Override public boolean evaluate(Object object) {
 866  0
                                 GroupMemberBo member = (GroupMemberBo) object;
 867  
                                 // keep in the collection (return true) if the activeToDate is null, or if it is set to a future date
 868  0
                                 return member.getActiveToDate() == null || today.before(member.getActiveToDate().toDate());
 869  
                         }
 870  
                 });
 871  
 
 872  0
         return new ArrayList<GroupMemberBo>(groupMembers);
 873  
         }
 874  
 
 875  
     /**
 876  
      * Sets the businessObjectService attribute value.
 877  
      *
 878  
      * @param businessObjectService The businessObjectService to set.
 879  
      */
 880  
     public void setBusinessObjectService(final BusinessObjectService businessObjectService) {
 881  0
         this.businessObjectService = businessObjectService;
 882  0
     }
 883  
 
 884  
     /**
 885  
      * Sets the criteriaLookupService attribute value.
 886  
      *
 887  
      * @param criteriaLookupService The criteriaLookupService to set.
 888  
      */
 889  
     public void setCriteriaLookupService(final CriteriaLookupService criteriaLookupService) {
 890  0
         this.criteriaLookupService = criteriaLookupService;
 891  0
     }
 892  
 
 893  
     private void incomingParamCheck(Object object, String name) {
 894  0
         if (object == null) {
 895  0
             throw new RiceIllegalArgumentException(name + " was null");
 896  0
         } else if (object instanceof String
 897  
                 && StringUtils.isBlank((String) object)) {
 898  0
             throw new RiceIllegalArgumentException(name + " was blank");
 899  
         }
 900  0
     }
 901  
 }