org.krysalis.barcode4j.impl.postnet.POSTNETLogicImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of barcode4j-fop-ext-0.20.5-complete Show documentation
Show all versions of barcode4j-fop-ext-0.20.5-complete Show documentation
Barcode4J is a flexible generator for barcodes written in Java inclusive
extensions to support Apache FOP 0.20.5.
The newest version!
/*
* Copyright 2003,2004 Jeremias Maerki.
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.krysalis.barcode4j.impl.postnet;
import org.krysalis.barcode4j.BarGroup;
import org.krysalis.barcode4j.ChecksumMode;
import org.krysalis.barcode4j.ClassicBarcodeLogicHandler;
/**
* Implements the United States Postal Service Postnet barcode.
*
* @author Chris Dolphy
* @version $Id: POSTNETLogicImpl.java,v 1.3 2006/11/07 16:42:17 jmaerki Exp $
*/
public class POSTNETLogicImpl {
private static final byte[][] CHARSET =
{{2, 2, 1, 1, 1}, //0
{1, 1, 1, 2, 2}, //1
{1, 1, 2, 1, 2}, //2
{1, 1, 2, 2, 1}, //3
{1, 2, 1, 1, 2}, //4
{1, 2, 1, 2, 1}, //5
{1, 2, 2, 1, 1}, //6
{2, 1, 1, 1, 2}, //7
{2, 1, 1, 2, 1}, //8
{2, 1, 2, 1, 1}}; //9
private static final char DASH = '-';
private ChecksumMode checksumMode = ChecksumMode.CP_AUTO;
private boolean displayChecksum = false;
/**
* Main constructor
* @param mode checksum mode
* @param displayChecksum Controls whether to display checksum
* in the human-readable message
*/
public POSTNETLogicImpl(ChecksumMode mode, boolean displayChecksum) {
this.checksumMode = mode;
this.displayChecksum = displayChecksum;
}
/**
* Returns the currently active checksum mode.
* @return the checksum mode
*/
public ChecksumMode getChecksumMode() {
return this.checksumMode;
}
/**
* Calculates the checksum for a message to be encoded as an
* POSTNET barcode.
* @param msg message to calculate the check digit for
* @return char the check digit
*/
public static char calcChecksum(String msg) {
int tmp = 0;
for (int i = 0; i < msg.length(); i++) {
if (isIgnoredChar(msg.charAt(i))) {
continue;
}
tmp += Character.digit(msg.charAt(i), 10);
if (tmp > 9) {
tmp -= 10;
}
}
return Character.forDigit((10 - tmp) % 10, 10);
}
/**
* Verifies the checksum for a message.
* @param msg message (check digit included)
* @return boolean True, if the checksum is correct
*/
public static boolean validateChecksum(String msg) {
char actual = msg.charAt(msg.length() - 1);
char expected = calcChecksum(msg.substring(0, msg.length() - 1));
return (actual == expected);
}
private static boolean isValidChar(char ch) {
return Character.isDigit(ch) || isIgnoredChar(ch);
}
/**
* Checks if a character is an ignored character (such as a '-' (dash)).
* @param c character to check
* @return True if the character is ignored
*/
public static boolean isIgnoredChar(char c) {
return c == DASH;
}
/**
* Removes ignored character from a valid POSTNET message.
* @param msg valid POSTNET message
* @return the message but without ignored characters
*/
public static String removeIgnoredCharacters(final String msg) {
StringBuffer sb = new StringBuffer(msg.length());
for (int i = 0; i < msg.length(); i++) {
final char ch = msg.charAt(i);
if (!isValidChar(ch)) {
throw new IllegalArgumentException("Invalid character: " + ch);
}
if (!isIgnoredChar(ch)) {
sb.append(ch);
}
}
return sb.toString();
}
private int heightAt(char ch, int index) {
int chidx = Character.digit(ch, 10);
if (chidx >= 0) {
int height = CHARSET[chidx][index];
return height;
} else {
throw new IllegalArgumentException("Invalid character: " + ch);
}
}
/**
* Encodes a single character.
* @param logic the logic handler to receive generated events
* @param c the character to encode
*/
protected void encodeChar(ClassicBarcodeLogicHandler logic, char c) {
if (isIgnoredChar(c)) {
return; // allow dash, but don't encode
}
logic.startBarGroup(BarGroup.MSG_CHARACTER, new Character(c).toString());
for (byte i = 0; i < 5; i++) {
int height = heightAt(c, i);
logic.addBar(true, height);
addIntercharacterGap(logic);
}
logic.endBarGroup();
}
private void addIntercharacterGap(ClassicBarcodeLogicHandler logic) {
logic.addBar(false, -1); //-1 is special
}
private String handleChecksum(StringBuffer sb) {
if (getChecksumMode() == ChecksumMode.CP_ADD) {
if (displayChecksum) {
sb.append(calcChecksum(sb.toString()));
return sb.toString();
} else {
String msg = sb.toString();
sb.append(calcChecksum(msg));
return msg;
}
} else if (getChecksumMode() == ChecksumMode.CP_CHECK) {
if (!validateChecksum(sb.toString())) {
throw new IllegalArgumentException("Message '"
+ sb.toString()
+ "' has a bad checksum. Expected: "
+ calcChecksum(sb.substring(0, sb.length() - 1)));
}
if (displayChecksum) {
return sb.toString();
} else {
return sb.substring(0, sb.length() - 1);
}
} else if (getChecksumMode() == ChecksumMode.CP_IGNORE) {
return sb.toString();
} else if (getChecksumMode() == ChecksumMode.CP_AUTO) {
return sb.toString(); //equals ignore
} else {
throw new UnsupportedOperationException(
"Unknown checksum mode: " + getChecksumMode());
}
}
/**
* Generates the barcode logic
* @param logic the logic handler to receive generated events
* @param msg the message to encode
*/
public void generateBarcodeLogic(ClassicBarcodeLogicHandler logic, String msg) {
StringBuffer sb = new StringBuffer(msg);
String formattedMsg = handleChecksum(sb);
logic.startBarcode(sb.toString(), formattedMsg);
// start frame bar
logic.addBar(true, 2);
addIntercharacterGap(logic);
// encode message
for (int i = 0; i < sb.length(); i++) {
final char ch = sb.charAt(i);
if (!isValidChar(ch)) {
throw new IllegalArgumentException("Invalid character: " + ch);
}
encodeChar(logic, ch);
}
// end frame bar
logic.addBar(true, 2);
logic.endBarcode();
}
}