KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * $Id: Interleaved2Of5LogicImpl.java,v 1.5 2003/04/17 12:21:41 jmaerki Exp $
3  * ============================================================================
4  * The Krysalis Patchy Software License, Version 1.1_01
5  * Copyright (c) 2002-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  * This class is an implementation of the Interleaved 2 of 5 barcode.
66  *
67  * @author Jeremias Maerki
68  */

69 public class Interleaved2Of5LogicImpl {
70
71     private static final byte[][] CHARSET = {{1, 1, 2, 2, 1},
72                                              {2, 1, 1, 1, 2},
73                                              {1, 2, 1, 1, 2},
74                                              {2, 2, 1, 1, 1},
75                                              {1, 1, 2, 1, 2},
76                                              {2, 1, 2, 1, 1},
77                                              {1, 2, 2, 1, 1},
78                                              {1, 1, 1, 2, 2},
79                                              {2, 1, 1, 2, 1},
80                                              {1, 2, 1, 2, 1}};
81
82     private ChecksumMode checksumMode = ChecksumMode.CP_AUTO;
83     
84     /**
85      * Main constructor.
86      * @param mode the checksum mode
87      */

88     public Interleaved2Of5LogicImpl(ChecksumMode mode) {
89         this.checksumMode = mode;
90     }
91
92     /**
93      * Returns the current checksum mode
94      * @return the checksum mode
95      */

96     public ChecksumMode getChecksumMode() {
97         return this.checksumMode;
98     }
99
100     /**
101      * Calculates the checksum for a message to be encoded as an
102      * Interleaved 2 of 5 barcode. The algorithm is a weighted modulo 10 scheme.
103      * @param msg message to calculate the check digit for
104      * @param oddMultiplier multiplier to be used for odd positions (usually 3 or 4)
105      * @param evenMultiplier multiplier to be used for even positions (usually 1 or 9)
106      * @return char the check digit
107      */

108     public static char calcChecksum(String JavaDoc msg, int oddMultiplier, int evenMultiplier) {
109         int oddsum = 0;
110         int evensum = 0;
111         for (int i = 0; i < msg.length(); i++) {
112             if (i % 2 == 0) {
113                 evensum += Character.digit(msg.charAt(i), 10);
114             } else {
115                 oddsum += Character.digit(msg.charAt(i), 10);
116             }
117         }
118         int check = 10 - ((evensum * oddMultiplier + oddsum * evenMultiplier) % 10);
119         if (check >= 10) check = 0;
120         return Character.forDigit(check, 10);
121     }
122
123     /**
124      * Calculates the checksum for a message to be encoded as an
125      * Interleaved 2 of 5 barcode. The algorithm is a weighted modulo 10 scheme.
126      * This method uses the default specification
127      * (ITF-14, EAN-14, SSC-14, DUN14 and USPS).
128      * @param msg message to calculate the check digit for
129      * @return char the check digit
130      */

131     public static char calcChecksum(String JavaDoc msg) {
132         return calcChecksum(msg, 3, 1);
133     }
134
135     /**
136      * Verifies the checksum for a message.
137      * @param msg message (check digit included)
138      * @return boolean True, if the checksum is correct
139      */

140     public static boolean validateChecksum(String JavaDoc msg) {
141         char actual = msg.charAt(msg.length() - 1);
142         char expected = calcChecksum(msg.substring(0, msg.length() - 1));
143         return (actual == expected);
144     }
145
146     private int widthAt(char ch, int index) {
147         if (Character.isDigit(ch)) {
148             int digit = Character.digit(ch, 10);
149             int width = CHARSET[digit][index];
150             return width;
151         } else {
152             throw new IllegalArgumentException JavaDoc("Invalid character '" + ch
153                     + " (" + Character.getNumericValue(ch)
154                     + ")'. Expected a digit.");
155         }
156     }
157
158     private void encodeGroup(ClassicBarcodeLogicHandler logic, String JavaDoc group) {
159         if (group.length() != 2) {
160             throw new IllegalArgumentException JavaDoc("Parameter group must have two characters");
161         }
162         
163         logic.startBarGroup(BarGroup.MSG_CHARACTER, group);
164         for (int index = 0; index < 5; index++) {
165             logic.addBar(true, widthAt(group.charAt(0), index));
166             logic.addBar(false, widthAt(group.charAt(1), index));
167         }
168         logic.endBarGroup();
169     }
170     
171     private String JavaDoc handleChecksum(String JavaDoc msg) {
172         if (getChecksumMode() == ChecksumMode.CP_ADD) {
173             return msg + calcChecksum(msg);
174         } else if (getChecksumMode() == ChecksumMode.CP_CHECK) {
175             if (!validateChecksum(msg)) {
176                 throw new IllegalArgumentException JavaDoc("Message '"
177                     + msg
178                     + "' has a bad checksum. Expected: "
179                     + calcChecksum(msg.substring(0, msg.length() - 1)));
180             }
181             return msg;
182         } else if (getChecksumMode() == ChecksumMode.CP_IGNORE) {
183             return msg;
184         } else if (getChecksumMode() == ChecksumMode.CP_AUTO) {
185             return msg; //equals ignore
186
} else {
187             throw new UnsupportedOperationException JavaDoc(
188                 "Unknown checksum mode: " + getChecksumMode());
189         }
190     }
191     
192     /**
193      * Generates the barcode logic.
194      * @param logic the logic handler to receive generated events
195      * @param msg the message to encode
196      */

197     public void generateBarcodeLogic(ClassicBarcodeLogicHandler logic, String JavaDoc msg) {
198         //Checksum handling as requested
199
String JavaDoc s = handleChecksum(msg);
200         
201         //Length must be even
202
if ((s.length() % 2) != 0) {
203             s = "0" + s;
204         }
205
206         logic.startBarcode(msg);
207
208         //Start character
209
logic.startBarGroup(BarGroup.START_CHARACTER, null);
210         logic.addBar(true, 1);
211         logic.addBar(false, 1);
212         logic.addBar(true, 1);
213         logic.addBar(false, 1);
214         logic.endBarGroup();
215
216         //Process string
217
int i = 0;
218         do {
219             encodeGroup(logic, s.substring(i, i + 2));
220             i += 2;
221         } while (i < s.length());
222
223         //End character
224
logic.startBarGroup(BarGroup.STOP_CHARACTER, null);
225         logic.addBar(true, 2);
226         logic.addBar(false, 1);
227         logic.addBar(true, 1);
228         logic.endBarGroup();
229
230         logic.endBarcode();
231     }
232
233 }
Popular Tags