21
21
import static java .math .RoundingMode .HALF_EVEN ;
22
22
import static java .util .Objects .requireNonNull ;
23
23
24
- import java .math .RoundingMode ;
25
24
import java .text .DecimalFormat ;
26
25
import java .text .DecimalFormatSymbols ;
27
26
import java .text .NumberFormat ;
40
39
*/
41
40
abstract class Field implements Format {
42
41
43
- static final DecimalFormatSymbols SYMBOLS =
42
+ private static final DecimalFormatSymbols SYMBOLS =
44
43
DecimalFormatSymbols .getInstance (Locale .US );
45
44
46
- final String _pattern ;
45
+ private final String _pattern ;
46
+ private boolean _prefixSign = false ;
47
+ private boolean _absolute = false ;
47
48
48
49
private final AtomicReference <NumberFormat > _format = new AtomicReference <>();
49
50
@@ -52,72 +53,50 @@ abstract class Field implements Format {
52
53
_format .set (new DecimalFormat (toDecimalPattern (pattern ), SYMBOLS ));
53
54
}
54
55
56
+ private String toDecimalPattern (final String pattern ) {
57
+ return pattern .replace (type (), '0' );
58
+ }
59
+
55
60
/**
56
61
* Return the type character of this field.
57
62
*
58
63
* @return the type character of this field
59
64
*/
60
65
abstract char type ();
61
66
62
- void setPrefixSign (final boolean b ) {
63
- }
67
+ final void setPrefixSign (final boolean b ) {
68
+ _prefixSign = b ;
64
69
65
- void setTruncate (final boolean b ) {
66
- _format .get ().setRoundingMode (b ? DOWN : HALF_EVEN );
67
- }
70
+ final String decimalPattern = toDecimalPattern (_pattern );
71
+ final String pattern = _prefixSign
72
+ ? "+%1$s;-%1$s" .formatted (decimalPattern )
73
+ : decimalPattern ;
68
74
69
- void setFormat (final NumberFormat format ) {
70
- _format .set (requireNonNull (format ));
75
+ setFormat (new DecimalFormat (pattern , SYMBOLS ));
71
76
}
72
77
73
- int getMinimumFractionDigits () {
74
- return _format . get (). getMinimumFractionDigits () ;
78
+ final boolean isPrefixSign () {
79
+ return _prefixSign ;
75
80
}
76
81
77
- static double toMinutes (final double degrees ) {
78
- double dd = abs (degrees );
79
- return (dd - floor (dd )) * 60.0 ;
82
+ final void setAbsolute (final boolean b ) {
83
+ _absolute = b ;
80
84
}
81
85
82
- static double toSeconds (final double degrees ) {
83
- double dd = abs (degrees );
84
- double d = floor (dd );
85
- double m = floor ((dd - d ) * 60.0 );
86
- return (dd - d - m / 60.0 ) * 3600.0 ;
86
+ final boolean isAbsolute () {
87
+ return _absolute ;
87
88
}
88
89
89
- static Optional <Field > ofPattern (final String pattern ) {
90
- // TODO better?
91
- for (int i = 0 ; i < pattern .length (); ++i ) {
92
- char c = pattern .charAt (i );
93
- switch (c ){
94
- case 'L' : {
95
- String p = pattern .replace ('L' , 'D' );
96
- return Optional .of (new LatitudeDegree (p ));
97
- }
98
- case 'D' : return Optional .of (new LatitudeDegree (pattern ));
99
- case 'M' : return Optional .of (new LatitudeMinute (pattern ));
100
- case 'S' : return Optional .of (new LatitudeSecond (pattern ));
101
- case 'l' : {
102
- String p = pattern .replace ('l' ,'d' );
103
- return Optional .of (new LongitudeDegree (p ));
104
- }
105
- case 'd' : return Optional .of (new LongitudeDegree (pattern ));
106
- case 'm' : return Optional .of (new LongitudeMinute (pattern ));
107
- case 's' : return Optional .of (new LongitudeSecond (pattern ));
108
- case 'E' : return Optional .of (new Elevation (pattern ));
109
- case 'H' : {
110
- String p = pattern .replace ('H' , 'E' );
111
- return Optional .of (new Elevation (p ));
112
- }
113
- }
114
- }
90
+ final void setTruncate (final boolean b ) {
91
+ _format .get ().setRoundingMode (b ? DOWN : HALF_EVEN );
92
+ }
115
93
116
- return Optional .empty ();
94
+ final void setFormat (final NumberFormat format ) {
95
+ _format .set (requireNonNull (format ));
117
96
}
118
97
119
- String toDecimalPattern ( final String pattern ) {
120
- return pattern . replace ( type (), '0' );
98
+ final int getMinimumFractionDigits ( ) {
99
+ return _format . get (). getMinimumFractionDigits ( );
121
100
}
122
101
123
102
@ Override
@@ -131,7 +110,7 @@ public String toPattern() {
131
110
* @param value the double value to format
132
111
* @return the formatted double value
133
112
*/
134
- String format (final double value ) {
113
+ final String format (final double value ) {
135
114
return _format .get ().format (value );
136
115
}
137
116
@@ -142,17 +121,16 @@ String format(final double value) {
142
121
* @param pos the parse position
143
122
* @return the parsed double value
144
123
*/
145
- double parse (final CharSequence in , final ParsePosition pos ) {
124
+ final double parse (final CharSequence in , final ParsePosition pos ) {
146
125
int i = pos .getIndex ();
147
126
String s = in .toString ();
148
- boolean strictWidth = 1 < _format .get ().getMinimumIntegerDigits (); //better?
127
+ boolean strictWidth = 1 < _format .get ().getMinimumIntegerDigits ();
149
128
if (strictWidth ) {
150
- int end = i + toPattern ().length (); // toPattern() rather than pattern because LatitudeDegree.toPattern()
151
- s = in .subSequence (0 , end ).toString (); // don't eat more digits
129
+ int end = i + toPattern ().length ();
130
+ s = in .subSequence (0 , end ).toString ();
152
131
}
153
132
154
- final Number n ;
155
- synchronized (_format ) {
133
+ final Number n ; synchronized (_format ) {
156
134
n = _format .get ().parse (s , pos );
157
135
}
158
136
@@ -164,4 +142,46 @@ String format(final double value) {
164
142
return n .doubleValue ();
165
143
}
166
144
145
+
146
+ static double toMinutes (final double degrees ) {
147
+ final double dd = abs (degrees );
148
+ return (dd - floor (dd )) * 60.0 ;
149
+ }
150
+
151
+ static double toSeconds (final double degrees ) {
152
+ final double dd = abs (degrees );
153
+ final double d = floor (dd );
154
+ final double m = floor ((dd - d ) * 60.0 );
155
+ return (dd - d - m / 60.0 ) * 3600.0 ;
156
+ }
157
+
158
+ static Optional <Field > ofPattern (final String pattern ) {
159
+ // TODO better?
160
+ for (int i = 0 ; i < pattern .length (); ++i ) {
161
+ switch (pattern .charAt (i )) {
162
+ case 'L' : {
163
+ final String p = pattern .replace ('L' , 'D' );
164
+ return Optional .of (new LatitudeDegree (p ));
165
+ }
166
+ case 'D' : return Optional .of (new LatitudeDegree (pattern ));
167
+ case 'M' : return Optional .of (new LatitudeMinute (pattern ));
168
+ case 'S' : return Optional .of (new LatitudeSecond (pattern ));
169
+ case 'l' : {
170
+ final String p = pattern .replace ('l' ,'d' );
171
+ return Optional .of (new LongitudeDegree (p ));
172
+ }
173
+ case 'd' : return Optional .of (new LongitudeDegree (pattern ));
174
+ case 'm' : return Optional .of (new LongitudeMinute (pattern ));
175
+ case 's' : return Optional .of (new LongitudeSecond (pattern ));
176
+ case 'E' : return Optional .of (new Elevation (pattern ));
177
+ case 'H' : {
178
+ final String p = pattern .replace ('H' , 'E' );
179
+ return Optional .of (new Elevation (p ));
180
+ }
181
+ }
182
+ }
183
+
184
+ return Optional .empty ();
185
+ }
186
+
167
187
}
0 commit comments