001 package edu.nrao.sss.model.project.scan; 002 003 import java.util.ArrayList; 004 import java.util.Date; 005 import java.util.HashSet; 006 import java.util.List; 007 import java.util.Set; 008 009 import javax.xml.bind.annotation.XmlElement; 010 import javax.xml.bind.annotation.XmlElementWrapper; 011 import javax.xml.bind.annotation.XmlRootElement; 012 import javax.xml.bind.annotation.XmlType; 013 014 import edu.nrao.sss.measure.TimeDuration; 015 import edu.nrao.sss.model.source.Source; 016 017 /** 018 * A scan that holds a list of {@link SwitchSetting switch settings}. 019 * <p> 020 * <b>CVS Info:</b> 021 * <table style="margin-left:2em"> 022 * <tr><td>$Revision: 161 $</td></tr> 023 * <tr><td>$Date: 2006-12-15 11:48:34 -0700 (Fri, 15 Dec 2006) $</td></tr> 024 * <tr><td>$Author: btruitt $</td></tr> 025 * </table></p> 026 * 027 * @author David M. Harland 028 * @since 2006-07-10 029 */ 030 @XmlRootElement 031 @XmlType(propOrder= {"timeOnTarget", "applyAutoPhasing", "switchSettings"}) 032 public class SwitchingScan 033 extends Scan 034 { 035 private TimeDuration timeOnTarget; 036 private boolean applyAutoPhasing; 037 private List<SwitchSetting> switchSettings; 038 039 /** Creates a new instance. */ 040 SwitchingScan() 041 { 042 super(); 043 044 timeOnTarget = new TimeDuration(); 045 applyAutoPhasing = false; 046 switchSettings = new ArrayList<SwitchSetting>(); 047 } 048 049 /** 050 * Sets the amount of time that this scan should spend on the target 051 * source, as opposed to on a calibrator. 052 * <p> 053 * If {@code duration} is <i>null</i>, it will be treated as 054 * a non-null duration of size zero.</p> 055 * 056 * @param duration the amount of time to be spent on the target source. 057 */ 058 public void setTimeOnTarget(TimeDuration duration) 059 { 060 timeOnTarget = (duration == null) ? new TimeDuration() : duration; 061 } 062 063 /** 064 * Returns the amount of time that this scan should spend on the target 065 * source, as opposed to on a calibrator. 066 * <p> 067 * The returned value is guaranteed to be non-null. It is also the 068 * duration that is held internally by this scan, so any changes 069 * made to the returned duration will be reflected in this object.</p> 070 * 071 * @return the amount of time to be spent on the target source. 072 */ 073 public TimeDuration getTimeOnTarget() 074 { 075 return timeOnTarget; 076 } 077 078 /** 079 * Indicates whether or not autophasing should be applied to this scan. 080 * 081 * @param apply <i>true</i> if autophasing is desired. 082 */ 083 public void setApplyAutoPhasing(boolean apply) 084 { 085 applyAutoPhasing = apply; 086 } 087 088 /** 089 * Returns true if this scan should perform autophasing. 090 * @return true if this scan should perform autophasing. 091 */ 092 public boolean getApplyAutoPhasing() { return applyAutoPhasing; } 093 094 /** 095 * Sets the list of switch settings held by this scan. 096 * A <i>null</i> {@code replacementList} will be interpreted 097 * as a new empty list. 098 * <p> 099 * This scan will hold a reference to {@code replacementList} 100 * (unless it is <i>null</i>), so any changes made to the list 101 * after calling this method will be reflected in this object.</p> 102 * 103 * @param replacementList a list of switch settings to be held by this 104 * scan. 105 */ 106 public void setSwitchSettings(List<SwitchSetting> replacementList) 107 { 108 switchSettings = (replacementList == null) ? new ArrayList<SwitchSetting>() 109 : replacementList; 110 111 } 112 113 /** 114 * Returns the list of pointing positions held by this scan. 115 * The returned list is guaranteed to be non-null, but may 116 * be empty. 117 * <p> 118 * The returned list is the actual list held by this scan, 119 * so changes made to the list will be reflected in this 120 * object.</p> 121 * 122 * @return the list of pointing positions held by this scan. 123 */ 124 @XmlElementWrapper(name="settings") 125 @XmlElement(name="switchSetting") 126 public List<SwitchSetting> getSwitchSettings() 127 { 128 //Tell each setting that it is part of this scan. 129 //(Note that, with the way the switchSetting methods are currently written, 130 //we cannot rely on the settings knowing about this scan. Though it may be 131 //redundant, we ensure the settings are up to date on a just-in-time basis. 132 //If this becomes too costly, we would need to: 133 // 1. Have this method return a clone of the settings. 134 // 2. Stop saving a reference to the incoming list in setSwitchSettings 135 // 3. Add an addSwitchSetting method and do the setScan call there.) 136 for (SwitchSetting ss : switchSettings) 137 ss.setScan(this); 138 139 return switchSettings; 140 } 141 142 /** 143 * Returns the set of all sources used by this scan. This includes the main 144 * source and the source used in each of the switch settings. 145 * @param dateTime the time for which sources are requested. 146 * @return the set of all sources used by this scan. 147 */ 148 public Set<Source> getSources(Date dateTime) 149 { 150 Set<Source> sources = new HashSet<Source>(); 151 152 sources.add(getSource(dateTime)); 153 154 for (SwitchSetting setting : switchSettings) 155 sources.add(setting.getSource(dateTime)); 156 157 return sources; 158 159 } 160 161 //============================================================================ 162 // 163 //============================================================================ 164 165 /* (non-Javadoc) 166 * @see edu.nrao.sss.model.project.scan.ScanLoopElement#toString() 167 */ 168 public String toSummaryString() 169 { 170 StringBuilder buff = new StringBuilder(super.toSummaryString()); 171 172 buff.append(", timeOnTgt=").append(timeOnTarget); 173 buff.append(", applyAutoPhas=").append(applyAutoPhasing); 174 buff.append(", switchCnt=").append(switchSettings.size()); 175 176 return buff.toString(); 177 } 178 179 /** 180 * Returns a switching scan that is a copy of this one. 181 * <p> 182 * The returned scan is, for the most part, a deep copy of this one. 183 * However, there are a few exceptions noted in the 184 * {@link ScanLoop#clone() clone method} of this class's parent.</p> 185 * <p> 186 * If anything goes wrong during the cloning procedure, 187 * a {@code RuntimeException} will be thrown.</p> 188 */ 189 public SwitchingScan clone() 190 { 191 SwitchingScan clone = null; 192 193 try 194 { 195 //This line takes care of the primitive & immutable fields properly 196 clone = (SwitchingScan)super.clone(); 197 198 clone.timeOnTarget = this.timeOnTarget.clone(); 199 200 //Need to clone set AND contained elements. 201 clone.switchSettings = new ArrayList<SwitchSetting>(); 202 for (SwitchSetting ss : this.switchSettings) 203 clone.switchSettings.add(ss.clone()); 204 } 205 catch (Exception ex) 206 { 207 throw new RuntimeException(ex); 208 } 209 210 return clone; 211 } 212 213 /** 214 * Returns <i>true</i> if {@code o} is equal to this switching scan. 215 * <p> 216 * In order for {@code o} to be equal to this scan, it must have 217 * equal switch settings in the same order as those of this scan. 218 * It must also follow the rules set forth in the 219 * {@link ScanLoop#equals(Object) equals method} of this class's parent.</p> 220 */ 221 public boolean equals(Object o) 222 { 223 //Quick exit if o is this object 224 if (o == this) 225 return true; 226 227 //Not equal if super class says not equal 228 if (!super.equals(o)) 229 return false; 230 231 //Super class tested for Class equality, so cast is safe 232 SwitchingScan other = (SwitchingScan)o; 233 234 //Compare attributes 235 return (other.applyAutoPhasing == this.applyAutoPhasing) && 236 other.timeOnTarget.equals(this.timeOnTarget) && 237 other.switchSettings.equals(this.switchSettings); 238 } 239 240 /* (non-Javadoc) 241 * @see edu.nrao.sss.model.project.scan.Scan#hashCode() 242 */ 243 public int hashCode() 244 { 245 //Taken from the Effective Java book by Joshua Bloch. 246 //The constant 37 is arbitrary & carries no meaning. 247 int result = 37 * super.hashCode(); 248 249 result = 37 * result + new Boolean(applyAutoPhasing).hashCode(); 250 result = 37 * result + timeOnTarget.hashCode(); 251 result = 37 * result + switchSettings.hashCode(); 252 253 return result; 254 } 255 }