View Javadoc

1   /*
2    *  Copyright (c) 2005, 2006 Imola Informatica.
3    *  All rights reserved. This program and the accompanying materials
4    *  are made available under the terms of the LGPL License v2.1
5    *  which accompanies this distribution, and is available at
6    *  http://www.gnu.org/licenses/lgpl.html
7    */
8   
9   
10  package it.imolinfo.jbi4cics.typemapping.cobol;
11  
12  import it.imolinfo.jbi4cics.Logger;
13  import it.imolinfo.jbi4cics.LoggerFactory;
14  import it.imolinfo.jbi4cics.exception.FormatException;
15  import java.lang.reflect.Array;
16  import java.math.BigDecimal;
17  import java.math.BigInteger;
18  
19  /**
20   * Helper class to manage Cobol types. This class is used by
21   * {@link CobolTypeDescriptor} to complete its functionalities.
22   * <p>
23   *
24   * @author <a href="mailto:mcimatti@imolinfo.it">Marco Cimatti</a>
25   */
26  public enum CobolType {
27  
28      // Es PIC X(n)
29      STRING {
30          Class getPreferredJavaType(CobolTypeDescriptor desc) {
31              return String.class;
32          }
33  
34          int getBufferedLength(CobolTypeDescriptor desc) throws FormatException {
35              return desc.getStringLength();
36          }
37  
38          void format(Object value, byte[] buffer, CobolTypeDescriptor desc,
39                      int startingOffset) throws FormatException {
40              if (value == null) {
41  
42                  // Gestione del null, siamo in fase di input.
43                  // Dato che non e' possibile distinguere fra valori di input e
44                  // di output in una copy vanno inseriti dei valori di default
45                  // perche' il formatter si aspetta qualcosa cobol
46                  value = "";
47              } else if (!(value instanceof String)) {
48                  LOG.error("CIC002104_String_not_found", value.getClass());
49                  throw new FormatException("CIC002104_String_not_found",
50                                            new Object[] { value.getClass() });
51              }
52              StringMarshaller.marshallStringIntoBuffer((String) value, buffer,
53                      startingOffset, desc.getCodePage(),
54                      desc.getBufferedLength(), desc.getJustification(),
55                      desc.getPadCharacter());
56          }
57  
58          Object unformat(byte[] buffer, CobolTypeDescriptor desc,
59                          int startingOffset) throws FormatException {
60              return StringMarshaller.unmarshallString(buffer, startingOffset,
61                      desc.getCodePage(), desc.getBufferedLength()).trim();
62          }
63      },
64  
65      // Es: PIC 9(n) comp o comp-4
66      INTEGER {
67          Class getPreferredJavaType(CobolTypeDescriptor desc) {
68              return BigInteger.class;
69          }
70  
71          int getBufferedLength(CobolTypeDescriptor desc) throws FormatException {
72              int length = desc.getIntegerPartLength();
73  
74              if ((length < 0) || (length >= BUFFERED_LENGTH.length)) {
75                  LOG.error("CIC002109_Integer_too_much_long", length);
76                  throw new FormatException("CIC002109_Integer_too_much_long",
77                                            new Object[] { length });
78              }
79              return BUFFERED_LENGTH[length];
80          }
81  
82          void format(Object value, byte[] buffer, CobolTypeDescriptor desc,
83                      int startingOffset) throws FormatException {
84              if (value == null) {
85  
86                  // Gestione del null, siamo in fase di input.
87                  // Dato che non e' possibile distinguere fra valori di input e
88                  // di output in una copy vanno inseriti dei valori di default
89                  // perche' il formatter si aspetta qualcosa cobol
90                  value = BigInteger.ZERO;
91              }
92              CobolFieldFormatter.formatInteger(value, buffer, desc,
93                                                startingOffset);
94          }
95  
96          Object unformat(byte[] buffer, CobolTypeDescriptor desc,
97                          int startingOffset) throws FormatException {
98              return IntegerMarshaller.unmarshallInteger(buffer, startingOffset,
99                      desc.getBufferedLength(), desc.isBigEndian());
100         }
101     },
102 
103     // Es: PIC 9(n) comp-3 (con virgola sempre virtuale)
104     PACKED_DECIMAL {
105         Class getPreferredJavaType(CobolTypeDescriptor desc) {
106             return BigDecimal.class;
107         }
108 
109         int getBufferedLength(CobolTypeDescriptor desc) throws FormatException {
110             return Math.round(((float) (desc.getIntegerPartLength()
111                                        + desc.getDecimalPartLength() + 1)) / 2);
112         }
113 
114         void format(Object value, byte[] buffer, CobolTypeDescriptor desc,
115                     int startingOffset) throws FormatException {
116             if (value == null){
117 
118                 // Gestione del null, siamo in fase di input.
119                 // Dato che non e' possibile distinguere fra valori di input e
120                 // di output in una copy vanno inseriti dei valori di default
121                 // perche' il formatter si aspetta qualcosa cobol
122                 value = BigDecimal.ZERO;
123             }
124             CobolFieldFormatter.formatPackedDecimal(value, buffer, desc,
125                                                     startingOffset);
126         }
127 
128         Object unformat(byte[] buffer, CobolTypeDescriptor desc,
129                         int startingOffset) throws FormatException {
130             return PackedDecimalMarshaller.unmarshallBigDecimal(buffer, desc,
131                                                                 startingOffset);
132         }
133     },
134 
135     // Es: PIC 9(n) (con virgola virtuale o reale)
136     ZONED {
137         Class getPreferredJavaType(CobolTypeDescriptor desc) {
138             return BigDecimal.class;
139         }
140 
141         int getBufferedLength(CobolTypeDescriptor desc) throws FormatException {
142 
143             // TODO inserire la gestione di +9(n)...
144             int length = desc.getIntegerPartLength()
145                          + desc.getDecimalPartLength();
146 
147             if (desc.getZonedSignFormat()
148                     == CobolTypeDescriptor.SIGN_FORMAT_LEADING_SEPARATE) {
149                 length++;
150             }
151             return length;
152 
153         }
154 
155         void format(Object value, byte[] buffer, CobolTypeDescriptor desc,
156                     int startingOffset) throws FormatException {
157             if (value == null) {
158 
159                 // Gestione del null, siamo in fase di input.
160                 // Dato che non e' possibile distinguere fra valori di input e
161                 // di output in una copy vanno inseriti dei valori di default
162                 // perche' il formatter si aspetta qualcosa cobol
163                 value = BigDecimal.ZERO;
164             }
165             CobolFieldFormatter.formatZoned(value, buffer, desc,
166                                             startingOffset);
167         }
168 
169         Object unformat(byte[] buffer, CobolTypeDescriptor desc,
170                         int startingOffset) throws FormatException {
171             return ZonedMarshaller.unmarshallZoned(buffer, startingOffset,
172                     desc.getBufferedLength(), desc.isSigned(),
173                     desc.getVirtualDecimalPoint(), desc.getZonedSignFormat(),
174                     desc.getCodePage());
175         }
176     },
177 
178     // Tipo contenitore: 01 MAIN.
179     NESTED_COMMAREA {
180         Class getPreferredJavaType(CobolTypeDescriptor desc) {
181             return desc.getNestedCommarea().getBeanClass();
182         }
183 
184         int getBufferedLength(CobolTypeDescriptor desc) throws FormatException {
185             return desc.getNestedCommarea().getBufferedLength();
186         }
187 
188         void format(Object value, byte[] buffer, CobolTypeDescriptor desc,
189                     int startingOffset) throws FormatException {
190             if (value == null) {
191 
192                 // Gestione del null, siamo in fase di input.
193                 // Dato che non e' possibile distinguere fra valori di input e
194                 // di output in una copy vanno inseriti dei valori di default
195                 // perche' il formatter si aspetta qualcosa cobol
196                 throw new FormatException("CIC002100_Null_nested_commarea");
197             }
198             CobolFieldFormatter.formatNestedCommarea(value, buffer, desc,
199                                                      startingOffset);
200         }
201 
202         Object unformat(byte[] buffer, CobolTypeDescriptor desc,
203                         int startingOffset) throws FormatException {
204             return CobolFieldFormatter.unformatNestedCommarea(buffer, desc,
205                                                               startingOffset);
206         }
207     },
208 
209     /**
210      * The <i>occurs</i> clause type.
211      */
212     OCCURS {
213         Class getPreferredJavaType(CobolTypeDescriptor desc) {
214             Class beanClass = desc.getNestedCommarea().getBeanClass();
215 
216             return Array.newInstance(beanClass, 0).getClass();
217         }
218 
219         int getBufferedLength(CobolTypeDescriptor desc) throws FormatException {
220             return desc.getNestedCommarea().getBufferedLength()
221                    * desc.getOccursSize();
222         }
223 
224         void format(Object value, byte[] buffer, CobolTypeDescriptor desc,
225                     int startingOffset) throws FormatException {
226             if (value == null) {
227 
228                 // Gestione del null, siamo in fase di input.
229                 // Dato che non e' possibile distinguere fra valori di input e
230                 // di output in una copy vanno inseriti dei valori di default
231                 // perche' il formatter si aspetta qualcosa cobol
232                 throw new FormatException("CIC002101_Null_occurs_value");
233             }
234             CobolFieldFormatter.formatOccurs(value, buffer, desc,
235                                              startingOffset);
236         }
237 
238         Object unformat(byte[] buffer, CobolTypeDescriptor desc,
239                         int startingOffset) throws FormatException {
240             return CobolFieldFormatter.unformatOccurs(buffer, desc,
241                                                       startingOffset);
242         }
243     };
244 
245     /**
246      * Lookup table to obtain the integer buffered length from its integer part
247      * length. The integer part length must be used as index of this array,
248      * while the corresponding entry value is the associated buffered length.
249      */
250     private static final int[] BUFFERED_LENGTH = new int[] {
251 
252         // 1 byte fino a 256 o +- 128 --> 10^2
253         // if (integerPartLength <= 2) return 1;
254         1, 1, 1,
255 
256         // 2 byte fino a 65536 o +- 32768 --> 10^4
257         // if (integerPartLength <= 4) return 2;
258         2, 2,
259 
260         // 4 byte fino a 4294967296 o +- 2147483648 --> 10^9
261         // if (integerPartLength <= 9) return 4;
262         4, 4, 4, 4, 4,
263 
264         // 8 byte fino a 18446744073709551616 o +- 9223372036854775808 --> 10^18
265         // if (integerPartLength <= 18) return 8;
266         8, 8, 8, 8, 8, 8, 8, 8, 8,
267 
268         // 16 byte fino a 3.402823669e+38 o +- 1.701411835e+38 --> 10^37
269         // if (integerPartLength <= 37) return 16;
270         16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
271         16
272     };
273 
274     /**
275      * The logger for this class and its instances.
276      */
277     private static final Logger LOG = LoggerFactory.getLogger(CobolType.class);
278 
279     abstract Class getPreferredJavaType(CobolTypeDescriptor desc);
280 
281     abstract int getBufferedLength(CobolTypeDescriptor desc)
282             throws FormatException;
283 
284     abstract void format(Object value, byte[] buffer, CobolTypeDescriptor desc,
285                          int startingOffset) throws FormatException;
286 
287     abstract Object unformat(byte[] buffer, CobolTypeDescriptor desc,
288                              int startingOffset) throws FormatException;
289 }