View Javadoc

1   /*
2    * File:    DecimalAttribute.java
3    * Created: 22.10.2006 17:11:19
4    *
5    * Copyright 2006 Michal Burda.
6    *
7    * This program is free software; you can redistribute it and/or modify
8    * it under the terms of the GNU General Public License as published by
9    * the Free Software Foundation; either version 2 of the License, or
10   * (at your option) any later version.
11   *
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Public License for more details.
16   *
17   * You should have received a copy of the GNU General Public License
18   * along with this program; if not, write to the Free Software
19   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20   */
21  
22  package net.sf.webmancer.db;
23  
24  import net.sf.webmancer.util.ContractChecker;
25  
26  /**
27   * @author Michal Burda
28   *
29   */
30  public class DecimalAttribute extends AbstractAttribute {
31      /**
32       * 
33       */
34      private double minimum;
35  
36      /**
37       * 
38       */
39      private double maximum;
40  
41      /**
42       * 
43       */
44      private int digits;
45  
46      /**
47       * 
48       */
49      private int scale;
50  
51      /**
52       * @param digits
53       * @param scale
54       */
55      public DecimalAttribute(int digits, int scale) {
56          super();
57          ContractChecker.mustBePositive(digits, "digits");
58          ContractChecker.mustNotBeNegative(scale, "scale");
59          ContractChecker.mustBe(digits >= scale, "The 'digits' parameter must be greater or equal to 'scale'");
60  
61          this.digits = digits;
62          this.scale = scale;
63          this.maximum = (Math.pow(10, digits) - 1) / Math.pow(10, scale);
64          this.minimum = -this.maximum;
65      }
66  
67      /**
68       * Gets the digits.
69       * 
70       * @return the digits
71       */
72      public int getDigits() {
73          return digits;
74      }
75  
76      /**
77       * Gets the maximum.
78       * 
79       * @return the maximum
80       */
81      public double getMaximum() {
82          return maximum;
83      }
84  
85      /**
86       * Sets the maximum.
87       * 
88       * @param maximum
89       *            the maximum to set
90       */
91      public void setMaximum(double maximum) {
92          checkNumberOfDigits(maximum, "maximum");
93          this.maximum = maximum;
94      }
95  
96      /**
97       * Gets the minimum.
98       * 
99       * @return the minimum
100      */
101     public double getMinimum() {
102         return minimum;
103     }
104 
105     /**
106      * Sets the minimum.
107      * 
108      * @param minimum
109      *            the minimum to set
110      */
111     public void setMinimum(double minimum) {
112         checkNumberOfDigits(minimum, "minimum");
113         this.minimum = minimum;
114     }
115 
116     /**
117      * Gets the scale.
118      * 
119      * @return the scale
120      */
121     public int getScale() {
122         return scale;
123     }
124 
125     /**
126      * @see net.sf.webmancer.db.AbstractAttribute#getMaximumInputLength()
127      */
128     @Override
129     public int getMaximumInputLength() {
130         // first, determine number of digits before decimal point needed to represent min or max value, respectively
131         int maxlog = getDigitsBeforeDecimalPoint(this.getMaximum());
132         int minlog = getDigitsBeforeDecimalPoint(this.getMinimum());
133         int maxlen = Math.max(maxlog, minlog);
134         
135         // add +1 to the maximum length if the minimum is longer than maximum (for the minus sign)
136         if (minlog >= maxlog) {
137             maxlen++; // for the minus sign
138         }
139         
140         // add length of digits after decimal point
141         if (this.getScale() > 0) {
142             maxlen += this.getScale() + 1; // for the decimal point
143             if (this.getScale() == this.getDigits()) {
144                 maxlen++; // for the leading "0"
145             }
146         }
147         return maxlen;
148     }
149     
150     /**
151      * @param value
152      * @return
153      */
154     private int getDigitsBeforeDecimalPoint(double value) {
155         return (int) Math.floor(Math.log10(Math.abs(value))) + 1;
156     }
157 
158     /**
159      * @param minimum2
160      */
161     private void checkNumberOfDigits(double value, String parameter) {
162         int r = getDigitsBeforeDecimalPoint(value);
163         int mustBeMax = this.getDigits() - this.getScale();
164         if (r > mustBeMax) {
165             ContractChecker.mustBe(false, "The number of digits in '" + parameter + "' is too large: " + r + " (should be " + mustBeMax + " at maximum)");
166         }
167     }
168 
169     /**
170      * @see net.sf.webmancer.db.AbstractAttribute#convertDbToInternal(java.lang.Object)
171      */
172     @Override
173     public Object convertDbToInternal(Object dbValue) {
174         // TODO Auto-generated method stub
175         throw new UnsupportedOperationException("NumericAttribute.convertDbToInternal");
176     }
177 
178     /**
179      * @see net.sf.webmancer.db.AbstractAttribute#convertInternalToInput(java.lang.Object)
180      */
181     @Override
182     public String convertInternalToInput(Object internal) {
183         ContractChecker.mustBeInstanceOf(internal, Number.class, "internal");
184         Number theVal = (Number) internal;
185         return theVal.toString();
186     }
187 
188     /**
189      * @see net.sf.webmancer.db.AbstractAttribute#convertInternalToOutput(java.lang.Object)
190      */
191     @Override
192     public String convertInternalToOutput(Object internal) {
193         ContractChecker.mustBeInstanceOf(internal, Number.class, "internal");
194         Number theVal = (Number) internal;
195         return theVal.toString();
196     }
197 
198 }