package de.persosim.simulator.documents;
import java.security.InvalidParameterException;
/**
* Represents the machine readable zone of a passport.
*
* Note: this class is under construction and will only provide basic functionality
*
* @author Alexander May
* @version 2.1.0
*
*/
@SuppressWarnings("all") // IMPL add functionality for all fields of MRZ
public abstract class Mrz {
interface DocumentFormat {
int getLengthMRZ();
int getOffsetDocType();
int getOffsetDocTypeEnd();
int getOffsetIssuingState();
int getOffsetIssuingStateEnd();
int getOffsetName();
int getOffsetNameEnd();
int getOffsetDocNo();
int getOffsetDocNoEnd();
int getOffsetDocNoCd();
int getOffsetDocNoCdEnd();
int getOffsetNationality();
int getOffsetNationalityEnd();
int getOffsetDoB();
int getOffsetDoBEnd();
int getOffsetDoBCd();
int getOffsetDoBCdEnd();
int getOffsetSex();
int getOffsetSexEnd();
int getOffsetDoE();
int getOffsetDoEEnd();
int getOffsetDoECd();
int getOffsetDoECdEnd();
int getOffsetOptionalData();
int getOffsetOptionalDataEnd();
int getOffsetOptionalData2();
int getOffsetOptionalData2End();
int getOffsetOptionalDataCd();
int getOffsetOptionalDataCdEnd();
int getOffsetCompositeCd();
int getOffsetCompositeCdEnd();
String calculateCompositeCd(String mrz);
}
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
protected static final DocumentFormat td1 = new DocumentFormat() {
@Override
public int getLengthMRZ() {return 90;}
//first line
@Override
public int getOffsetDocType() {return 0;}
@Override
public int getOffsetDocTypeEnd() {return 2;}
@Override
public int getOffsetIssuingState() {return 2;}
@Override
public int getOffsetIssuingStateEnd() {return 5;}
@Override
public int getOffsetDocNo() {return 5;}
@Override
public int getOffsetDocNoEnd() {return 14;}
@Override
public int getOffsetDocNoCd() {return 14;}
@Override
public int getOffsetDocNoCdEnd() {return 15;}
@Override
public int getOffsetOptionalData() {return 15;}
@Override
public int getOffsetOptionalDataEnd() {return 30;}
//second line
@Override
public int getOffsetDoB() {return 30;}
@Override
public int getOffsetDoBEnd() {return 36;}
@Override
public int getOffsetDoBCd() {return 36;}
@Override
public int getOffsetDoBCdEnd() {return 37;}
@Override
public int getOffsetSex() {return 37;}
@Override
public int getOffsetSexEnd() {return 38;}
@Override
public int getOffsetDoE() {return 38;}
@Override
public int getOffsetDoEEnd() {return 44;}
@Override
public int getOffsetDoECd() {return 44;}
@Override
public int getOffsetDoECdEnd() {return 45;}
@Override
public int getOffsetNationality() {return 45;}
@Override
public int getOffsetNationalityEnd() {return 48;}
@Override
public int getOffsetOptionalData2() {return 48;}
@Override
public int getOffsetOptionalData2End() {return 59;}
@Override
public int getOffsetCompositeCd() {return 59;}
@Override
public int getOffsetCompositeCdEnd() {return 60;}
//third line
@Override
public int getOffsetName() {return 60;}
@Override
public int getOffsetNameEnd() {return 90;}
//not present
@Override
public int getOffsetOptionalDataCd() {return 0;}
@Override
public int getOffsetOptionalDataCdEnd() {return 0;}
@Override
public String calculateCompositeCd(String mrz) {
String compositeData = mrz.substring(getOffsetDocNo(), getOffsetOptionalDataEnd());
compositeData += mrz.substring(getOffsetDoB(), getOffsetDoBCdEnd());
compositeData += mrz.substring(getOffsetDoE(), getOffsetDoECdEnd());
compositeData += mrz.substring(getOffsetOptionalData2(), getOffsetOptionalData2End());
return new String(new byte[] {computeChecksum(compositeData.getBytes(), 0, compositeData.length())});
}
};
protected static final DocumentFormat td2 = new DocumentFormat() {
@Override
public int getLengthMRZ() {return 74;}
//first line
@Override
public int getOffsetDocType() {return 0;}
@Override
public int getOffsetDocTypeEnd() {return 2;}
@Override
public int getOffsetIssuingState() {return 2;}
@Override
public int getOffsetIssuingStateEnd() {return 5;}
@Override
public int getOffsetName() {return 5;}
@Override
public int getOffsetNameEnd() {return 36;}
//second line
@Override
public int getOffsetDocNo() {return 36;}
@Override
public int getOffsetDocNoEnd() {return 45;}
@Override
public int getOffsetDocNoCd() {return 45;}
@Override
public int getOffsetDocNoCdEnd() {return 46;}
@Override
public int getOffsetNationality() {return 46;}
@Override
public int getOffsetNationalityEnd() {return 49;}
@Override
public int getOffsetDoB() {return 49;}
@Override
public int getOffsetDoBEnd() {return 55;}
@Override
public int getOffsetDoBCd() {return 55;}
@Override
public int getOffsetDoBCdEnd() {return 56;}
@Override
public int getOffsetSex() {return 56;}
@Override
public int getOffsetSexEnd() {return 57;}
@Override
public int getOffsetDoE() {return 57;}
@Override
public int getOffsetDoEEnd() {return 63;}
@Override
public int getOffsetDoECd() {return 63;}
@Override
public int getOffsetDoECdEnd() {return 64;}
@Override
public int getOffsetOptionalData() {return 64;}
@Override
public int getOffsetOptionalDataEnd() {return 73;}
@Override
public int getOffsetCompositeCd() {return 73;}
@Override
public int getOffsetCompositeCdEnd() {return 74;}
//not present
@Override
public int getOffsetOptionalDataCd() {return 0;}
@Override
public int getOffsetOptionalDataCdEnd() {return 0;}
@Override
public int getOffsetOptionalData2() {return 0;}
@Override
public int getOffsetOptionalData2End() {return 0;}
@Override
public String calculateCompositeCd(String mrz) {
String compositeData = mrz.substring(getOffsetDocNo(), getOffsetDocNoCdEnd());
compositeData += mrz.substring(getOffsetDoB(), getOffsetDoBCdEnd());
compositeData += mrz.substring(getOffsetDoE(), getOffsetDoECdEnd());
compositeData += mrz.substring(getOffsetOptionalData(), getOffsetOptionalDataEnd());
return new String(new byte[] {computeChecksum(compositeData.getBytes(), 0, compositeData.length())});
}
};
protected static final DocumentFormat mrp = new DocumentFormat() {
@Override
public int getLengthMRZ() {return 88;}
//first line
@Override
public int getOffsetDocType() {return 0;}
@Override
public int getOffsetDocTypeEnd() {return 2;}
@Override
public int getOffsetIssuingState() {return 2;}
@Override
public int getOffsetIssuingStateEnd() {return 5;}
@Override
public int getOffsetName() {return 5;}
@Override
public int getOffsetNameEnd() {return 44;}
//second line
@Override
public int getOffsetDocNo() {return 44;}
@Override
public int getOffsetDocNoEnd() {return 53;}
@Override
public int getOffsetDocNoCd() {return 53;}
@Override
public int getOffsetDocNoCdEnd() {return 54;}
@Override
public int getOffsetNationality() {return 54;}
@Override
public int getOffsetNationalityEnd() {return 57;}
@Override
public int getOffsetDoB() {return 57;}
@Override
public int getOffsetDoBEnd() {return 63;}
@Override
public int getOffsetDoBCd() {return 63;}
@Override
public int getOffsetDoBCdEnd() {return 64;}
@Override
public int getOffsetSex() {return 64;}
@Override
public int getOffsetSexEnd() {return 65;}
@Override
public int getOffsetDoE() {return 65;}
@Override
public int getOffsetDoEEnd() {return 71;}
@Override
public int getOffsetDoECd() {return 71;}
@Override
public int getOffsetDoECdEnd() {return 72;}
@Override
public int getOffsetOptionalData() {return 72;}
@Override
public int getOffsetOptionalDataEnd() {return 86;}
@Override
public int getOffsetOptionalDataCd() {return 86;}
@Override
public int getOffsetOptionalDataCdEnd() {return 87;}
@Override
public int getOffsetCompositeCd() {return 87;}
@Override
public int getOffsetCompositeCdEnd() {return 88;}
//not present
@Override
public int getOffsetOptionalData2() {return 0;}
@Override
public int getOffsetOptionalData2End() {return 0;}
@Override
public String calculateCompositeCd(String mrz) {
String compositeData = mrz.substring(getOffsetDocNo(), getOffsetDocNoCdEnd());
compositeData += mrz.substring(getOffsetDoB(), getOffsetDoBCdEnd());
compositeData += mrz.substring(getOffsetDoE(), getOffsetDoECdEnd());
compositeData += mrz.substring(getOffsetOptionalData(), getOffsetOptionalDataCdEnd());
return new String(new byte[] {computeChecksum(compositeData.getBytes(), 0, compositeData.length())});
}
};
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
public static final String Blank = " "; //$NON-NLS-1$
public static final String Filler = "<"; //$NON-NLS-1$ character used to fill spaces
private static final int LENGTH_COUNTRYCODE = 3; // length of the country code
private static final int LENGTH_DOCTYPE = 2; // length of the type field
// static constants
private static final int LENGTH_MRZ = 88; // length of the MRZ record
// of issuing state field
private static final int LENGTH_NAME = 39; // length of the name field
private static final int LENGTH_NO = 9; // length of the document number
// field
private static final int LENGTH_OPTIONALDATA = 14; // length of the optional
// mrz
private static final int OFFSET_CHECKSUM = 87; // offset of checksum in mrz
// data field
private static final int OFFSET_CODE = 2; // offset of the country code in
// in mrz
private static final int OFFSET_DOB = 57; // offset of date of birth in mrz
private static final int OFFSET_DOE = 65; // offset of date of expiry in mrz
private static final int OFFSET_NATIONALITY = 54; // offset of nationality
private static final int OFFSET_NO = 44; // offset of document number in mrz
private static final int OFFSET_ODATA = 72; // offset of optional data in
private static final int OFFSET_SEX = 64; // offset of sex in mrz
// mrz
private static final int OFFSET_SURNAME = 5; // offset of name in mrz
/**
* calculates the checksum as defined in ICAO Doc9303
*
* This method calculates the checksum of the pbuffer as defined in ICAO
* Doc9303. For the calculation the elements pbufer[0] to pbuffer[length]
* are used. The offset has no influence on the elements that are used for
* calculating the checksum. It is used as an offset in the weight function.
*
* @param pbuffer
* buffer to calculate the checksum of
*
* @param offset
* offset used in the weight function
*
* @param length
* length of the buffer that should be used for the checksum
* @return
*/
public static byte computeChecksum(byte[] pbuffer, int offset, int length) {
int[] weight = { 7, 3, 1 };
int csum = 0;
byte ctemp = (byte) 0x00;
for (int i = 0; i < length; i++) {
ctemp = pbuffer[i];
/*
* '<' will be neglected '0' has value 0 (dec) ... '9' has value 9
* (dec) 'A' has value 10 (dec) ... 'Z' has value 35 (dec) the rest
* is 0 (dec)
*/
if ((ctemp >= 'A') && (ctemp <= 'Z')) {
ctemp -= (byte) 0x37;
} else if ((ctemp >= '0') && (ctemp <= '9')) {
ctemp -= (byte) 0x30;
} else {
ctemp = 0;
}
csum += ctemp * weight[(i + offset) % 3];
}
ctemp = (byte) (csum % 10);
ctemp += (byte) 0x30;
return ctemp;
}
/*--------------------------------------------------------------------------------*/
private String countryCode; /* issuing state or organization */
private String dateOfBirth; /* date of birth */
private String dobCd; /* date of birth check digit */
private String dateOfExpiry; /* date of expiry */
private String dateOfExpiryCd; /* date of expiry check digit */
private String docNo; // Document number
private String docNoCd; // Fields needed for the MRZ
private String docType; // Document type
private String givenName; // Given Name of Holder
private String nationality; /* nationality */
private String optionalData; /* optional data */
private String sex; /* sex */
private String surname; // Surname of Holder
/*--------------------------------------------------------------------------------*/
private boolean safetyOn;
private String originalMRZ;
/*--------------------------------------------------------------------------------*/
/**
* Constructs a new MRZ from the input material defined in mrzString.
*
* @param mrzString
* String representation of a MRZ
*/
public Mrz(String mrz, boolean safety) {
DocumentFormat docFormat;
this.safetyOn = safety;
this.originalMRZ = mrz;
docFormat = this.getDocumentFormat();
this.setDocNumber(Mrz.extractDocNo(mrz, docFormat));
this.setDocNumberCd(Mrz.extractDocNoCd(mrz, docFormat));
this.setDateOfBirth(Mrz.extractDoB(mrz, docFormat));
this.setDateOfBirthCd(Mrz.extractDoBCd(mrz, docFormat));
this.setDateOfExpiry(Mrz.extractDoE(mrz, docFormat));
this.setDateOfExpiryCd(Mrz.extractDoECd(mrz, docFormat));
}
public Mrz(String mrz) {
this(mrz, false);
}
/**
* Constructs a new MRZ from the input material byte array.
*
* @param values
* byte array containing byte representation of a MRZ
*/
public Mrz(byte[] values) {
this(new String(values));
}
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
protected abstract DocumentFormat getDocumentFormat();
/*--------------------------------------------------------------------------------*/
@Override
public String toString() {
return this.getOriginalMRZ();
}
/**
* Returns the country code of issuing state.
*
* @return country code
*/
public String getCountryCode() {
return this.countryCode;
}
/**
* Returns date of birth of holder.
*
* @return date of birth of holder
*/
public String getDateOfBirth() {
return this.dateOfBirth;
}
public String getDateOfBirthCd() {
return this.dobCd;
}
/**
* Returns date of expiry.
*
* @return date of expiry
*/
public String getDateOfExpiry() {
return this.dateOfExpiry;
}
public String getDateOfExpiryCd() {
return this.dateOfExpiryCd;
}
/**
* Returns document number.
*
* @return document number
*/
public String getDocumentNumber() {
return this.docNo;
}
public String getDocumentNumberCd() {
return this.docNoCd;
}
/**
* Returns document type.
*
* @return document type
*/
public String getDocumentType() {
return this.docType;
}
// /**
// * Returns given name of holder.
// *
// * @return given name of holder
// */
// public String getGivenName() {
// return givenName;
// }
// /**
// * Return length of value field
// *
// * @return Length in bytes
// */
// public int getLength() {
// return MRZ.LENGTH_MRZ;
// }
// /**
// * calculates the string representation of the MRZ form the variables
// * provided
// *
// * @return string representation of MRZ
// */
// public String getMRZString() {
// String mrz1stLine = "";
// String mrz2ndLine = "";
// String tmpString = "";
//
// // add document type
// tmpString = this.docType;
// while (tmpString.length() < MRZ.LENGTH_DOCTYPE) {
// tmpString += LdsConstants.Filler;
// }
// mrz1stLine += tmpString;
//
// // add issuing state
// tmpString = this.countryCode;
// while (tmpString.length() < MRZ.LENGTH_COUNTRYCODE) {
// tmpString += LdsConstants.Filler;
// }
// mrz1stLine += tmpString;
//
// // add name of holder
// tmpString = this.surname + LdsConstants.Filler + LdsConstants.Filler
// + this.givenName;
// tmpString = tmpString.replaceAll("[\\s-,]+", LdsConstants.Filler); // replace spaces with filler characters
//
// if (tmpString.length() > MRZ.LENGTH_NAME)
// tmpString = tmpString.substring(0, MRZ.LENGTH_NAME);
// while (tmpString.length() < MRZ.LENGTH_NAME) {
// tmpString += LdsConstants.Filler;
// }
// mrz1stLine += tmpString;
//
// // add document number and check digit
// tmpString = this.docNo;
// while (tmpString.length() < MRZ.LENGTH_NO) {
// tmpString += LdsConstants.Filler;
// }
// tmpString += String.valueOf((char) MRZ.computeChecksum(tmpString
// .getBytes(), 0, tmpString.length()));
// mrz2ndLine += tmpString;
//
// // add nationality
// tmpString = this.nationality;
// mrz2ndLine += tmpString;
//
// // add date of birth and check digit
// tmpString = this.dateOfBirth;
// tmpString += String.valueOf((char) MRZ.computeChecksum(tmpString
// .getBytes(), 0, tmpString.length()));
// mrz2ndLine += tmpString;
//
// // add sex
// tmpString = this.sex;
// mrz2ndLine += tmpString;
//
// // add date of expiry and check digit
// tmpString = this.dateOfExpiry;
// tmpString += String.valueOf((char) MRZ.computeChecksum(tmpString
// .getBytes(), 0, tmpString.length()));
// mrz2ndLine += tmpString;
//
// // add optional data and check digit
// tmpString = this.optionalData;
// while (tmpString.length() < MRZ.LENGTH_OPTIONALDATA) {
// tmpString += LdsConstants.Filler;
// }
// tmpString += String.valueOf((char) MRZ.computeChecksum(tmpString
// .getBytes(), 0, tmpString.length()));
// mrz2ndLine += tmpString;
//
// // add checkdigit for 2nd line
// mrz2ndLine += String.valueOf((char) MRZ.computeChecksum(mrz2ndLine
// .getBytes(), 0, mrz2ndLine.length()));
//
// return mrz1stLine + mrz2ndLine;
// }
/**
* Returns nationality of holder.
*
* @return nationality of holder
*/
public String getNationality() {
return this.nationality;
}
// /**
// * Returns optional data.
// *
// * @return optional data
// */
// public String getOptionalData() {
// return optionalData;
// }
/**
* Returns sex of holder.
*
* @return sex of holder
*/
public String getSex() {
return this.sex;
}
// /**
// * Returns surname of holder.
// *
// * @return surname of holder
// */
// public String getSurname() {
// return surname;
// }
/**
* Sets the fields of this object according to the MRZ string given.
*
* @param mrzString
* MRZ String containing the values to bee set
*/
public void parseString(String mrzString) {
try {
/*
* Cookbook MRZ parsing: First, check the length and final checksum
*/
switch (mrzString.length()) {
case 88:
break;
default:
throw new InvalidParameterException(
"MRZ illegally encoded. MRZ has wrong length.");
}
mrzString = mrzString.toUpperCase();
byte[] checksumData = getCompositeCheckDigitData(mrzString);
byte checksum = computeChecksum(checksumData, 0,
checksumData.length);
if (checksum != (byte) mrzString.charAt(OFFSET_CHECKSUM)) {
throw new InvalidParameterException(
"MRZ illegally encoded. Wrong MRZ check digit.");
}
/*
* Get type and country code at predefined offset positions
*/
setDocType(mrzString.substring(0, OFFSET_CODE));
setCountryCode(mrzString.substring(OFFSET_CODE, OFFSET_SURNAME));
/*
* Get name and split at <<, extract given and surname
*/
String name = mrzString.substring(OFFSET_SURNAME, OFFSET_NO);
int i = name.indexOf(Filler + Filler);
setSurname(name.substring(0, i).replaceAll(Filler, Blank));
setGivenName(name.substring(i + 2).replaceAll(Filler, Blank).trim());
/*
* Get the document number and verify check digit
*/
String value = mrzString.substring(OFFSET_NO,
OFFSET_NATIONALITY - 1);
checksum = computeChecksum(value.getBytes(), 0, value.length());
if (checksum != (byte) mrzString.charAt(OFFSET_NATIONALITY - 1)) {
throw new InvalidParameterException(
"MRZ illegally encoded. Wrong passport number check digit.");
}
setDocNumber(value.replaceAll(Filler, ""));
/*
* Get the nationality
*/
setNationality(mrzString.substring(OFFSET_NATIONALITY, OFFSET_DOB)
.replaceAll(Filler, ""));
/*
* Get the DOB and verify check digit
*/
value = mrzString.substring(OFFSET_DOB, OFFSET_SEX - 1);
checksum = computeChecksum(value.getBytes(), 0, value.length());
if (checksum != (byte) mrzString.charAt(OFFSET_SEX - 1)) {
throw new InvalidParameterException(
"MRZ illegally encoded. Wrong DOB check digit.");
}
setDateOfBirth(value);
/*
* get the sex
*/
setSex(mrzString.substring(OFFSET_SEX, OFFSET_DOE));
/*
* Get the DOE and verify check digit
*/
value = mrzString.substring(OFFSET_DOE, OFFSET_ODATA - 1);
checksum = computeChecksum(value.getBytes(), 0, value.length());
if (checksum != (byte) mrzString.charAt(OFFSET_ODATA - 1)) {
throw new InvalidParameterException(
"MRZ illegally encoded. Wrong DOE check digit.");
}
setDateOfExpiry(value);
/*
* Get the optional data and verify check digit
*/
value = mrzString.substring(OFFSET_ODATA, OFFSET_CHECKSUM - 1);
checksum = computeChecksum(value.getBytes(), 0, value.length());
if (checksum != (byte) mrzString.charAt(OFFSET_CHECKSUM - 1)) {
throw new InvalidParameterException(
"MRZ illegally encoded. Wrong optional data check digit.");
}
setOptionalData(value.replaceAll(Filler, ""));
} catch (ArrayIndexOutOfBoundsException e) {
throw new InvalidParameterException(
"MRZ illegally encoded. Incorrect lengths."); //$NON-NLS-1$
} catch (InvalidParameterException e) {
throw new InvalidParameterException(e.getMessage());
}
}
private byte[] getCompositeCheckDigitData(String mrzString) {
if (mrzString.length() == LENGTH_MRZ) {
String cdData = mrzString.substring(OFFSET_NO, OFFSET_NATIONALITY);
cdData += mrzString.substring(OFFSET_DOB, OFFSET_SEX);
cdData += mrzString.substring(OFFSET_DOE, OFFSET_CHECKSUM);
return cdData.getBytes();
}
return null;
}
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/**
* Sets the country code according to param.
*
* @param newCountryCode
* new country code
* @throws InvalidParameterException
*/
public void setCountryCode(String newCountryCode) throws InvalidParameterException {
if (newCountryCode.length() > Mrz.LENGTH_COUNTRYCODE)
throw new InvalidParameterException(
"Length of country code may not exceed "
+ Mrz.LENGTH_COUNTRYCODE + " characters.");
if (!newCountryCode.matches("^[a-zA-Z<]{0,3}$"))
throw new InvalidParameterException(
"Country code must only consist of characters and spaces.");
countryCode = newCountryCode.toUpperCase();
}
/**
* Sets the date of birth according to param.
*
* @param dob
* new date of birth
* @throws InvalidParameterException
*/
public void setDateOfBirth(String dob) throws InvalidParameterException {
if (this.safetyOn && !dob.matches("^\\d{6}$")) {
throw new InvalidParameterException("Date of birth must consist of 6 digits.");
}
this.dateOfBirth = dob;
}
public void setDateOfBirthCd(String dobCd) {
this.dobCd = dobCd;
}
/**
* Sets the date of expiry according to param.
*
* @param doe
* new date of expiry
* @throws InvalidParameterException
*/
public void setDateOfExpiry(String doe) throws InvalidParameterException {
if (this.safetyOn && !doe.matches("^\\d{6}$")) {
throw new InvalidParameterException("Date of expiry must consist of 6 digits.");
}
dateOfExpiry = doe;
}
public void setDateOfExpiryCd(String doeCd) {
this.dateOfExpiryCd = doeCd;
}
/**
* Sets the document number according to param.
*
* @param newDocNumber
* new document number
* @throws InvalidParameterException
*/
public void setDocNumber(String newDocNumber) {
if (!newDocNumber.matches("^[a-zA-Z0-9 ]+$")) {
throw new InvalidParameterException("Document number must only consist of characters, numbers and spaces.");
}
docNo = newDocNumber.toUpperCase();
}
public void setDocNumberCd(String docNumberCd) {
this.docNoCd = docNumberCd;
}
/**
* Sets the document type according to param.
*
* @param newDocType
* new document type
* @throws InvalidParameterException
*/
public void setDocType(String newDocType) {
if (newDocType.length() > Mrz.LENGTH_DOCTYPE)
throw new InvalidParameterException(
"Length of document type may not exceed "
+ Mrz.LENGTH_DOCTYPE + " characters.");
if (!newDocType.matches("^[a-zA-Z< ]{0,2}$"))
throw new InvalidParameterException(
"Document type must only consist of characters and spaces.");
docType = newDocType.toUpperCase();
}
/**
* Sets the given name oh holder.
*
* @param newGivenName
* new given name oh holder
* @throws InvalidParameterException
*/
public void setGivenName(String newGivenName)
throws InvalidParameterException {
if (!newGivenName.matches("^[a-zA-Z\\s,\']*$"))
throw new InvalidParameterException(
"Given Name must consist of characters a-z, A-Z, space, comma and apostroph only.");
givenName = newGivenName.replaceAll("\\s+", " ").toUpperCase();
}
/**
* Sets the nationality of holder.
*
* @param newNationality
* new nationality of holder
* @throws InvalidParameterException
*/
public void setNationality(String newNationality) {
if (newNationality.length() > Mrz.LENGTH_COUNTRYCODE)
throw new InvalidParameterException(
"Length of country code may not exceed "
+ Mrz.LENGTH_COUNTRYCODE + " characters.");
if (!newNationality.matches("^[a-zA-Z]{0,3}$"))
throw new InvalidParameterException(
"Country code must only consist of characters and spaces.");
nationality = newNationality.toUpperCase();
}
/**
* Sets the optional data.
*
* @param newOptionalData
* new optional data
* @throws InvalidParameterException
*/
public void setOptionalData(String newOptionalData) {
if (!newOptionalData.matches("^[a-zA-Z0-9 ]+$"))
throw new InvalidParameterException(
"Country code must only consist of characters, numbers and spaces.");
optionalData = newOptionalData.toUpperCase();
}
/**
* Set sex of holder.
*
* @param newSex
* new sex of holder
*/
public void setSex(String newSex) {
if (!newSex.matches("^[FM<]$"))
throw new InvalidParameterException("Sex must be either F, M or <");
sex = newSex;
}
/**
* Set surname of holder.
*
* @param newSurname
* new surname of holder
*/
public void setSurname(String newSurname) {
if (!newSurname.matches("^[a-zA-Z\\s,\']+$"))
throw new InvalidParameterException(
"Given Name mus only consist of characters a-z, A-Z, space, comma and apostroph.");
surname = newSurname.replaceAll("\\s+", " ").toUpperCase();
}
/**
* @return the safetyOn
*/
public boolean isSafetyOn() {
return safetyOn;
}
/**
* @param safetyOn the safetyOn to set
*/
public void setSafetyOn(boolean safetyOn) {
this.safetyOn = safetyOn;
}
/**
* @return the originalMRZ
*/
public String getOriginalMRZ() {
return originalMRZ;
}
/**
* @param originalMRZ the originalMRZ to set
*/
public void setOriginalMRZ(String originalMRZ) {
this.originalMRZ = originalMRZ;
}
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------------*/
private static DocumentFormat getDocumentFormat(String mrz) {
switch (mrz.length()) {
case 90:
return td1;
case 76:
return td2;
case 88:
return mrp;
default:
throw new InvalidParameterException(
"MRZ illegally encoded. MRZ has wrong length.");
}
}
/*--------------------------------------------------------------------------------*/
public static String extractDocType(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetDocType(), docFormat.getOffsetDocTypeEnd());
}
public static String extractIssuingState(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetIssuingState(), docFormat.getOffsetIssuingStateEnd());
}
public static String extractName(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetName(), docFormat.getOffsetNameEnd());
}
public static String extractDocNo(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetDocNo(), docFormat.getOffsetDocNoEnd());
}
public static String extractDocNoCd(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetDocNoCd(), docFormat.getOffsetDocNoCdEnd());
}
public static String extractNationality(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetNationality(), docFormat.getOffsetNationalityEnd());
}
public static String extractDoB(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetDoB(), docFormat.getOffsetDoBEnd());
}
public static String extractDoBCd(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetDoBCd(), docFormat.getOffsetDoBCdEnd());
}
public static String extractSex(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetSex(), docFormat.getOffsetSexEnd());
}
public static String extractDoE(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetDoE(), docFormat.getOffsetDoEEnd());
}
public static String extractDoECd(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetDoECd(), docFormat.getOffsetDoECdEnd());
}
public static String extractOptionalData(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetOptionalData(), docFormat.getOffsetOptionalDataEnd());
}
public static String extractOptionalDataCd(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetOptionalDataCd(), docFormat.getOffsetOptionalDataCdEnd());
}
public static String extractCompositeCd(String mrz, DocumentFormat docFormat){
return mrz.substring(docFormat.getOffsetCompositeCd(), docFormat.getOffsetCompositeCdEnd());
}
public static String calculateCompositeCd(String mrz, DocumentFormat docFormat){
return docFormat.calculateCompositeCd(mrz);
}
}