001: /*
002: The contents of this file are subject to the Common Public Attribution License
003: Version 1.0 (the "License"); you may not use this file except in compliance with
004: the License. You may obtain a copy of the License at
005: http://www.projity.com/license . The License is based on the Mozilla Public
006: License Version 1.1 but Sections 14 and 15 have been added to cover use of
007: software over a computer network and provide for limited attribution for the
008: Original Developer. In addition, Exhibit A has been modified to be consistent
009: with Exhibit B.
010:
011: Software distributed under the License is distributed on an "AS IS" basis,
012: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the
013: specific language governing rights and limitations under the License. The
014: Original Code is OpenProj. The Original Developer is the Initial Developer and
015: is Projity, Inc. All portions of the code written by Projity are Copyright (c)
016: 2006, 2007. All Rights Reserved. Contributors Projity, Inc.
017:
018: Alternatively, the contents of this file may be used under the terms of the
019: Projity End-User License Agreeement (the Projity License), in which case the
020: provisions of the Projity License are applicable instead of those above. If you
021: wish to allow use of your version of this file only under the terms of the
022: Projity License and not to allow others to use your version of this file under
023: the CPAL, indicate your decision by deleting the provisions above and replace
024: them with the notice and other provisions required by the Projity License. If
025: you do not delete the provisions above, a recipient may use your version of this
026: file under either the CPAL or the Projity License.
027:
028: [NOTE: The text of this license may differ slightly from the text of the notices
029: in Exhibits A and B of the license at http://www.projity.com/license. You should
030: use the latest text at http://www.projity.com/license for your modifications.
031: You may not remove this license text from the source files.]
032:
033: Attribution Information: Attribution Copyright Notice: Copyright © 2006, 2007
034: Projity, Inc. Attribution Phrase (not exceeding 10 words): Powered by OpenProj,
035: an open source solution from Projity. Attribution URL: http://www.projity.com
036: Graphic Image as provided in the Covered Code as file: openproj_logo.png with
037: alternatives listed on http://www.projity.com/logo
038:
039: Display of Attribution Information is required in Larger Works which are defined
040: in the CPAL as a work which combines Covered Code or portions thereof with code
041: not governed by the terms of the CPAL. However, in addition to the other notice
042: obligations, all copies of the Covered Code in Executable and Source Code form
043: distributed must, as a form of attribution of the original author, include on
044: each user interface screen the "OpenProj" logo visible to all users. The
045: OpenProj logo should be located horizontally aligned with the menu bar and left
046: justified on the top left of the screen adjacent to the File menu. The logo
047: must be at least 100 x 25 pixels. When users click on the "OpenProj" logo it
048: must direct them back to http://www.projity.com.
049: */
050: package com.projity.datatype;
051:
052: import java.text.FieldPosition;
053: import java.text.Format;
054: import java.text.NumberFormat;
055: import java.text.ParsePosition;
056:
057: import com.projity.configuration.Settings;
058: import com.projity.options.ScheduleOption;
059: import com.projity.util.ClassUtils;
060:
061: /**
062: *
063: */
064: public class RateFormat extends Format implements TimeUnit {
065: private static NumberFormat MONEY_FORMAT = Money
066: .getMoneyFormatInstance(); //NumberFormat.getCurrencyInstance();
067: private static NumberFormat NUMBER_FORMAT = NumberFormat
068: .getNumberInstance();
069: private static NumberFormat PERCENT_FORMAT = NumberFormat
070: .getPercentInstance();
071:
072: private static RateFormat moneyInstance = null;
073: private static RateFormat instance = null;
074: private static RateFormat percentInstance = null;
075: private static RateFormat nonTemporalInstance = null;
076: private String timeUnitLabel;
077: private boolean money;
078: public boolean percent;
079: private boolean temporal;
080:
081: public static RateFormat getInstance(Object object, boolean money,
082: boolean percent, boolean temporal) {
083: if (instance == null) {
084: instance = new RateFormat(null, false, false, true);
085: moneyInstance = new RateFormat(null, true, false, true);
086: percentInstance = new RateFormat(null, false, true, true);
087: nonTemporalInstance = new RateFormat(null, false, false,
088: false);
089: }
090: String timeUnit = unitLabelOfObject(object);
091: if (percent)
092: return percentInstance;
093: if (timeUnit != null)
094: return new RateFormat(timeUnit, money, false, temporal);
095: if (money)
096: return moneyInstance;
097: else if (temporal)
098: return instance;
099: else
100: return nonTemporalInstance;
101: }
102:
103: public static String unitLabelOfObject(Object object) {
104: String result = null;
105: if (object != null) {
106: if (object instanceof String)
107: result = (String) object;
108: else if (object instanceof CanSupplyRateUnit) {
109: result = ((CanSupplyRateUnit) object)
110: .getTimeUnitLabel();
111: if (result == null)
112: result = "";
113: }
114: }
115: return result;
116: }
117:
118: /**
119: *
120: */
121: private RateFormat(String timeUnitLabel, boolean money,
122: boolean percent, boolean temporal) {
123: super ();
124: this .money = money;
125: this .percent = percent;
126: this .timeUnitLabel = timeUnitLabel;
127: this .temporal = temporal;
128: }
129:
130: /* (non-Javadoc)
131: * @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
132: */
133: public Object parseObject(String rateString, ParsePosition pos) {
134: if (rateString.length() == 0)
135: return null;
136:
137: if (rateString.charAt(pos.getIndex()) == '+') // if string begins with + sign, ignore it
138: pos.setIndex(pos.getIndex() + 1);
139:
140: Number numberResult = null;
141: if (percent) {
142: numberResult = PERCENT_FORMAT.parse(rateString, pos);
143: if (numberResult == null) {
144: numberResult = NUMBER_FORMAT.parse(rateString, pos);
145: if (numberResult != null)
146: numberResult = new Double(numberResult
147: .doubleValue() / 100.0D);
148: }
149: if (numberResult == null)
150: return null;
151: return new Rate(numberResult.doubleValue(),
152: TimeUnit.PERCENT);
153: }
154:
155: if (money)
156: numberResult = MONEY_FORMAT.parse(rateString, pos);
157: if (numberResult == null)
158: numberResult = NUMBER_FORMAT.parse(rateString, pos);
159: if (numberResult == null)
160: return null;
161: double rate = numberResult.doubleValue();
162: String durationPart = rateString.substring(pos.getIndex());
163: durationPart = durationPart.trim();
164:
165: // at this point, we have the number and are now focusing on the suffix
166: int type = TimeUnit.NON_TEMPORAL;
167: int slashIndex = durationPart.indexOf(Settings.SLASH);
168: if (slashIndex == -1) { // if no slash
169: if (timeUnitLabel == null && temporal) // temporal types use default
170: type = getDefaultType();
171: } else {
172: durationPart = "1"
173: + durationPart.substring(slashIndex + 1,
174: durationPart.length());// replace the slash with a 1
175: Duration duration = (Duration) DurationFormat.getInstance()
176: .parseObject(durationPart, new ParsePosition(0));
177: if (duration == null)
178: return null;
179: type = Duration.getEffectiveType(duration
180: .getEncodedMillis());
181: }
182: rate /= Duration.timeUnitFactor(type);
183: return new Rate(rate, type);
184: }
185:
186: /* (non-Javadoc)
187: * @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
188: */
189: public StringBuffer format(Object rateObject,
190: StringBuffer toAppendTo, FieldPosition pos) {
191:
192: if (rateObject == null)
193: return toAppendTo;
194: else if (rateObject == ClassUtils.defaultRate)
195: return toAppendTo; // do nothing
196: else if (rateObject == ClassUtils.defaultUnitlessRate)
197: return toAppendTo;
198:
199: Rate rate = (Rate) rateObject;
200: double rateValue = rate.getValue();
201: int type = rate.getTimeUnit();
202: if (type == TimeUnit.NONE && temporal) // if no unit, use default
203: type = getDefaultType();
204:
205: if (percent) {
206: PERCENT_FORMAT.format(new Double(rateValue), toAppendTo,
207: pos);
208: } else {
209: rateValue *= Duration.timeUnitFactor(type);
210: if (money) {
211: MONEY_FORMAT.format(new Double(rateValue), toAppendTo,
212: pos);
213: } else {
214: NumberFormat.getInstance().format(
215: new Double(rateValue), toAppendTo, pos);
216: if (timeUnitLabel != null && !timeUnitLabel.equals(""))
217: toAppendTo.append(" " + timeUnitLabel);
218: }
219:
220: if (type != TimeUnit.NON_TEMPORAL) { // if value is expressed in duration
221: toAppendTo.append(Settings.SLASH);
222: String unit = DurationFormat.formatTypeUnit(type);
223: toAppendTo.append(unit);
224: }
225: }
226: return toAppendTo;
227: }
228:
229: private int getDefaultType() {
230: return ScheduleOption.getInstance().getRateEnteredIn();
231: }
232: }
|