1 package nom.tam.fits;
2
3 /*
4 * #%L
5 * nom.tam FITS library
6 * %%
7 * Copyright (C) 1996 - 2024 nom-tam-fits
8 * %%
9 * This is free and unencumbered software released into the public domain.
10 *
11 * Anyone is free to copy, modify, publish, use, compile, sell, or
12 * distribute this software, either in source code form or as a compiled
13 * binary, for any purpose, commercial or non-commercial, and by any
14 * means.
15 *
16 * In jurisdictions that recognize copyright laws, the author or authors
17 * of this software dedicate any and all copyright interest in the
18 * software to the public domain. We make this dedication for the benefit
19 * of the public at large and to the detriment of our heirs and
20 * successors. We intend this dedication to be an overt act of
21 * relinquishment in perpetuity of all present and future rights to this
22 * software under copyright law.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
27 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
28 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
29 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
30 * OTHER DEALINGS IN THE SOFTWARE.
31 * #L%
32 */
33
34 import java.util.Date;
35
36 import nom.tam.fits.header.IFitsHeader;
37
38 /**
39 * Builder pattern implementation for easy readable header card creation.
40 *
41 * @author nir
42 */
43 public class HeaderCardBuilder {
44
45 /**
46 * the header to fill.
47 */
48 private final Header header;
49
50 /**
51 * the current card to fill.
52 */
53 private HeaderCard card;
54
55 /**
56 * the current selected key.
57 */
58 private IFitsHeader key;
59
60 /**
61 * scale to use for decimal values.
62 */
63 private int precision = -1;
64
65 /**
66 * constructor to the header card builder.
67 *
68 * @param header the header to fill.
69 * @param key the first header card to set.
70 */
71 protected HeaderCardBuilder(Header header, IFitsHeader key) {
72 this.header = header;
73 card(key);
74 }
75
76 /**
77 * get the current build card of the builder.
78 *
79 * @return the current card
80 */
81 public HeaderCard card() {
82 return card;
83 }
84
85 /**
86 * switch focus to the card with the specified key. If the card does not exist the card will be created when the
87 * value or the comment is set.
88 *
89 * @param newKey the new card to set
90 *
91 * @return this
92 */
93 public HeaderCardBuilder card(IFitsHeader newKey) {
94 key = newKey;
95 card = header.getCard(key);
96 return this;
97 }
98
99 /**
100 * set the comment of the current card. If the card does not exist yet the card is created with a null value, if the
101 * card needs a value use the value setter first!
102 *
103 * @param newComment the new comment to set.
104 *
105 * @return this
106 *
107 * @throws HeaderCardException if the card creation failed.
108 */
109 public HeaderCardBuilder comment(String newComment) throws HeaderCardException {
110 if (card == null) {
111 card = new HeaderCard(key.key(), (String) null, null);
112 header.addLine(card);
113 }
114 card.setComment(newComment);
115 return this;
116 }
117
118 /**
119 * set the value of the current card.If the card did not exist yet the card will be created.
120 *
121 * @param newValue the new value to set.
122 *
123 * @return this
124 *
125 * @throws HeaderCardException if the card creation failed.
126 */
127 public HeaderCardBuilder value(boolean newValue) throws HeaderCardException {
128 if (card == null) {
129 card = new HeaderCard(key.key(), newValue, null);
130 header.addLine(card);
131 } else {
132 card.setValue(newValue);
133 }
134 return this;
135 }
136
137 /**
138 * set the value of the current card. If the card did not exist yet the card will be created.
139 *
140 * @param newValue the new value to set.
141 *
142 * @return this
143 *
144 * @throws HeaderCardException if the card creation failed.
145 */
146 public HeaderCardBuilder value(Date newValue) throws HeaderCardException {
147 return value(FitsDate.getFitsDateString(newValue));
148 }
149
150 /**
151 * Sets a new number value for the current card. If the card did not exist yet the card will be created.
152 *
153 * @param value the new number value to set.
154 *
155 * @return this
156 *
157 * @throws HeaderCardException if the card creation failed.
158 * @throws LongValueException if the number value cannot be represented in the space available for it in the
159 * 80-character wide FITS header record.
160 */
161 public HeaderCardBuilder value(Number value) throws HeaderCardException, LongValueException {
162 if (card == null) {
163 card = new HeaderCard(key.key(), value, precision, null);
164 header.addLine(card);
165 } else {
166 card.setValue(value, precision);
167 }
168 return this;
169 }
170
171 /**
172 * set the value of the current card.If the card did not exist yet the card will be created.
173 *
174 * @param newValue the new value to set.
175 *
176 * @return this
177 *
178 * @throws HeaderCardException if the card creation failed.
179 * @throws LongValueException if the number value cannot be represented in the space available for it in the
180 * 80-character wide FITS header record.
181 */
182 public HeaderCardBuilder value(String newValue) throws HeaderCardException, LongValueException {
183 if (card == null) {
184 card = new HeaderCard(key.key(), newValue, null);
185 header.addLine(card);
186 } else {
187 card.setValue(newValue);
188 }
189 return this;
190 }
191
192 /**
193 * Sets the number of decimals to show for the following decimal values. This method is now deprecated. Use
194 * {@link #precision(int)} instead.
195 *
196 * @param decimals the new number of decimal places to show.
197 *
198 * @return this
199 *
200 * @deprecated Use {@link #precision(int)} instead.
201 */
202 @Deprecated
203 public HeaderCardBuilder scale(int decimals) {
204 precision = decimals;
205 return this;
206 }
207
208 /**
209 * Sets the number of decimals to show for the following decimal values. Trailing zeroes will be ommitted.
210 *
211 * @param decimals the number of decimals to show for the following decimal values.
212 *
213 * @return this
214 *
215 * @since 1.16
216 */
217 public HeaderCardBuilder precision(int decimals) {
218 precision = decimals;
219 return this;
220 }
221
222 /**
223 * This method has been deprecated. Please use {@link #autoPrecision()} instead.
224 *
225 * @return this
226 *
227 * @deprecated Use {@link #autoPrecision()} instead
228 */
229 @Deprecated
230 public HeaderCardBuilder noScale() {
231 precision = -1;
232 return this;
233 }
234
235 /**
236 * Use the native precision for the given number type. Trailing zeroes will be ommitted.
237 *
238 * @return this
239 *
240 * @since 1.16
241 */
242 public HeaderCardBuilder autoPrecision() {
243 precision = -1;
244 return this;
245 }
246
247 /**
248 * Returns the FITS header object that this builder is used with
249 *
250 * @return the filled header.
251 */
252 public Header header() {
253 return header;
254 }
255 }