1 /* gnuDynFixed.java --
2    Copyright (C) 2005 Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package gnu.CORBA.DynAn;
40 
41 import org.omg.CORBA.Any;
42 import org.omg.CORBA.BAD_OPERATION;
43 import org.omg.CORBA.BAD_PARAM;
44 import org.omg.CORBA.ORB;
45 import org.omg.CORBA.TypeCode;
46 import org.omg.DynamicAny.DynAny;
47 import org.omg.DynamicAny.DynAnyPackage.InvalidValue;
48 import org.omg.DynamicAny.DynAnyPackage.TypeMismatch;
49 import org.omg.DynamicAny.DynFixed;
50 import org.omg.DynamicAny.DynFixedOperations;
51 
52 import java.math.BigDecimal;
53 
54 /**
55  * Implements DynAny, holding CORBA <code>fixed</code>. This class is derived
56  * from gnuDynEnm to avoid repetetive inclusion of unused DynAny methods.
57  *
58  * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
59  */
60 public class gnuDynFixed extends UndivideableAny implements DynFixed
61 {
62   /**
63    * Use serialVersionUID for interoperability.
64    */
65   private static final long serialVersionUID = 1;
66 
67   /**
68    * The default value, assigned in the new instance.
69    */
70   static final BigDecimal ZERO = new BigDecimal("0.0");
71 
72   /**
73    * The content of the dyn fixed, wrapped in this DynAny.
74    */
75   BigDecimal value;
76 
77   /**
78    * The number of digits after the decimal point.
79    */
80   final int scale;
81 
82   /**
83    * The number of digits.
84    */
85   final int digits;
86 
87   /**
88    * Create a new instance of the dyn fixed.
89    */
gnuDynFixed(TypeCode oType, TypeCode aType, gnuDynAnyFactory aFactory, ORB anOrb )90   public gnuDynFixed(TypeCode oType, TypeCode aType,
91     gnuDynAnyFactory aFactory, ORB anOrb
92   )
93   {
94     super(oType, aType, aFactory, anOrb);
95     try
96       {
97         digits = final_type.fixed_digits();
98         scale = final_type.fixed_scale();
99       }
100     catch (Exception e)
101       {
102         throw new BAD_PARAM("Not a fixed");
103       }
104     value = ZERO;
105   }
106 
107   /**
108    * Clone the current instance.
109    */
gnuDynFixed(gnuDynFixed from)110   public gnuDynFixed(gnuDynFixed from)
111   {
112     super(from.official_type, from.final_type, from.factory, from.orb);
113     digits = from.digits;
114     scale = from.scale;
115     value = from.value;
116   }
117 
118   /**
119    * Get the value of the wrapped dyn fixed, as string.
120    */
get_value()121   public String get_value()
122   {
123     return value.toString();
124   }
125 
126   /**
127    * Set the value.
128    */
set_value(String fixed_value)129   public boolean set_value(String fixed_value)
130     throws TypeMismatch, InvalidValue
131   {
132     // Count the digits till decimal point.
133     int digs = 0;
134     char c;
135     boolean leading0 = true;
136     Digs:
137     for (int i = 0; i < fixed_value.length(); i++)
138       {
139         c = fixed_value.charAt(i);
140         if (Character.isDigit(c))
141           {
142             if (!(c == '0' && leading0))
143               digs++;
144             if (c != '0')
145               leading0 = false;
146           }
147         else if (c == '.')
148           break Digs;
149       }
150     if (digs > (digits - scale))
151       throw new InvalidValue("Too many digits: " + digs + " for " + digits +
152         "." + scale
153       );
154 
155     try
156       {
157         value = new BigDecimal(fixed_value);
158       }
159     catch (NumberFormatException ex)
160       {
161         if (fixed_value.trim().length() == 0)
162           throw new InvalidValue("Empty string passed");
163 
164         TypeMismatch inva =
165           new TypeMismatch("Not a number: '" + fixed_value + "'");
166         inva.initCause(ex);
167         throw inva;
168       }
169 
170     valueChanged();
171     return value.scale() <= scale;
172   }
173 
174   /**
175    * Assign the value from another BigDecimal.
176    */
assign(DynAny from)177   public void assign(DynAny from) throws TypeMismatch
178   {
179     checkType(official_type, from.type());
180 
181     if (from instanceof gnuDynFixed)
182       {
183         gnuDynFixed other = (gnuDynFixed) from;
184         value = other.value;
185       }
186     else if (from instanceof DynFixedOperations)
187       {
188         value = new BigDecimal(((DynFixedOperations) from).get_value());
189       }
190     else
191       throw new TypeMismatch("Not a DynFixed");
192     valueChanged();
193   }
194 
195   /**
196    * Create a copy.
197    */
copy()198   public DynAny copy()
199   {
200     return new gnuDynFixed(this);
201   }
202 
203   /**
204    * Compare for equality.
205    */
equal(DynAny other)206   public boolean equal(DynAny other)
207   {
208     if (other instanceof gnuDynFixed)
209       {
210         // Normally, this code would be executed.
211         return value.equals(((gnuDynFixed) other).value);
212       }
213     if (other instanceof DynFixedOperations)
214       {
215         // This may be involved when mixing implementations.
216         return ((DynFixedOperations) other).get_value().equals(get_value());
217       }
218     else
219       return false;
220   }
221 
222   /**
223    * Set the value from Any (must hold <code>fixed</code> with the matching
224    * typecode.).
225    */
from_any(Any an_any)226   public void from_any(Any an_any) throws TypeMismatch, InvalidValue
227   {
228     try
229       {
230         checkType(official_type, an_any.type());
231 
232         value = an_any.extract_fixed();
233         valueChanged();
234       }
235     catch (BAD_OPERATION e)
236       {
237         InvalidValue t = new InvalidValue();
238         t.initCause(e);
239         throw t;
240       }
241   }
242 
243   /**
244    * Create and return Any, holding this DynFixed value.
245    */
to_any()246   public Any to_any()
247   {
248     Any g = createAny();
249     g.insert_fixed(value, official_type);
250     return g;
251   }
252 }
253