KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > krysalis > barcode > impl > POSTNETLogicImpl


1 /*
2  * $Id: POSTNETLogicImpl.java,v 1.1 2003/08/18 19:31:37 jmaerki Exp $
3  * ============================================================================
4  * The Krysalis Patchy Software License, Version 1.1_01
5  * Copyright (c) 2003 Nicola Ken Barozzi. All rights reserved.
6  *
7  * This Licence is compatible with the BSD licence as described and
8  * approved by http://www.opensource.org/, and is based on the
9  * Apache Software Licence Version 1.1.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * 1. Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  *
18  * 2. Redistributions in binary form must reproduce the above copyright
19  * notice, this list of conditions and the following disclaimer in
20  * the documentation and/or other materials provided with the
21  * distribution.
22  *
23  * 3. The end-user documentation included with the redistribution,
24  * if any, must include the following acknowledgment:
25  * "This product includes software developed for project
26  * Krysalis (http://www.krysalis.org/)."
27  * Alternately, this acknowledgment may appear in the software itself,
28  * if and wherever such third-party acknowledgments normally appear.
29  *
30  * 4. The names "Krysalis" and "Nicola Ken Barozzi" and
31  * "Krysalis Barcode" must not be used to endorse or promote products
32  * derived from this software without prior written permission. For
33  * written permission, please contact nicolaken@krysalis.org.
34  *
35  * 5. Products derived from this software may not be called "Krysalis",
36  * "Krysalis Barcode", nor may "Krysalis" appear in their name,
37  * without prior written permission of Nicola Ken Barozzi.
38  *
39  * 6. This software may contain voluntary contributions made by many
40  * individuals, who decided to donate the code to this project in
41  * respect of this licence, and was originally created by
42  * Jeremias Maerki <jeremias@maerki.org>.
43  *
44  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
45  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
46  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
47  * DISCLAIMED. IN NO EVENT SHALL THE KRYSALIS PROJECT OR
48  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
49  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
50  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
51  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
52  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
53  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
54  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
55  * SUCH DAMAGE.
56  * ====================================================================
57  */

58 package org.krysalis.barcode.impl;
59
60 import org.krysalis.barcode.BarGroup;
61 import org.krysalis.barcode.ChecksumMode;
62 import org.krysalis.barcode.ClassicBarcodeLogicHandler;
63
64 /**
65  * Implements the United States Postal Service Postnet barcode.
66  *
67  * @author Chris Dolphy
68  */

69 public class POSTNETLogicImpl {
70
71     private static final byte[][] CHARSET =
72                         {{2, 2, 1, 1, 1}, //0
73
{1, 1, 1, 2, 2}, //1
74
{1, 1, 2, 1, 2}, //2
75
{1, 1, 2, 2, 1}, //3
76
{1, 2, 1, 1, 2}, //4
77
{1, 2, 1, 2, 1}, //5
78
{1, 2, 2, 1, 1}, //6
79
{2, 1, 1, 1, 2}, //7
80
{2, 1, 1, 2, 1}, //8
81
{2, 1, 2, 1, 1}}; //9
82

83     private ChecksumMode checksumMode = ChecksumMode.CP_AUTO;
84     private static final char DASH = '-';
85
86     /**
87      * Main constructor
88      * @param mode checksum mode
89      */

90     public POSTNETLogicImpl(ChecksumMode mode) {
91         this.checksumMode = mode;
92     }
93
94     /**
95      * Returns the currently active checksum mode.
96      * @return the checksum mode
97      */

98     public ChecksumMode getChecksumMode() {
99         return this.checksumMode;
100     }
101
102     /**
103      * Calculates the checksum for a message to be encoded as an
104      * Code39 barcode.
105      * @param msg message to calculate the check digit for
106      * @return char the check digit
107      */

108     public static char calcChecksum(String JavaDoc msg) {
109         int tmp = 0;
110         for (int i = 0; i < msg.length(); i++) {
111             if (isIgnoredChar(msg.charAt(i))) {
112                 continue;
113             }
114             tmp += Character.digit(msg.charAt(i), 10);
115             if (tmp > 9) {
116                 tmp -= 10;
117             }
118         }
119         return Character.forDigit((10 - tmp) % 10, 10);
120     }
121
122
123     /**
124      * Verifies the checksum for a message.
125      * @param msg message (check digit included)
126      * @return boolean True, if the checksum is correct
127      */

128     public static boolean validateChecksum(String JavaDoc msg) {
129         char actual = msg.charAt(msg.length() - 1);
130         char expected = calcChecksum(msg.substring(0, msg.length() - 1));
131         return (actual == expected);
132     }
133
134     private static boolean isValidChar(char ch) {
135         return Character.isDigit(ch) || isIgnoredChar(ch);
136     }
137     
138     /**
139      * Checks if a character is an ignored character (such as a '-' (dash)).
140      * @param c character to check
141      * @return True if the character is ignored
142      */

143     public static boolean isIgnoredChar(char c) {
144         return c == DASH;
145     }
146     
147     /**
148      * Removes ignored character from a valid POSTNET message.
149      * @param msg valid POSTNET message
150      * @return the message but without ignored characters
151      */

152     public static String JavaDoc removeIgnoredCharacters(final String JavaDoc msg) {
153         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(msg.length());
154         for (int i = 0; i < msg.length(); i++) {
155             final char ch = msg.charAt(i);
156             if (!isValidChar(ch)) {
157                 throw new IllegalArgumentException JavaDoc("Invalid character: " + ch);
158             }
159             if (!isIgnoredChar(ch)) {
160                 sb.append(ch);
161             }
162         }
163         return sb.toString();
164     }
165
166     private int heightAt(char ch, int index) {
167         int chidx = Character.digit(ch, 10);
168         if (chidx >= 0) {
169             int height = CHARSET[chidx][index];
170             return height;
171         } else {
172             throw new IllegalArgumentException JavaDoc("Invalid character: " + ch);
173         }
174     }
175
176     /**
177      * Encodes a single character.
178      * @param logic the logic handler to receive generated events
179      * @param c the character to encode
180      */

181     protected void encodeChar(ClassicBarcodeLogicHandler logic, char c) {
182         if (isIgnoredChar(c)) {
183             return; // allow dash, but don't encode
184
}
185         logic.startBarGroup(BarGroup.MSG_CHARACTER, new Character JavaDoc(c).toString());
186         for (byte i = 0; i < 5; i++) {
187             int height = heightAt(c, i);
188             logic.addBar(true, height);
189             addIntercharacterGap(logic);
190         }
191         logic.endBarGroup();
192     }
193
194     private void addIntercharacterGap(ClassicBarcodeLogicHandler logic) {
195         logic.addBar(false, -1); //-1 is special
196
}
197         
198     private void handleChecksum(StringBuffer JavaDoc sb) {
199         if (getChecksumMode() == ChecksumMode.CP_ADD) {
200             sb.append(calcChecksum(sb.toString()));
201         } else if (getChecksumMode() == ChecksumMode.CP_CHECK) {
202             if (!validateChecksum(sb.toString())) {
203                 throw new IllegalArgumentException JavaDoc("Message '"
204                     + sb.toString()
205                     + "' has a bad checksum. Expected: "
206                     + calcChecksum(sb.toString()));
207             }
208         } else if (getChecksumMode() == ChecksumMode.CP_IGNORE) {
209             return;
210         } else if (getChecksumMode() == ChecksumMode.CP_AUTO) {
211             return; //equals ignore
212
}
213     }
214
215     /**
216      * Generates the barcode logic
217      * @param logic the logic handler to receive generated events
218      * @param msg the message to encode
219      */

220     public void generateBarcodeLogic(ClassicBarcodeLogicHandler logic, String JavaDoc msg) {
221         logic.startBarcode(msg);
222
223         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(msg);
224
225         handleChecksum(sb);
226
227         // start frame bar
228
logic.addBar(true, 2);
229         addIntercharacterGap(logic);
230
231         // encode message
232
for (int i = 0; i < sb.length(); i++) {
233             final char ch = sb.charAt(i);
234             if (!isValidChar(ch)) {
235                 throw new IllegalArgumentException JavaDoc("Invalid character: " + ch);
236             }
237             encodeChar(logic, ch);
238         }
239
240         // end frame bar
241
logic.addBar(true, 2);
242
243         logic.endBarcode();
244     }
245
246
247 }
248
Popular Tags