001    /**
002     *  This library is free software; you can redistribute it and/or modify it
003     *  under the terms of the GNU Lesser General Public License (LGPL) as
004     *  published by the Free Software Foundation; either version 3.0 of the
005     *  License, or (at your option) any later version.
006     *
007     *  This library is distributed in the hope that it will be useful, but
008     *  WITHOUT ANY WARRANTY; without even the implied warranty of
009     *  MERCHANTABILITY of FITNESS FOR A PARTICULAR PURPOSE. See the GNU
010     *  Lesser General Public License for more details. 
011     */
012    
013    /**
014     * Title:        JBarcodeBean
015     * Description:  Barcode JavaBeans Component
016     * Copyright:    Copyright (C) 2004
017     * Company:      Dafydd Walters
018     */
019    package net.sourceforge.jbarcodebean.model;
020    
021    import net.sourceforge.jbarcodebean.BarcodeException;
022    
023    /**
024     * Base class for Code39 variants.
025     */
026    public abstract class BaseCode39 extends AbstractBarcodeStrategy {
027    
028      /**
029       * A static array of
030       * {@link AbstractBarcodeStrategy.CharacterCode CharacterCode} objects
031       * for the 3:1 (wide) variants of Code 39.  The
032       * {@link AbstractBarcodeStrategy#getCodes() getCodes()} method of the wide
033       * Code 39 subclasses ({@link Code39} and {@link ExtendedCode39})
034       * return this array.
035       */
036      protected static CharacterCode[] codes = {
037        new CharacterCode('0', new byte[] {1,1,1,3,3,1,3,1,1,1}, 0),
038        new CharacterCode('1', new byte[] {3,1,1,3,1,1,1,1,3,1}, 1),
039        new CharacterCode('2', new byte[] {1,1,3,3,1,1,1,1,3,1}, 2),
040        new CharacterCode('3', new byte[] {3,1,3,3,1,1,1,1,1,1}, 3),
041        new CharacterCode('4', new byte[] {1,1,1,3,3,1,1,1,3,1}, 4),
042        new CharacterCode('5', new byte[] {3,1,1,3,3,1,1,1,1,1}, 5),
043        new CharacterCode('6', new byte[] {1,1,3,3,3,1,1,1,1,1}, 6),
044        new CharacterCode('7', new byte[] {1,1,1,3,1,1,3,1,3,1}, 7),
045        new CharacterCode('8', new byte[] {3,1,1,3,1,1,3,1,1,1}, 8),
046        new CharacterCode('9', new byte[] {1,1,3,3,1,1,3,1,1,1}, 9),
047        new CharacterCode('A', new byte[] {3,1,1,1,1,3,1,1,3,1}, 10),
048        new CharacterCode('B', new byte[] {1,1,3,1,1,3,1,1,3,1}, 11),
049        new CharacterCode('C', new byte[] {3,1,3,1,1,3,1,1,1,1}, 12),
050        new CharacterCode('D', new byte[] {1,1,1,1,3,3,1,1,3,1}, 13),
051        new CharacterCode('E', new byte[] {3,1,1,1,3,3,1,1,1,1}, 14),
052        new CharacterCode('F', new byte[] {1,1,3,1,3,3,1,1,1,1}, 15),
053        new CharacterCode('G', new byte[] {1,1,1,1,1,3,3,1,3,1}, 16),
054        new CharacterCode('H', new byte[] {3,1,1,1,1,3,3,1,1,1}, 17),
055        new CharacterCode('I', new byte[] {1,1,3,1,1,3,3,1,1,1}, 18),
056        new CharacterCode('J', new byte[] {1,1,1,1,3,3,3,1,1,1}, 19),
057        new CharacterCode('K', new byte[] {3,1,1,1,1,1,1,3,3,1}, 20),
058        new CharacterCode('L', new byte[] {1,1,3,1,1,1,1,3,3,1}, 21),
059        new CharacterCode('M', new byte[] {3,1,3,1,1,1,1,3,1,1}, 22),
060        new CharacterCode('N', new byte[] {1,1,1,1,3,1,1,3,3,1}, 23),
061        new CharacterCode('O', new byte[] {3,1,1,1,3,1,1,3,1,1}, 24),
062        new CharacterCode('P', new byte[] {1,1,3,1,3,1,1,3,1,1}, 25),
063        new CharacterCode('Q', new byte[] {1,1,1,1,1,1,3,3,3,1}, 26),
064        new CharacterCode('R', new byte[] {3,1,1,1,1,1,3,3,1,1}, 27),
065        new CharacterCode('S', new byte[] {1,1,3,1,1,1,3,3,1,1}, 28),
066        new CharacterCode('T', new byte[] {1,1,1,1,3,1,3,3,1,1}, 29),
067        new CharacterCode('U', new byte[] {3,3,1,1,1,1,1,1,3,1}, 30),
068        new CharacterCode('V', new byte[] {1,3,3,1,1,1,1,1,3,1}, 31),
069        new CharacterCode('W', new byte[] {3,3,3,1,1,1,1,1,1,1}, 32),
070        new CharacterCode('X', new byte[] {1,3,1,1,3,1,1,1,3,1}, 33),
071        new CharacterCode('Y', new byte[] {3,3,1,1,3,1,1,1,1,1}, 34),
072        new CharacterCode('Z', new byte[] {1,3,3,1,3,1,1,1,1,1}, 35),
073        new CharacterCode('-', new byte[] {1,3,1,1,1,1,3,1,3,1}, 36),
074        new CharacterCode('.', new byte[] {3,3,1,1,1,1,3,1,1,1}, 37),
075        new CharacterCode(' ', new byte[] {1,3,3,1,1,1,3,1,1,1}, 38),
076        new CharacterCode('*', new byte[] {1,3,1,1,3,1,3,1,1,1}, -1), // Start and End Sentinel
077        new CharacterCode('$', new byte[] {1,3,1,3,1,3,1,1,1,1}, 39),
078        new CharacterCode('/', new byte[] {1,3,1,3,1,1,1,3,1,1}, 40),
079        new CharacterCode('+', new byte[] {1,3,1,1,1,3,1,3,1,1}, 41),
080        new CharacterCode('%', new byte[] {1,1,1,3,1,3,1,3,1,1}, 42)
081      };
082    
083      /**
084       * A static array of
085       * {@link AbstractBarcodeStrategy.CharacterCode CharacterCode} objects
086       * for the 2:1 (narrow) variants of Code 39.  The
087       * {@link AbstractBarcodeStrategy#getCodes() getCodes()} method of the narrow
088       * Code 39 subclasses ({@link Code39_2to1} and {@link ExtendedCode39_2to1})
089       * return this array.
090       */
091      protected static CharacterCode[] codes2to1 = {
092        new CharacterCode('0', new byte[] {1,1,1,2,2,1,2,1,1,1}, 0),
093        new CharacterCode('1', new byte[] {2,1,1,2,1,1,1,1,2,1}, 1),
094        new CharacterCode('2', new byte[] {1,1,2,2,1,1,1,1,2,1}, 2),
095        new CharacterCode('3', new byte[] {2,1,2,2,1,1,1,1,1,1}, 3),
096        new CharacterCode('4', new byte[] {1,1,1,2,2,1,1,1,2,1}, 4),
097        new CharacterCode('5', new byte[] {2,1,1,2,2,1,1,1,1,1}, 5),
098        new CharacterCode('6', new byte[] {1,1,2,2,2,1,1,1,1,1}, 6),
099        new CharacterCode('7', new byte[] {1,1,1,2,1,1,2,1,2,1}, 7),
100        new CharacterCode('8', new byte[] {2,1,1,2,1,1,2,1,1,1}, 8),
101        new CharacterCode('9', new byte[] {1,1,2,2,1,1,2,1,1,1}, 9),
102        new CharacterCode('A', new byte[] {2,1,1,1,1,2,1,1,2,1}, 10),
103        new CharacterCode('B', new byte[] {1,1,2,1,1,2,1,1,2,1}, 11),
104        new CharacterCode('C', new byte[] {2,1,2,1,1,2,1,1,1,1}, 12),
105        new CharacterCode('D', new byte[] {1,1,1,1,2,2,1,1,2,1}, 13),
106        new CharacterCode('E', new byte[] {2,1,1,1,2,2,1,1,1,1}, 14),
107        new CharacterCode('F', new byte[] {1,1,2,1,2,2,1,1,1,1}, 15),
108        new CharacterCode('G', new byte[] {1,1,1,1,1,2,2,1,2,1}, 16),
109        new CharacterCode('H', new byte[] {2,1,1,1,1,2,2,1,1,1}, 17),
110        new CharacterCode('I', new byte[] {1,1,2,1,1,2,2,1,1,1}, 18),
111        new CharacterCode('J', new byte[] {1,1,1,1,2,2,2,1,1,1}, 19),
112        new CharacterCode('K', new byte[] {2,1,1,1,1,1,1,2,2,1}, 20),
113        new CharacterCode('L', new byte[] {1,1,2,1,1,1,1,2,2,1}, 21),
114        new CharacterCode('M', new byte[] {2,1,2,1,1,1,1,2,1,1}, 22),
115        new CharacterCode('N', new byte[] {1,1,1,1,2,1,1,2,2,1}, 23),
116        new CharacterCode('O', new byte[] {2,1,1,1,2,1,1,2,1,1}, 24),
117        new CharacterCode('P', new byte[] {1,1,2,1,2,1,1,2,1,1}, 25),
118        new CharacterCode('Q', new byte[] {1,1,1,1,1,1,2,2,2,1}, 26),
119        new CharacterCode('R', new byte[] {2,1,1,1,1,1,2,2,1,1}, 27),
120        new CharacterCode('S', new byte[] {1,1,2,1,1,1,2,2,1,1}, 28),
121        new CharacterCode('T', new byte[] {1,1,1,1,2,1,2,2,1,1}, 29),
122        new CharacterCode('U', new byte[] {2,2,1,1,1,1,1,1,2,1}, 30),
123        new CharacterCode('V', new byte[] {1,2,2,1,1,1,1,1,2,1}, 31),
124        new CharacterCode('W', new byte[] {2,2,2,1,1,1,1,1,1,1}, 32),
125        new CharacterCode('X', new byte[] {1,2,1,1,2,1,1,1,2,1}, 33),
126        new CharacterCode('Y', new byte[] {2,2,1,1,2,1,1,1,1,1}, 34),
127        new CharacterCode('Z', new byte[] {1,2,2,1,2,1,1,1,1,1}, 35),
128        new CharacterCode('-', new byte[] {1,2,1,1,1,1,2,1,2,1}, 36),
129        new CharacterCode('.', new byte[] {2,2,1,1,1,1,2,1,1,1}, 37),
130        new CharacterCode(' ', new byte[] {1,2,2,1,1,1,2,1,1,1}, 38),
131        new CharacterCode('*', new byte[] {1,2,1,1,2,1,2,1,1,1}, -1), // Start and End Sentinel
132        new CharacterCode('$', new byte[] {1,2,1,2,1,2,1,1,1,1}, 39),
133        new CharacterCode('/', new byte[] {1,2,1,2,1,1,1,2,1,1}, 40),
134        new CharacterCode('+', new byte[] {1,2,1,1,1,2,1,2,1,1}, 41),
135        new CharacterCode('%', new byte[] {1,1,1,2,1,2,1,2,1,1}, 42)
136      };
137    
138      /**
139       * Always returns {@link BarcodeStrategy#OPTIONAL_CHECKSUM}.
140       */
141      public int requiresChecksum() {
142        // Checksum is not mandatory
143        return OPTIONAL_CHECKSUM;
144      }
145    
146      /**
147       * Always returns 11 (eleven).
148       */
149      protected byte getMarginWidth() {
150        return 11;
151      }
152    
153      /**
154       * Always returns '*' (asterisk).
155       */
156      protected char getStartSentinel() {
157        return '*';
158      }
159    
160      /**
161       * Always returns '*' (asterisk).
162       */
163      protected char getStopSentinel() {
164        return '*';
165      }
166    
167      /**
168       * Always returns <tt>false</tt>.
169       */
170      protected boolean isInterleaved() {
171        return false;
172      }
173    
174      /**
175       * Does nothing except return the String passed to the method.
176       */
177      protected String postprocess(String text) {
178        return text;
179      }
180    
181      /**
182       * Returns a String containing the checksum-encoded version of the text passed
183       * to the method.
184       * Start and End sentinels must NOT be included in the text passed to this method.
185       */
186      protected String augmentWithChecksum(String text) throws BarcodeException {
187        int checkTotal = 0;
188        CharacterCode cc;
189        for (int i = 0; i < text.length(); i++) {
190          char ch = text.charAt(i);
191          cc = getCharacterCode(ch);            // get code by character
192          if (cc == null) {
193            throw new BarcodeException("Invalid character in barcode");
194          }
195          // Exclude start and end sentinels from checksum
196          if (cc.check > 0) {
197            checkTotal += cc.check;
198          }
199        }
200        cc = getCharacterCode(checkTotal % 43); // get code by check number
201        return text + cc.character;
202      }
203    
204    
205    }