/*+--------------------------------------------------------------------------+* *| |* *| B A R C O D E C L A S S |* *| |* *| ITSE2417 Introduction to Java: Project 2 |* *| BarCodes |* *| Due 03/20/01 |* *| |* *| Jim Connelley |* *| |* *| This BarCode class encapsulates all the complexity associated with |* *| decoding and encoding a US postal Barcode. |* *| |* *| For faster sorting of letters, the United States Postal Service |* *| encourages companies that send large volumes of mail to use a bar |* *| code denoting the zip code. This project is a program that takes |* *| a five-digit zip code and prints the bar code following USPS standards |* *| This program can also take a ASCII bar code or a Binary bar code |* *| |* *| The ASCII encoding scheme for a five-digit zip code is: |* *| '|' represents a full bar (binary 1) |* *| ':' represents a half bar (binary 0) |* *| |* *| ZIP code 95014 will be represented as: |* *| |* *| 9 5 0 1 4 1 |* *| | |:|:: :|:|: ||::: :::|| :|::| :::|| | |* *| frame bar digit1 digit2 digit3 digit4 digit5 check frame bar |* *| |* *| Each digit is repsented by a sequence of 5 bars |* *| There are 5 digits in the zip code + 1 check digit |* *| That gives 5 * 6 = 30 bars representing digits. |* *| The front and back is bracketed by a frame bar. |* *| That gives us a total of 32 characters (or bars) |* *| The check digit is computed as follows: |* *| 1: Add up all the digits |* *| 2: chose the check digit to make the sum the next multiple of 10 |* *| |* *| |* *| The following table represents the digital encoding: |* *| |* *| digit | c o d e |* *| +--+----+----+----+----+----+ |* *| |1 | 0 | 0 | 0 | 1 | 1 | |* *| +--+----+----+----+----+----+ |* *| |2 | 0 | 0 | 1 | 0 | 1 | |* *| +--+----+----+----+----+----+ |* *| |3 | 0 | 0 | 1 | 1 | 0 | |* *| +--+----+----+----+----+----+ |* *| |4 | 0 | 1 | 0 | 0 | 1 | |* *| +--+----+----+----+----+----+ |* *| |5 | 0 | 1 | 0 | 1 | 0 | |* *| +--+----+----+----+----+----+ |* *| |6 | 0 | 1 | 1 | 0 | 0 | |* *| +--+----+----+----+----+----+ |* *| |7 | 1 | 0 | 0 | 0 | 1 | |* *| +--+----+----+----+----+----+ |* *| |8 | 1 | 0 | 0 | 1 | 0 | |* *| +--+----+----+----+----+----+ |* *| |9 | 1 | 0 | 1 | 0 | 0 | |* *| +--+----+----+----+----+----+ |* *| |0 | 1 | 1 | 0 | 0 | 0 | |* *| +--+----+----+----+----+----+ |* *| |* *+--------------------------------------------------------------------------+* */ import java.awt.*; import java.lang.*; /** * */ public class BarCode { //Constants final String [] ASCII = {":::||","::|:|","::||:",":|::|",":|:|:", ":||::","|:::|","|::|:","|:|::","||:::"}; final String [] BINARY = {"11000","00011","00101","00110","01001", "01010","01100","10001","10010","10100"}; final String ERR_RANGE = "Zipcode must be > 0 and < 100000: "; final String ERR_L5_L32 = "String length must be 5 or 32: "; final String ERR_NUMERIC = "String is not numeric: "; final String ERR_FOUND = "Error Found: "; final String ERR_START = "No valid starting character found: "; final String ERR_TERM = "Invalid terminating character: '"; final String ERR_DECODE = "Unable to decode "; final String ERR_NONE = "No errors found"; //Fields private int myZipCode; //five digit zip code private String myASCIICode; //32 ASCII symbol barcode private String myBinaryCode; //32 binary (1's and 0's) symbol bar code private String myErrorMsg; //error message private boolean myErrorInd; //error indicator //Constructor accepting an integer public BarCode(int someInt){ if(someInt > 99999 || someInt <= 0) setErrorTrue(ERR_RANGE + someInt); else encode(someInt); } //Constructor accepting a string public BarCode(String someStr){ if(someStr.length() != 5) if(someStr.length() != 32) // not 5 or 32 bytes setErrorTrue(ERR_L5_L32 + someStr); else // it may be a valid 32 character barCode isThereAnError(someStr); else // it may be a 5 character integer string { int mult = 10000; // each digit value times 10 int someInt = 0; char someChar; for (int x = 0 ; x < 5 ; x++){ someChar = someStr.charAt(x); if(someChar >= '0' && someChar <= '9') someInt += mult * (someChar - '0'); else setErrorTrue(ERR_NUMERIC + someStr); mult /= 10; // divide by 10 } if(getErrorInd() == false) // any error so far? encode(someInt); // handle as an integer } } //Accessor returns the Zip Code public int getZipCode(){ return myZipCode; } //Accessor returns the ASCII Bar Code public String getASCII(){ return myASCIICode; } //Accessor returns the Binary Bar Code public String getBinary(){ return myBinaryCode; } //Accessor returns an error message public String getErrorMsg(){ return myErrorMsg; } //Accessor returns an error indicator public boolean getErrorInd(){ return myErrorInd; } //Accessor returns string of BarCode public String toString(){ if(getErrorInd() == false) return "zipcode=" + getZipCode() + ";ASCII=" + getASCII() + ";Binary=" + getBinary(); else return ERR_FOUND + getErrorMsg(); } /*-----------------------------------------------------------------------* * Private helper functions * *-----------------------------------------------------------------------* */ /*-----------------------------------------------------------------------* * * * This function converts the input integer into a 32 character * * ASCIIstring and also a 32 character Binary string * * * *-----------------------------------------------------------------------* */ private void encode(int someInteger){ myZipCode = someInteger; StringBuffer buf = new StringBuffer("" + myZipCode); //The following loop adjust the passed integer to //a string with leading zeros as needed. while(buf.length() < 5) buf.insert(0,'0'); // insert leading zero int [] digit = new int [5]; int temptot = 0; StringBuffer tempASCIICode = new StringBuffer("|"); StringBuffer tempBinaryCode = new StringBuffer("1"); //The following loop builds the barcode representation of //the 5 digits in the zip code, both ASCII and Binary for(int x = 0 ; x < 5 ; x++){ digit[x] = buf.charAt(x) - '0'; tempASCIICode.append(int2ASCII(digit[x])); tempBinaryCode.append(int2Binary(digit[x])); temptot += digit[x]; } int check = (10 - (temptot % 10))%10; // complete the ASCII values tempASCIICode.append(int2ASCII(check)); tempASCIICode.append("|"); // complete the binary values tempBinaryCode.append(int2Binary(check)); tempBinaryCode.append("1"); // We're on a roll setErrorFalse(tempASCIICode.toString(),tempBinaryCode.toString()); } /*-----------------------------------------------------------------------* * * * isThereAnError checks the validity of characters passed to the * * String constructor and decodes the string into a zipcode * * returns true if anything fails validity check * * * *-----------------------------------------------------------------------* */ private boolean isThereAnError(String someString){ char ch = someString.charAt(0); if('|' == ch) // is it ASCII? return isThereAnyError(someString,"ASCII",'|',':'); else if('1' == ch) // is it Binary? return isThereAnyError(someString,"Binary",'1','0'); else{ // No valid starting character ('1' or '|') return setErrorTrue(ERR_START + someString); } } /*-----------------------------------------------------------------------* * * * isThereAnyError checks '0' and '1' characters passed to the * * String constructor and decodes the string into a zipcode * * returns true if anything fails validity check * * * *-----------------------------------------------------------------------* */ private boolean isThereAnyError(String someString,String stringType,char one,char zero){ StringBuffer tempASCIICode = new StringBuffer(""); StringBuffer tempBinaryCode = new StringBuffer(""); for(int x = 0;x < 32;x++){ char ch = someString.charAt(x); if(zero == ch){ tempASCIICode.append(':'); tempBinaryCode.append('0'); } else if(one == ch){ tempASCIICode.append('|'); tempBinaryCode.append('1'); } else{ // not zero or one return setErrorTrue("Invalid " + stringType + " Char offset: " + x + " " + someString); } } if(someString.charAt(31) != one){ // Check Frameing char return setErrorTrue(ERR_TERM + someString.charAt(31) + "'" + " " + someString); } myZipCode = decode(tempBinaryCode.toString()); if(myZipCode == -1) // Didn't decode correctly? return setErrorTrue(ERR_DECODE + stringType + " String: " + someString); else return setErrorFalse(tempASCIICode.toString(),tempBinaryCode.toString()); } /*-----------------------------------------------------------------------* * * * This function is called whenever an error is determined. * * The error message is passed as a parameter and it is * * used to instantiate String object for myErrorMsg * * myASCIICode and myBinaryCode are set to null. * * myZipCode is set to -1 * * * *-----------------------------------------------------------------------* */ private boolean setErrorTrue(String errorMsg){ myErrorMsg = new String(errorMsg); myErrorInd = true; myASCIICode = new String(""); myBinaryCode = new String(""); myZipCode = -1; return true; } /*-----------------------------------------------------------------------* * * * The error message is set to null * * The error indicator is set to false * * * *-----------------------------------------------------------------------* */ private boolean setErrorFalse(String ASCII,String Binary){ myASCIICode = new String(ASCII); myBinaryCode = new String(Binary); myErrorMsg = new String(ERR_NONE); myErrorInd = false; return false; } /*-----------------------------------------------------------------------* * * * decode breaks the passed string into 5 digits plus * * a check digit and decodes the string into a zipcode * * returns -1 if any portion fails validity check * * * *-----------------------------------------------------------------------* */ private int decode(String binCode){ int [] digit = new int[5]; int check = Binary2Int(binCode.substring(26,31)); int retval = 0; // initial return value int multiplier = 10000; // each digit value times 10 for (int x = 0 ; x < digit.length ; x++){ digit[x] = Binary2Int(binCode.substring((x*5)+1,(x*5)+6)); if((digit[x] == -1)) // Validity check return -1; // failed check += digit[x]; retval += digit[x] * multiplier; multiplier /= 10; } if(check%10 != 0) return -1; // check digit does not add up else return retval; } /*-----------------------------------------------------------------------* * * * Binary2Int compares a passed value against any one of * * ten possible values. returns -1 if the passed string * * is not one of the ten possible values * * * *-----------------------------------------------------------------------* */ private int Binary2Int(String binCode){ for(int x = 0 ; x < BINARY.length ; x++) if(binCode.compareTo(BINARY[x]) == 0) return x; return -1; } /*-----------------------------------------------------------------------* * * * Int2Binary compares a passed integer against any one of * * ten possible values. returns "XXXXX" if the passed integer * * is not a single digit otherwise it returns one of the 10 * * possible 5 character strings * * * *-----------------------------------------------------------------------* */ private String int2Binary(int digit){ if (digit < 10) return BINARY[digit]; else return "XXXXX"; } /*-----------------------------------------------------------------------* * * * Int2ASCII compares a passed integer against any one of * * ten possible values. returns "XXXXX" if the passed * * integer is not a single digit otherwise it returns one * * of the 10 possible 5 character strings * * * *-----------------------------------------------------------------------* */ private String int2ASCII(int digit){ if (digit < 10) return ASCII[digit]; else return "XXXXX"; } /*-----------------------------------------------------------------------* * * * DrawBarCode Will Draw a BarCode graphically in the Passed Graphics * * context. * * * *-----------------------------------------------------------------------* */ public void DrawBarCode(Graphics g){ //create a temporary graphics context to be polite int x = 200; int y = 300; int fullHeight = 30; int halfHeight = 15; int barWidth = 5; int barGap = 10; Graphics graphicsBarCode = g.create(); graphicsBarCode.setColor(Color.yellow); graphicsBarCode.fillRect(x,y,320,30); graphicsBarCode.setColor(Color.black); if(getErrorInd() == false){ for(int j = 0 ; j < 32 ; j++){ char ch = myBinaryCode.charAt(j); if(ch == '1') graphicsBarCode.fillRect(x,y,barWidth,fullHeight); else graphicsBarCode.fillRect(x,y+halfHeight,barWidth,halfHeight); x += barGap; } } } }