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