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