package nom.tam.fits; /* * Copyright: Thomas McGlynn 1997-1998. * This code may be used for any purpose, non-commercial * or commercial so long as this copyright notice is retained * in the source code or included in or referred to in any * derived software. * Many thanks to David Glowacki (U. Wisconsin) for substantial * improvements, enhancements and bug fixes -- including * this class. */ /** This class describes methods to access and manipulate the individual * cards for a FITS Header. */ public class HeaderCard { /** The keyword part of the card (set to null if there's no keyword) */ String key; /** The value part of the card (set to null if there's no value) */ String value; /** The comment part of the card (set to null if there's no comment) */ String comment; /** A flag indicating whether or not this is a string value */ boolean isString; /** Maximum length of a FITS keyword field */ private static final int MAX_KEYWORD_LENGTH = 8; /** Maximum length of a FITS value field */ private static final int MAX_VALUE_LENGTH = 70; /** padding for building card images */ private String space40 = " "; /** Create a HeaderCard from its component parts * @param key keyword (null for a comment) * @param value value (null for a comment or keyword without an '=') * @param comment comment * @exception HeaderCardException for any invalid keyword or value */ public HeaderCard(String key, String value, String comment) throws HeaderCardException { if (key == null && value != null) { throw new HeaderCardException("Null keyword with non-null value"); } if (key != null && key.length() > MAX_KEYWORD_LENGTH) { throw new HeaderCardException("Keyword too long"); } if (value != null) { value = value.trim(); if (value.length() > MAX_VALUE_LENGTH) { throw new HeaderCardException("Value too long"); } if (value.charAt(0) == '\'') { if (value.charAt(value.length()-1) != '\'') { throw new HeaderCardException("Missing end quote in string value"); } value = value.substring(1,value.length()-1).trim(); isString = true; } } this.key = key; this.value = value; this.comment = comment; } /** Create a HeaderCard from a FITS card image * @param card the 80 character card image */ public HeaderCard(String card) { key = null; value = null; comment = null; isString = false; // We are going to assume that the value has no blanks in // it unless it is enclosed in quotes. Also, we assume that // a / terminates the string (except inside quotes) // treat short lines as special keywords if (card.length() < 9) { key = card; return; } // extract the key key = card.substring(0, 8).trim(); // if it's an empty key, assume the remainder of the card is a comment if (key.length() == 0) { key = ""; comment = card.substring(8); return; } // Non-key/value pair lines are treated as keyed comments if (!card.substring(8,10).equals("= ")) { comment = card.substring(8); return; } // extract the value/comment part of the string String valcom = card.substring(10).trim(); // if there's no value/comment part, we're done if (valcom.length() == 0) { value = ""; return; } int vend = -1; boolean quote = false; // If we have a ' then find the matching quote. if (valcom.charAt(0) == '\'') { int offset = 1; while (offset < valcom.length()) { // look for next single-quote character vend = valcom.indexOf("'", offset);; // if the quote character is the last character on the line... if (vend == valcom.length()-1) { break; } // if we didn't find a matching single-quote... if (vend == -1) { // pretend this is a comment card key = null; comment = card; return; } // if this isn't an escaped single-quote, we're done if (valcom.charAt(vend+1) != '\'') { break; } // skip past escaped single-quote offset = vend+2; } // break apart character string value = valcom.substring(1, vend).trim(); isString = true; } // look for a / to terminate the field. int slashLoc = valcom.indexOf('/'); if (slashLoc != -1) { comment = valcom.substring(slashLoc+1).trim(); valcom = valcom.substring(0, slashLoc).trim(); } // if we didn't already save a string value, do it now if (!isString) { value = valcom; } } /** Does this card contain a string value? */ public boolean isStringValue() { return isString; } /** Is this a key/value card? */ public boolean isKeyValuePair() { return (key != null && value != null); } /** Return the keyword from this card */ public String getKey() { return key; } /** Return the value from this card */ public String getValue() { return value; } /** Return the comment from this card */ public String getComment() { return comment; } /** Return the 80 character card image */ public String toString() { StringBuffer buf = new StringBuffer(80); // start with the keyword, if there is one if (key != null) { buf.append(key); } // fill keyword field with blanks while (buf.length() < 8) { buf.append(' '); } if (value != null) { buf.append("= "); if (isString) { // left justify the string inside the quotes buf.append('\''); buf.append(value); while (buf.length() < 19) { buf.append(' '); } buf.append('\''); } else { int offset = buf.length(); buf.append(value); // right justify the value field to column 30 while (buf.length() < 30) { buf.insert(offset, ' '); } } // if there's a comment, add a comment delimiter if (comment != null) { buf.append(" / "); } } else if (comment != null && comment.startsWith("= ")) { buf.append(" "); } // finally, add any comment if (comment != null) { buf.append(comment); } // make sure the final string is exactly 80 characters long if (buf.length() > 80) { buf.setLength(80); } else { if (buf.length() < 40) { buf.append(space40); } if (buf.length() < 80) { buf.append(space40.substring(0, 80 - buf.length())); } } return buf.toString(); } }