View Javadoc

1   /**
2    * Copyright 2005-2011 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kim.impl.identity;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.criteria.CriteriaLookupService;
20  import org.kuali.rice.core.api.criteria.GenericQueryResults;
21  import org.kuali.rice.core.api.criteria.QueryByCriteria;
22  import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
23  import org.kuali.rice.core.api.exception.RiceIllegalStateException;
24  import org.kuali.rice.kim.api.identity.CodedAttribute;
25  import org.kuali.rice.kim.api.identity.IdentityService;
26  import org.kuali.rice.kim.api.identity.address.EntityAddress;
27  import org.kuali.rice.kim.api.identity.affiliation.EntityAffiliation;
28  import org.kuali.rice.kim.api.identity.affiliation.EntityAffiliationType;
29  import org.kuali.rice.kim.api.identity.citizenship.EntityCitizenship;
30  import org.kuali.rice.kim.api.identity.email.EntityEmail;
31  import org.kuali.rice.kim.api.identity.employment.EntityEmployment;
32  import org.kuali.rice.kim.api.identity.entity.Entity;
33  import org.kuali.rice.kim.api.identity.entity.EntityDefault;
34  import org.kuali.rice.kim.api.identity.entity.EntityDefaultQueryResults;
35  import org.kuali.rice.kim.api.identity.entity.EntityQueryResults;
36  import org.kuali.rice.kim.api.identity.external.EntityExternalIdentifier;
37  import org.kuali.rice.kim.api.identity.external.EntityExternalIdentifierType;
38  import org.kuali.rice.kim.api.identity.name.EntityName;
39  import org.kuali.rice.kim.api.identity.name.EntityNameQueryResults;
40  import org.kuali.rice.kim.api.identity.personal.EntityBioDemographics;
41  import org.kuali.rice.kim.api.identity.personal.EntityEthnicity;
42  import org.kuali.rice.kim.api.identity.phone.EntityPhone;
43  import org.kuali.rice.kim.api.identity.principal.Principal;
44  import org.kuali.rice.kim.api.identity.privacy.EntityPrivacyPreferences;
45  import org.kuali.rice.kim.api.identity.residency.EntityResidency;
46  import org.kuali.rice.kim.api.identity.type.EntityTypeContactInfo;
47  import org.kuali.rice.kim.api.identity.visa.EntityVisa;
48  import org.kuali.rice.kim.impl.KIMPropertyConstants;
49  import org.kuali.rice.kim.impl.identity.address.EntityAddressBo;
50  import org.kuali.rice.kim.impl.identity.address.EntityAddressTypeBo;
51  import org.kuali.rice.kim.impl.identity.affiliation.EntityAffiliationBo;
52  import org.kuali.rice.kim.impl.identity.affiliation.EntityAffiliationTypeBo;
53  import org.kuali.rice.kim.impl.identity.citizenship.EntityCitizenshipBo;
54  import org.kuali.rice.kim.impl.identity.citizenship.EntityCitizenshipStatusBo;
55  import org.kuali.rice.kim.impl.identity.email.EntityEmailBo;
56  import org.kuali.rice.kim.impl.identity.email.EntityEmailTypeBo;
57  import org.kuali.rice.kim.impl.identity.employment.EntityEmploymentBo;
58  import org.kuali.rice.kim.impl.identity.employment.EntityEmploymentStatusBo;
59  import org.kuali.rice.kim.impl.identity.employment.EntityEmploymentTypeBo;
60  import org.kuali.rice.kim.impl.identity.entity.EntityBo;
61  import org.kuali.rice.kim.impl.identity.external.EntityExternalIdentifierBo;
62  import org.kuali.rice.kim.impl.identity.external.EntityExternalIdentifierTypeBo;
63  import org.kuali.rice.kim.impl.identity.name.EntityNameBo;
64  import org.kuali.rice.kim.impl.identity.name.EntityNameTypeBo;
65  import org.kuali.rice.kim.impl.identity.personal.EntityBioDemographicsBo;
66  import org.kuali.rice.kim.impl.identity.personal.EntityEthnicityBo;
67  import org.kuali.rice.kim.impl.identity.phone.EntityPhoneBo;
68  import org.kuali.rice.kim.impl.identity.phone.EntityPhoneTypeBo;
69  import org.kuali.rice.kim.impl.identity.principal.PrincipalBo;
70  import org.kuali.rice.kim.impl.identity.privacy.EntityPrivacyPreferencesBo;
71  import org.kuali.rice.kim.impl.identity.residency.EntityResidencyBo;
72  import org.kuali.rice.kim.impl.identity.type.EntityTypeContactInfoBo;
73  import org.kuali.rice.kim.impl.identity.visa.EntityVisaBo;
74  import org.kuali.rice.kim.impl.services.KimImplServiceLocator;
75  import org.kuali.rice.krad.service.BusinessObjectService;
76  
77  import java.util.ArrayList;
78  import java.util.Collection;
79  import java.util.Collections;
80  import java.util.HashMap;
81  import java.util.List;
82  import java.util.Map;
83  
84  /**
85   * Base implementation of the identity (identity) service.  This version assumes the KimEntity
86   * and related data is located within the KIM database. 
87   * 
88   * @author Kuali Rice Team (rice.collab@kuali.org)
89   */
90  
91  public class IdentityServiceImpl implements IdentityService {
92  
93      private CriteriaLookupService criteriaLookupService;
94  	private BusinessObjectService businessObjectService;
95  
96      @Override
97  	public Entity getEntity(String entityId) throws RiceIllegalArgumentException {
98          incomingParamCheck(entityId, "entityId");
99  
100 		EntityBo entity = getEntityBo( entityId );
101 		if ( entity == null ) {
102 			return null;
103 		}
104 		return EntityBo.to( entity );
105 	}
106 	
107     @Override
108 	public Entity getEntityByPrincipalId(String principalId) throws RiceIllegalArgumentException {
109         incomingParamCheck(principalId, "principalId");
110 
111 		EntityBo entity = getEntityBoByPrincipalId(principalId);
112 		if ( entity == null ) {
113 			return null;
114 		}
115 		return EntityBo.to(entity);
116 	}
117 	
118     @Override
119 	public Entity getEntityByPrincipalName(String principalName) throws RiceIllegalArgumentException{
120         incomingParamCheck(principalName, "principalName");
121 
122 		EntityBo entity = getEntityBoByPrincipalName(principalName);
123 		if ( entity == null ) {
124 			return null;
125 		}
126 		return EntityBo.to(entity);
127 	}
128 	
129     @Override
130 	public EntityDefault getEntityDefault(String entityId) throws RiceIllegalArgumentException {
131         incomingParamCheck(entityId, "entityId");
132 
133 		EntityBo entity = getEntityBo( entityId );
134 		if ( entity == null ) {
135 			return null;
136 		}
137 		return EntityBo.toDefault( entity );
138 	}
139 	
140     @Override
141 	public EntityDefault getEntityDefaultByPrincipalId(String principalId) throws RiceIllegalArgumentException {
142         incomingParamCheck(principalId, "principalId");
143 
144 		EntityBo entity = getEntityBoByPrincipalId(principalId);
145 		if ( entity == null ) {
146 			return null;
147 		}
148 		return EntityBo.toDefault(entity);
149 	}
150 	
151     @Override
152 	public EntityDefault getEntityDefaultByPrincipalName(String principalName) throws RiceIllegalArgumentException {
153         incomingParamCheck(principalName, "principalName");
154 
155 		EntityBo entity = getEntityBoByPrincipalName(principalName);
156 		if ( entity == null ) {
157 			return null;
158 		}
159 		return EntityBo.toDefault(entity);
160 	}
161 	
162     @Override
163 	public Principal getPrincipalByPrincipalNameAndPassword(String principalName, String password) throws RiceIllegalArgumentException {
164         incomingParamCheck(principalName, "principalName");
165         incomingParamCheck(password, "password");
166 
167 		Map<String,Object> criteria = new HashMap<String,Object>(3);
168         criteria.put(KIMPropertyConstants.Principal.PRINCIPAL_NAME, principalName);
169         criteria.put(KIMPropertyConstants.Principal.PASSWORD, password);
170         criteria.put(KIMPropertyConstants.Principal.ACTIVE, Boolean.TRUE);
171         Collection<PrincipalBo> principals = businessObjectService.findMatching(PrincipalBo.class, criteria);
172 
173         if (!principals.isEmpty()) {
174             return PrincipalBo.to(principals.iterator().next());
175         }
176         return null;
177 	}
178 
179     @Override
180     public Principal addPrincipalToEntity(Principal principal) throws RiceIllegalArgumentException, RiceIllegalStateException {
181         incomingParamCheck(principal, "principal");
182 
183         if (StringUtils.isEmpty(principal.getEntityId()) || StringUtils.isBlank(principal.getEntityId())
184                 || StringUtils.isEmpty(principal.getPrincipalName()) || StringUtils.isBlank(principal.getPrincipalName())) {
185             throw new RiceIllegalStateException("Principal's entityId and PrincipalName must be populated before creation");
186         }  else {
187             if (getPrincipalByPrincipalName(principal.getPrincipalName()) != null) {
188                 throw new RiceIllegalStateException("the Principal to create already exists: " + principal);
189             }
190         }
191         PrincipalBo bo = PrincipalBo.from(principal);
192         return PrincipalBo.to(businessObjectService.save(bo));
193     }
194 
195     @Override
196     public Principal updatePrincipal(Principal principal) throws RiceIllegalArgumentException, RiceIllegalStateException {
197         incomingParamCheck(principal, "principal");
198         Principal originalPrincipal = null;
199         if (StringUtils.isEmpty(principal.getEntityId()) || StringUtils.isBlank(principal.getEntityId())
200                 || StringUtils.isEmpty(principal.getPrincipalName()) || StringUtils.isBlank(principal.getPrincipalName())) {
201             throw new RiceIllegalStateException("Principal's entityId and PrincipalName must be populated before update");
202         }  else {
203              originalPrincipal = getPrincipalByPrincipalName(principal.getPrincipalName());
204             if (StringUtils.isEmpty(principal.getPrincipalId()) || originalPrincipal == null) {
205                 throw new RiceIllegalStateException("the Principal to update does not exist: " + principal);
206             }
207         }
208         PrincipalBo bo = PrincipalBo.from(principal);
209         PrincipalBo updatedPrincipal = businessObjectService.save(bo);
210         if (originalPrincipal.isActive()
211                 && !updatedPrincipal.isActive()) {
212             KimImplServiceLocator.getRoleInternalService().principalInactivated(updatedPrincipal.getPrincipalId());
213         }
214         return PrincipalBo.to(updatedPrincipal);
215     }
216 
217     @Override
218     public Principal inactivatePrincipal(String principalId) throws RiceIllegalArgumentException, RiceIllegalStateException {
219         incomingParamCheck(principalId, "principalId");
220 
221         Principal principal = getPrincipal(principalId);
222         if (principal == null) {
223             throw new RiceIllegalStateException("Principal with principalId: " + principalId + " does not exist");
224         }
225         PrincipalBo bo = PrincipalBo.from(principal);
226         bo.setActive(false);
227         return PrincipalBo.to(businessObjectService.save(bo));
228     }
229 
230     @Override
231     public Principal inactivatePrincipalByName(String principalName) throws RiceIllegalArgumentException, RiceIllegalStateException {
232         incomingParamCheck(principalName, "principalName");
233 
234         Principal principal = getPrincipalByPrincipalName(principalName);
235         if (principal == null) {
236             throw new RiceIllegalStateException("Principal with principalName: " + principalName + " does not exist");
237         }
238         PrincipalBo bo = PrincipalBo.from(principal);
239         bo.setActive(false);
240         return PrincipalBo.to(businessObjectService.save(bo));
241     }
242 
243     @Override
244     public EntityTypeContactInfo addEntityTypeContactInfoToEntity(EntityTypeContactInfo entityTypeData) throws RiceIllegalArgumentException, RiceIllegalStateException {
245         incomingParamCheck(entityTypeData, "entityTypeData");
246 
247         if (StringUtils.isEmpty(entityTypeData.getEntityId()) || StringUtils.isBlank(entityTypeData.getEntityId())
248                 || StringUtils.isEmpty(entityTypeData.getEntityTypeCode()) || StringUtils.isBlank(entityTypeData.getEntityTypeCode())) {
249             throw new RiceIllegalStateException("EntityTypeData's entityId and entityTypeCode must be populated before creation");
250         }  else {
251             if (getEntityTypeDataBo(entityTypeData.getEntityId(), entityTypeData.getEntityTypeCode()) != null) {
252                 throw new RiceIllegalStateException("the entityTypeData to create already exists: " + entityTypeData);
253             }
254         }
255         EntityTypeContactInfoBo bo = EntityTypeContactInfoBo.from(entityTypeData);
256         return EntityTypeContactInfoBo.to(businessObjectService.save(bo));
257     }
258 
259     private EntityTypeContactInfoBo getEntityTypeDataBo(String entityId, String entityTypeCode) {
260         Map<String,Object> criteria = new HashMap<String,Object>(3);
261          criteria.put(KIMPropertyConstants.Entity.ENTITY_ID, entityId);
262          criteria.put(KIMPropertyConstants.Entity.ENTITY_TYPE_CODE, entityTypeCode);
263          criteria.put(KIMPropertyConstants.Entity.ACTIVE, Boolean.TRUE);
264          return businessObjectService.findByPrimaryKey(EntityTypeContactInfoBo.class, criteria);
265     }
266 
267     @Override
268     public EntityTypeContactInfo updateEntityTypeContactInfo(EntityTypeContactInfo entityTypeContactInfo) throws RiceIllegalArgumentException, RiceIllegalStateException {
269         incomingParamCheck(entityTypeContactInfo, "entityTypeContactInfo");
270 
271         if (StringUtils.isBlank(entityTypeContactInfo.getEntityId()) || StringUtils.isEmpty(entityTypeContactInfo.getEntityId())
272                 || StringUtils.isBlank(entityTypeContactInfo.getEntityTypeCode()) || StringUtils.isEmpty(entityTypeContactInfo.getEntityTypeCode())) {
273             throw new RiceIllegalStateException("EntityTypeData's entityId and entityTypeCode must be populated before update");
274         }  else {
275             if (getEntityTypeDataBo(entityTypeContactInfo.getEntityId(), entityTypeContactInfo.getEntityTypeCode()) == null) {
276                 throw new RiceIllegalStateException("the entityTypeData to update does not exist: " + entityTypeContactInfo);
277             }
278         }
279         EntityTypeContactInfoBo bo = EntityTypeContactInfoBo.from(entityTypeContactInfo);
280         return EntityTypeContactInfoBo.to(businessObjectService.save(bo));
281     }
282 
283     @Override
284     public EntityTypeContactInfo inactivateEntityTypeContactInfo(String entityId, String entityTypeCode) throws RiceIllegalArgumentException, RiceIllegalStateException {
285         incomingParamCheck(entityId, "entityId");
286         incomingParamCheck(entityTypeCode, "entityTypeCode");
287 
288         EntityTypeContactInfoBo bo = getEntityTypeDataBo(entityId, entityTypeCode);
289         if (bo == null) {
290             throw new RiceIllegalStateException("EntityTypeData with entityId: " + entityId + " entityTypeCode: " + entityTypeCode + " does not exist");
291         }
292         bo.setActive(false);
293         return EntityTypeContactInfoBo.to(businessObjectService.save(bo));
294     }
295 
296     private EntityAddressBo getEntityAddressBo(String entityId, String entityTypeCode, String addressTypeCode) {
297         Map<String,Object> criteria = new HashMap<String,Object>(4);
298         criteria.put(KIMPropertyConstants.Entity.ENTITY_ID, entityId);
299         criteria.put(KIMPropertyConstants.Entity.ENTITY_TYPE_CODE, entityTypeCode);
300         criteria.put("addressTypeCode", addressTypeCode);
301         criteria.put(KIMPropertyConstants.Entity.ACTIVE, Boolean.TRUE);
302         return businessObjectService.findByPrimaryKey(EntityAddressBo.class, criteria);
303     }
304 
305     private EntityAddressBo getEntityAddressBo(String addressId) {
306         Map<String,Object> criteria = new HashMap<String,Object>(4);
307         criteria.put(KIMPropertyConstants.Entity.ID, addressId);
308         return businessObjectService.findByPrimaryKey(EntityAddressBo.class, criteria);
309     }
310 
311     @Override
312     public EntityAddress addAddressToEntity(EntityAddress address) throws RiceIllegalArgumentException, RiceIllegalStateException {
313         incomingParamCheck(address, "address");
314 
315         if (StringUtils.isEmpty(address.getEntityId()) || StringUtils.isBlank(address.getEntityId())
316                 || StringUtils.isEmpty(address.getEntityTypeCode()) || StringUtils.isBlank(address.getEntityTypeCode())) {
317             throw new RiceIllegalStateException("Address's entityId and entityTypeCode must be populated before creation");
318         }  else {
319             if (address.getAddressType() == null) {
320                 throw new RiceIllegalStateException("Address's type must be populated before creation");
321             }
322             if (getEntityAddressBo(address.getEntityId(), address.getEntityTypeCode(), address.getAddressType().getCode()) != null) {
323                 throw new RiceIllegalStateException("the address to create already exists: " + address);
324             }
325         }
326         EntityAddressBo bo = EntityAddressBo.from(address);
327         return EntityAddressBo.to(businessObjectService.save(bo));
328     }
329 
330     @Override
331     public EntityAddress updateAddress(EntityAddress address) throws RiceIllegalArgumentException, RiceIllegalStateException {
332         incomingParamCheck(address, "address");
333 
334         if (StringUtils.isEmpty(address.getEntityId()) || StringUtils.isBlank(address.getEntityId())
335                 || StringUtils.isEmpty(address.getEntityTypeCode()) || StringUtils.isBlank(address.getEntityTypeCode())) {
336             throw new RiceIllegalStateException("Address's entityId and entityTypeCode must be populated before creation");
337         }  else {
338             if (address.getAddressType() == null) {
339                 throw new RiceIllegalStateException("Address's type must be populated before creation");
340             }
341             if (StringUtils.isEmpty(address.getId())
342                   ||  getEntityAddressBo(address.getEntityId(), address.getEntityTypeCode(), address.getAddressType().getCode()) == null) {
343                 throw new RiceIllegalStateException("the address to update does not exists: " + address);
344             }
345         }
346         EntityAddressBo bo = EntityAddressBo.from(address);
347         return EntityAddressBo.to(businessObjectService.save(bo));
348     }
349 
350     @Override
351     public EntityAddress inactivateAddress(String addressId) throws RiceIllegalArgumentException, RiceIllegalStateException {
352         incomingParamCheck(addressId, "addressId");
353 
354         EntityAddressBo bo = getEntityAddressBo(addressId);
355         if (bo == null) {
356             throw new RiceIllegalStateException("Address with addressId: " + addressId + " does not exist");
357         }
358         bo.setActive(false);
359         return EntityAddressBo.to(businessObjectService.save(bo));
360     }
361 
362     private EntityEmailBo getEntityEmailBo(String entityId, String entityTypeCode, String emailTypeCode) {
363         Map<String,Object> criteria = new HashMap<String,Object>(4);
364         criteria.put(KIMPropertyConstants.Entity.ENTITY_ID, entityId);
365         criteria.put(KIMPropertyConstants.Entity.ENTITY_TYPE_CODE, entityTypeCode);
366         criteria.put("emailTypeCode", emailTypeCode);
367         criteria.put(KIMPropertyConstants.Entity.ACTIVE, Boolean.TRUE);
368         return businessObjectService.findByPrimaryKey(EntityEmailBo.class, criteria);
369     }
370 
371     private EntityEmailBo getEntityEmailBo(String emailId) {
372         Map<String,Object> criteria = new HashMap<String,Object>(4);
373         criteria.put(KIMPropertyConstants.Entity.ID, emailId);
374         return businessObjectService.findByPrimaryKey(EntityEmailBo.class, criteria);
375     }
376     @Override
377     public EntityEmail addEmailToEntity(EntityEmail email) throws RiceIllegalArgumentException, RiceIllegalStateException {
378         incomingParamCheck(email, "email");
379 
380         if (StringUtils.isEmpty(email.getEntityId()) || StringUtils.isBlank(email.getEntityId())
381                 || StringUtils.isEmpty(email.getEntityTypeCode()) || StringUtils.isBlank(email.getEntityTypeCode())) {
382             throw new RiceIllegalStateException("Email's entityId and entityTypeCode must be populated before creation");
383         }  else {
384             if (email.getEmailType() == null) {
385                 throw new RiceIllegalStateException("Email's type must be populated before creation");
386             }
387             if (getEntityEmailBo(email.getEntityId(), email.getEntityTypeCode(), email.getEmailType().getCode()) != null) {
388                 throw new RiceIllegalStateException("the email to create already exists: " + email);
389             }
390         }
391         EntityEmailBo bo = EntityEmailBo.from(email);
392         return EntityEmailBo.to(businessObjectService.save(bo));
393     }
394 
395     @Override
396     public EntityEmail updateEmail(EntityEmail email) throws RiceIllegalArgumentException, RiceIllegalStateException {
397         incomingParamCheck(email, "email");
398 
399         if (StringUtils.isEmpty(email.getEntityId()) || StringUtils.isBlank(email.getEntityId())
400                 || StringUtils.isEmpty(email.getEntityTypeCode()) || StringUtils.isBlank(email.getEntityTypeCode())) {
401             throw new RiceIllegalStateException("Email's entityId and entityTypeCode must be populated before creation");
402         }  else {
403             if (email.getEmailType() == null) {
404                 throw new RiceIllegalStateException("Email's type must be populated before creation");
405             }
406             if (StringUtils.isEmpty(email.getId())
407                   ||  getEntityEmailBo(email.getEntityId(), email.getEntityTypeCode(), email.getEmailType().getCode()) == null) {
408                 throw new RiceIllegalStateException("the email to update does not exists: " + email);
409             }
410         }
411         EntityEmailBo bo = EntityEmailBo.from(email);
412         return EntityEmailBo.to(businessObjectService.save(bo));
413     }
414 
415     @Override
416     public EntityEmail inactivateEmail(String emailId) throws RiceIllegalArgumentException, RiceIllegalStateException {
417         incomingParamCheck(emailId, "emailId");
418 
419         EntityEmailBo bo = getEntityEmailBo(emailId);
420         if (bo == null) {
421             throw new RiceIllegalStateException("Email with emailId: " + emailId + " does not exist");
422         }
423         bo.setActive(false);
424         return EntityEmailBo.to(businessObjectService.save(bo));
425     }
426 
427     private EntityPhoneBo getEntityPhoneBo(String entityId, String entityTypeCode, String phoneTypeCode) {
428         Map<String,Object> criteria = new HashMap<String,Object>(4);
429         criteria.put(KIMPropertyConstants.Entity.ENTITY_ID, entityId);
430         criteria.put(KIMPropertyConstants.Entity.ENTITY_TYPE_CODE, entityTypeCode);
431         criteria.put("phoneTypeCode", phoneTypeCode);
432         criteria.put(KIMPropertyConstants.Entity.ACTIVE, Boolean.TRUE);
433         return businessObjectService.findByPrimaryKey(EntityPhoneBo.class, criteria);
434     }
435 
436     private EntityPhoneBo getEntityPhoneBo(String phoneId) {
437         Map<String,Object> criteria = new HashMap<String,Object>(4);
438         criteria.put(KIMPropertyConstants.Entity.ID, phoneId);
439         return businessObjectService.findByPrimaryKey(EntityPhoneBo.class, criteria);
440     }
441 
442     @Override
443     public EntityPhone addPhoneToEntity(EntityPhone phone) throws RiceIllegalArgumentException, RiceIllegalStateException {
444         incomingParamCheck(phone, "phone");
445 
446         if (StringUtils.isEmpty(phone.getEntityId()) || StringUtils.isBlank(phone.getEntityId())
447                 || StringUtils.isEmpty(phone.getEntityTypeCode()) || StringUtils.isBlank(phone.getEntityTypeCode())) {
448             throw new RiceIllegalStateException("Phone's entityId and entityTypeCode must be populated before creation");
449         }  else {
450             if (phone.getPhoneType() == null) {
451                 throw new RiceIllegalStateException("Phone's type must be populated before creation");
452             }
453             if (getEntityPhoneBo(phone.getEntityId(), phone.getEntityTypeCode(), phone.getPhoneType().getCode()) != null) {
454                 throw new RiceIllegalStateException("the phone to create already exists: " + phone);
455             }
456         }
457         EntityPhoneBo bo = EntityPhoneBo.from(phone);
458         return EntityPhoneBo.to(businessObjectService.save(bo));
459     }
460 
461     @Override
462     public EntityPhone updatePhone(EntityPhone phone) throws RiceIllegalArgumentException, RiceIllegalStateException {
463         incomingParamCheck(phone, "phone");
464 
465         if (StringUtils.isEmpty(phone.getEntityId()) || StringUtils.isBlank(phone.getEntityId())
466                 || StringUtils.isEmpty(phone.getEntityTypeCode()) || StringUtils.isBlank(phone.getEntityTypeCode())) {
467             throw new RiceIllegalStateException("Phone's entityId and entityTypeCode must be populated before creation");
468         }  else {
469             if (phone.getPhoneType() == null) {
470                 throw new RiceIllegalStateException("Phone's type must be populated before creation");
471             }
472             if (StringUtils.isEmpty(phone.getId())
473                   ||  getEntityPhoneBo(phone.getEntityId(), phone.getEntityTypeCode(), phone.getPhoneType().getCode()) == null) {
474                 throw new RiceIllegalStateException("the phone to update does not exists: " + phone);
475             }
476         }
477         EntityPhoneBo bo = EntityPhoneBo.from(phone);
478         return EntityPhoneBo.to(businessObjectService.save(bo));
479     }
480 
481     @Override
482     public EntityPhone inactivatePhone(String phoneId) throws RiceIllegalArgumentException, RiceIllegalStateException {
483         incomingParamCheck(phoneId, "phoneId");
484 
485         EntityPhoneBo bo = getEntityPhoneBo(phoneId);
486         if (bo == null) {
487             throw new RiceIllegalStateException("Phone with phoneId: " + phoneId + " does not exist");
488         }
489         bo.setActive(false);
490         return EntityPhoneBo.to(businessObjectService.save(bo));
491     }
492 
493 
494     private EntityExternalIdentifierBo getEntityExternalIdentifierBo(String entityId, String externalIdentifierTypeCode) {
495         Map<String,Object> criteria = new HashMap<String,Object>(4);
496         criteria.put(KIMPropertyConstants.Entity.ENTITY_ID, entityId);
497         criteria.put("externalIdentifierTypeCode", externalIdentifierTypeCode);
498         return businessObjectService.findByPrimaryKey(EntityExternalIdentifierBo.class, criteria);
499     }
500 
501     @Override
502     public EntityExternalIdentifier addExternalIdentifierToEntity(EntityExternalIdentifier externalId) throws RiceIllegalArgumentException, RiceIllegalStateException {
503         incomingParamCheck(externalId, "externalId");
504 
505         if (StringUtils.isEmpty(externalId.getEntityId()) || StringUtils.isBlank(externalId.getEntityId())
506                 || StringUtils.isEmpty(externalId.getExternalIdentifierTypeCode()) || StringUtils.isBlank(externalId.getExternalIdentifierTypeCode())) {
507             throw new RiceIllegalStateException("EntityExternalIdentifier's entityId and entityTypeCode must be populated before creation");
508         }  else {
509             if (getEntityExternalIdentifierBo(externalId.getEntityId(), externalId.getExternalIdentifierTypeCode()) != null) {
510                 throw new RiceIllegalStateException("the EntityExternalIdentifier to create already exists: " + externalId);
511             }
512         }
513         EntityExternalIdentifierBo bo = EntityExternalIdentifierBo.from(externalId);
514         return EntityExternalIdentifierBo.to(businessObjectService.save(bo));
515     }
516 
517     @Override
518     public EntityExternalIdentifier updateExternalIdentifier(EntityExternalIdentifier externalId) throws RiceIllegalArgumentException, RiceIllegalStateException {
519         incomingParamCheck(externalId, "externalId");
520 
521         if (StringUtils.isEmpty(externalId.getEntityId()) || StringUtils.isBlank(externalId.getEntityId())
522                 || StringUtils.isEmpty(externalId.getExternalIdentifierTypeCode()) || StringUtils.isBlank(externalId.getExternalIdentifierTypeCode())) {
523             throw new RiceIllegalStateException("EntityExternalIdentifier's entityId and externalIdentifierTypeCode must be populated before creation");
524         }  else {
525             if (StringUtils.isEmpty(externalId.getId())
526                   ||  getEntityExternalIdentifierBo(externalId.getEntityId(), externalId.getExternalIdentifierTypeCode()) == null) {
527                 throw new RiceIllegalStateException("the external identifier to update does not exist: " + externalId);
528             }
529         }
530         EntityExternalIdentifierBo bo = EntityExternalIdentifierBo.from(externalId);
531         return EntityExternalIdentifierBo.to(businessObjectService.save(bo));
532     }
533 
534 
535     private EntityAffiliationBo getEntityAffiliationBo(String id) {
536         Map<String,Object> criteria = new HashMap<String,Object>();
537         criteria.put(KIMPropertyConstants.Entity.ID, id);
538         return businessObjectService.findByPrimaryKey(EntityAffiliationBo.class, criteria);
539     }
540 
541     @Override
542     public EntityAffiliation addAffiliationToEntity(EntityAffiliation affiliation) throws RiceIllegalArgumentException, RiceIllegalStateException {
543         incomingParamCheck(affiliation, "affiliation");
544 
545         if (StringUtils.isEmpty(affiliation.getEntityId()) || StringUtils.isBlank(affiliation.getEntityId())) {
546             throw new RiceIllegalStateException("Affiliation's entityId must be populated before creation");
547         }  else {
548             if (affiliation.getAffiliationType() == null) {
549                 throw new RiceIllegalStateException("EntityAffiliation's type must be populated before creation");
550             }
551             if (getEntityAffiliationBo(affiliation.getId()) != null) {
552                 throw new RiceIllegalStateException("the EntityAffiliation to create already exists: " + affiliation);
553             }
554         }
555         EntityAffiliationBo bo = EntityAffiliationBo.from(affiliation);
556         return EntityAffiliationBo.to(businessObjectService.save(bo));
557     }
558 
559     @Override
560     public EntityAffiliation updateAffiliation(EntityAffiliation affiliation) throws RiceIllegalArgumentException, RiceIllegalStateException {
561         incomingParamCheck(affiliation, "affiliation");
562 
563         if (StringUtils.isEmpty(affiliation.getEntityId()) || StringUtils.isBlank(affiliation.getEntityId())) {
564             throw new RiceIllegalStateException("Affiliation's entityId must be populated before creation");
565         }  else {
566             if (affiliation.getAffiliationType() == null) {
567                 throw new RiceIllegalStateException("EntityAffiliation's type must be populated before creation");
568             }
569             if (StringUtils.isEmpty(affiliation.getId())
570                   ||  getEntityAffiliationBo(affiliation.getId()) == null) {
571                 throw new RiceIllegalStateException("the EntityAffiliation to update already exists: " + affiliation);
572             }
573         }
574         EntityAffiliationBo bo = EntityAffiliationBo.from(affiliation);
575         return EntityAffiliationBo.to(businessObjectService.save(bo));
576     }
577 
578     @Override
579     public EntityAffiliation inactivateAffiliation(String id) throws RiceIllegalArgumentException, RiceIllegalStateException {
580         incomingParamCheck(id, "id");
581 
582         EntityAffiliationBo bo = getEntityAffiliationBo(id);
583         if (bo == null) {
584             throw new RiceIllegalStateException("EntityAffiliation with id: " + id + " does not exist");
585         }
586         bo.setActive(false);
587         return EntityAffiliationBo.to(businessObjectService.save(bo));
588     }
589 
590     @Override
591 	public EntityQueryResults findEntities(QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
592 		incomingParamCheck(queryByCriteria, "queryByCriteria");
593 
594         GenericQueryResults<EntityBo> results = criteriaLookupService.lookup(EntityBo.class, queryByCriteria);
595 
596         EntityQueryResults.Builder builder = EntityQueryResults.Builder.create();
597         builder.setMoreResultsAvailable(results.isMoreResultsAvailable());
598         builder.setTotalRowCount(results.getTotalRowCount());
599 
600         final List<Entity.Builder> ims = new ArrayList<Entity.Builder>();
601         for (EntityBo bo : results.getResults()) {
602             ims.add(Entity.Builder.create(bo));
603         }
604 
605         builder.setResults(ims);
606         return builder.build();
607 	}
608 
609     @Override
610 	public EntityDefaultQueryResults findEntityDefaults(QueryByCriteria queryByCriteria) throws RiceIllegalArgumentException {
611 		incomingParamCheck(queryByCriteria, "queryByCriteria");
612 
613         GenericQueryResults<EntityBo> results = criteriaLookupService.lookup(EntityBo.class, queryByCriteria);
614 
615         EntityDefaultQueryResults.Builder builder = EntityDefaultQueryResults.Builder.create();
616         builder.setMoreResultsAvailable(results.isMoreResultsAvailable());
617         builder.setTotalRowCount(results.getTotalRowCount());
618 
619         final List<EntityDefault.Builder> ims = new ArrayList<EntityDefault.Builder>();
620         for (EntityBo bo : results.getResults()) {
621             ims.add(EntityDefault.Builder.create(bo));
622         }
623 
624         builder.setResults(ims);
625         return builder.build();
626 	}
627 
628 	protected EntityNameQueryResults findNames(QueryByCriteria queryByCriteria) {
629 		incomingParamCheck(queryByCriteria, "queryByCriteria");
630 
631         GenericQueryResults<EntityNameBo> results = criteriaLookupService.lookup(EntityNameBo.class, queryByCriteria);
632 
633         EntityNameQueryResults.Builder builder = EntityNameQueryResults.Builder.create();
634         builder.setMoreResultsAvailable(results.isMoreResultsAvailable());
635         builder.setTotalRowCount(results.getTotalRowCount());
636 
637         final List<EntityName.Builder> ims = new ArrayList<EntityName.Builder>();
638         for (EntityNameBo bo : results.getResults()) {
639             ims.add(EntityName.Builder.create(bo));
640         }
641 
642         builder.setResults(ims);
643         return builder.build();
644 	}
645 
646     @Override
647 	public EntityPrivacyPreferences getEntityPrivacyPreferences(String entityId) throws RiceIllegalArgumentException {
648         incomingParamCheck(entityId, "entityId");
649 		Map<String,String> criteria = new HashMap<String,String>(1);
650         criteria.put(KIMPropertyConstants.Entity.ENTITY_ID, entityId);
651 		return EntityPrivacyPreferencesBo.to(businessObjectService.findByPrimaryKey(EntityPrivacyPreferencesBo.class, criteria));
652 	}
653 
654     @Override
655 	public Principal getPrincipal(String principalId) throws RiceIllegalArgumentException {
656 		incomingParamCheck(principalId, "principalId");
657 
658         PrincipalBo principal = getPrincipalBo(principalId);
659 		if ( principal == null ) {
660 			return null;
661 		}
662 		return PrincipalBo.to(principal);
663 	}
664 	
665 	private PrincipalBo getPrincipalBo(String principalId) {
666 		Map<String,String> criteria = new HashMap<String,String>(1);
667         criteria.put(KIMPropertyConstants.Principal.PRINCIPAL_ID, principalId);
668 		return businessObjectService.findByPrimaryKey(PrincipalBo.class, criteria);
669 	}
670 
671 	private EntityBo getEntityBo(String entityId) {
672 		return businessObjectService.findByPrimaryKey(EntityBo.class, Collections.singletonMap("id", entityId));
673 	}
674 
675 	@Override
676 	public Principal getPrincipalByPrincipalName(String principalName) throws RiceIllegalArgumentException {
677 		incomingParamCheck(principalName, "principalName");
678 
679 		Map<String,Object> criteria = new HashMap<String,Object>(1);
680         criteria.put(KIMPropertyConstants.Principal.PRINCIPAL_NAME, principalName.toLowerCase());
681         Collection<PrincipalBo> principals = businessObjectService.findMatching(PrincipalBo.class, criteria);
682         if (!principals.isEmpty() && principals.size() == 1) {
683             return PrincipalBo.to(principals.iterator().next());
684         }
685         return null;
686     }
687 
688 	/**
689 	 * @see org.kuali.rice.kim.api.identity.IdentityService#getEntityByPrincipalName(java.lang.String)
690 	 */
691 	protected EntityBo getEntityBoByPrincipalName(String principalName) {
692 		if ( StringUtils.isBlank( principalName ) ) {
693 			return null;
694 		}
695         return getEntityByKeyValue("principals." + KIMPropertyConstants.Principal.PRINCIPAL_NAME, principalName.toLowerCase());
696 	}
697 
698 	/**
699 	 * @see org.kuali.rice.kim.api.identity.IdentityService#getEntityByPrincipalId(java.lang.String)
700 	 */
701 	protected EntityBo getEntityBoByPrincipalId(String principalId) {
702 		if ( StringUtils.isBlank( principalId ) ) {
703 			return null;
704 		}
705         return getEntityByKeyValue("principals." + KIMPropertyConstants.Principal.PRINCIPAL_ID, principalId);
706 	}
707 
708 	/**
709 	 * Generic helper method for performing a lookup through the business object service.
710 	 */
711 	protected EntityBo getEntityByKeyValue(String key, String value) {
712 		Map<String,String> criteria = new HashMap<String,String>(1);
713         criteria.put(key, value);
714         Collection<EntityBo> entities = businessObjectService.findMatching(EntityBo.class, criteria);
715         if (entities != null && entities.size() >= 1) {
716         	return entities.iterator().next();
717         }
718 		return null;
719 	}
720 
721     @Override
722 	public CodedAttribute getAddressType( String code ) throws RiceIllegalArgumentException {
723         incomingParamCheck(code, "code");
724 		EntityAddressTypeBo impl = businessObjectService.findBySinglePrimaryKey(EntityAddressTypeBo.class, code);
725 		if ( impl == null ) {
726 			return null;
727 		}
728 		return EntityAddressTypeBo.to(impl);
729 	}
730 
731 
732     @Override
733     public EntityAffiliationType getAffiliationType( String code ) throws RiceIllegalArgumentException {
734         incomingParamCheck(code, "code");
735 
736         EntityAffiliationTypeBo impl = businessObjectService.findBySinglePrimaryKey(EntityAffiliationTypeBo.class, code);
737 		if ( impl == null ) {
738 			return null;
739 		}
740 		return EntityAffiliationTypeBo.to(impl);
741 	}
742 
743     @Override
744     public CodedAttribute getCitizenshipStatus( String code ) throws RiceIllegalArgumentException {
745 		incomingParamCheck(code, "code");
746         EntityCitizenshipStatusBo impl = businessObjectService.findBySinglePrimaryKey(EntityCitizenshipStatusBo.class, code);
747 		if ( impl == null ) {
748 			return null;
749 		}
750 		return EntityCitizenshipStatusBo.to(impl);
751 	}
752     @Override
753     public CodedAttribute getEmailType( String code ) throws RiceIllegalArgumentException {
754 		incomingParamCheck(code, "code");
755         EntityEmailTypeBo impl = businessObjectService.findBySinglePrimaryKey(EntityEmailTypeBo.class, code);
756 		if ( impl == null ) {
757 			return null;
758 		}
759 		return EntityEmailTypeBo.to(impl);
760 	}
761     @Override
762     public CodedAttribute getEmploymentStatus( String code ) throws RiceIllegalArgumentException {
763 		incomingParamCheck(code, "code");
764         EntityEmploymentStatusBo impl = businessObjectService.findBySinglePrimaryKey(EntityEmploymentStatusBo.class, code);
765 		if ( impl == null ) {
766 			return null;
767 		}
768 		return EntityEmploymentStatusBo.to(impl);
769 	}
770     @Override
771     public CodedAttribute getEmploymentType( String code ) throws RiceIllegalArgumentException {
772 		incomingParamCheck(code, "code");
773         EntityEmploymentTypeBo impl = businessObjectService.findBySinglePrimaryKey(EntityEmploymentTypeBo.class, code);
774 		if ( impl == null ) {
775 			return null;
776 		}
777 		return EntityEmploymentTypeBo.to(impl);
778 	}
779     @Override
780     public CodedAttribute getNameType(String code) throws RiceIllegalArgumentException {
781 		incomingParamCheck(code, "code");
782         EntityNameTypeBo impl = businessObjectService.findBySinglePrimaryKey(EntityNameTypeBo.class, code);
783 		if ( impl == null ) {
784 			return null;
785 		}
786 		return EntityNameTypeBo.to(impl);
787 	}
788     @Override
789     public CodedAttribute getEntityType( String code ) throws RiceIllegalArgumentException {
790 		incomingParamCheck(code, "code");
791         EntityTypeBo impl = businessObjectService.findBySinglePrimaryKey(EntityTypeBo.class, code);
792 		if ( impl == null ) {
793 			return null;
794 		}
795 		return EntityTypeBo.to(impl);
796 	}
797 
798     @Override
799     public EntityExternalIdentifierType getExternalIdentifierType( String code ) throws RiceIllegalArgumentException {
800 		incomingParamCheck(code, "code");
801 
802         EntityExternalIdentifierTypeBo impl = businessObjectService.findBySinglePrimaryKey(EntityExternalIdentifierTypeBo.class, code);
803 		if ( impl == null ) {
804 			return null;
805 		}
806 		return EntityExternalIdentifierTypeBo.to(impl);
807 	}
808 
809 
810     @Override
811     public CodedAttribute getPhoneType( String code ) throws RiceIllegalArgumentException {
812 		incomingParamCheck(code, "code");
813         EntityPhoneTypeBo impl = businessObjectService.findBySinglePrimaryKey(EntityPhoneTypeBo.class, code);
814 		if ( impl == null ) {
815 			return null;
816 		}
817 		return EntityPhoneTypeBo.to(impl);
818 	}
819 
820     @Override
821     public Entity createEntity(Entity entity) throws RiceIllegalArgumentException, RiceIllegalStateException {
822         incomingParamCheck(entity, "entity");
823 
824         if (StringUtils.isNotBlank(entity.getId()) && getEntity(entity.getId()) != null) {
825             throw new RiceIllegalStateException("the Entity to create already exists: " + entity);
826         }
827 
828         EntityBo bo = EntityBo.from(entity);
829         return EntityBo.to(businessObjectService.save(bo));
830     }
831 
832     @Override
833     public Entity updateEntity(Entity entity) throws RiceIllegalArgumentException, RiceIllegalStateException {
834         incomingParamCheck(entity, "entity");
835 
836         if (StringUtils.isBlank(entity.getId()) || getEntity(entity.getId()) == null) {
837             throw new RiceIllegalStateException("the Entity does not exist: " + entity);
838         }
839 
840         EntityBo bo = EntityBo.from(entity);
841         return EntityBo.to(businessObjectService.save(bo));
842     }
843 
844     @Override
845     public Entity inactivateEntity(String entityId) throws RiceIllegalArgumentException, RiceIllegalStateException {
846         incomingParamCheck(entityId, "entityId");
847 
848         Entity entity = getEntity(entityId);
849         if (entity == null) {
850             throw new RiceIllegalStateException("an Entity does not exist for entityId: " + entityId);
851         }
852 
853         EntityBo bo = EntityBo.from(entity);
854         bo.setActive(false);
855         return EntityBo.to(businessObjectService.save(bo));
856     }
857 
858     @Override
859     public EntityPrivacyPreferences addPrivacyPreferencesToEntity(EntityPrivacyPreferences privacyPreferences) throws RiceIllegalArgumentException, RiceIllegalStateException {
860         incomingParamCheck(privacyPreferences, "privacyPreferences");
861 
862         if (StringUtils.isEmpty(privacyPreferences.getEntityId()) || StringUtils.isBlank(privacyPreferences.getEntityId())) {
863             throw new RiceIllegalStateException("PrivacyPreferences' entityId must be populated before creation");
864         }  else {
865             if (getEntityPrivacyPreferences(privacyPreferences.getEntityId()) != null) {
866                 throw new RiceIllegalStateException("the PrivacyPreferences to create already exists: " + privacyPreferences);
867             }
868         }
869         EntityPrivacyPreferencesBo bo = EntityPrivacyPreferencesBo.from(privacyPreferences);
870         return EntityPrivacyPreferencesBo.to(businessObjectService.save(bo));
871     }
872 
873     @Override
874     public EntityPrivacyPreferences updatePrivacyPreferences(EntityPrivacyPreferences privacyPreferences) throws RiceIllegalArgumentException, RiceIllegalStateException {
875         incomingParamCheck(privacyPreferences, "privacyPreferences");
876 
877         if (StringUtils.isEmpty(privacyPreferences.getEntityId()) || StringUtils.isBlank(privacyPreferences.getEntityId())) {
878             throw new RiceIllegalStateException("PrivacyPreferences' entityId must be populated before update");
879         }  else {
880             if (getEntityPrivacyPreferences(privacyPreferences.getEntityId()) == null) {
881                 throw new RiceIllegalStateException("the PrivacyPreferences to update does not exist: " + privacyPreferences);
882             }
883         }
884         EntityPrivacyPreferencesBo bo = EntityPrivacyPreferencesBo.from(privacyPreferences);
885         return EntityPrivacyPreferencesBo.to(businessObjectService.save(bo));
886     }
887 
888     private EntityCitizenshipBo getEntityCitizenshipBo(String entityId, String citizenshipStatusCode) {
889         if (StringUtils.isEmpty(entityId) || StringUtils.isEmpty(citizenshipStatusCode)) {
890             return null;
891         }
892         Map<String,Object> criteria = new HashMap<String,Object>(4);
893         criteria.put(KIMPropertyConstants.Entity.ENTITY_ID, entityId);
894         criteria.put("statusCode", citizenshipStatusCode);
895         criteria.put(KIMPropertyConstants.Entity.ACTIVE, Boolean.TRUE);
896         return businessObjectService.findByPrimaryKey(EntityCitizenshipBo.class, criteria);
897     }
898 
899     private EntityCitizenshipBo getEntityCitizenshipBo(String id) {
900         if (StringUtils.isEmpty(id)) {
901             return null;
902         }
903         Map<String,Object> criteria = new HashMap<String,Object>();
904         criteria.put(KIMPropertyConstants.Entity.ID, id);
905         criteria.put(KIMPropertyConstants.Entity.ACTIVE, Boolean.TRUE);
906         return businessObjectService.findByPrimaryKey(EntityCitizenshipBo.class, criteria);
907     }
908 
909     @Override
910     public EntityCitizenship addCitizenshipToEntity(EntityCitizenship citizenship) throws RiceIllegalArgumentException, RiceIllegalStateException {
911         incomingParamCheck(citizenship, "citizenship");
912 
913         if (StringUtils.isEmpty(citizenship.getEntityId()) || StringUtils.isBlank(citizenship.getEntityId())) {
914             throw new RiceIllegalStateException("Citizenship's entityId must be populated before creation");
915         }  else {
916             if (citizenship.getStatus() == null) {
917                 throw new RiceIllegalStateException("Citizenship's status must be populated before creation");
918             }
919             if (getEntityCitizenshipBo(citizenship.getEntityId(), citizenship.getStatus().getCode()) != null) {
920                 throw new RiceIllegalStateException("the EntityCitizenship to create already exists: " + citizenship);
921             }
922         }
923         EntityCitizenshipBo bo = EntityCitizenshipBo.from(citizenship);
924         return EntityCitizenshipBo.to(businessObjectService.save(bo));
925     }
926 
927     @Override
928     public EntityCitizenship updateCitizenship(EntityCitizenship citizenship) throws RiceIllegalArgumentException, RiceIllegalStateException {
929         incomingParamCheck(citizenship, "citizenship");
930 
931         if (StringUtils.isEmpty(citizenship.getEntityId()) || StringUtils.isBlank(citizenship.getEntityId())) {
932             throw new RiceIllegalStateException("Email's entityId must be populated before creation");
933         }  else {
934             if (citizenship.getStatus() == null) {
935                 throw new RiceIllegalStateException("Citizenship's status must be populated before creation");
936             }
937             if (getEntityCitizenshipBo(citizenship.getEntityId(), citizenship.getStatus().getCode()) == null) {
938                 throw new RiceIllegalStateException("the EntityCitizenship to update does not exist: " + citizenship);
939             }
940         }
941         EntityCitizenshipBo bo = EntityCitizenshipBo.from(citizenship);
942         return EntityCitizenshipBo.to(businessObjectService.save(bo));
943     }
944 
945     @Override
946     public EntityCitizenship inactivateCitizenship(String id) throws RiceIllegalArgumentException, RiceIllegalStateException {
947         incomingParamCheck(id, "id");
948 
949         EntityCitizenshipBo bo = getEntityCitizenshipBo(id);
950         if (bo == null) {
951             throw new RiceIllegalStateException("the EntityCitizenship with id: " + id + " does not exist");
952         }
953         bo.setActive(false);
954         return EntityCitizenshipBo.to(businessObjectService.save(bo));
955     }
956 
957     private EntityEthnicityBo getEntityEthnicityBo(String ethnicityId) {
958         if (StringUtils.isEmpty(ethnicityId)) {
959             return null;
960         }
961         Map<String,Object> criteria = new HashMap<String,Object>();
962         criteria.put(KIMPropertyConstants.Entity.ID, ethnicityId);
963         return businessObjectService.findByPrimaryKey(EntityEthnicityBo.class, criteria);
964     }
965     @Override
966     public EntityEthnicity addEthnicityToEntity(EntityEthnicity ethnicity) throws RiceIllegalArgumentException {
967         incomingParamCheck(ethnicity, "ethnicity");
968 
969         if (StringUtils.isEmpty(ethnicity.getEntityId()) || StringUtils.isBlank(ethnicity.getEntityId())) {
970             throw new RiceIllegalStateException("Ethnicity's entityId must be populated before creation");
971         }  else {
972             if (StringUtils.isNotEmpty(ethnicity.getId()) && getEntityEthnicityBo(ethnicity.getId()) != null) {
973                 throw new RiceIllegalStateException("the EntityEthnicity to create already exists: " + ethnicity);
974             }
975         }
976         EntityEthnicityBo bo = EntityEthnicityBo.from(ethnicity);
977         return EntityEthnicityBo.to(businessObjectService.save(bo));
978     }
979 
980     @Override
981     public EntityEthnicity updateEthnicity(EntityEthnicity ethnicity) throws RiceIllegalArgumentException, RiceIllegalStateException {
982         incomingParamCheck(ethnicity, "ethnicity");
983 
984         if (StringUtils.isEmpty(ethnicity.getEntityId()) || StringUtils.isBlank(ethnicity.getEntityId())) {
985             throw new RiceIllegalStateException("Ethnicity's entityId must be populated before creation");
986         }  else {
987             if (StringUtils.isEmpty(ethnicity.getId()) || getEntityEthnicityBo(ethnicity.getId()) == null) {
988                 throw new RiceIllegalStateException("the EntityEthnicity to update does not exist: " + ethnicity);
989             }
990         }
991         EntityEthnicityBo bo = EntityEthnicityBo.from(ethnicity);
992         return EntityEthnicityBo.to(businessObjectService.save(bo));
993     }
994 
995     private EntityResidencyBo getEntityResidencyBo(String residencyId) {
996         if (StringUtils.isEmpty(residencyId)) {
997             return null;
998         }
999         Map<String,Object> criteria = new HashMap<String,Object>();
1000         criteria.put(KIMPropertyConstants.Entity.ID, residencyId);
1001         return businessObjectService.findByPrimaryKey(EntityResidencyBo.class, criteria);
1002     }
1003 
1004     @Override
1005     public EntityResidency addResidencyToEntity(EntityResidency residency) throws RiceIllegalArgumentException, RiceIllegalStateException {
1006         incomingParamCheck(residency, "residency");
1007 
1008         if (StringUtils.isEmpty(residency.getEntityId()) || StringUtils.isBlank(residency.getEntityId())) {
1009             throw new RiceIllegalStateException("Residency's entityId must be populated before creation");
1010         }  else {
1011             if (StringUtils.isNotEmpty(residency.getId()) && getEntityResidencyBo(residency.getId()) != null) {
1012                 throw new RiceIllegalStateException("the EntityResidency to create already exists: " + residency);
1013             }
1014         }
1015         EntityResidencyBo bo = EntityResidencyBo.from(residency);
1016         return EntityResidencyBo.to(businessObjectService.save(bo));
1017     }
1018 
1019     @Override
1020     public EntityResidency updateResidency(EntityResidency residency) throws RiceIllegalArgumentException, RiceIllegalStateException {
1021         incomingParamCheck(residency, "residency");
1022 
1023         if (StringUtils.isEmpty(residency.getEntityId()) || StringUtils.isBlank(residency.getEntityId())) {
1024             throw new RiceIllegalStateException("Residency's entityId must be populated before creation");
1025         }  else {
1026             if (StringUtils.isEmpty(residency.getId()) || getEntityResidencyBo(residency.getId()) == null) {
1027                 throw new RiceIllegalStateException("the EntityResidency to update does not exist: " + residency);
1028             }
1029         }
1030         EntityResidencyBo bo = EntityResidencyBo.from(residency);
1031         return EntityResidencyBo.to(businessObjectService.save(bo));
1032     }
1033 
1034     private EntityVisaBo getEntityVisaBo(String visaId) {
1035         if (StringUtils.isEmpty(visaId)) {
1036             return null;
1037         }
1038         Map<String,Object> criteria = new HashMap<String,Object>();
1039         criteria.put(KIMPropertyConstants.Entity.ID, visaId);
1040         return businessObjectService.findByPrimaryKey(EntityVisaBo.class, criteria);
1041     }
1042 
1043     @Override
1044     public EntityVisa addVisaToEntity(EntityVisa visa) throws RiceIllegalArgumentException, RiceIllegalStateException {
1045         incomingParamCheck(visa, "visa");
1046 
1047         if (StringUtils.isEmpty(visa.getEntityId()) || StringUtils.isBlank(visa.getEntityId())) {
1048             throw new RiceIllegalStateException("Visa's entityId must be populated before creation");
1049         }  else {
1050             if (StringUtils.isNotEmpty(visa.getId()) && getEntityVisaBo(visa.getId()) != null) {
1051                 throw new RiceIllegalStateException("the EntityVisa to create already exists: " + visa);
1052             }
1053         }
1054         EntityVisaBo bo = EntityVisaBo.from(visa);
1055         return EntityVisaBo.to(businessObjectService.save(bo));
1056     }
1057 
1058     @Override
1059     public EntityVisa updateVisa(EntityVisa visa) throws RiceIllegalArgumentException, RiceIllegalStateException {
1060         incomingParamCheck(visa, "visa");
1061 
1062         if (StringUtils.isEmpty(visa.getEntityId()) || StringUtils.isBlank(visa.getEntityId())) {
1063             throw new RiceIllegalStateException("Visa's entityId must be populated before creation");
1064         }  else {
1065             if (StringUtils.isEmpty(visa.getId()) || getEntityVisaBo(visa.getId()) == null) {
1066                 throw new RiceIllegalStateException("the EntityVisa to update does not exist: " + visa);
1067             }
1068         }
1069         EntityVisaBo bo = EntityVisaBo.from(visa);
1070         return EntityVisaBo.to(businessObjectService.save(bo));
1071     }
1072 
1073     private EntityNameBo getEntityNameBo(String entityId, String nameTypeCode) {
1074         if (StringUtils.isEmpty(entityId) || StringUtils.isEmpty(nameTypeCode)) {
1075             return null;
1076         }
1077         Map<String,Object> criteria = new HashMap<String,Object>();
1078         criteria.put(KIMPropertyConstants.Entity.ENTITY_ID, entityId);
1079         criteria.put("nameCode", nameTypeCode);
1080         criteria.put(KIMPropertyConstants.Entity.ACTIVE, "Y");
1081         return businessObjectService.findByPrimaryKey(EntityNameBo.class, criteria);
1082     }
1083 
1084     private EntityNameBo getEntityNameBo(String id) {
1085         if (StringUtils.isEmpty(id)) {
1086             return null;
1087         }
1088         Map<String,Object> criteria = new HashMap<String,Object>();
1089         criteria.put(KIMPropertyConstants.Entity.ID, id);
1090         criteria.put(KIMPropertyConstants.Entity.ACTIVE, "Y");
1091         return businessObjectService.findByPrimaryKey(EntityNameBo.class, criteria);
1092     }
1093 
1094     @Override
1095     public EntityName addNameToEntity(EntityName name) throws RiceIllegalArgumentException, RiceIllegalStateException {
1096         incomingParamCheck(name, "name");
1097 
1098         if (StringUtils.isEmpty(name.getEntityId()) || StringUtils.isBlank(name.getEntityId())) {
1099             throw new RiceIllegalStateException("Name's entityId must be populated before creation");
1100         }  else {
1101             if (name.getNameType() == null) {
1102                 throw new RiceIllegalStateException("EntityName's type must be populated before creation");
1103             }
1104             if (getEntityNameBo(name.getEntityId(), name.getNameType().getCode()) != null) {
1105                 throw new RiceIllegalStateException("the EntityName to create already exists: " + name);
1106             }
1107         }
1108         EntityNameBo bo = EntityNameBo.from(name);
1109         return EntityNameBo.to(businessObjectService.save(bo));
1110     }
1111 
1112     @Override
1113     public EntityName updateName(EntityName name) throws RiceIllegalArgumentException, RiceIllegalStateException {
1114         incomingParamCheck(name, "name");
1115 
1116         if (StringUtils.isEmpty(name.getEntityId()) || StringUtils.isBlank(name.getEntityId())) {
1117             throw new RiceIllegalStateException("Name's entityId must be populated before update");
1118         }  else {
1119             if (name.getNameType() == null) {
1120                 throw new RiceIllegalStateException("EntityName's type must be populated before update");
1121             }
1122             if (StringUtils.isEmpty(name.getId()) || getEntityNameBo(name.getId()) == null) {
1123                 throw new RiceIllegalStateException("the EntityName to update does not exist: " + name);
1124             }
1125         }
1126         EntityNameBo bo = EntityNameBo.from(name);
1127         return EntityNameBo.to(businessObjectService.save(bo));
1128     }
1129 
1130     @Override
1131     public EntityName inactivateName(String id) throws RiceIllegalArgumentException, RiceIllegalStateException {
1132         incomingParamCheck(id, "id");
1133 
1134         EntityNameBo bo = getEntityNameBo(id);
1135         if (bo == null) {
1136             throw new RiceIllegalStateException("the EntityName to inactivate does not exist");
1137         }
1138 
1139         bo.setActive(false);
1140         return EntityNameBo.to(businessObjectService.save(bo));
1141     }
1142 
1143     private EntityEmploymentBo getEntityEmploymentBo(String entityId, String employmentTypeCode,
1144                         String employmentStatusCode, String employmentAffiliationId) {
1145         if (StringUtils.isEmpty(entityId) || StringUtils.isEmpty(employmentTypeCode)
1146                 || StringUtils.isEmpty(employmentStatusCode) || StringUtils.isEmpty(employmentAffiliationId)) {
1147             return null;
1148         }
1149         Map<String,Object> criteria = new HashMap<String,Object>();
1150         criteria.put(KIMPropertyConstants.Entity.ENTITY_ID, entityId);
1151         criteria.put("employeeTypeCode", employmentTypeCode);
1152         criteria.put("employeeStatusCode", employmentStatusCode);
1153         criteria.put("entityAffiliationId", employmentAffiliationId);
1154         criteria.put(KIMPropertyConstants.Entity.ACTIVE, "Y");
1155         return businessObjectService.findByPrimaryKey(EntityEmploymentBo.class, criteria);
1156     }
1157 
1158     private EntityEmploymentBo getEntityEmploymentBo(String id) {
1159         if (StringUtils.isEmpty(id)) {
1160             return null;
1161         }
1162         Map<String,Object> criteria = new HashMap<String,Object>();
1163         criteria.put(KIMPropertyConstants.Entity.ID, id);
1164         criteria.put(KIMPropertyConstants.Entity.ACTIVE, "Y");
1165         return businessObjectService.findByPrimaryKey(EntityEmploymentBo.class, criteria);
1166     }
1167     @Override
1168     public EntityEmployment addEmploymentToEntity(EntityEmployment employment) throws RiceIllegalArgumentException, RiceIllegalStateException {
1169         incomingParamCheck(employment, "employment");
1170 
1171         if (StringUtils.isEmpty(employment.getEntityId()) || StringUtils.isBlank(employment.getEntityId())) {
1172             throw new RiceIllegalStateException("EntityEmployment's entityId must be populated before creation");
1173         }  else {
1174             if (employment.getEmployeeType() == null
1175                     || employment.getEmployeeStatus() == null
1176                     || employment.getEntityAffiliation() == null) {
1177                 throw new RiceIllegalStateException("EntityEmployment's status, type, and entity affiliation must be populated before creation");
1178             }
1179             if (getEntityEmploymentBo(employment.getEntityId(), employment.getEmployeeType().getCode(), employment.getEmployeeStatus().getCode(), employment.getEntityAffiliation().getId()) != null) {
1180                 throw new RiceIllegalStateException("the EntityEmployment to create already exists: " + employment);
1181             }
1182         }
1183         EntityEmploymentBo bo = EntityEmploymentBo.from(employment);
1184         return EntityEmploymentBo.to(businessObjectService.save(bo));
1185     }
1186 
1187     @Override
1188     public EntityEmployment updateEmployment(EntityEmployment employment) throws RiceIllegalArgumentException, RiceIllegalStateException {
1189         incomingParamCheck(employment, "employment");
1190 
1191         if (StringUtils.isEmpty(employment.getEntityId()) || StringUtils.isBlank(employment.getEntityId())) {
1192             throw new RiceIllegalStateException("EntityEmployment's entityId must be populated before update");
1193         }  else {
1194             if (employment.getEmployeeType() == null
1195                     || employment.getEmployeeStatus() == null
1196                     || employment.getEntityAffiliation() == null) {
1197                 throw new RiceIllegalStateException("EntityEmployment's status, type, and entity affiliation must be populated before update");
1198             }
1199             if (getEntityEmploymentBo(employment.getEntityId(), employment.getEmployeeType().getCode(), employment.getEmployeeStatus().getCode(), employment.getEntityAffiliation().getId()) == null) {
1200                 throw new RiceIllegalStateException("the EntityEmployment to udpate does not exist: " + employment);
1201             }
1202         }
1203         EntityEmploymentBo bo = EntityEmploymentBo.from(employment);
1204         return EntityEmploymentBo.to(businessObjectService.save(bo));
1205     }
1206 
1207     @Override
1208     public EntityEmployment inactivateEmployment(String id) throws RiceIllegalArgumentException, RiceIllegalStateException {
1209         incomingParamCheck(id, "id");
1210 
1211         EntityEmploymentBo bo = getEntityEmploymentBo(id);
1212         if (bo == null) {
1213             throw new RiceIllegalStateException("the EntityEmployment to inactivate does not exist");
1214         }
1215         bo.setActive(false);
1216         return EntityEmploymentBo.to(businessObjectService.save(bo));
1217     }
1218 
1219 	private EntityBioDemographicsBo getEntityBioDemographicsBo(String entityId) {
1220         if (StringUtils.isEmpty(entityId)) {
1221             return null;
1222         }
1223 		Map<String,String> criteria = new HashMap<String,String>(1);
1224         criteria.put(KIMPropertyConstants.Entity.ENTITY_ID, entityId);
1225 		return businessObjectService.findByPrimaryKey(EntityBioDemographicsBo.class, criteria);
1226 	}
1227 
1228     @Override
1229     public EntityBioDemographics addBioDemographicsToEntity(EntityBioDemographics bioDemographics) throws RiceIllegalArgumentException, RiceIllegalStateException {
1230         incomingParamCheck(bioDemographics, "bioDemographics");
1231 
1232         if (StringUtils.isEmpty(bioDemographics.getEntityId()) || StringUtils.isBlank(bioDemographics.getEntityId())) {
1233             throw new RiceIllegalStateException("BioDemographics' entityId must be populated before creation");
1234         }  else {
1235             if (getEntityBioDemographicsBo(bioDemographics.getEntityId()) != null) {
1236                 throw new RiceIllegalStateException("the EntityBioDemographics to create already exists: " + bioDemographics);
1237             }
1238         }
1239         EntityBioDemographicsBo bo = EntityBioDemographicsBo.from(bioDemographics);
1240         return EntityBioDemographicsBo.to(businessObjectService.save(bo));
1241     }
1242 
1243     @Override
1244     public EntityBioDemographics updateBioDemographics(EntityBioDemographics bioDemographics) throws RiceIllegalArgumentException, RiceIllegalStateException {
1245         incomingParamCheck(bioDemographics, "bioDemographics");
1246 
1247         if (getEntityBioDemographicsBo(bioDemographics.getEntityId()) == null) {
1248             throw new RiceIllegalStateException("the EntityBioDemographics to update does not exist: " + bioDemographics);
1249         }
1250         EntityBioDemographicsBo bo = EntityBioDemographicsBo.from(bioDemographics);
1251         return EntityBioDemographicsBo.to(businessObjectService.save(bo));
1252     }
1253 
1254 
1255     public void setCriteriaLookupService(final CriteriaLookupService criteriaLookupService) {
1256         this.criteriaLookupService = criteriaLookupService;
1257     }
1258 
1259     public void setBusinessObjectService(final BusinessObjectService businessObjectService) {
1260         this.businessObjectService = businessObjectService;
1261     }
1262 
1263     private void incomingParamCheck(Object object, String name) {
1264         if (object == null) {
1265             throw new RiceIllegalArgumentException(name + " was null");
1266         } else if (object instanceof String
1267                 && StringUtils.isBlank((String) object)) {
1268             throw new RiceIllegalArgumentException(name + " was blank");
1269         }
1270     }
1271 }