/**
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
* License for the specific language governing rights and limitations under
* the License.
*
* The Original Code is OpenELIS code.
*
* Copyright (C) CIRG, University of Washington, Seattle WA. All Rights Reserved.
*
*/
package us.mn.state.health.lims.common.provider.validation;
import us.mn.state.health.lims.common.provider.validation.IAccessionNumberValidator.ValidationResults;
import us.mn.state.health.lims.common.util.ConfigurationProperties;
import us.mn.state.health.lims.common.util.ConfigurationProperties.Property;
import us.mn.state.health.lims.common.util.DateUtil;
import us.mn.state.health.lims.common.util.StringUtil;
import us.mn.state.health.lims.sample.dao.SampleDAO;
import us.mn.state.health.lims.sample.daoimpl.SampleDAOImpl;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.Set;
public abstract class BaseSiteYearAccessionValidator {
protected static final String INCREMENT_STARTING_VALUE = "000001";
protected static final int UPPER_INC_RANGE = 999999;
protected static final int SITE_START = 0;
protected int SITE_END = getSiteEndIndex();
protected int YEAR_START = getYearStartIndex();
protected int YEAR_END = getYearEndIndex();
protected int INCREMENT_START = getIncrementStartIndex();
protected int INCREMENT_END = getMaxAccessionLength();
protected int LENGTH = getMaxAccessionLength();
protected static final boolean NEED_PROGRAM_CODE = false;
private static Set<String> REQUESTED_NUMBERS = new HashSet<String>();
public boolean needProgramCode() {
return NEED_PROGRAM_CODE;
}
// input parameter is not used in this case
public String createFirstAccessionNumber(String nullPrefix) {
return getPrefix() + DateUtil.getTwoDigitYear() + INCREMENT_STARTING_VALUE;
}
public String getInvalidMessage(ValidationResults results) {
String suggestedAccessionNumber = getNextAvailableAccessionNumber(null);
return StringUtil.getMessageForKey("sample.entry.invalid.accession.number.suggestion") + " " + suggestedAccessionNumber;
}
// input parameter is not used in this case
public String getNextAvailableAccessionNumber(String nullPrefix) {
String nextAccessionNumber;
SampleDAO sampleDAO = new SampleDAOImpl();
String curLargestAccessionNumber = sampleDAO.getLargestAccessionNumberMatchingPattern(ConfigurationProperties.getInstance().getPropertyValue(Property.ACCESSION_NUMBER_PREFIX),
getMaxAccessionLength());
if (curLargestAccessionNumber == null) {
if( REQUESTED_NUMBERS.isEmpty()){
nextAccessionNumber = createFirstAccessionNumber(null);
}else{
nextAccessionNumber = REQUESTED_NUMBERS.iterator().next();
}
} else {
nextAccessionNumber = incrementAccessionNumber(curLargestAccessionNumber);
}
while( REQUESTED_NUMBERS.contains(nextAccessionNumber) ){
nextAccessionNumber = incrementAccessionNumber(nextAccessionNumber);
}
REQUESTED_NUMBERS.add(nextAccessionNumber);
return nextAccessionNumber;
}
public String incrementAccessionNumber(String currentHighAccessionNumber) throws IllegalArgumentException {
// if the year differs then start the sequence again. If not then
// increment but check for overflow into year
int year = new GregorianCalendar().get(Calendar.YEAR) - 2000;
try {
if (year != Integer.parseInt(currentHighAccessionNumber.substring(YEAR_START, YEAR_END))) {
return createFirstAccessionNumber(null);
}
} catch (NumberFormatException nfe) {
return createFirstAccessionNumber(null);
}
int increment = Integer.parseInt(currentHighAccessionNumber.substring(INCREMENT_START));
String incrementAsString;
if (increment < UPPER_INC_RANGE) {
increment++;
incrementAsString = String.format("%06d", increment);
} else {
throw new IllegalArgumentException("AccessionNumber has no next value");
}
return currentHighAccessionNumber.substring(SITE_START, YEAR_END) + incrementAsString;
}
// recordType parameter is not used in this case
public boolean accessionNumberIsUsed(String accessionNumber, String recordType) {
SampleDAO SampleDAO = new SampleDAOImpl();
return SampleDAO.getSampleByAccessionNumber(accessionNumber) != null;
}
public ValidationResults checkAccessionNumberValidity(String accessionNumber, String recordType, String isRequired,
String projectFormName) {
ValidationResults results = validFormat(accessionNumber, true);
//TODO refactor accessionNumberIsUsed into two methods so the null isn't needed. (Its only used for program accession number)
if (results == ValidationResults.SUCCESS && accessionNumberIsUsed(accessionNumber, null)) {
results = ValidationResults.USED_FAIL;
}
return results;
}
public ValidationResults validFormat(String accessionNumber, boolean checkDate) {
if (accessionNumber.length() != LENGTH) {
return ValidationResults.LENGTH_FAIL;
}
if (!accessionNumber.substring(SITE_START, SITE_END).equals( getPrefix())) {
return ValidationResults.SITE_FAIL;
}
if (checkDate) {
int year = new GregorianCalendar().get(Calendar.YEAR);
try {
if ((year - 2000) != Integer.parseInt(accessionNumber.substring(YEAR_START, YEAR_END))) {
return ValidationResults.YEAR_FAIL;
}
} catch (NumberFormatException nfe) {
return ValidationResults.YEAR_FAIL;
}
}else{
try { //quick and dirty to make sure they are digits
Integer.parseInt(accessionNumber.substring(YEAR_START, YEAR_END));
} catch (NumberFormatException nfe) {
return ValidationResults.YEAR_FAIL;
}
}
try {
Integer.parseInt(accessionNumber.substring(INCREMENT_START));
} catch (NumberFormatException e) {
return ValidationResults.FORMAT_FAIL;
}
return ValidationResults.SUCCESS;
}
public String getInvalidFormatMessage( ValidationResults results ){
return StringUtil.getMessageForKey( "sample.entry.invalid.accession.number.format.corrected", getFormatPattern(), getFormatExample() );
}
private String getFormatPattern(){
StringBuilder format = new StringBuilder( getPrefix() );
format.append( StringUtil.getMessageForKey( "date.two.digit.year" ) );
for( int i = 0; i < getChangeableLength(); i++){
format.append( "#" );
}
return format.toString();
}
private String getFormatExample(){
StringBuilder format = new StringBuilder( getPrefix() );
format.append( DateUtil.getTwoDigitYear() );
for( int i = 0; i < getChangeableLength() - 1; i++){
format.append( "0" );
}
format.append( "1" );
return format.toString();
}
protected abstract String getPrefix();
protected abstract int getIncrementStartIndex();
protected abstract int getYearEndIndex();
protected abstract int getYearStartIndex();
protected abstract int getSiteEndIndex();
protected abstract int getMaxAccessionLength();
protected abstract int getChangeableLength();
}