agave-profiles/profiles-core/src/main/java/org/iplantc/service/profile/dao/ScimProfileDAO.java
/**
	 * Handles the updating of an existing SCIM {@link UserResource} with the values from an Agave {@link ScimProfile}.
	 * Ordering and formatting are preserved, along with all existing metadata. Note that this operation does not
	 * implement PATCH behavior. Any nulled out or missing values from the updatedProfile will be removed from the
	 * {@code existingResource}.
	 *
	 * @param existingResource the remote SCIM resource to udpate
	 * @param updatedProfile the user-supplied values to apply to the {@code existingResource}
	 * @return the {@code existingResource} updated with values from {@code updatedProfile}
	 * @throws ProfileException if any of the updatedProfile values are invalid.
	 * @throws IOException if unable to serialized the {@link UserResource} or {@link ScimProfile}.
	 */
Handles the updating of an existing SCIM  UserResource with the values from an Agave  ScimProfile.
Ordering and formatting are preserved, along with all existing metadata. Note that this operation does not
implement PATCH behavior. Any nulled out or missing values from the updatedProfile will be removed from the
existingResource.

@param existingResource the remote SCIM resource to udpate
@param updatedProfile the user-supplied values to apply to the  existingResource
@return the  existingResource updated with values from  updatedProfile
@throws ProfileException if any of the updatedProfile values are invalid.
@throws IOException if unable to serialized the  UserResource or  ScimProfile.
Handles the updating of an existing SCIM UserResource with the values from an Agave ScimProfile . Ordering and formatting are preserved along with all existing metadata . Note that this operation does not implement PATCH behavior . Any nulled out or missing values from the updatedProfile will be removed from the existingResource . @param existingResource the remote SCIM resource to udpate @param updatedProfile the user - supplied values to apply to the existingResource @return the existingResource updated with values from updatedProfile @throws ProfileException if any of the updatedProfile values are invalid . @throws IOException if unable to serialized the UserResource or ScimProfile .
protected UserResource mergeExistingUserResource(UserResource existingResource, ScimProfile updatedProfile) throws ProfileException, IOException {
		ScimProfile existingProfile = new ScimProfile(existingResource);
		ObjectMapper mapper = new ObjectMapper();
		JsonDiff jsonDiff = new JsonDiff();
		List<PatchOperation> patches = jsonDiff.diff(
				(ObjectNode) mapper.readTree(existingProfile.toJSON()),
				(ObjectNode) mapper.readTree(updatedProfile.toJSON()),
				true);
		for (PatchOperation patchOperation: patches) {
			switch (patchOperation.getPath().toString()) {
				case "lastName":
					if (existingResource.getName() == null) {
						existingResource.setName(new Name());
					}
					existingResource.getName().setFamilyName(updatedProfile.getLastName());
					break;
				case "firstName":
					if (existingResource.getName() == null) {
						existingResource.setName(new Name());
					}
					existingResource.getName().setGivenName(updatedProfile.getFirstName());
					break;
				case "email":
					if (patchOperation.getOpType() == PatchOpType.REMOVE) {
						throw new ProfileException("Email address is required.");
					}
				case "position":
					existingResource.setTitle(updatedProfile.getPosition());
					break;
				case "active":
					existingResource.setActive(updatedProfile.isActive());
					break;
				case "mobilePhone":
					if (patchOperation.getOpType() == PatchOpType.ADD) {
						existingResource.getPhoneNumbers().add(new PhoneNumber()
								.setType("mobile")
								.setValue(ServiceUtils.formatPhoneNumber(updatedProfile.getMobilePhone())));
					} else {
						for (int i = 0; i < existingResource.getPhoneNumbers().size(); i++) {
							if (StringUtils.equalsIgnoreCase(existingResource.getPhoneNumbers().get(i).getType(), "mobile")) {
								if (patchOperation.getOpType() == PatchOpType.REMOVE) {
									existingResource.getPhoneNumbers().remove(i);
								} else {
									existingResource.getPhoneNumbers().get(i).setValue(
											ServiceUtils.formatPhoneNumber(updatedProfile.getMobilePhone(), "%s-%s-%s"));
								}
								break;
							}
						}
					}
					break;
				case "fax":
					if (patchOperation.getOpType() == PatchOpType.ADD) {
						existingResource.getPhoneNumbers().add(new PhoneNumber()
								.setType("fax")
								.setValue(ServiceUtils.formatPhoneNumber(updatedProfile.getFax())));
					} else {
						for (int i = 0; i < existingResource.getPhoneNumbers().size(); i++) {
							if (StringUtils.equalsIgnoreCase(existingResource.getPhoneNumbers().get(i).getType(), "fax")) {
								if (patchOperation.getOpType() == PatchOpType.REMOVE) {
									existingResource.getPhoneNumbers().remove(i);
								} else {
									existingResource.getPhoneNumbers().get(i).setValue(
											ServiceUtils.formatPhoneNumber(updatedProfile.getFax(), "%s-%s-%s"));
								}
								break;
							}
						}
					}
					break;
				case "phone":
					if (patchOperation.getOpType() == PatchOpType.ADD) {
						existingResource.getPhoneNumbers().add(new PhoneNumber()
								.setType("home")
								.setValue(ServiceUtils.formatPhoneNumber(updatedProfile.getPhone())));
					} else {
						String existingPhone = ServiceUtils.formatPhoneNumber(existingProfile.getPhone(), "%s-%s-%s");
						if (patchOperation.getOpType() == PatchOpType.REMOVE) {
							for (int i = 0; i < existingResource.getPhoneNumbers().size(); i++) {
								if (List.of("mobile", "fax").contains(existingResource.getPhoneNumbers().get(i).getType().toLowerCase()))
									continue;
								String phoneA = ServiceUtils.formatPhoneNumber(existingResource.getPhoneNumbers().get(i).getValue(), "%s-%s-%s");
								if (StringUtils.equals(existingPhone, phoneA)) {
									existingResource.getPhoneNumbers().remove(i);
									break;
								}
							}
						} else {
							for (int i = 0; i < existingResource.getPhoneNumbers().size(); i++) {
								if (List.of("mobile", "fax").contains(existingResource.getPhoneNumbers().get(i).getType().toLowerCase()))
									continue;
								String phoneA = ServiceUtils.formatPhoneNumber(existingResource.getPhoneNumbers().get(i).getValue(), "%s-%s-%s");
								if (StringUtils.equals(existingPhone, phoneA)) {
									existingResource.getPhoneNumbers().get(i).setValue(existingPhone);
									break;
								}
							}
						}
					}
					break;
				case "institution":
					EnterpriseUserExtension enterpriseExtension = existingResource.getExtension(EnterpriseUserExtension.class);
					if (enterpriseExtension != null) {
						enterpriseExtension.setOrganization(updatedProfile.getInstitution());
						existingResource.setExtension(enterpriseExtension);
					}
					break;
			}
		}
		return existingResource;
	}
protected UserResource mergeExistingUserResource ( UserResource existingResource , ScimProfile updatedProfile ) throws ProfileException , IOException { ScimProfile existingProfile = new ScimProfile ( existingResource ) ; ObjectMapper mapper = new ObjectMapper ( ) ; JsonDiff jsonDiff = new JsonDiff ( ) ; List < PatchOperation > patches = jsonDiff . diff ( ( ObjectNode ) mapper . readTree ( existingProfile . toJSON ( ) ) , ( ObjectNode ) mapper . readTree ( updatedProfile . toJSON ( ) ) , true ) ; for ( PatchOperation patchOperation : patches ) { switch ( patchOperation . getPath ( ) . toString ( ) ) { case "lastName" : if ( existingResource . getName ( ) == null ) { existingResource . setName ( new Name ( ) ) ; } existingResource . getName ( ) . setFamilyName ( updatedProfile . getLastName ( ) ) ; break ; case "firstName" : if ( existingResource . getName ( ) == null ) { existingResource . setName ( new Name ( ) ) ; } existingResource . getName ( ) . setGivenName ( updatedProfile . getFirstName ( ) ) ; break ; case "email" : if ( patchOperation . getOpType ( ) == PatchOpType . REMOVE ) { throw new ProfileException ( "Email address is required." ) ; } case "position" : existingResource . setTitle ( updatedProfile . getPosition ( ) ) ; break ; case "active" : existingResource . setActive ( updatedProfile . isActive ( ) ) ; break ; case "mobilePhone" : if ( patchOperation . getOpType ( ) == PatchOpType . ADD ) { existingResource . getPhoneNumbers ( ) . add ( new PhoneNumber ( ) . setType ( "mobile" ) . setValue ( ServiceUtils . formatPhoneNumber ( updatedProfile . getMobilePhone ( ) ) ) ) ; } else { for ( int i = 0 ; i < existingResource . getPhoneNumbers ( ) . size ( ) ; i ++ ) { if ( StringUtils . equalsIgnoreCase ( existingResource . getPhoneNumbers ( ) . get ( i ) . getType ( ) , "mobile" ) ) { if ( patchOperation . getOpType ( ) == PatchOpType . REMOVE ) { existingResource . getPhoneNumbers ( ) . remove ( i ) ; } else { existingResource . getPhoneNumbers ( ) . get ( i ) . setValue ( ServiceUtils . formatPhoneNumber ( updatedProfile . getMobilePhone ( ) , "%s-%s-%s" ) ) ; } break ; } } } break ; case "fax" : if ( patchOperation . getOpType ( ) == PatchOpType . ADD ) { existingResource . getPhoneNumbers ( ) . add ( new PhoneNumber ( ) . setType ( "fax" ) . setValue ( ServiceUtils . formatPhoneNumber ( updatedProfile . getFax ( ) ) ) ) ; } else { for ( int i = 0 ; i < existingResource . getPhoneNumbers ( ) . size ( ) ; i ++ ) { if ( StringUtils . equalsIgnoreCase ( existingResource . getPhoneNumbers ( ) . get ( i ) . getType ( ) , "fax" ) ) { if ( patchOperation . getOpType ( ) == PatchOpType . REMOVE ) { existingResource . getPhoneNumbers ( ) . remove ( i ) ; } else { existingResource . getPhoneNumbers ( ) . get ( i ) . setValue ( ServiceUtils . formatPhoneNumber ( updatedProfile . getFax ( ) , "%s-%s-%s" ) ) ; } break ; } } } break ; case "phone" : if ( patchOperation . getOpType ( ) == PatchOpType . ADD ) { existingResource . getPhoneNumbers ( ) . add ( new PhoneNumber ( ) . setType ( "home" ) . setValue ( ServiceUtils . formatPhoneNumber ( updatedProfile . getPhone ( ) ) ) ) ; } else { String existingPhone = ServiceUtils . formatPhoneNumber ( existingProfile . getPhone ( ) , "%s-%s-%s" ) ; if ( patchOperation . getOpType ( ) == PatchOpType . REMOVE ) { for ( int i = 0 ; i < existingResource . getPhoneNumbers ( ) . size ( ) ; i ++ ) { if ( List . of ( "mobile" , "fax" ) . contains ( existingResource . getPhoneNumbers ( ) . get ( i ) . getType ( ) . toLowerCase ( ) ) ) continue ; String phoneA = ServiceUtils . formatPhoneNumber ( existingResource . getPhoneNumbers ( ) . get ( i ) . getValue ( ) , "%s-%s-%s" ) ; if ( StringUtils . equals ( existingPhone , phoneA ) ) { existingResource . getPhoneNumbers ( ) . remove ( i ) ; break ; } } } else { for ( int i = 0 ; i < existingResource . getPhoneNumbers ( ) . size ( ) ; i ++ ) { if ( List . of ( "mobile" , "fax" ) . contains ( existingResource . getPhoneNumbers ( ) . get ( i ) . getType ( ) . toLowerCase ( ) ) ) continue ; String phoneA = ServiceUtils . formatPhoneNumber ( existingResource . getPhoneNumbers ( ) . get ( i ) . getValue ( ) , "%s-%s-%s" ) ; if ( StringUtils . equals ( existingPhone , phoneA ) ) { existingResource . getPhoneNumbers ( ) . get ( i ) . setValue ( existingPhone ) ; break ; } } } } break ; case "institution" : EnterpriseUserExtension enterpriseExtension = existingResource . getExtension ( EnterpriseUserExtension . class ) ; if ( enterpriseExtension != null ) { enterpriseExtension . setOrganization ( updatedProfile . getInstitution ( ) ) ; existingResource . setExtension ( enterpriseExtension ) ; } break ; } } return existingResource ; }
Handles the updating of an existing SCIM {@link UserResource} with the values from an Agave {@link ScimProfile}.
Handles the updating of an existing SCIM { @link UserResource } with the values from an Agave { @link ScimProfile } .
// convert to a ScimProfile for apples-to-apples comparison with the updated profile requested by the // api user. // now we can walk through the fields that differ between the existing and updated ScimProfile objects // and adjust the existing UserResource by matching values. We then just post back the UserResource // to the SCIM service, thereby preserving all non-mapped fields and ordering. // username is not changeable // look for an existing phone number of type mobile. notice that if there are multiple mobile numbers, // this approach will fail //								PhoneNumber phoneNumberItem = existingResource.getPhoneNumbers().get(i); // if we're deleting the node, get that out of the way here // otherwise, update the existing value. formatting is // look for an existing phone number of type mobile. notice that if there are multiple mobile numbers, // this approach will fail // if we're deleting the node, get that out of the way here // otherwise, update the existing value. formatting is // format the phone number so we can properly compare them // don't get confused with mobile and fax numbers // look for an existing phone number without type of fax or mobile. notice that // if there are multiple matches, only the first will ever be udpated. // don't get confused with mobile and fax numbers // otherwise, update the existing value. formatting is