001 package edu.nrao.sss.model.project.scan; 002 003 import javax.xml.bind.annotation.XmlTransient; 004 005 import edu.nrao.sss.measure.TimeDuration; 006 007 /** 008 * A setting used in a {@code DelayScan}. 009 * <p> 010 * <b>Version Info:</b> 011 * <table style="margin-left:2em"> 012 * <tr><td>$Revision: 1494 $</td></tr> 013 * <tr><td>$Date: 2008-08-14 13:51:17 -0600 (Thu, 14 Aug 2008) $</td></tr> 014 * <tr><td>$Author: dharland $ (last person to modify)</td></tr> 015 * </table></p> 016 * 017 * @author David M. Harland 018 * @since 2006-07-21 019 */ 020 public class DelaySetting 021 implements Cloneable, Comparable<DelaySetting> 022 { 023 private static final ScanTimeType DEFAULT_TYPE = 024 ScanTimeType.ON_SOURCE_SIDEREAL; 025 026 private double nanoseconds; 027 private TimeDuration timeAtSetting; 028 private ScanTimeType durationType; 029 030 /** Creates a new instance. */ 031 public DelaySetting() 032 { 033 nanoseconds = 0.0; 034 timeAtSetting = new TimeDuration(); 035 durationType = DEFAULT_TYPE; 036 } 037 038 //============================================================================ 039 // PERSISTED PROPERTIES 040 //============================================================================ 041 042 /** 043 * Sets the nanosecond delay used in this setting. 044 * This value is allowed to be negative because it refers to a delay that is 045 * relative to the current setting. 046 * 047 * @param ns the nanosecond delay used in this setting. 048 */ 049 public void setNanoseconds(double ns) 050 { 051 nanoseconds = ns; 052 } 053 054 /** 055 * Returns the nanosecond delay used in this setting. 056 * @return the nanosecond delay used in this setting. 057 * @see #setNanoseconds(double) 058 */ 059 public double getNanoseconds() 060 { 061 return nanoseconds; 062 } 063 064 /** 065 * Sets the amount of time that should be spent at this setting. 066 * <p> 067 * If {@code duration} is <i>null</i>, it will be treated as 068 * an non-null duration of size zero.</p> 069 * 070 * @param duration the amount of time that should be spent at this setting. 071 */ 072 public void setTimeAtSetting(TimeDuration duration) 073 { 074 timeAtSetting = (duration == null) ? new TimeDuration() : duration; 075 } 076 077 /** 078 * Returns the amount of time that should be spent at this setting. 079 * <p> 080 * The returned value is guaranteed to be non-null. It is also the 081 * duration that is held internally by this position, so any changes 082 * made to the returned duration will be reflected in this object.</p> 083 * 084 * @return the amount of time that should be spent at this setting. 085 */ 086 087 public TimeDuration getTimeAtSetting() 088 { 089 return timeAtSetting; 090 } 091 092 /** 093 * Sets a new duration type for this setting. 094 * 095 * @param newType 096 * the new duration type for this setting. 097 * If this value is <i>null</i>, the default duration type of 098 * <tt>ON_SOURCE_SIDEREAL</tt> will be used. 099 * This value must have its <tt>isDuration()</tt> method 100 * return <i>true</i>. If it does not, an 101 * <tt>IllegalArgumentException</tt> is thrown. 102 * 103 * @throws IllegalArgumentException 104 * if {@code newType} is not a duration type. 105 */ 106 public void setDurationType(ScanTimeType newType) 107 { 108 if (newType == null) 109 newType = DEFAULT_TYPE; 110 111 if (!newType.isDuration()) 112 throw new IllegalArgumentException("newType '" + newType + 113 "' must be a duration type."); 114 115 durationType = newType; 116 } 117 118 /** 119 * Returns the type of duration used by this setting. 120 * This method helps clients interpret the value returned by 121 * {@link #getTimeAtSetting()}. 122 * <p> 123 * The returned type will be non-null and its <tt>isDuration()</tt> method 124 * will always return <i>true</i>.</p> 125 * 126 * @return 127 * the type of duration used by this setting. 128 */ 129 public ScanTimeType getDurationType() 130 { 131 return durationType; 132 } 133 134 //============================================================================ 135 // CONVENIENCE METHODS 136 //============================================================================ 137 138 /** 139 * A convenience method for setting the time spent at this setting. 140 * This setting will <i>not</i> hold a reference to <tt>newSpec</tt>. 141 * Instead, this method will use its 142 * {@link ScanTimeSpecification#getTimeType() getTimeType()} and 143 * {@link ScanTimeSpecification#getDuration() getDuration()} methods 144 * to set the time at setting and duration type of this object. 145 * 146 * @param newSpec 147 * the provider of the time at setting and duration type values for 148 * this setting. A value of <i>null</i> will result in a 149 * {@code NullPointerException}. 150 * 151 * @throws IllegalArgumentException 152 * if the time type held by {@code newSpec} is not a duration type. 153 */ 154 @XmlTransient 155 public void setTimeSpec(ScanTimeSpecification newSpec) 156 { 157 setDurationType(newSpec.getTimeType()); 158 setTimeAtSetting(newSpec.getDuration()); 159 } 160 161 /** 162 * A convenience method for fetching the time spent at this setting. 163 * The returned object is guaranteed to be non-null. 164 * It is not referenced internally by this setting, so any changes made 165 * to it by clients will not affect this object. 166 * 167 * @return 168 * the time at setting and duration type of this offset. 169 */ 170 public ScanTimeSpecification getTimeSpec() 171 { 172 ScanTimeSpecification spec = new ScanTimeSpecification(); 173 174 spec.set(durationType, timeAtSetting); 175 176 return spec; 177 } 178 179 //============================================================================ 180 // 181 //============================================================================ 182 183 /** 184 * Returns a text representation of this delay setting. 185 * The returned string is of the form <i>nanoseconds,timeAtSetting</i>. 186 */ 187 @Override 188 public String toString() 189 { 190 StringBuilder buff = new StringBuilder(); 191 192 buff.append(nanoseconds); 193 buff.append(',').append(timeAtSetting); 194 buff.append(',').append(durationType); 195 196 return buff.toString(); 197 } 198 199 /** 200 * Compares this setting with {@code other} for order. 201 * <p> 202 * If this setting has a smaller delay than the other's, a negative 203 * value is returned; if larger, a positive value is returned. If both 204 * settings have the delay, a negative value is returned if this 205 * setting has a smaller time duration than the other. The duration type 206 * is not used for figuring out which time duration is larger or smaller. 207 * If the durations are equal in magnitude, though, a comparison of 208 * durations will be used to break the tie, but only in order to stay 209 * consistent with equals().</p> 210 */ 211 public int compareTo(DelaySetting other) 212 { 213 int result = (int)Math.signum(this.nanoseconds - other.nanoseconds); 214 if (result != 0) 215 return result; 216 217 result = this.timeAtSetting.compareTo(other.timeAtSetting); 218 if (result != 0) 219 return result; 220 221 return this.durationType.compareTo(other.durationType); 222 } 223 224 /** 225 * Returns a setting that is a copy of this one. 226 * <p> 227 * If anything goes wrong during the cloning procedure, 228 * a {@code RuntimeException} will be thrown.</p> 229 */ 230 @Override 231 public DelaySetting clone() 232 { 233 DelaySetting clone = null; 234 235 try 236 { 237 //This line takes care of primitive & immutable fields properly 238 clone = (DelaySetting)super.clone(); 239 240 clone.timeAtSetting = this.timeAtSetting.clone(); 241 } 242 catch (Exception ex) 243 { 244 throw new RuntimeException(ex); 245 } 246 247 return clone; 248 } 249 250 /** Returns <i>true</i> if {@code o} is equal to this setting. */ 251 @Override 252 public boolean equals(Object o) 253 { 254 //Quick exit if o is null 255 if (o == null) 256 return false; 257 258 //Quick exit if o is this object 259 if (o == this) 260 return true; 261 262 //Quick exit if classes are different 263 if (!o.getClass().equals(this.getClass())) 264 return false; 265 266 //A safe cast if we got this far 267 DelaySetting other = (DelaySetting)o; 268 269 //Compare attributes 270 return 271 this.nanoseconds == other.nanoseconds && 272 this.durationType.equals(other.durationType) && 273 this.timeAtSetting.equals(other.timeAtSetting); 274 } 275 276 /** Returns a hash code value for this setting. */ 277 @Override 278 public int hashCode() 279 { 280 //Taken from the Effective Java book by Joshua Bloch. 281 //The constants 17 & 37 are arbitrary & carry no meaning. 282 int result = 17; 283 284 result = 37 * result + new Double(nanoseconds).hashCode(); 285 result = 37 * result + durationType.hashCode(); 286 result = 37 * result + timeAtSetting.hashCode(); 287 288 return result; 289 } 290 }