001: /*
002: * Copyright (c) 2002-2007 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.binding.value;
032:
033: import java.text.Format;
034: import java.text.ParseException;
035:
036: /**
037: * A factory that vends ValueModels that convert types, for example
038: * Dates to Strings. More formally, a converting ValueModel <i>VM1</i>
039: * converts the type <i>T2</i> of an object being held as a value in
040: * one ValueModel <i>VM2</i> into another type <i>T1</i>.
041: * When reading a value from VM1, instances of T2 are read from VM2
042: * and are converted to T1. When storing a new value to VM1,
043: * the type converter will perform the inverse conversion and
044: * will convert an instance of T1 to T2.<p>
045: *
046: * Type converters should be used judiciously and only to bridge two
047: * ValueModels. To bind non-Strings to a text UI component
048: * you should better use a {@link javax.swing.JFormattedTextField}.
049: * They provide a more powerful means to convert strings to objects
050: * and handle many cases that arise around invalid input. See also the classes
051: * {@link com.jgoodies.binding.adapter.Bindings} and
052: * {@link com.jgoodies.binding.adapter.BasicComponentFactory} on how to
053: * bind ValueModels to formatted text fields.<p>
054: *
055: * The inner converter implementations have a 'public' visibility
056: * to enable reflection access.
057: *
058: * @author Karsten Lentzsch
059: * @version $Revision: 1.7 $
060: *
061: * @see ValueModel
062: * @see Format
063: * @see javax.swing.JFormattedTextField
064: */
065: public final class ConverterFactory {
066:
067: private ConverterFactory() {
068: // Overrides default constructor; prevents instantiation.
069: }
070:
071: // Factory Methods ********************************************************
072:
073: /**
074: * Creates and returns a ValueModel that negates Booleans and leaves
075: * null unchanged.<p>
076: *
077: * <strong>Constraints:</strong> The subject is of type <code>Boolean</code>.
078: *
079: * @param booleanSubject a Boolean ValueModel
080: * @return a ValueModel that inverts Booleans
081: *
082: * @throws NullPointerException if the subject is <code>null</code>
083: */
084: public static ValueModel createBooleanNegator(
085: ValueModel booleanSubject) {
086: return new BooleanNegator(booleanSubject);
087: }
088:
089: /**
090: * Creates and returns a ValueModel that converts Booleans
091: * to the associated of the two specified strings, and vice versa.
092: * Null values are mapped to an empty string.
093: * Ignores cases when setting a text.<p>
094: *
095: * <strong>Constraints:</strong> The subject is of type <code>Boolean</code>.
096: *
097: * @param booleanSubject a Boolean ValueModel
098: * @param trueText the text associated with <code>Boolean.TRUE</code>
099: * @param falseText the text associated with <code>Boolean.FALSE</code>
100: *
101: * @return a ValueModel that converts boolean to the associated text
102: *
103: * @throws NullPointerException if the subject, trueText or falseText
104: * is <code>null</code>
105: * @throws IllegalArgumentException if the trueText equals the falseText
106: */
107: public static ValueModel createBooleanToStringConverter(
108: ValueModel booleanSubject, String trueText, String falseText) {
109: return createBooleanToStringConverter(booleanSubject, trueText,
110: falseText, "");
111: }
112:
113: /**
114: * Creates and returns a ValueModel that converts Booleans
115: * to the associated of the two specified strings, and vice versa.
116: * Null values are mapped to the specified text.
117: * Ignores cases when setting a text.<p>
118: *
119: * <strong>Constraints:</strong> The subject is of type <code>Boolean</code>.
120: *
121: * @param booleanSubject a Boolean ValueModel
122: * @param trueText the text associated with <code>Boolean.TRUE</code>
123: * @param falseText the text associated with <code>Boolean.FALSE</code>
124: * @param nullText the text associated with <code>null</code>
125: *
126: * @return a ValueModel that converts boolean to the associated text
127: *
128: * @throws NullPointerException if the subject, trueText, falseText
129: * or nullText is <code>null</code>
130: * @throws IllegalArgumentException if the trueText equals the falseText
131: */
132: public static ValueModel createBooleanToStringConverter(
133: ValueModel booleanSubject, String trueText,
134: String falseText, String nullText) {
135: return new BooleanToStringConverter(booleanSubject, trueText,
136: falseText, nullText);
137: }
138:
139: /**
140: * Creates and returns a ValueModel that converts Doubles using the
141: * specified multiplier.<p>
142: *
143: * Examples: multiplier=100, Double(1.23) -> Double(123),
144: * multiplier=1000, Double(1.23) -> Double(1230)<p>
145: *
146: * <strong>Constraints:</strong> The subject is of type <code>Double</code>.
147: *
148: * @param doubleSubject a Double ValueModel
149: * @param multiplier the multiplier used for the conversion
150: *
151: * @return a ValueModel that converts Doubles using the specified multiplier
152: *
153: * @throws NullPointerException if the subject is <code>null</code>
154: *
155: * @since 1.0.2
156: */
157: public static ValueModel createDoubleConverter(
158: ValueModel doubleSubject, double multiplier) {
159: return new DoubleConverter(doubleSubject, multiplier);
160: }
161:
162: /**
163: * Creates and returns a ValueModel that converts Doubles to Integer,
164: * and vice versa.<p>
165: *
166: * <strong>Constraints:</strong> The subject is of type <code>Double</code>.
167: *
168: * @param doubleSubject a Double ValueModel
169: *
170: * @return a ValueModel that converts Doubles to Integer
171: *
172: * @throws NullPointerException if the subject is <code>null</code>
173: */
174: public static ValueModel createDoubleToIntegerConverter(
175: ValueModel doubleSubject) {
176: return createDoubleToIntegerConverter(doubleSubject, 1);
177: }
178:
179: /**
180: * Creates and returns a ValueModel that converts Doubles to Integer,
181: * and vice versa. The multiplier can be used to convert Doubles
182: * to percent, permill, etc. For a percentage, set the multiplier to be 100,
183: * for a permill, set the multiplier to be 1000.<p>
184: *
185: * Examples: multiplier=100, Double(1.23) -> Integer(123),
186: * multiplier=1000, Double(1.23) -> Integer(1230)<p>
187: *
188: * <strong>Constraints:</strong> The subject is of type <code>Double</code>.
189: *
190: * @param doubleSubject a Double ValueModel
191: * @param multiplier the multiplier used to convert the Double to Integer
192: *
193: * @return a ValueModel that converts Doubles to Integer
194: *
195: * @throws NullPointerException if the subject is <code>null</code>
196: */
197: public static ValueModel createDoubleToIntegerConverter(
198: ValueModel doubleSubject, int multiplier) {
199: return new DoubleToIntegerConverter(doubleSubject, multiplier);
200: }
201:
202: /**
203: * Creates and returns a ValueModel that converts Floats using the
204: * specified multiplier.<p>
205: *
206: * Examples: multiplier=100, Float(1.23) -> Float(123),
207: * multiplier=1000, Float(1.23) -> Float(1230)<p>
208: *
209: * <strong>Constraints:</strong> The subject is of type <code>Float</code>.
210: *
211: * @param floatSubject a Float ValueModel
212: * @param multiplier the multiplier used for the conversion
213: *
214: * @return a ValueModel that converts Float using the specified multiplier
215: *
216: * @throws NullPointerException if the subject is <code>null</code>
217: *
218: * @since 1.0.2
219: */
220: public static ValueModel createFloatConverter(
221: ValueModel floatSubject, float multiplier) {
222: return new FloatConverter(floatSubject, multiplier);
223: }
224:
225: /**
226: * Creates and returns a ValueModel that converts Floats to Integer,
227: * and vice versa.<p>
228: *
229: * <strong>Constraints:</strong> The subject is of type <code>Float</code>.
230: * s
231: * @param floatSubject a Float ValueModel
232: *
233: * @return a ValueModel that converts Floats to Integer
234: *
235: * @throws NullPointerException if the subject is <code>null</code>
236: */
237: public static ValueModel createFloatToIntegerConverter(
238: ValueModel floatSubject) {
239: return createFloatToIntegerConverter(floatSubject, 1);
240: }
241:
242: /**
243: * Creates and returns a ValueModel that converts Floats to Integer,
244: * and vice versa. The multiplier can be used to convert Floats
245: * to percent, permill, etc. For a percentage, set the multiplier to be 100,
246: * for a permill, set the multiplier to be 1000.<p>
247: *
248: * <strong>Constraints:</strong> The subject is of type <code>Float</code>.
249: *
250: * @param floatSubject a Float ValueModel
251: * @param multiplier the multiplier used to convert the Float to Integer
252: *
253: * @return a ValueModel that converts Floats to Integer
254: *
255: * @throws NullPointerException if the subject is <code>null</code>
256: */
257: public static ValueModel createFloatToIntegerConverter(
258: ValueModel floatSubject, int multiplier) {
259: return new FloatToIntegerConverter(floatSubject, multiplier);
260: }
261:
262: /**
263: * Creates and returns a ValueModel that converts Integers using the
264: * specified multiplier.<p>
265: *
266: * Examples: multiplier=100, Integer(3) -> Integer(300),
267: * multiplier=1000, Integer(3) -> Integer(3000)<p>
268: *
269: * <strong>Constraints:</strong> The subject is of type <code>Integer</code>.
270: *
271: * @param integerSubject a Integer ValueModel
272: * @param multiplier the multiplier used for the conversion
273: *
274: * @return a ValueModel that converts Integers using the specified multiplier
275: *
276: * @throws NullPointerException if the subject is <code>null</code>
277: *
278: * @since 1.0.2
279: */
280: public static ValueModel createIntegerConverter(
281: ValueModel integerSubject, double multiplier) {
282: return new IntegerConverter(integerSubject, multiplier);
283: }
284:
285: /**
286: * Creates and returns a ValueModel that converts Long using the
287: * specified multiplier.<p>
288: *
289: * Examples: multiplier=100, Long(3) -> Long(300),
290: * multiplier=1000, Long(3) -> Long(3000)<p>
291: *
292: * <strong>Constraints:</strong> The subject is of type <code>Long</code>.
293: *
294: * @param longSubject a Long ValueModel
295: * @param multiplier the multiplier used for the conversion
296: *
297: * @return a ValueModel that converts Longs using the specified multiplier
298: *
299: * @throws NullPointerException if the subject is <code>null</code>
300: *
301: * @since 1.0.2
302: */
303: public static ValueModel createLongConverter(
304: ValueModel longSubject, double multiplier) {
305: return new LongConverter(longSubject, multiplier);
306: }
307:
308: /**
309: * Creates and returns a ValueModel that converts Longs to Integer
310: * and vice versa.<p>
311: *
312: * <strong>Constraints:</strong> The subject is of type <code>Long</code>,
313: * values written to the converter are of type <code>Integer</code>.
314: *
315: * @param longSubject a Long ValueModel
316: * @return a ValueModel that converts Longs to Integer
317: *
318: * @throws NullPointerException if the subject is <code>null</code>
319: */
320: public static ValueModel createLongToIntegerConverter(
321: ValueModel longSubject) {
322: return createLongToIntegerConverter(longSubject, 1);
323: }
324:
325: /**
326: * Creates and returns a ValueModel that converts Longs to Integer
327: * and vice versa.<p>
328: *
329: * <strong>Constraints:</strong> The subject is of type <code>Long</code>,
330: * values written to the converter are of type <code>Integer</code>.
331: *
332: * @param longSubject a Long ValueModel
333: * @param multiplier used to multiply the Long when converting to Integer
334: * @return a ValueModel that converts Longs to Integer
335: *
336: * @throws NullPointerException if the subject is <code>null</code>
337: */
338: public static ValueModel createLongToIntegerConverter(
339: ValueModel longSubject, int multiplier) {
340: return new LongToIntegerConverter(longSubject, multiplier);
341: }
342:
343: /**
344: * Creates and returns a ValueModel that converts objects to Strings
345: * and vice versa. The conversion is performed by a <code>Format</code>.<p>
346: *
347: * <strong>Constraints:</strong> The subject is of type <code>Object</code>;
348: * it must be formattable and parsable via the given <code>Format</code>.
349: *
350: * @param subject the underlying ValueModel.
351: * @param format the <code>Format</code> used to format and parse
352: *
353: * @return a ValueModel that converts objects to Strings and vice versa
354: *
355: * @throws NullPointerException if the subject or the format
356: * is <code>null</code>
357: */
358: public static ValueModel createStringConverter(ValueModel subject,
359: Format format) {
360: return new StringConverter(subject, format);
361: }
362:
363: // Converter Implementations **********************************************
364:
365: /**
366: * Negates Booleans leaving null unchanged. Maps Boolean.TRUE
367: * to Boolean.FALSE, Boolean.FALSE to Boolean.TRUE, and null to null.
368: */
369: public static final class BooleanNegator extends AbstractConverter {
370:
371: BooleanNegator(ValueModel booleanSubject) {
372: super (booleanSubject);
373: }
374:
375: /**
376: * Negates Booleans leaving null unchanged.
377: * Maps Boolean.TRUE to Boolean.FALSE,
378: * Boolean.FALSE to Boolean.TRUE, and null to null.
379: *
380: * @param subjectValue the subject value to invert
381: * @return the text that represents the subject value
382: *
383: * @throws ClassCastException if the subject's value is not a Boolean
384: */
385: @Override
386: public Object convertFromSubject(Object subjectValue) {
387: return negate(subjectValue);
388: }
389:
390: /**
391: * Inverts the given Boolean and sets it as the subject's new value.
392: *
393: * @param newValue the value to be inverted and set as new subject value
394: * @throws ClassCastException if the new value is not a Boolean
395: * @throws IllegalArgumentException if the new value does neither match
396: * the trueText nor the falseText
397: */
398: public void setValue(Object newValue) {
399: subject.setValue(negate(newValue));
400: }
401:
402: /**
403: * Negates Booleans leaving null unchanged.
404: * Maps Boolean.TRUE to Boolean.FALSE ,
405: * Boolean.FALSE to Boolean.TRUE, and null to null.
406: *
407: * @param value the value to invert
408: * @return the inverted Boolean value, or null if value is null
409: *
410: * @throws ClassCastException if the value is not a Boolean
411: */
412: private Boolean negate(Object value) {
413: if (value == null)
414: return null;
415: else if (Boolean.TRUE.equals(value))
416: return Boolean.FALSE;
417: else if (Boolean.FALSE.equals(value))
418: return Boolean.TRUE;
419: else
420: throw new ClassCastException(
421: "The value must be a Boolean.");
422: }
423:
424: }
425:
426: /**
427: * Converts Booleans to Strings and vice-versa using given texts for
428: * true, false, and null. Throws a ClassCastException if the value
429: * to convert is not a Boolean, or not a String for the reverse conversion.
430: */
431: public static final class BooleanToStringConverter extends
432: AbstractConverter {
433:
434: private final String trueText;
435: private final String falseText;
436: private final String nullText;
437:
438: BooleanToStringConverter(ValueModel booleanSubject,
439: String trueText, String falseText, String nullText) {
440: super (booleanSubject);
441: if ((trueText == null) || (falseText == null)
442: || (nullText == null)) {
443: throw new NullPointerException(
444: "The trueText, falseText and nullText must not be null.");
445: }
446: if (trueText.equals(falseText)) {
447: throw new IllegalArgumentException(
448: "The trueText and falseText must be different.");
449: }
450: this .trueText = trueText;
451: this .falseText = falseText;
452: this .nullText = nullText;
453: }
454:
455: /**
456: * Converts the subject value to associated text representation.
457: * Rejects non-Boolean values.
458: *
459: * @param subjectValue the subject's new value
460: * @return the text that represents the subject value
461: *
462: * @throws ClassCastException if the subject's value is not a Boolean
463: */
464: @Override
465: public Object convertFromSubject(Object subjectValue) {
466: if (Boolean.TRUE.equals(subjectValue))
467: return trueText;
468: else if (Boolean.FALSE.equals(subjectValue))
469: return falseText;
470: else if (subjectValue == null)
471: return nullText;
472: else
473: throw new ClassCastException(
474: "The subject value must be of type Boolean.");
475: }
476:
477: /**
478: * Converts the given String and sets the associated Boolean as
479: * the subject's new value. In case the new value equals neither
480: * this class' trueText, nor the falseText, nor the nullText,
481: * an IllegalArgumentException is thrown.
482: *
483: * @param newValue the value to be converted and set as new subject value
484: * @throws ClassCastException if the new value is not a String
485: * @throws IllegalArgumentException if the new value does neither match
486: * the trueText nor the falseText nor the nullText
487: */
488: public void setValue(Object newValue) {
489: if (!(newValue instanceof String))
490: throw new ClassCastException(
491: "The new value must be a string.");
492:
493: String newString = (String) newValue;
494: if (trueText.equalsIgnoreCase(newString)) {
495: subject.setValue(Boolean.TRUE);
496: } else if (falseText.equalsIgnoreCase(newString)) {
497: subject.setValue(Boolean.FALSE);
498: } else if (nullText.equalsIgnoreCase(newString)) {
499: subject.setValue(null);
500: } else
501: throw new IllegalArgumentException(
502: "The new value must be one of: " + trueText
503: + '/' + falseText + '/' + nullText);
504: }
505:
506: }
507:
508: /**
509: * Converts Doubles using a given multiplier.
510: */
511: public static final class DoubleConverter extends AbstractConverter {
512:
513: private final double multiplier;
514:
515: DoubleConverter(ValueModel doubleSubject, double multiplier) {
516: super (doubleSubject);
517: this .multiplier = multiplier;
518: }
519:
520: /**
521: * Converts the subject's value and returns a
522: * corresponding <code>Double</code> using the multiplier.
523: *
524: * @param subjectValue the subject's value
525: * @return the converted subjectValue
526: * @throws ClassCastException if the subject value is not of type
527: * <code>Double</code>
528: */
529: @Override
530: public Object convertFromSubject(Object subjectValue) {
531: double doubleValue = ((Double) subjectValue).doubleValue();
532: return Double.valueOf(doubleValue * multiplier);
533: }
534:
535: /**
536: * Converts a <code>Double</code> using the multiplier
537: * and sets it as new value.
538: *
539: * @param newValue the <code>Double</code> object that shall be converted
540: * @throws ClassCastException if the new value is not of type
541: * <code>Double</code>
542: */
543: public void setValue(Object newValue) {
544: double doubleValue = ((Double) newValue).doubleValue();
545: subject.setValue(Double.valueOf(doubleValue / multiplier));
546: }
547:
548: }
549:
550: /**
551: * Converts Doubles to Integers and vice-versa.
552: */
553: public static final class DoubleToIntegerConverter extends
554: AbstractConverter {
555:
556: private final int multiplier;
557:
558: DoubleToIntegerConverter(ValueModel doubleSubject,
559: int multiplier) {
560: super (doubleSubject);
561: this .multiplier = multiplier;
562: }
563:
564: /**
565: * Converts the subject's value and returns a
566: * corresponding <code>Integer</code> value using the multiplier.
567: *
568: * @param subjectValue the subject's value
569: * @return the converted subjectValue
570: * @throws ClassCastException if the subject value is not of type
571: * <code>Double</code>
572: */
573: @Override
574: public Object convertFromSubject(Object subjectValue) {
575: double doubleValue = ((Double) subjectValue).doubleValue();
576: if (multiplier != 1)
577: doubleValue *= multiplier;
578: return Integer.valueOf((int) Math.round(doubleValue));
579: }
580:
581: /**
582: * Converts a <code>Double</code> using the multiplier
583: * and sets it as new value.
584: *
585: * @param newValue the <code>Integer</code> object that shall
586: * be converted
587: * @throws ClassCastException if the new value is not of type
588: * <code>Integer</code>
589: */
590: public void setValue(Object newValue) {
591: double doubleValue = ((Integer) newValue).doubleValue();
592: if (multiplier != 1)
593: doubleValue /= multiplier;
594: subject.setValue(Double.valueOf(doubleValue));
595: }
596:
597: }
598:
599: /**
600: * Converts Floats using a given multiplier.
601: */
602: public static final class FloatConverter extends AbstractConverter {
603:
604: private final float multiplier;
605:
606: FloatConverter(ValueModel floatSubject, float multiplier) {
607: super (floatSubject);
608: this .multiplier = multiplier;
609: }
610:
611: /**
612: * Converts the subject's value and returns a
613: * corresponding <code>Float</code> using the multiplier.
614: *
615: * @param subjectValue the subject's value
616: * @return the converted subjectValue
617: * @throws ClassCastException if the subject value is not of type
618: * <code>Float</code>
619: */
620: @Override
621: public Object convertFromSubject(Object subjectValue) {
622: float floatValue = ((Float) subjectValue).floatValue();
623: return Float.valueOf(floatValue * multiplier);
624: }
625:
626: /**
627: * Converts a <code>Float</code> using the multiplier
628: * and sets it as new value.
629: *
630: * @param newValue the <code>Float</code> object that shall be converted
631: * @throws ClassCastException if the new value is not of type
632: * <code>Float</code>
633: */
634: public void setValue(Object newValue) {
635: float floatValue = ((Float) newValue).floatValue();
636: subject.setValue(Float.valueOf(floatValue / multiplier));
637: }
638:
639: }
640:
641: /**
642: * Converts Floats to Integers and vice-versa.
643: */
644: public static final class FloatToIntegerConverter extends
645: AbstractConverter {
646:
647: private final int multiplier;
648:
649: FloatToIntegerConverter(ValueModel floatSubject, int multiplier) {
650: super (floatSubject);
651: this .multiplier = multiplier;
652: }
653:
654: /**
655: * Converts the subject's value and returns a
656: * corresponding <code>Integer</code> using the multiplier.
657: *
658: * @param subjectValue the subject's value
659: * @return the converted subjectValue
660: * @throws ClassCastException if the subject value is not of type
661: * <code>Float</code>
662: */
663: @Override
664: public Object convertFromSubject(Object subjectValue) {
665: float floatValue = ((Float) subjectValue).floatValue();
666: if (multiplier != 1)
667: floatValue *= multiplier;
668: return Integer.valueOf(Math.round(floatValue));
669: }
670:
671: /**
672: * Converts a <code>Float</code> using the multiplier and
673: * sets it as new value.
674: *
675: * @param newValue the <code>Integer</code> object that shall be converted
676: * @throws ClassCastException if the new value is not of type
677: * <code>Integer</code>
678: */
679: public void setValue(Object newValue) {
680: float floatValue = ((Integer) newValue).floatValue();
681: if (multiplier != 1)
682: floatValue /= multiplier;
683: subject.setValue(Float.valueOf(floatValue));
684: }
685:
686: }
687:
688: /**
689: * Converts Longs using a given multiplier.
690: */
691: public static final class LongConverter extends AbstractConverter {
692:
693: private final double multiplier;
694:
695: LongConverter(ValueModel longSubject, double multiplier) {
696: super (longSubject);
697: this .multiplier = multiplier;
698: }
699:
700: /**
701: * Converts the subject's value and returns a
702: * corresponding <code>Long</code> using the multiplier.
703: *
704: * @param subjectValue the subject's value
705: * @return the converted subjectValue
706: * @throws ClassCastException if the subject value is not of type
707: * <code>Long</code>
708: */
709: @Override
710: public Object convertFromSubject(Object subjectValue) {
711: double doubleValue = ((Long) subjectValue).doubleValue();
712: return Long.valueOf((long) (doubleValue * multiplier));
713: }
714:
715: /**
716: * Converts a <code>Long</code> using the multiplier
717: * and sets it as new value.
718: *
719: * @param newValue the <code>Long</code> object that shall be converted
720: * @throws ClassCastException if the new value is not of type
721: * <code>Long</code>
722: */
723: public void setValue(Object newValue) {
724: double doubleValue = ((Long) newValue).doubleValue();
725: subject.setValue(Long
726: .valueOf((long) (doubleValue / multiplier)));
727: }
728:
729: }
730:
731: /**
732: * Converts Integers using a given multiplier.
733: */
734: public static final class IntegerConverter extends
735: AbstractConverter {
736:
737: private final double multiplier;
738:
739: IntegerConverter(ValueModel integerSubject, double multiplier) {
740: super (integerSubject);
741: this .multiplier = multiplier;
742: }
743:
744: /**
745: * Converts the subject's value and returns a
746: * corresponding <code>Integer</code> using the multiplier.
747: *
748: * @param subjectValue the subject's value
749: * @return the converted subjectValue
750: * @throws ClassCastException if the subject value is not of type
751: * <code>Integer</code>
752: */
753: @Override
754: public Object convertFromSubject(Object subjectValue) {
755: double doubleValue = ((Integer) subjectValue).doubleValue();
756: return Integer.valueOf((int) (doubleValue * multiplier));
757: }
758:
759: /**
760: * Converts a <code>Integer</code> using the multiplier
761: * and sets it as new value.
762: *
763: * @param newValue the <code>Integer</code> object that shall be converted
764: * @throws ClassCastException if the new value is not of type
765: * <code>Integer</code>
766: */
767: public void setValue(Object newValue) {
768: double doubleValue = ((Integer) newValue).doubleValue();
769: subject.setValue(Integer
770: .valueOf((int) (doubleValue / multiplier)));
771: }
772:
773: }
774:
775: /**
776: * Converts Longs to Integers and vice-versa.
777: */
778: public static final class LongToIntegerConverter extends
779: AbstractConverter {
780:
781: private final int multiplier;
782:
783: LongToIntegerConverter(ValueModel longSubject, int multiplier) {
784: super (longSubject);
785: this .multiplier = multiplier;
786: }
787:
788: /**
789: * Converts the subject's value and returns a
790: * corresponding <code>Integer</code>.
791: *
792: * @param subjectValue the subject's value
793: * @return the converted subjectValue
794: * @throws ClassCastException if the subject value is not of type
795: * <code>Float</code>
796: */
797: @Override
798: public Object convertFromSubject(Object subjectValue) {
799: int intValue = ((Long) subjectValue).intValue();
800: if (multiplier != 1)
801: intValue *= multiplier;
802: return Integer.valueOf(intValue);
803: }
804:
805: /**
806: * Converts an Integer to Long and sets it as new value.
807: *
808: * @param newValue the <code>Integer</code> object that represents
809: * the percent value
810: * @throws ClassCastException if the new value is not of type
811: * <code>Integer</code>
812: */
813: public void setValue(Object newValue) {
814: long longValue = ((Integer) newValue).longValue();
815: if (multiplier != 1)
816: longValue /= multiplier;
817: subject.setValue(Long.valueOf(longValue));
818: }
819:
820: }
821:
822: /**
823: * Converts Values to Strings and vice-versa using a given Format.
824: */
825: public static final class StringConverter extends AbstractConverter {
826:
827: /**
828: * Holds the <code>Format</code> used to format and parse.
829: */
830: private final Format format;
831:
832: // Instance Creation **************************************************
833:
834: /**
835: * Constructs a <code>StringConverter</code> on the given
836: * subject using the specified <code>Format</code>.
837: *
838: * @param subject the underlying ValueModel.
839: * @param format the <code>Format</code> used to format and parse
840: * @throws NullPointerException if the subject or the format is null.
841: */
842: StringConverter(ValueModel subject, Format format) {
843: super (subject);
844: if (format == null) {
845: throw new NullPointerException(
846: "The format must not be null.");
847: }
848: this .format = format;
849: }
850:
851: // Implementing Abstract Behavior *************************************
852:
853: /**
854: * Formats the subject value and returns a String representation.
855: *
856: * @param subjectValue the subject's value
857: * @return the formatted subjectValue
858: */
859: @Override
860: public Object convertFromSubject(Object subjectValue) {
861: return format.format(subjectValue);
862: }
863:
864: // Implementing ValueModel ********************************************
865:
866: /**
867: * Parses the given String encoding and sets it as the subject's
868: * new value. Silently catches <code>ParseException</code>.
869: *
870: * @param value the value to be converted and set as new subject value
871: */
872: public void setValue(Object value) {
873: try {
874: subject.setValue(format.parseObject((String) value));
875: } catch (ParseException e) {
876: // Do not change the subject value
877: }
878: }
879:
880: }
881:
882: }
|