/*
* $Id:$
*
* Copyright (C) 2002 Idega hf. All Rights Reserved.
*
* This software is the proprietary information of Idega hf.
* Use is subject to license terms.
*
*/
package se.idega.util;
import java.sql.Date;
import com.idega.util.IWTimestamp;
/**
* A class containing some common functions for working with
* PersonalIds - Swedish social security numbers (Personnummer)
*
* @author <a href="palli@idega.is">Pall Helgason</a>
* @version 1.0
*/
public class PIDChecker {
private static PIDChecker _instance = null;
/**
* Does very little today.....
*/
private PIDChecker() {
}
/**
* A method to get an instance of this class.
*
* @return An instance of the SSNChecker class.
*/
public static PIDChecker getInstance() {
if (_instance == null)
_instance = new PIDChecker();
return _instance;
}
/**
* A method to check if a Swedish social security number is valid.
*
* @param ssn A string representation of the ssn. Can be of the form
* [XX]XXXXXX[-]XXXX
* @return true if the ssn is valid, false otherwise.
*/
public boolean isValid(String personalID) {
return isValid(personalID, false);
}
/**
* A method to check if a Swedish social security number is valid.
*
* @param ssn A string representation of the ssn. Can be of the form
* [XX]XXXXXX[-]XXXX
* @return true if the ssn is valid, false otherwise.
*/
public boolean isValid(String personalID, boolean allowTemporary) {
personalID = trimSSN(personalID);
if (personalID.length() != 10)
return false;
if (allowTemporary && personalID.indexOf("TF") != -1){
return true;
}
else {
int values[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int sum = 0;
for (int i = 0; i < 10; i++) {
values[i] = personalID.charAt(i) - '0';
if (i % 2 == 0) {
values[i] *= 2;
if (values[i] > 9)
values[i] -= 9;
}
sum += values[i];
}
return (sum % 10 == 0);
}
}
/**
* A method that removes all minus signs from the ssn, and also removes the
* first two digits if the ssn length equals 12.
*
* @return A trimmed down version of the ssn.
*/
private String trimSSN(String personalID) {
String localSSN = trim(personalID);
if (localSSN.length() == 12)
personalID = localSSN.substring(2);
else
personalID = localSSN.toString();
return personalID;
}
/**
* A method that removes all minus signs from the ssn.
*
* @return A trimmed down version of the ssn.
*/
public String trim(String personalID) {
StringBuffer localSSN = new StringBuffer(personalID);
int i = personalID.indexOf('-');
if (i != -1) {
localSSN.deleteCharAt(i);
}
return localSSN.toString();
}
/**
* A method that checks if the owner of a ssn is female.
*
* @param ssn A string representation of the ssn. Can be of the form
* [XX]XXXXXX[-]XXXX
* @return true if the owner is female, false otherwise. Also returns false if the ssn is invalid.
*/
public boolean isFemale(String personalID) {
personalID = trimSSN(personalID);
if (personalID.length() != 10)
return false;
int sex = personalID.charAt(8) - '0';
return (sex % 2 == 0);
}
/**
* A method that checks if the owner of a ssn is male.
*
* @param ssn A string representation of the ssn. Can be of the form
* [XX]XXXXXX[-]XXXX
* @return true if the owner is male, false otherwise. Also returns false if the ssn is invalid.
*/
public boolean isMale(String personalID) {
return !isFemale(personalID);
}
/**
* The main method to run methods of this class.
* If no parameters are given it returns a random generated PID.
* If a parameter is given it tries to validate it as a personalId if the length is larger than 4.
* If the length of the parameter is 2 or 4 it accepts it as a year and generates a random PID for that year.
*/
public static void main(String blabla[]) {
PIDChecker checker = PIDChecker.getInstance();
if (blabla.length > 0) {
String value = blabla[0];
if (value.length() == 4 || value.length() == 2) {
int year = Integer.parseInt(value);
System.out.println("Generating a random PersonalID born in year: " + year);
String pid = checker.getRandomValidPID(Integer.toString(year));
System.out.println("Random valid PID : " + pid);
} else {
System.out.println("Checking ssn = " + value);
if (checker.isValid(blabla[0])) {
System.out.println(blabla[0] + " is valid");
if (checker.isFemale(blabla[0]))
System.out.println(blabla[0] + " belongs to a female");
else
System.out.println(blabla[0] + " belongs to a male");
} else
System.out.println(blabla[0] + " is not valid");
}
} else {
System.out.println("Generating a random PersonalID:");
String pid = checker.getRandomValidPID();
System.out.println("Random valid PID : " + pid);
}
}
/**
* A method to convert a personal ID string to <code>Date</code>.
* @param personalID The personal ID to convert to date.
* @return Date Returns null if personal ID is not valid.
*/
public Date getDateFromPersonalID(String personalID) {
if (isValid(personalID, true)) {
personalID = trim(personalID);
int year = 0;
int month = 0;
int day = 0;
IWTimestamp stampNow = new IWTimestamp();
if (personalID.length() == 10) {
year = Integer.parseInt(personalID.substring(0, 2)) + 1900;
if (stampNow.getYear() - year > 99) {
year = year + 100;
}
month = Integer.parseInt(personalID.substring(2, 4));
day = Integer.parseInt(personalID.substring(4, 6));
} else if (personalID.length() == 12) {
year = Integer.parseInt(personalID.substring(0, 4));
month = Integer.parseInt(personalID.substring(4, 6));
day = Integer.parseInt(personalID.substring(6, 8));
}
IWTimestamp stamp = new IWTimestamp(day, month, year);
return stamp.getDate();
}
return null;
}
/**
* Get a random valid PersonalID as string representation of in the form XXXXXX-XXXX
*/
private String getRandomValidPID() {
String randomYearString = getRandomIntDecimalString() + getRandomIntDecimalString();
return getRandomValidPID(randomYearString);
}
/**
* Get a random valid PersonalID as string representation of in the form XXXXXX-XXXX, with the year provided by yearString (either 2 or 4 in length)
*/
public String getRandomValidPID(String yearString) {
String tryString = "";
while (true) {
String shortYearString = yearString;
if(yearString.length()== 4){
shortYearString = yearString.substring(2);
}
tryString = shortYearString + getRandomMonthString() + getRandomMonthDayString() + "-" + getRandomIntDecimalString() + getRandomIntDecimalString() + getRandomIntDecimalString() + getRandomIntDecimalString();
//System.out.println("Trying: "+tryString);
if (isValid(tryString)) {
return tryString;
}
}
//throw new RuntimeException("No valid PID found");
}
/**
* Gets a random int on the range from 0-9 as a String
* @return
*/
public String getRandomIntDecimalString() {
return Integer.toString(getRandomIntDecimal());
}
/**
* Gets a random int on the range from 0-9
* @return
*/
public int getRandomIntDecimal() {
int theReturn = (int)Math.round(10 * Math.random() - 1);
while (theReturn > 9 || theReturn < 0) {
theReturn = (int)Math.round(10 * Math.random() - 1);
}
return theReturn;
}
/**
* Gets a random int on the range from 1-12 as a double digit String (0 in front i number is lower than 10)
* @return
*/
public String getRandomMonthString() {
int month = getRandomMonth();
if (month < 10) {
return "0" + month;
} else {
return Integer.toString(month);
}
}
/**
* Gets a random int on the range from 1-12
* @return
*/
public int getRandomMonth() {
int theReturn = (int)Math.round(12 * Math.random()) + 1;
while (theReturn > 12) {
theReturn = (int)Math.round(12 * Math.random()) + 1;
}
return theReturn;
}
/**
* Gets a random int on the range from 1-28 as a double digit String (0 in front i number is lower than 10)
* @return
*/
public String getRandomMonthDayString() {
int monthday = getRandomMonthDay();
if (monthday < 10) {
return "0" + monthday;
} else {
return Integer.toString(monthday);
}
}
/**
* Gets a random int on the range from 1-28
* @return
*/
public int getRandomMonthDay() {
int theReturn = (int)Math.round(28 * Math.random()) + 1;
while (theReturn > 28) {
theReturn = (int)Math.round(28 * Math.random()) + 1;
}
return theReturn;
}
}