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 it.imolinfo.jbi4cics.messageformat.commarea.CommareaBeanMappingDescriptor;
16  import it.imolinfo.jbi4cics.messageformat.commarea.CommareaFormatter;
17  import it.imolinfo.jbi4cics.service.ServiceContext;
18  import java.lang.reflect.Array;
19  import java.math.BigDecimal;
20  import java.math.BigInteger;
21  
22  /**
23   * Questo metodo formatta un tipo java in un buffer di byte secondo il formato
24   * cobol. Il metodo ha i seguenti vincoli: Tipo cobol STRING l'oggetto passato
25   * deve essere di tipo String Tipo cobol PACKED_DECIMAL l'oggetto passato deve
26   * essere BigInteger o BigDecimal o Long o Integer o Float o Double Tipo cobol
27   * INTEGER l'oggetto passato deve essere di tipo Number, se la dimensione e' >
28   * 16 ci possono essere problemi di conversione Tipo cobol ZONED l'oggetto
29   * passato deve essere BigInteger o BigDecimal o Long o Integer o Float o Double
30   * l'invariante di questo metodo e' che alla fine lo spazio occupato sull'array
31   * sara' sempre esattamente cobolType.getBufferedSize()
32   * TODO ATTENZIONE su questo punto vanno fatte maggiori verifiche (ad esempio
33   * come comportarsi nel caso una stringa sia troppo lunga...)
34   *
35   * @author raffaele
36   * @author <a href="mailto:mcimatti@imolinfo.it">Marco Cimatti</a>
37   */
38  public final class CobolFieldFormatter {
39  
40      /**
41       * The logger for this class and its instances.
42       */
43      private static final Logger LOG
44              = LoggerFactory.getLogger(CobolFieldFormatter.class);
45  
46      /**
47       * Does nothing. This constructor is declared <code>private</code> to
48       * prevent the instances creation of this class.
49       */
50      private CobolFieldFormatter() {
51      }
52  
53      public static void format(Object value, byte[] buffer,
54              CobolTypeDescriptor desc, int offset) throws FormatException {
55          CobolType ct = desc.getType();
56  
57          if (ct == null) {
58              LOG.error("CIC002102_Unrecognized_cobol_type", ct);
59              throw new FormatException("CIC002102_Unrecognized_cobol_type",
60                                        new Object[] { ct });
61          }
62          if ((buffer.length - offset) < desc.getBufferedLength()) {
63              Object[] args = { buffer.length, offset, desc.getBufferedLength() };
64  
65              LOG.error("CIC002103_Not_enough_space_writing_cobol_type", args);
66              throw new FormatException("CIC002103_Not_enough_space", args);
67          }
68          ct.format(value, buffer, desc, offset);
69      }
70  
71      static void formatOccurs(Object value, byte[] buffer,
72              CobolTypeDescriptor desc, int offset) throws FormatException {
73          Object[] valueArray;
74          boolean debug = LOG.isDebugEnabled();
75  
76          if (!(value instanceof Object[])) {
77              Object[] args = { value.getClass() };
78  
79              LOG.error("CIC002105_Array_not_found", args);
80              throw new FormatException("CIC002105_Array_not_found", args);
81          }
82          valueArray = (Object[]) value;
83          if (valueArray.length > desc.getOccursSize()) {
84              Object[] args = { valueArray.length, desc.getOccursSize() };
85  
86              LOG.error("CIC002106_Array_size_not_allowed", args);
87              throw new FormatException("CIC002106_Array_size_not_allowed", args);
88          }
89          for (int i = 0; i < valueArray.length; i++) {
90  
91              // questo serve a riutilizzare quanto scritto per
92              // formatNestedCommarea, costruisce in cobolTypeNested finto
93              CobolTypeDescriptor nestedDesc = new CobolTypeDescriptor();
94              CommareaBeanMappingDescriptor nested = desc.getNestedCommarea();
95  
96              if (debug) {
97                  LOG.debug("buffer.length: " + buffer.length + " index i: " + i
98                            + " startingOffset: " + offset);
99              }
100 
101             nestedDesc.setType(CobolType.NESTED_COMMAREA);
102             nestedDesc.setNestedCommarea(nested);
103             formatNestedCommarea(valueArray[i], buffer, nestedDesc, offset);
104             offset += nested.getBufferedLength();
105         }
106     }
107 
108     static void formatNestedCommarea(Object value, byte[] buffer,
109             CobolTypeDescriptor desc, int offset) throws FormatException {
110         ServiceContext ctx = new ServiceContext();
111 
112         ctx.setInputBean(value);
113         ctx.setInputMappingDescriptor(desc.getNestedCommarea());
114         new CommareaFormatter().mapInputBeanToInputMessage(ctx);
115         System.arraycopy(ctx.getInputMessage(), 0, buffer, offset,
116                          desc.getBufferedLength());
117     }
118 
119     static void formatInteger(Object value, byte[] buffer,
120             CobolTypeDescriptor desc, int offset) throws FormatException {
121         if (value instanceof Number) {
122             String valueToString = value.toString();
123             BigInteger bigIntegerValue;
124 
125             if (LOG.isDebugEnabled()) {
126                 LOG.debug("numberValue.toString(): " + valueToString);
127             }
128             bigIntegerValue = new BigDecimal(valueToString).toBigIntegerExact();
129             IntegerMarshaller.marshallInteger(bigIntegerValue, buffer,
130                     offset, desc.getBufferedLength(), desc.isBigEndian());
131         } else {
132             Object[] args = { value.getClass() };
133 
134             LOG.error("CIC002107_Number_not_found", args);
135             throw new FormatException("CIC002107_Number_not_found", args);
136         }
137     }
138 
139     static void formatPackedDecimal(Object value, byte[] buffer,
140             CobolTypeDescriptor desc, int offset) throws FormatException {
141         if (value instanceof Number) {
142             String valueToString = value.toString();
143             BigDecimal bigDecimalValue;
144 
145             if (LOG.isDebugEnabled()) {
146                 LOG.debug("numberValue.toString(): " + valueToString);
147             }
148             bigDecimalValue = new BigDecimal(valueToString);
149             PackedDecimalMarshaller.marshallBigDecimal(bigDecimalValue, buffer,
150                                                        desc, offset);
151         } else {
152             Object[] args = { value.getClass() };
153 
154             LOG.error("CIC002107_Number_not_found", args);
155             throw new FormatException("CIC002107_Number_not_found", args);
156         }
157     }
158 
159     static void formatZoned(Object value, byte[] buffer,
160             CobolTypeDescriptor desc, int offset) throws FormatException {
161         if (value instanceof Number) {
162             String valueToString = value.toString();
163             BigDecimal bigDecimalValue;
164 
165             if (LOG.isDebugEnabled()) {
166                 LOG.debug("numberValue.toString(): " + valueToString);
167             }
168             bigDecimalValue = new BigDecimal(valueToString);
169             ZonedMarshaller.marshallZoned(bigDecimalValue, buffer,
170                     offset, desc.getBufferedLength(), desc.isSigned(),
171                     desc.getVirtualDecimalPoint(), desc.getZonedSignFormat(),
172                     desc.getCodePage());
173         } else {
174             Object[] args = { value.getClass() };
175 
176             LOG.error("CIC002107_Number_not_found", args);
177             throw new FormatException("CIC002107_Number_not_found", args);
178         }
179     }
180 
181     /**
182      * Questo metodo legge un tipo cobol descritto da cobolType nel buffer a
183      * partire da startingOffset e crea il corrispondente tipo java le
184      * corrispondenze sono le seguenti: tipo cobol STRING tipo java String tipo
185      * cobol PACKED_DECIMAL tipo java BigDecimal tipo cobol INTEGER tipo java
186      * BigInteger tipo cobol ZONED tipo java BigDecimal
187      *
188      * @param buffer
189      * @param desc
190      * @param offset
191      * @return
192      * @throws FormatException
193      */
194     public static Object unformat(byte[] buffer, CobolTypeDescriptor desc,
195             int offset) throws FormatException {
196         CobolType cobolType = desc.getType();
197 
198         if ((buffer.length - offset) < desc.getBufferedLength()) {
199             Object[] args = { buffer.length, offset, desc.getBufferedLength() };
200 
201             LOG.error("CIC002108_Not_enough_space_reading_cobol_type", args);
202             throw new FormatException(
203                     "CIC002108_Not_enough_space_reading_cobol_type", args);
204         }
205         if (cobolType == null) {
206             LOG.error("CIC002102_Unrecognized_cobol_type", cobolType);
207             throw new FormatException("CIC002102_Unrecognized_cobol_type",
208                                       new Object[] { cobolType });
209         }
210         return cobolType.unformat(buffer, desc, offset);
211     }
212 
213     static Object unformatOccurs(byte[] buffer, CobolTypeDescriptor desc,
214             int offset) throws FormatException {
215         CommareaBeanMappingDescriptor nested = desc.getNestedCommarea();
216         Object[] value = (Object[]) Array.newInstance(nested.getBeanClass(),
217                                                       desc.getOccursSize());
218 
219         for (int i = 0; i < value.length; i++) {
220 
221             // questo serve a riutilizzare quanto scritto per
222             // formatNestedCommarea, costruisce in cobolTypeNested finto
223             CobolTypeDescriptor nestedDesc = new CobolTypeDescriptor();
224 
225             nestedDesc.setType(CobolType.NESTED_COMMAREA);
226             nestedDesc.setNestedCommarea(nested);
227             value[i] = unformatNestedCommarea(buffer, nestedDesc, offset);
228             offset += nested.getBufferedLength();
229         }
230         return value;
231     }
232 
233     static Object unformatNestedCommarea(byte[] buffer,
234             CobolTypeDescriptor desc, int offset) throws FormatException {
235         ServiceContext ctx = new ServiceContext();
236         byte[] outputMessage = new byte[desc.getBufferedLength()];
237 
238         System.arraycopy(buffer, offset, outputMessage, 0,
239                          outputMessage.length);
240         ctx.setOutputMessage(outputMessage);
241         ctx.setOutputMappingDescriptor(desc.getNestedCommarea());
242         new CommareaFormatter().mapOutputMessageToOutputBean(ctx);
243         return ctx.getOutputBean();
244     }
245 }