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   package it.imolinfo.jbi4cics.typemapping.cobol;
9   
10  import it.imolinfo.jbi4cics.Logger;
11  import it.imolinfo.jbi4cics.LoggerFactory;
12  import it.imolinfo.jbi4cics.exception.FormatException;
13  import it.imolinfo.jbi4cics.jbi.Messages;
14  
15  import java.math.BigDecimal;
16  
17  public class PackedDecimalMarshaller {
18  	
19    /**
20     * The logger for this class and its instances.
21     */
22    private static final Logger LOG
23            = LoggerFactory.getLogger(PackedDecimalMarshaller.class);
24    
25    /**
26     * The responsible to translate localized messages.
27     */
28    private static final Messages MESSAGES
29            = Messages.getMessages(PackedDecimalMarshaller.class);
30    
31    
32      
33    public final static byte POSITIVE_SIGN = 0x0C;
34    public final static byte NEGATIVE_SIGN = 0x0D;
35    public final static byte NO_SIGN = 0x0F;
36    
37    /**
38     * void constructor.
39     */
40      public PackedDecimalMarshaller(){
41      }
42    
43    /*
44     * questo formato memorizza due cifre per byte. 
45     */
46    public static void marshallBigDecimal(BigDecimal value, byte[] buffer, CobolTypeDescriptor cobolType, int startingOffset) throws FormatException{
47      LOG.debug("value: "+value);
48      //log.debug("virtualDecimalPoint: "+cobolType.getVirtualDecimalPoint());
49      value=value.movePointRight(cobolType.getVirtualDecimalPoint());
50      //log.debug("value2: "+value);
51      value=value.setScale(0);
52      //log.debug("value3: "+value);
53      boolean isNegative=false;
54      if (value.compareTo(new BigDecimal(0))==-1){
55        value=value.abs();
56        isNegative=true;
57      }
58      //log.debug("value4: "+value);
59      String stringValue=value.toPlainString();
60      //log.debug("stringValue: "+stringValue);
61      StringBuffer stringBufferValue=new StringBuffer();
62      int numberSize=cobolType.getIntegerPartLength()+cobolType.getDecimalPartLength();
63  //  at this point we don't have scale and comma and sign
64      for (int i=0;i<(numberSize-stringValue.length());i++){
65        stringBufferValue.append('0');
66      }
67      // at this point we have the right length
68      stringValue=stringBufferValue+stringValue;
69      //log.debug("stringValue after padding: "+stringValue.toString());
70      byte[] valueArray=stringValue.toString().getBytes();
71      int bufferedLength=cobolType.getBufferedLength();
72      for (int i=bufferedLength-1;i>=0;i--){
73        byte result;
74        if (i==bufferedLength-1){
75        // gestione del segno
76          byte signByte;
77          if (cobolType.isSigned()){
78            if (isNegative){
79              signByte=NEGATIVE_SIGN;
80            }
81            else {
82              signByte=POSITIVE_SIGN;
83            }
84          }
85          else {
86            signByte=NO_SIGN;
87          }
88          result=(byte)((valueArray[i*2+(valueArray.length%2)-1]<<4)|signByte);
89        }
90        else {
91          if (i==0 && (valueArray.length%2)==0){
92            result=(byte)(0x0f&valueArray[0]);
93          }
94          else {
95            byte lowSemibyte=(byte)(0x0f&valueArray[i*2+(valueArray.length%2)]);
96            byte highSemibyte=(byte)(0x0f&valueArray[i*2+(valueArray.length%2)-1]);
97  //          log.debug("indice: "+i+Arrays.toString(valueArray));
98  //          log.debug("indice lowsemibyte:"+(i*2+(valueArray.length%2))+" lowSemibyte:       "+lowSemibyte);
99  //          log.debug("lowSemibyte:       ["+HexDump.toHex(lowSemibyte)+"]");
100 //          log.debug("indice highSemibyte: "+(i*2+(valueArray.length%2)-1)+" highSemibyte:       "+highSemibyte);
101 //          log.debug("highSemibyte:       ["+HexDump.toHex(highSemibyte)+"]");
102           result=(byte)( (highSemibyte << 4) | lowSemibyte );
103         }
104       }
105       // a questo punto abbiamo il byte dobbiamo inserirlo al punto giusto
106       buffer[startingOffset+i]=result;      
107     }    
108   }
109   
110   public static BigDecimal unmarshallBigDecimal(byte[] buffer, CobolTypeDescriptor cobolType,int startingOffset) throws FormatException{
111     StringBuffer stringBuffer=new StringBuffer();
112     boolean positive=true;
113     for (int i=0;i<cobolType.getBufferedLength();i++){      
114       byte currentByte=buffer[startingOffset+i];
115       //log.debug("current byte: "+currentByte);
116       if (i==cobolType.getBufferedLength()-1){
117         //gestione del segno
118         if (cobolType.isSigned()){
119           byte signbyte=(byte)(currentByte&0x0F);
120           switch (signbyte) {
121             case POSITIVE_SIGN : {positive=true;break;}
122             case NEGATIVE_SIGN : {positive=false;break;}
123             default: {
124               LOG.error("CIC002115_Signed_decimal_int_not_found", signbyte);
125               throw new FormatException(MESSAGES.getString("CIC002115_Signed_decimal_int_not_found", signbyte));
126             }
127           }
128         }        
129         byte firstChar=(byte)((currentByte&0xF0)>>4);
130         stringBuffer.append(String.valueOf(firstChar));
131       }
132       else {
133         byte lowSemiByte=(byte)(currentByte&0x0F);
134         byte highSemiByte=(byte)((currentByte&0xF0)>>4);
135         //log.debug("lowSemiByte: "+lowSemiByte);
136         //log.debug("highSemiByte: "+highSemiByte);
137         stringBuffer.append(String.valueOf(highSemiByte));
138         stringBuffer.append(String.valueOf(lowSemiByte));
139         
140         //log.debug("stringbuffer: "+stringBuffer);
141       }        
142     }
143     //log.debug("stringbuffer: "+stringBuffer);
144     BigDecimal result=new BigDecimal(stringBuffer.toString());
145     //log.debug("result1: "+result);
146     result=result.setScale(0);
147     //log.debug("result2: "+result);
148     result=result.movePointLeft(cobolType.getVirtualDecimalPoint());
149     //log.debug("result3: "+result);
150     if (!positive){
151       result=result.negate();
152     }
153     //log.debug("result4: "+result);
154     return result;
155   }
156 
157 }