Hello, we trying to get some assistance on an attribute generator rule. It seems to pass both the validation and RDK. Our RDK test takes Joan as firstname, Arnold as lastname. This evaluates properly to joarnold as jarnold is taken. Anything clearly wrong with this rule? We always get object exists in ISC when a duplicate user is provisioned.
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="PRHCCreateUsername" type="AttributeGenerator">
<Description>Generate a unique username for Active Directory using progressive firstname prefix + lastname. Uniqueness checked via getAccountAttribute against sAMAccountName.</Description>
<Source><![CDATA[
import java.text.Normalizer;
import sailpoint.tools.GeneralException;
// --- config ---
int MAX_USERNAME_LENGTH = 15;
boolean ADD_DOT = false; // set true if you want "prefix.lastname"
// --- helpers (JDK-only) ---
String trimToNull(String s) {
if (s == null) return null;
s = s.trim();
return s.isEmpty() ? null : s;
}
String clean(String s) {
s = Normalizer.normalize(s, Normalizer.Form.NFD)
.replaceAll("\\p{InCombiningDiacriticalMarks}+", "")
.replaceAll("[^a-zA-Z0-9]", "");
return s;
}
String buildAndTrim(String firstPart, String lastPart, String suffix) {
String sep = ADD_DOT ? "." : "";
String base = (firstPart + (ADD_DOT ? sep : "") + lastPart).toLowerCase();
// If we have a suffix, trim the BASE to leave room for it
if (suffix != null && suffix.length() > 0) {
int maxBaseLen = Math.max(0, MAX_USERNAME_LENGTH - suffix.length());
if (base.length() > maxBaseLen) base = base.substring(0, maxBaseLen);
return (base + suffix).toLowerCase();
}
// No suffix case
if (base.length() > MAX_USERNAME_LENGTH) base = base.substring(0, MAX_USERNAME_LENGTH);
return base.toLowerCase();
}
boolean isUnique(String username) throws GeneralException {
// Check for existing account with this sAMAccountName
Object existing = idn.getAccountAttribute(application.getName(), "sAMAccountName", username);
return (existing == null);
}
// --- main logic ---
String generateUsername(String firstName, String lastName) throws GeneralException {
firstName = trimToNull(firstName);
lastName = trimToNull(lastName);
if (firstName != null) firstName = clean(firstName);
if (lastName != null) lastName = clean(lastName);
if (firstName == null || lastName == null) {
try { if (log != null) log.debug("AD Create User Name | Missing first/last"); } catch (Throwable t) {}
return null;
}
// Progressive prefixes: j + lastname, jo + lastname, ..., firstname + lastname
for (int i = 1; i <= firstName.length(); i++) {
String prefix = firstName.substring(0, i);
String candidate = buildAndTrim(prefix, lastName, "");
if (isUnique(candidate)) {
try { if (log != null) log.debug("AD Create User Name | Unique: " + candidate); } catch (Throwable t) {}
return candidate;
}
}
// Fallback: append numbers to full firstname+lastname (…1, …2, …3, …)
for (int n = 1; n <= 9999; n++) {
String candidate = buildAndTrim(firstName, lastName, String.valueOf(n));
if (isUnique(candidate)) {
try { if (log != null) log.debug("AD Create User Name | Unique with suffix: " + candidate); } catch (Throwable t) {}
return candidate;
}
}
return null;
}
// Kickoff
return generateUsername(identity.getFirstname(), identity.getLastname());
]]></Source>
</Rule>