1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kim.impl.identity;
17
18 import org.apache.commons.beanutils.PropertyUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.log4j.Logger;
21 import org.kuali.rice.core.api.CoreApiServiceLocator;
22 import org.kuali.rice.core.api.criteria.CountFlag;
23 import org.kuali.rice.core.api.criteria.Predicate;
24 import org.kuali.rice.core.api.criteria.PredicateUtils;
25 import org.kuali.rice.core.api.criteria.QueryByCriteria;
26 import org.kuali.rice.kim.api.identity.IdentityService;
27 import org.kuali.rice.kim.api.identity.Person;
28 import org.kuali.rice.kim.api.identity.PersonService;
29 import org.kuali.rice.kim.api.identity.entity.EntityDefault;
30 import org.kuali.rice.kim.api.identity.entity.EntityDefaultQueryResults;
31 import org.kuali.rice.kim.api.identity.external.EntityExternalIdentifierType;
32 import org.kuali.rice.kim.api.identity.principal.Principal;
33 import org.kuali.rice.kim.api.identity.type.EntityTypeContactInfoDefault;
34 import org.kuali.rice.kim.api.role.RoleService;
35 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
36 import org.kuali.rice.kim.impl.KIMPropertyConstants;
37 import org.kuali.rice.kns.service.BusinessObjectMetaDataService;
38 import org.kuali.rice.kns.service.KNSServiceLocator;
39 import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
40 import org.kuali.rice.krad.bo.BusinessObject;
41 import org.kuali.rice.krad.bo.DataObjectRelationship;
42 import org.kuali.rice.krad.lookup.CollectionIncomplete;
43 import org.kuali.rice.krad.util.KRADConstants;
44 import org.kuali.rice.krad.util.KRADPropertyConstants;
45 import org.kuali.rice.krad.util.ObjectUtils;
46
47 import java.security.GeneralSecurityException;
48 import java.util.ArrayList;
49 import java.util.Collection;
50 import java.util.Collections;
51 import java.util.HashMap;
52 import java.util.HashSet;
53 import java.util.Iterator;
54 import java.util.List;
55 import java.util.Map;
56 import java.util.Set;
57
58
59
60
61
62
63
64 public class PersonServiceImpl implements PersonService {
65
66 private static Logger LOG = Logger.getLogger( PersonServiceImpl.class );
67 protected static final String ENTITY_EXT_ID_PROPERTY_PREFIX = "externalIdentifiers.";
68 protected static final String ENTITY_AFFILIATION_PROPERTY_PREFIX = "affiliations.";
69 protected static final String ENTITY_TYPE_PROPERTY_PREFIX = "entityTypeContactInfos.";
70 protected static final String ENTITY_EMAIL_PROPERTY_PREFIX = "entityTypeContactInfos.emailAddresses.";
71 protected static final String ENTITY_PHONE_PROPERTY_PREFIX = "entityTypeContactInfos.phoneNumbers.";
72 protected static final String ENTITY_ADDRESS_PROPERTY_PREFIX = "entityTypeContactInfos.addresses.";
73 protected static final String ENTITY_NAME_PROPERTY_PREFIX = "names.";
74 protected static final String PRINCIPAL_PROPERTY_PREFIX = "principals.";
75 protected static final String ENTITY_EMPLOYEE_ID_PROPERTY_PREFIX = "employmentInformation.";
76
77 protected static final String EXTENSION = "extension";
78
79 private IdentityService identityService;
80 private RoleService roleService;
81 private BusinessObjectMetaDataService businessObjectMetaDataService;
82 private MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
83
84 protected List<String> personEntityTypeCodes = new ArrayList<String>( 4 );
85
86 private String personEntityTypeLookupCriteria = null;
87
88 protected Map<String,String> baseLookupCriteria = new HashMap<String,String>();
89 protected Map<String,String> criteriaConversion = new HashMap<String,String>();
90 protected ArrayList<String> personCachePropertyNames = new ArrayList<String>();
91 {
92
93
94 baseLookupCriteria.put( KIMPropertyConstants.Person.ACTIVE, "Y" );
95 baseLookupCriteria.put( ENTITY_TYPE_PROPERTY_PREFIX + KRADPropertyConstants.ACTIVE, "Y" );
96
97
98 criteriaConversion.put( KIMPropertyConstants.Person.ENTITY_ID, KIMPropertyConstants.Entity.ID);
99 criteriaConversion.put( KIMPropertyConstants.Person.ACTIVE, PRINCIPAL_PROPERTY_PREFIX + KRADPropertyConstants.ACTIVE );
100 criteriaConversion.put( KIMPropertyConstants.Person.PRINCIPAL_ID, PRINCIPAL_PROPERTY_PREFIX + KIMPropertyConstants.Person.PRINCIPAL_ID );
101 criteriaConversion.put( KIMPropertyConstants.Person.PRINCIPAL_NAME, PRINCIPAL_PROPERTY_PREFIX + KIMPropertyConstants.Person.PRINCIPAL_NAME );
102 criteriaConversion.put( KIMPropertyConstants.Person.FIRST_NAME, "names.firstName" );
103 criteriaConversion.put( KIMPropertyConstants.Person.LAST_NAME, "names.lastName" );
104 criteriaConversion.put( KIMPropertyConstants.Person.MIDDLE_NAME, "names.middleName" );
105 criteriaConversion.put( KIMPropertyConstants.Person.EMAIL_ADDRESS, "entityTypeContactInfos.emailAddresses.emailAddress" );
106 criteriaConversion.put( KIMPropertyConstants.Person.PHONE_NUMBER, "entityTypeContactInfos.phoneNumbers.phoneNumber" );
107 criteriaConversion.put( KIMPropertyConstants.Person.ADDRESS_LINE_1, "entityTypeContactInfos.addresses.line1" );
108 criteriaConversion.put( KIMPropertyConstants.Person.ADDRESS_LINE_2, "entityTypeContactInfos.addresses.line2" );
109 criteriaConversion.put( KIMPropertyConstants.Person.ADDRESS_LINE_3, "entityTypeContactInfos.addresses.line3" );
110 criteriaConversion.put( KIMPropertyConstants.Person.CITY, "entityTypeContactInfos.addresses.city" );
111 criteriaConversion.put( KIMPropertyConstants.Person.STATE_CODE, "entityTypeContactInfos.addresses.stateProvinceCode" );
112 criteriaConversion.put( KIMPropertyConstants.Person.POSTAL_CODE, "entityTypeContactInfos.addresses.postalCode" );
113 criteriaConversion.put( KIMPropertyConstants.Person.COUNTRY_CODE, "entityTypeContactInfos.addresses.countryCode" );
114 criteriaConversion.put( KIMPropertyConstants.Person.CAMPUS_CODE, "affiliations.campusCode" );
115 criteriaConversion.put( KIMPropertyConstants.Person.AFFILIATION_TYPE_CODE, "affiliations.affiliationTypeCode" );
116 criteriaConversion.put( KIMPropertyConstants.Person.EXTERNAL_IDENTIFIER_TYPE_CODE, "externalIdentifiers.externalIdentifierTypeCode" );
117 criteriaConversion.put( KIMPropertyConstants.Person.EXTERNAL_ID, "externalIdentifiers.externalId" );
118 criteriaConversion.put( KIMPropertyConstants.Person.EMPLOYEE_TYPE_CODE, "employmentInformation.employeeTypeCode" );
119 criteriaConversion.put( KIMPropertyConstants.Person.EMPLOYEE_STATUS_CODE, "employmentInformation.employeeStatusCode" );
120 criteriaConversion.put( KIMPropertyConstants.Person.EMPLOYEE_ID, "employmentInformation.employeeId" );
121 criteriaConversion.put( KIMPropertyConstants.Person.BASE_SALARY_AMOUNT, "employmentInformation.baseSalaryAmount" );
122 criteriaConversion.put( KIMPropertyConstants.Person.PRIMARY_DEPARTMENT_CODE, "employmentInformation.primaryDepartmentCode" );
123
124 personCachePropertyNames.add( KIMPropertyConstants.Person.PRINCIPAL_ID );
125 personCachePropertyNames.add( KIMPropertyConstants.Person.PRINCIPAL_NAME );
126 personCachePropertyNames.add( KIMPropertyConstants.Person.ENTITY_ID );
127 personCachePropertyNames.add( KIMPropertyConstants.Person.FIRST_NAME );
128 personCachePropertyNames.add( KIMPropertyConstants.Person.LAST_NAME );
129 personCachePropertyNames.add( KIMPropertyConstants.Person.MIDDLE_NAME );
130 personCachePropertyNames.add( KIMPropertyConstants.Person.CAMPUS_CODE );
131 personCachePropertyNames.add( KIMPropertyConstants.Person.EMPLOYEE_ID );
132 personCachePropertyNames.add( KIMPropertyConstants.Person.PRIMARY_DEPARTMENT_CODE );
133 }
134
135
136
137
138
139 public Person getPerson(String principalId) {
140 if ( StringUtils.isBlank(principalId) ) {
141 return null;
142 }
143
144
145 final Principal principal = getIdentityService().getPrincipal( principalId );
146
147 if ( principal != null ) {
148 final EntityDefault entity = getIdentityService().getEntityDefault(principal.getEntityId());
149
150
151 if (entity != null ) {
152 return convertEntityToPerson( entity, principal );
153 }
154 }
155 return null;
156 }
157
158 protected PersonImpl convertEntityToPerson( EntityDefault entity, Principal principal ) {
159 try {
160
161 for ( String entityTypeCode : personEntityTypeCodes ) {
162 EntityTypeContactInfoDefault entType = entity.getEntityType( entityTypeCode );
163
164 if ( entType == null ) {
165 continue;
166 }
167
168
169 return new PersonImpl( principal, entity, entityTypeCode );
170 }
171 return null;
172 } catch ( Exception ex ) {
173
174 if ( ex instanceof RuntimeException ) {
175 throw (RuntimeException)ex;
176 }
177 throw new RuntimeException( "Problem building person object", ex );
178 }
179 }
180
181
182
183
184
185 public Person getPersonByPrincipalName(String principalName) {
186 if ( StringUtils.isBlank(principalName) ) {
187 return null;
188 }
189
190
191 final Principal principal = getIdentityService().getPrincipalByPrincipalName( principalName );
192
193 if ( principal != null ) {
194 final EntityDefault entity = getIdentityService().getEntityDefault(principal.getEntityId());
195
196
197 if ( entity != null ) {
198 return convertEntityToPerson( entity, principal );
199 }
200 }
201 return null;
202 }
203
204 public Person getPersonByEmployeeId(String employeeId) {
205 if ( StringUtils.isBlank( employeeId ) ) {
206 return null;
207 }
208
209 final List<Person> people = findPeople( Collections.singletonMap(KIMPropertyConstants.Person.EMPLOYEE_ID, employeeId) );
210 if ( !people.isEmpty() ) {
211 return people.get(0);
212
213 }
214
215
216 EntityDefault entity = getIdentityService().getEntityDefaultByEmployeeId(employeeId);
217 if (entity != null) {
218 if ( !entity.getPrincipals().isEmpty() ) {
219 Principal principal = getIdentityService().getPrincipal(entity.getPrincipals().get(0).getPrincipalId());
220 if (principal != null) {
221 return convertEntityToPerson( entity, principal );
222 }
223 }
224 }
225
226 return null;
227 }
228
229
230
231
232 public List<Person> findPeople(Map<String, String> criteria) {
233 return findPeople(criteria, true);
234 }
235
236
237
238
239 public List<Person> findPeople(Map<String, String> criteria, boolean unbounded) {
240 List<Person> people = null;
241
242 if ( criteria == null ) {
243 criteria = Collections.emptyMap();
244 }
245
246 criteria = new HashMap<String, String>( criteria );
247
248
249 String roleName = criteria.get( "lookupRoleName" );
250 String namespaceCode = criteria.get( "lookupRoleNamespaceCode" );
251 criteria.remove("lookupRoleName");
252 criteria.remove("lookupRoleNamespaceCode");
253 if ( StringUtils.isNotBlank(namespaceCode) && StringUtils.isNotBlank(roleName) ) {
254 Integer searchResultsLimit = org.kuali.rice.kns.lookup.LookupUtils.getSearchResultsLimit(PersonImpl.class);
255 int searchResultsLimitInt = Integer.MAX_VALUE;
256 if (searchResultsLimit != null) {
257 searchResultsLimitInt = searchResultsLimit.intValue();
258 }
259 if ( LOG.isDebugEnabled() ) {
260 LOG.debug("Performing Person search including role filter: " + namespaceCode + "/" + roleName );
261 }
262 if ( criteria.size() == 1 && criteria.containsKey(KIMPropertyConstants.Person.ACTIVE) ) {
263 if ( LOG.isDebugEnabled() ) {
264 LOG.debug( "Only active criteria specified, running role search first" );
265 }
266
267 Collection<String> principalIds = getRoleService().getRoleMemberPrincipalIds(namespaceCode, roleName, Collections.<String, String>emptyMap());
268 StringBuffer sb = new StringBuffer(principalIds.size()*15);
269 Iterator<String> pi = principalIds.iterator();
270 while ( pi.hasNext() ) {
271 sb.append( pi.next() );
272 if ( pi.hasNext() ) sb.append( '|' );
273 }
274
275 criteria.put( KIMPropertyConstants.Person.PRINCIPAL_ID, sb.toString() );
276 people = findPeopleInternal(criteria, false);
277 } else if ( !criteria.isEmpty() ) {
278 if ( LOG.isDebugEnabled() ) {
279 LOG.debug( "Person criteria also specified, running that search first" );
280 }
281
282 people = findPeopleInternal(criteria, true);
283
284
285 List<String> principalIds = peopleToPrincipalIds( people );
286
287 principalIds = getRoleService().getPrincipalIdSubListWithRole(principalIds, namespaceCode, roleName, Collections.<String, String>emptyMap());
288
289 if ( !unbounded && principalIds.size() > searchResultsLimitInt ) {
290 int actualResultSize = principalIds.size();
291
292 principalIds = new ArrayList<String>(principalIds).subList(0, searchResultsLimitInt);
293 people = getPeople(principalIds);
294 people = new CollectionIncomplete<Person>( people.subList(0, searchResultsLimitInt), new Long(actualResultSize) );
295 } else {
296 people = getPeople(principalIds);
297 }
298 } else {
299 if ( LOG.isDebugEnabled() ) {
300 LOG.debug( "No Person criteria specified - only using role service." );
301 }
302
303 Collection<String> principalIds = getRoleService().getRoleMemberPrincipalIds(namespaceCode, roleName, Collections.<String, String>emptyMap());
304 if ( !unbounded && principalIds.size() > searchResultsLimitInt ) {
305 int actualResultSize = principalIds.size();
306
307 principalIds = new ArrayList<String>(principalIds).subList(0, searchResultsLimitInt);
308 people = getPeople(principalIds);
309 people = new CollectionIncomplete<Person>( people.subList(0, searchResultsLimitInt), new Long(actualResultSize) );
310 } else {
311 people = getPeople(principalIds);
312 }
313 }
314 } else {
315 if ( LOG.isDebugEnabled() ) {
316 LOG.debug( "No Role criteria specified, running person lookup as normal." );
317 }
318 people = findPeopleInternal(criteria, unbounded);
319 }
320
321
322
323
324
325 Set<String> peopleNoDupsSet = new HashSet<String>();
326 List<Person> peopleNoDupsList = new ArrayList<Person>();
327
328 for (Iterator<Person> iter = people.iterator(); iter.hasNext(); ) {
329 Person person = iter.next();
330 if (peopleNoDupsSet.add(person.getEntityId() + person.getPrincipalId() + person.getPrincipalName())) {
331 peopleNoDupsList.add(person);
332 }
333 }
334
335 people.clear();
336 people.addAll(peopleNoDupsList);
337
338 return people;
339 }
340
341 @SuppressWarnings("unchecked")
342 protected List<Person> findPeopleInternal(Map<String,String> criteria, boolean unbounded ) {
343
344
345
346 Map<String,String> entityCriteria = convertPersonPropertiesToEntityProperties( criteria );
347
348 Predicate predicate = PredicateUtils.convertMapToPredicate(entityCriteria);
349
350 QueryByCriteria.Builder queryBuilder = QueryByCriteria.Builder.create();
351 queryBuilder.setPredicates(predicate);
352
353 if (!unbounded) {
354 Integer searchResultsLimit = org.kuali.rice.kns.lookup.LookupUtils.getSearchResultsLimit(PersonImpl.class);
355 if (searchResultsLimit != null && searchResultsLimit >= 0) {
356 queryBuilder.setMaxResults(searchResultsLimit);
357 queryBuilder.setCountFlag(CountFlag.INCLUDE);
358 }
359 }
360
361 List<Person> people = new ArrayList<Person>();
362
363 EntityDefaultQueryResults qr = getIdentityService().findEntityDefaults( queryBuilder.build() );
364
365 for ( EntityDefault e : qr.getResults() ) {
366
367 for ( Principal p : e.getPrincipals() ) {
368 people.add( convertEntityToPerson( e, p ) );
369 }
370 }
371
372 return people;
373 }
374
375 public Map<String,String> convertPersonPropertiesToEntityProperties( Map<String,String> criteria ) {
376 if ( LOG.isDebugEnabled() ) {
377 LOG.debug( "convertPersonPropertiesToEntityProperties: " + criteria );
378 }
379 boolean nameCriteria = false;
380 boolean addressCriteria = false;
381 boolean externalIdentifierCriteria = false;
382 boolean affiliationCriteria = false;
383 boolean affiliationDefaultOnlyCriteria = false;
384 boolean phoneCriteria = false;
385 boolean emailCriteria = false;
386 boolean employeeIdCriteria = false;
387
388 HashMap<String,String> newCriteria = new HashMap<String,String>();
389 newCriteria.putAll( baseLookupCriteria );
390
391 newCriteria.put( "entityTypeContactInfos.entityTypeCode", personEntityTypeLookupCriteria );
392
393 if ( criteria != null ) {
394 for ( String key : criteria.keySet() ) {
395
396 if(key.equals(KIMPropertyConstants.Person.ACTIVE)) {
397 newCriteria.put(criteriaConversion.get(KIMPropertyConstants.Person.ACTIVE), criteria.get(KIMPropertyConstants.Person.ACTIVE));
398 } else {
399
400 if (!(criteria.containsKey(KIMPropertyConstants.Person.ACTIVE))) {
401 newCriteria.remove( KIMPropertyConstants.Person.ACTIVE );
402 }
403 }
404
405
406 if ( StringUtils.isEmpty( criteria.get(key) ) ) {
407 continue;
408 }
409
410
411 if ( key.equals( KIMPropertyConstants.Person.EXTERNAL_ID ) && StringUtils.isNotBlank(criteria.get(key)) ) {
412
413 if ( criteria.containsKey( KIMPropertyConstants.Person.EXTERNAL_IDENTIFIER_TYPE_CODE ) ) {
414 String extIdTypeCode = criteria.get(KIMPropertyConstants.Person.EXTERNAL_IDENTIFIER_TYPE_CODE);
415 if ( StringUtils.isNotBlank(extIdTypeCode) ) {
416
417 EntityExternalIdentifierType extIdType = getIdentityService().getExternalIdentifierType(extIdTypeCode);
418
419 if ( extIdType != null && extIdType.isEncryptionRequired() ) {
420 try {
421 criteria.put(key,
422 CoreApiServiceLocator.getEncryptionService().encrypt(criteria.get(key))
423 );
424 } catch (GeneralSecurityException ex) {
425 LOG.error("Unable to encrypt value for external ID search of type " + extIdTypeCode, ex );
426 }
427 }
428 }
429 }
430 }
431
432
433 String entityProperty = criteriaConversion.get( key );
434 if ( entityProperty != null ) {
435 newCriteria.put( entityProperty, criteria.get( key ) );
436 } else {
437 entityProperty = key;
438
439 newCriteria.put( key, criteria.get( key ) );
440 }
441
442 if ( isNameEntityCriteria( entityProperty ) ) {
443 nameCriteria = true;
444 }
445 if ( isExternalIdentifierEntityCriteria( entityProperty ) ) {
446 externalIdentifierCriteria = true;
447 }
448 if ( isAffiliationEntityCriteria( entityProperty ) ) {
449 affiliationCriteria = true;
450 }
451 if ( isAddressEntityCriteria( entityProperty ) ) {
452 addressCriteria = true;
453 }
454 if ( isPhoneEntityCriteria( entityProperty ) ) {
455 phoneCriteria = true;
456 }
457 if ( isEmailEntityCriteria( entityProperty ) ) {
458 emailCriteria = true;
459 }
460 if ( isEmployeeIdEntityCriteria( entityProperty ) ) {
461 employeeIdCriteria = true;
462 }
463
464
465 if ( key.equals( "campusCode" ) ) {
466 affiliationDefaultOnlyCriteria = true;
467 }
468 }
469
470 if ( nameCriteria ) {
471 newCriteria.put( ENTITY_NAME_PROPERTY_PREFIX + "active", "Y" );
472 newCriteria.put( ENTITY_NAME_PROPERTY_PREFIX + "defaultValue", "Y" );
473
474 }
475 if ( addressCriteria ) {
476 newCriteria.put( ENTITY_ADDRESS_PROPERTY_PREFIX + "active", "Y" );
477 newCriteria.put( ENTITY_ADDRESS_PROPERTY_PREFIX + "defaultValue", "Y" );
478 }
479 if ( phoneCriteria ) {
480 newCriteria.put( ENTITY_PHONE_PROPERTY_PREFIX + "active", "Y" );
481 newCriteria.put( ENTITY_PHONE_PROPERTY_PREFIX + "defaultValue", "Y" );
482 }
483 if ( emailCriteria ) {
484 newCriteria.put( ENTITY_EMAIL_PROPERTY_PREFIX + "active", "Y" );
485 newCriteria.put( ENTITY_EMAIL_PROPERTY_PREFIX + "defaultValue", "Y" );
486 }
487 if ( employeeIdCriteria ) {
488 newCriteria.put( ENTITY_EMPLOYEE_ID_PROPERTY_PREFIX + "active", "Y" );
489 newCriteria.put( ENTITY_EMPLOYEE_ID_PROPERTY_PREFIX + "primary", "Y" );
490 }
491 if ( affiliationCriteria ) {
492 newCriteria.put( ENTITY_AFFILIATION_PROPERTY_PREFIX + "active", "Y" );
493 }
494 if ( affiliationDefaultOnlyCriteria ) {
495 newCriteria.put( ENTITY_AFFILIATION_PROPERTY_PREFIX + "defaultValue", "Y" );
496 }
497 }
498
499 if ( LOG.isDebugEnabled() ) {
500 LOG.debug( "Converted: " + newCriteria );
501 }
502 return newCriteria;
503 }
504
505 protected boolean isNameEntityCriteria( String propertyName ) {
506 return propertyName.startsWith( ENTITY_NAME_PROPERTY_PREFIX );
507 }
508 protected boolean isAddressEntityCriteria( String propertyName ) {
509 return propertyName.startsWith( ENTITY_ADDRESS_PROPERTY_PREFIX );
510 }
511 protected boolean isPhoneEntityCriteria( String propertyName ) {
512 return propertyName.startsWith( ENTITY_PHONE_PROPERTY_PREFIX );
513 }
514 protected boolean isEmailEntityCriteria( String propertyName ) {
515 return propertyName.startsWith( ENTITY_EMAIL_PROPERTY_PREFIX );
516 }
517 protected boolean isEmployeeIdEntityCriteria( String propertyName ) {
518 return propertyName.startsWith( ENTITY_EMPLOYEE_ID_PROPERTY_PREFIX );
519 }
520 protected boolean isAffiliationEntityCriteria( String propertyName ) {
521 return propertyName.startsWith( ENTITY_AFFILIATION_PROPERTY_PREFIX );
522 }
523 protected boolean isExternalIdentifierEntityCriteria( String propertyName ) {
524 return propertyName.startsWith( ENTITY_EXT_ID_PROPERTY_PREFIX );
525 }
526
527
528
529
530
531
532 public List<String> getPersonEntityTypeCodes() {
533 return this.personEntityTypeCodes;
534 }
535
536 public void setPersonEntityTypeCodes(List<String> personEntityTypeCodes) {
537 this.personEntityTypeCodes = personEntityTypeCodes;
538 personEntityTypeLookupCriteria = null;
539 for ( String entityTypeCode : personEntityTypeCodes ) {
540 if ( personEntityTypeLookupCriteria == null ) {
541 personEntityTypeLookupCriteria = entityTypeCode;
542 } else {
543 personEntityTypeLookupCriteria = personEntityTypeLookupCriteria + "|" + entityTypeCode;
544 }
545 }
546 }
547
548
549 protected List<Person> getPeople( Collection<String> principalIds ) {
550 List<Person> people = new ArrayList<Person>( principalIds.size() );
551 for ( String principalId : principalIds ) {
552 people.add( getPerson(principalId) );
553 }
554 return people;
555 }
556
557 protected List<String> peopleToPrincipalIds( List<Person> people ) {
558 List<String> principalIds = new ArrayList<String>();
559
560 for ( Person person : people ) {
561 principalIds.add( person.getPrincipalId() );
562 }
563
564 return principalIds;
565 }
566
567
568
569
570 public List<Person> getPersonByExternalIdentifier(String externalIdentifierTypeCode, String externalId) {
571 if (StringUtils.isBlank( externalIdentifierTypeCode ) || StringUtils.isBlank( externalId ) ) {
572 return null;
573 }
574 Map<String,String> criteria = new HashMap<String,String>( 2 );
575 criteria.put( KIMPropertyConstants.Person.EXTERNAL_IDENTIFIER_TYPE_CODE, externalIdentifierTypeCode );
576 criteria.put( KIMPropertyConstants.Person.EXTERNAL_ID, externalId );
577 return findPeople( criteria );
578 }
579
580
581
582
583 public Person updatePersonIfNecessary(String sourcePrincipalId, Person currentPerson ) {
584 if (currentPerson == null
585 || !StringUtils.equals(sourcePrincipalId, currentPerson.getPrincipalId() )
586 || currentPerson.getEntityId() == null ) {
587 Person person = getPerson( sourcePrincipalId );
588
589
590 if ( person == null ) {
591 if ( currentPerson != null && currentPerson.getEntityId() == null ) {
592 return currentPerson;
593 }
594 }
595
596 if ( person == null && currentPerson == null ) {
597 try {
598 return new PersonImpl();
599 } catch ( Exception ex ) {
600 LOG.error( "unable to instantiate an object of type: " + getPersonImplementationClass() + " - returning null", ex );
601 return null;
602 }
603 }
604 return person;
605 }
606
607 return currentPerson;
608 }
609
610
611
612
613
614 private Map<String,String> getNonPersonSearchCriteria( BusinessObject bo, Map<String,String> fieldValues) {
615 Map<String,String> nonUniversalUserSearchCriteria = new HashMap<String,String>();
616 for ( String propertyName : fieldValues.keySet() ) {
617 if (!isPersonProperty(bo, propertyName)) {
618 nonUniversalUserSearchCriteria.put(propertyName, fieldValues.get(propertyName));
619 }
620 }
621 return nonUniversalUserSearchCriteria;
622 }
623
624
625 private boolean isPersonProperty(BusinessObject bo, String propertyName) {
626 try {
627 if ( ObjectUtils.isNestedAttribute( propertyName )
628 && !StringUtils.contains(propertyName, "add.") ) {
629 Class<?> type = PropertyUtils.getPropertyType(bo, ObjectUtils.getNestedAttributePrefix( propertyName ));
630
631 if ( type != null ) {
632 return Person.class.isAssignableFrom(type);
633 }
634 LOG.warn( "Unable to determine type of nested property: " + bo.getClass().getName() + " / " + propertyName );
635 }
636 } catch (Exception ex) {
637 if ( LOG.isDebugEnabled() ) {
638 LOG.debug("Unable to determine if property on " + bo.getClass().getName() + " to a person object: " + propertyName, ex );
639 }
640 }
641 return false;
642 }
643
644
645
646
647 @SuppressWarnings("unchecked")
648 public Map<String,String> resolvePrincipalNamesToPrincipalIds(BusinessObject businessObject, Map<String,String> fieldValues) {
649 if ( fieldValues == null ) {
650 return null;
651 }
652 if ( businessObject == null ) {
653 return fieldValues;
654 }
655 StringBuffer resolvedPrincipalIdPropertyName = new StringBuffer();
656
657
658 Map<String,String> processedFieldValues = getNonPersonSearchCriteria(businessObject, fieldValues);
659 for ( String propertyName : fieldValues.keySet() ) {
660 if ( !StringUtils.isBlank(fieldValues.get(propertyName))
661 && isPersonProperty(businessObject, propertyName)
662 ) {
663
664 String personPropertyName = ObjectUtils.getNestedAttributePrimitive( propertyName );
665
666 if ( StringUtils.equals( KIMPropertyConstants.Person.PRINCIPAL_NAME, personPropertyName) ) {
667 Class targetBusinessObjectClass = null;
668 BusinessObject targetBusinessObject = null;
669 resolvedPrincipalIdPropertyName.setLength( 0 );
670
671
672 String personReferenceObjectPropertyName = ObjectUtils.getNestedAttributePrefix( propertyName );
673
674
675 if ( ObjectUtils.isNestedAttribute( personReferenceObjectPropertyName ) ) {
676 String targetBusinessObjectPropertyName = ObjectUtils.getNestedAttributePrefix( personReferenceObjectPropertyName );
677 targetBusinessObject = (BusinessObject)ObjectUtils.getPropertyValue( businessObject, targetBusinessObjectPropertyName );
678 if (targetBusinessObject != null) {
679 targetBusinessObjectClass = targetBusinessObject.getClass();
680 resolvedPrincipalIdPropertyName.append(targetBusinessObjectPropertyName).append(".");
681 } else {
682 LOG.error("Could not find target property '"+propertyName+"' in class "+businessObject.getClass().getName()+". Property value was null.");
683 }
684 } else {
685 targetBusinessObjectClass = businessObject.getClass();
686 targetBusinessObject = businessObject;
687 }
688
689 if (targetBusinessObjectClass != null) {
690
691
692
693 String propName = ObjectUtils.getNestedAttributePrimitive( personReferenceObjectPropertyName );
694 DataObjectRelationship rel = getBusinessObjectMetaDataService().getBusinessObjectRelationship( targetBusinessObject, propName );
695 if ( rel != null ) {
696 String sourcePrimitivePropertyName = rel.getParentAttributeForChildAttribute(KIMPropertyConstants.Person.PRINCIPAL_ID);
697 resolvedPrincipalIdPropertyName.append(sourcePrimitivePropertyName);
698
699 String principalName = fieldValues.get( propertyName );
700 Principal principal = getIdentityService().getPrincipalByPrincipalName( principalName );
701 if (principal != null ) {
702 processedFieldValues.put(resolvedPrincipalIdPropertyName.toString(), principal.getPrincipalId());
703 } else {
704 processedFieldValues.put(resolvedPrincipalIdPropertyName.toString(), null);
705 try {
706
707
708
709
710 ObjectUtils.setObjectProperty(targetBusinessObject, resolvedPrincipalIdPropertyName.toString(), null );
711 ObjectUtils.setObjectProperty(targetBusinessObject, propName, null );
712 ObjectUtils.setObjectProperty(targetBusinessObject, propName + ".principalName", principalName );
713 } catch ( Exception ex ) {
714 LOG.error( "Unable to blank out the person object after finding that the person with the given principalName does not exist.", ex );
715 }
716 }
717 } else {
718 LOG.error( "Missing relationship for " + propName + " on " + targetBusinessObjectClass.getName() );
719 }
720 } else {
721 processedFieldValues.put(resolvedPrincipalIdPropertyName.toString(), null);
722 }
723 }
724
725
726
727 } else if (propertyName.endsWith("." + KIMPropertyConstants.Person.PRINCIPAL_NAME)){
728
729 String principalName = fieldValues.get(propertyName);
730 if ( StringUtils.isNotEmpty( principalName ) ) {
731 String containerPropertyName = propertyName;
732 if (containerPropertyName.startsWith(KRADConstants.MAINTENANCE_ADD_PREFIX)) {
733 containerPropertyName = StringUtils.substringAfter( propertyName, KRADConstants.MAINTENANCE_ADD_PREFIX );
734 }
735
736
737
738 if ( ObjectUtils.isNestedAttribute( containerPropertyName ) ) {
739
740 String collectionName = StringUtils.substringBefore( containerPropertyName, "." );
741
742
743
744 Class<? extends BusinessObject> collectionBusinessObjectClass = getMaintenanceDocumentDictionaryService()
745 .getCollectionBusinessObjectClass(
746 getMaintenanceDocumentDictionaryService()
747 .getDocumentTypeName(businessObject.getClass()), collectionName);
748 if (collectionBusinessObjectClass != null) {
749
750
751 List<DataObjectRelationship> relationships =
752 getBusinessObjectMetaDataService().getBusinessObjectRelationships( collectionBusinessObjectClass );
753
754
755 for ( DataObjectRelationship rel : relationships ) {
756 String parentAttribute = rel.getParentAttributeForChildAttribute( KIMPropertyConstants.Person.PRINCIPAL_ID );
757 if ( parentAttribute == null ) {
758 continue;
759 }
760
761 processedFieldValues.remove( propertyName );
762 String fieldPrefix = StringUtils.substringBeforeLast( StringUtils.substringBeforeLast( propertyName, "." + KIMPropertyConstants.Person.PRINCIPAL_NAME ), "." );
763 String relatedPrincipalIdPropertyName = fieldPrefix + "." + parentAttribute;
764
765 if(EXTENSION.equals(StringUtils.substringAfterLast(fieldPrefix, ".")) && EXTENSION.equals(StringUtils.substringBefore(parentAttribute, ".")))
766 {
767 relatedPrincipalIdPropertyName = fieldPrefix + "." + StringUtils.substringAfter(parentAttribute, ".");
768 }
769 String currRelatedPersonPrincipalId = processedFieldValues.get(relatedPrincipalIdPropertyName);
770 if ( StringUtils.isBlank( currRelatedPersonPrincipalId ) ) {
771 Principal principal = getIdentityService().getPrincipalByPrincipalName( principalName );
772 if ( principal != null ) {
773 processedFieldValues.put(relatedPrincipalIdPropertyName, principal.getPrincipalId());
774 } else {
775 processedFieldValues.put(relatedPrincipalIdPropertyName, null);
776 }
777 }
778 }
779 } else {
780 if ( LOG.isDebugEnabled() ) {
781 LOG.debug( "Unable to determine class for collection referenced as part of property: " + containerPropertyName + " on " + businessObject.getClass().getName() );
782 }
783 }
784 } else {
785 if ( LOG.isDebugEnabled() ) {
786 LOG.debug( "Non-nested property ending with 'principalName': " + containerPropertyName + " on " + businessObject.getClass().getName() );
787 }
788 }
789 }
790 }
791 }
792 return processedFieldValues;
793 }
794
795
796
797 protected IdentityService getIdentityService() {
798 if ( identityService == null ) {
799 identityService = KimApiServiceLocator.getIdentityService();
800 }
801 return identityService;
802 }
803
804 protected RoleService getRoleService() {
805 if ( roleService == null ) {
806 roleService = KimApiServiceLocator.getRoleService();
807 }
808 return roleService;
809 }
810
811
812 public Class<? extends Person> getPersonImplementationClass() {
813 return PersonImpl.class;
814 }
815
816 protected BusinessObjectMetaDataService getBusinessObjectMetaDataService() {
817 if ( businessObjectMetaDataService == null ) {
818 businessObjectMetaDataService = KNSServiceLocator.getBusinessObjectMetaDataService();
819 }
820 return businessObjectMetaDataService;
821 }
822
823 protected MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
824 if ( maintenanceDocumentDictionaryService == null ) {
825 maintenanceDocumentDictionaryService = KNSServiceLocator.getMaintenanceDocumentDictionaryService();
826 }
827 return maintenanceDocumentDictionaryService;
828 }
829 }