package com.hida.model;
/**
* An Id Generator that creates Pids. For each Pid, every digit in their names
* will be created using the possible characters provided by a character map.
* Each digit in a character map references a different Token object.
*
*
* @author lruffin
*/
public class CustomIdGenerator extends IdGenerator {
/**
* The mapping used to describe range of possible characters at each of the
* id's root's digits. There are total of 5 different ranges that a charMap
* can contain:
*
* <pre>
* d: digits only
* l: lower case letters only
* u: upper case letters only
* m: letters only
* e: any valid character specified by d, l, u, and m.
* </pre>
*
*/
private String charMap_;
/**
* An array of Strings that contains the possible characters at each index
* of Pid's root name. This field is generated by charMap_.
*/
private final String[] tokenMap_;
/**
* A variable that will affect whether or not vowels have the possibility of
* being included in each id.
*/
private boolean sansVowel_;
/**
* Instantiates an Id Generator that creates Pids primarily based on a
* charMap. The only valid charMap characters are regex("[dlume]+"). No
* restrictions are placed on the other parameters.
*
* @param prefix A sequence of characters that appear in the beginning of
* PIDs
* @param sansVowel Dictates whether or not vowels are allowed
* @param charMap A sequence of characters used to configure Pids
*/
public CustomIdGenerator(String prefix, boolean sansVowel, String charMap) {
super(prefix);
this.charMap_ = charMap;
this.tokenMap_ = new String[charMap.length()];
this.sansVowel_ = sansVowel;
this.maxPermutation_ = getMaxPermutation();
initializeTokenMap();
}
/**
* This method calculates and returns the total possible number of
* permutations using the values given in the constructor.
*
* @return number of permutations
*/
@Override
final public long getMaxPermutation() {
long totalPermutations = 1;
for (int i = 0; i < charMap_.length(); i++) {
if (charMap_.charAt(i) == 'd') {
totalPermutations *= 10;
}
else if (charMap_.charAt(i) == 'l' || charMap_.charAt(i) == 'u') {
totalPermutations *= (sansVowel_) ? 20 : 26;
}
else if (charMap_.charAt(i) == 'm') {
totalPermutations *= (sansVowel_) ? 40 : 52;
}
else if (charMap_.charAt(i) == 'e') {
totalPermutations *= (sansVowel_) ? 50 : 62;
}
}
return totalPermutations;
}
/**
* Initializes TokenMap to contain a String of characters at each index to
* designate the possible values that can be assigned to each index of a
* Pid's BaseMap.
*/
private void initializeTokenMap() {
for (int i = 0; i < tokenMap_.length; i++) {
// get char
char c = charMap_.charAt(i);
// assign each index a string of characters
if (c == 'd') {
tokenMap_[i] = Token.DIGIT.getCharacters();
}
else if (c == 'l') {
tokenMap_[i] = (sansVowel_) ? Token.LOWER_CONSONANTS.getCharacters()
: Token.LOWER_ALPHABET.getCharacters();
}
else if (c == 'u') {
tokenMap_[i] = (sansVowel_) ? Token.UPPER_CONSONANTS.getCharacters()
: Token.UPPER_ALPHABET.getCharacters();
}
else if (c == 'm') {
tokenMap_[i] = (sansVowel_) ? Token.MIXED_CONSONANTS.getCharacters()
: Token.MIXED_ALPHABET.getCharacters();
}
else {
tokenMap_[i] = (sansVowel_) ? Token.MIXED_CONSONANTS_EXTENDED.getCharacters()
: Token.MIXED_ALPHABET_EXTENDED.getCharacters();
}
}
}
/**
* Increments a value of a PID. If the maximum limit is reached the values
* will wrap around.
*
* @param pid The pid to increment
*/
@Override
public void incrementPid(Pid pid) {
long next = (this.PidToLong(pid) + 1) % this.maxPermutation_;
pid.setName(this.longToName(next));
}
/**
* Translates an ordinal number into a sequence of characters with a radix
* based on TokenType.
*
* @param ordinal The nth position of a permutation
* @return The sequence at the nth position
*/
@Override
protected String longToName(long ordinal) {
StringBuilder name = new StringBuilder("");
int fullNameLength = charMap_.length() + prefix_.length();
long remainder = ordinal;
for (int i = fullNameLength - 1; i >= prefix_.length(); i--) {
String map = tokenMap_[i - prefix_.length()];
int radix = map.length();
name.insert(0, map.charAt((int) (remainder % radix)));
remainder /= radix;
}
return prefix_ + name.toString();
}
/**
* Translates a Pid into an ordinal number.
*
* @param pid A persistent identifier
* @return The ordinal number of the Pid
*/
@Override
protected long PidToLong(Pid pid) {
String name = pid.getName();
int fullNameLength = charMap_.length() + prefix_.length();
int totalRadix = 1;
long ordinal = 0;
for (int i = fullNameLength - 1; i >= prefix_.length(); i--) {
String map = tokenMap_[i - prefix_.length()];
int mapIndex = map.indexOf(name.charAt(i));
int currentRadix = map.length();
ordinal += totalRadix * mapIndex;
totalRadix *= currentRadix;
}
return ordinal;
}
/* getters and setters */
public String getCharMap() {
return charMap_;
}
public void setCharMap(String CharMap) {
this.charMap_ = CharMap;
}
public boolean isSansVowel() {
return sansVowel_;
}
public void setSansVowel(boolean SansVowel) {
this.sansVowel_ = SansVowel;
}
}