1 package nom.tam.fits; 2 3 import java.io.Serializable; 4 import java.util.Hashtable; 5 6 import static nom.tam.fits.header.Standard.BITPIX; 7 import static nom.tam.fits.header.Standard.BLOCKED; 8 import static nom.tam.fits.header.Standard.END; 9 import static nom.tam.fits.header.Standard.EXTEND; 10 import static nom.tam.fits.header.Standard.GCOUNT; 11 import static nom.tam.fits.header.Standard.NAXIS; 12 import static nom.tam.fits.header.Standard.PCOUNT; 13 import static nom.tam.fits.header.Standard.SIMPLE; 14 import static nom.tam.fits.header.Standard.TFIELDS; 15 import static nom.tam.fits.header.Standard.THEAP; 16 import static nom.tam.fits.header.Standard.XTENSION; 17 18 /* 19 * #%L 20 * nom.tam FITS library 21 * %% 22 * Copyright (C) 2004 - 2024 nom-tam-fits 23 * %% 24 * This is free and unencumbered software released into the public domain. 25 * 26 * Anyone is free to copy, modify, publish, use, compile, sell, or 27 * distribute this software, either in source code form or as a compiled 28 * binary, for any purpose, commercial or non-commercial, and by any 29 * means. 30 * 31 * In jurisdictions that recognize copyright laws, the author or authors 32 * of this software dedicate any and all copyright interest in the 33 * software to the public domain. We make this dedication for the benefit 34 * of the public at large and to the detriment of our heirs and 35 * successors. We intend this dedication to be an overt act of 36 * relinquishment in perpetuity of all present and future rights to this 37 * software under copyright law. 38 * 39 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 40 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 41 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 42 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 43 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 44 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 45 * OTHER DEALINGS IN THE SOFTWARE. 46 * #L% 47 */ 48 49 /** 50 * This class implements a comparator which ensures that FITS keywords are written out in a proper order. 51 * 52 * @deprecated (<i>for internal use</i>) Visibility should be reduced to package level in the future 53 */ 54 public class HeaderOrder implements java.util.Comparator<String>, Serializable { 55 56 /** 57 * 58 */ 59 private static final long serialVersionUID = -5900038332559417655L; 60 61 /** 62 * This array defines the order of ordered keywords, except END (which we handle separately) 63 */ 64 private static final String[] ORDER = {SIMPLE.key(), XTENSION.key(), BITPIX.key(), NAXIS.key(), PCOUNT.key(), 65 GCOUNT.key(), EXTEND.key(), TFIELDS.key(), BLOCKED.key(), THEAP.key()}; 66 67 /** 68 * Every keyword is assigned an index. Because NAXIS can have 999 NAXISn variants, we'll space the indices of the 69 * ordered keys by 1000, to allow adding in 999 ordered variants between the major slots. 70 */ 71 private static final int SPACING = 1000; 72 73 /** 74 * Keys that do not need ordering get an index that comes after the last ordered key, but before END. 75 */ 76 private static final int UNORDERED = SPACING * ORDER.length; 77 78 /** 79 * The END keyword comes last, so assign it an index after unordered. 80 */ 81 private static final int LAST = UNORDERED + SPACING; 82 83 /** 84 * Hash table for looking up the index of ordered keys. 85 */ 86 private static final Hashtable<String, Integer> LOOKUP = new Hashtable<>(); 87 88 // Initialize the hash lookup from the order array 89 static { 90 for (int i = 0; i < ORDER.length; i++) { 91 LOOKUP.put(ORDER[i], SPACING * i); 92 } 93 } 94 95 /** 96 * Returns a virtual ordering index of a given keyword. Keywords with lower indices should precede keywords that 97 * have higher indices. Order does not matter if the indices are the same. 98 * 99 * @param key FITS keyword 100 * 101 * @return The ordering index of that key 102 */ 103 private static int indexOf(String key) { 104 if (key == null) { 105 return UNORDERED; 106 } 107 if (key.startsWith(NAXIS.key())) { 108 if (NAXIS.key().length() == key.length()) { 109 return LOOKUP.get(NAXIS.key()); 110 } 111 try { 112 int i = Integer.parseInt(key.substring(NAXIS.key().length())); 113 if (i < 0 || i >= SPACING) { 114 return UNORDERED; 115 } 116 return LOOKUP.get(NAXIS.key()) + i; 117 } catch (NumberFormatException e) { 118 return UNORDERED; 119 } 120 } 121 if (key.equals(END.key())) { 122 return LAST; 123 } 124 Integer i = LOOKUP.get(key); 125 return i == null ? UNORDERED : i; 126 } 127 128 /** 129 * Determines the order in which the cards should be added to the header. This method assumes that the arguments are 130 * either the FITS Header keywords as strings, and some other type (or null) for comment style keywords. 131 * 132 * @return -1 if the first argument should be written first <br> 133 * 1 if the second argument should be written first <br> 134 * 0 if either is legal. 135 */ 136 @Override 137 public int compare(String c1, String c2) { 138 int i1 = indexOf(c1); 139 int i2 = indexOf(c2); 140 if (i1 == i2) { 141 return 0; 142 } 143 return i1 < i2 ? -1 : 1; 144 } 145 146 }