001 /** 002 * Do we want to use this space for anything? Eg, revision history? 003 */ 004 package edu.nrao.sss.model.proposal; 005 006 import java.math.BigDecimal; 007 import java.util.HashSet; 008 import java.util.Set; 009 010 import edu.nrao.sss.measure.TimeDuration; 011 import edu.nrao.sss.util.Identifiable; 012 013 /** <i>Placeholder for time when we integrate proposal work.</i> 014 * A proposed observation session. 015 * <p> 016 * A session consists of one or more {@link SessionPair session pairs}, each 017 * of which brings together a source and a resource. A session is a close 018 * cousin of a scheduling block, which is used 019 * during the observation preparation and scheduling phases.</p> 020 * <p> 021 * <b>CVS Info:</b> 022 * <table style="margin-left:2em"> 023 * <tr><td>$Revision: 1709 $</td> 024 * <tr><td>$Date: 2008-11-14 11:22:37 -0700 (Fri, 14 Nov 2008) $</td> 025 * <tr><td>$Author: dharland $</td> 026 * </table></p> 027 * 028 * @since 2006-03-23 029 */ 030 public class Session 031 implements Identifiable//, XmlSerializable 032 { 033 private static final String DEFAULT_NAME = "[Not Specified]"; 034 private static final String NO_CONSTRAINT = ""; 035 private static final String NO_COMMENTS = ""; 036 private static final String NO_MINIMUM_LST = "00:00:00"; 037 private static final String NO_MAXIMUM_LST = "23:59:59"; 038 private static final double MINIMUM_ELEVATION = 0.0; 039 //private static final double MAXIMUM_ELEVATION = 90.0; 040 041 //IDENTIFICATION 042 private Long id; //A unique identifier for the persistence layer. 043 private String name; 044 045 //CONTAINED OBJECTS (SessionPairs) 046 private Set<SessionPair> sessionPairs; 047 048 //CONSTRAINTS 049 private String minimumLst; 050 private String maximumLst; 051 private double minimumElevation; 052 private String schedulingConstraint; 053 054 //LENGTH OF OBSERVATION 055 private int repeatCount; 056 private TimeDuration sessionTime; 057 private TimeDuration separation; 058 059 //OTHER ATTRIBUTES 060 private String comments; 061 062 /** Creates a new instance. */ 063 public Session() 064 { 065 sessionPairs = new HashSet<SessionPair>(); 066 sessionTime = new TimeDuration(); 067 separation = new TimeDuration(); 068 069 initialize(); 070 } 071 072 /** Initializes the instance variables of this class. */ 073 private void initialize() 074 { 075 id = Identifiable.UNIDENTIFIED; 076 name = DEFAULT_NAME; 077 078 minimumLst = NO_MINIMUM_LST; 079 maximumLst = NO_MAXIMUM_LST; 080 minimumElevation = MINIMUM_ELEVATION; 081 schedulingConstraint = NO_CONSTRAINT; 082 083 repeatCount = 0; 084 085 comments = NO_COMMENTS; 086 } 087 088 /** 089 * Resets this session to its initial state. 090 * A reset session has the same state as a new session. 091 */ 092 public void reset() 093 { 094 initialize(); 095 096 sessionPairs.clear(); 097 sessionTime.reset(); 098 separation.reset(); 099 } 100 101 //============================================================================ 102 // IDENTIFICATION 103 //============================================================================ 104 105 /* (non-Javadoc) 106 * @see edu.nrao.sss.util.Identifiable#getId() 107 */ 108 public Long getId() 109 { 110 return id; 111 } 112 113 @SuppressWarnings("unused") 114 private void setId(Long id) 115 { 116 this.id = id; 117 } 118 119 /** 120 * Sets the name of this session to {@code newName}. 121 * <p> 122 * If {@code newName} is <i>null</i> or the empty string 123 * (<tt>""</tt>), the request to change the name will be 124 * denied and the current name will remain in place.</p> 125 * 126 * @param newName the name of this session. 127 */ 128 public void setName(String newName) 129 { 130 if (newName != name && newName.length() > 0) 131 name = newName; 132 } 133 134 /** 135 * Returns the name of this session. 136 * 137 * @return the name of this session. 138 */ 139 public String getName() 140 { 141 return name; 142 } 143 144 //============================================================================ 145 // CONTAINED OBJECTS (SessionPairs) 146 //============================================================================ 147 148 /** 149 * Add a new session pair to this session. 150 * 151 * @param newPair the new session pair to be added to this session. If 152 * {@code newPair} is <i>null</i> this method does nothing. 153 */ 154 public void addSessionPair(SessionPair newPair) 155 { 156 if (newPair != null) 157 sessionPairs.add(newPair); 158 } 159 160 /** 161 * Removes the given session pair from this session. 162 * 163 * @param oldPair the session pair to be removed from this session. 164 */ 165 public void removeSessionPair(SessionPair oldPair) 166 { 167 if (oldPair != null) 168 sessionPairs.remove(oldPair); 169 } 170 171 /** 172 * Returns this session's set of session pairs. 173 * <p> 174 * Note that this session's actual collection of pairs is returned, not 175 * a clone thereof. This means that any changes a client makes to the 176 * collection will be reflected in this session.</p> 177 * <p> 178 * This method is guaranteed to return a non-null value, though the 179 * set it returns may be empty.</p> 180 * 181 * @return this session's set of session pairs. 182 */ 183 public Set<SessionPair> getSessionPairs() 184 { 185 return sessionPairs; 186 } 187 188 /** 189 * Replaces this session's session pairs with the given collection. 190 * <p> 191 * If {@code replacementSet} is <i>null</i>, this session's collection 192 * will be replaced with an empty collection.</p> 193 * 194 * @param replacementSet a new set of session pairs that replaces this 195 * session's current set. 196 */ 197 @SuppressWarnings("unused") 198 private void setSessionPairs(Set<SessionPair> replacementSet) 199 { 200 sessionPairs = (replacementSet == null) ? new HashSet<SessionPair>() 201 : replacementSet; 202 } 203 204 //============================================================================ 205 // OBSERVATION CONSTRAINTS 206 //============================================================================ 207 208 /** 209 * Sets the earliest local sidereal time for this observation session. 210 * <p> 211 * The general form of the string is <tt>hh:mm:ss.sss</tt>. Leading zeroes 212 * are not required, though all three parts (hours, minutes, seconds) are 213 * required. Fractional seconds are not required. 214 * Examples of valid text strings: 215 * <ul> 216 * <li>00:00:00</li> 217 * <li>23:59:59.987</li> 218 * <li>2:3:4.</li> 219 * <li>0:07:8.1</li> 220 * </ul></p> 221 * <p> 222 * Valid ranges for each part: 223 * <ul> 224 * <li>hh - [0-23]</li> 225 * <li>mm - [0-59]</li> 226 * <li>ss.sss... - [0-60) (i.e., zero up to, but not including, 60)</li> 227 * </ul></p> 228 * <p> 229 * If the parameter string is not well formed, or if the values are not in 230 * the ranges given above, an {@code IllegalArgumentException} is thrown.</p> 231 * <p> 232 * See the note in {@link #getMinimumLst()} about the relationship between 233 * the minimum and maximum LST values.</p> 234 * 235 * @param lstMin the earliest local sidereal time for this observation 236 * session. 237 * 238 * @throws IllegalArgumentException if {@code lstMin} does not follow the 239 * conventions set forth in the method comments. 240 */ 241 public void setMinimumLst(String lstMin) 242 { 243 /* TODO: Reactivate once R.A.'s parsing is restored 244 //Using the R.A. class to parse the string is a temporary kludge. 245 //My hunch is that we'll want to have some kind of LST class, or 246 //a general time class that be expressed in LST. 247 if (hhmmssParser == null) 248 hhmmssParser = new Longitude(); 249 250 //If lstMin is not valid, the next line will throw an illegal arg ex 251 hhmmssParser.parse(lstMin); 252 */ 253 minimumLst = lstMin; 254 } 255 256 /** 257 * Returns the earliest local sidereal time for this observation session. 258 * <p> 259 * Note that, using a 24-hour clock that resets to zero at LST midnight, 260 * the "minimum" might be a greater number than the maximum. In this 261 * situation, it will be understood that the interval crosses midnight 262 * and into the next day.</p> 263 * 264 * @return the earliest local sidereal time for this observation session. 265 */ 266 public String getMinimumLst() 267 { 268 return minimumLst; 269 } 270 271 /** 272 * Sets the latest local sidereal time for this observation session. 273 * <p> 274 * See {@link #setMinimumLst(String)} for information about the form of 275 * the parameter string. See also the note in {@link #getMinimumLst()} 276 * about the relationship between the minimum and maximum LST values.</p> 277 * 278 * @param lstMax the latest local sidereal time for this observation 279 * session. 280 * 281 * @throws IllegalArgumentException if {@code lstMax} does not follow the 282 * conventions set forth in the method comments of 283 * {@code setLstMinimum}. 284 */ 285 public void setMaximumLst(String lstMax) 286 { 287 /* TODO: Reactivate once R.A.'s parsing is restored 288 //Using the R.A. class to parse the string is a temporary kludge. 289 //My hunch is that we'll want to have some kind of LST class, or 290 //a general time class that be expressed in LST. 291 if (hhmmssParser == null) 292 hhmmssParser = new Longitude(); 293 294 //If lstMin is not valid, the next line will throw an illegal arg ex 295 hhmmssParser.parse(lstMax); 296 */ 297 maximumLst = lstMax; 298 } 299 300 /** 301 * Returns the latest local sidereal time for this observation session. 302 * See note in {@link #getMinimumLst()}. 303 * 304 * @return the latest local sidereal time for this observation session. 305 */ 306 public String getMaximumLst() 307 { 308 return maximumLst; 309 } 310 311 /** 312 * Sets the minimum acceptable elevation (of which source?) for this session. 313 * 314 * @param degrees the minimum acceptable elevation, measured in degrees above 315 * the horizon. This value must be between 0.0 and 90.0, 316 * inclusive. 317 * 318 * @throws IllegalArgumentException if {@code degrees} is not within the range 319 * stated above. 320 */ 321 public void setMinimumElevation(double degrees) 322 { 323 if (degrees < 0.0 || degrees > 90.0) 324 throw new IllegalArgumentException( 325 "Minimum elevation must be between 0 and 90 degrees, inclusive."); 326 327 minimumElevation = degrees; 328 } 329 330 /** 331 * Returns the minimum acceptable elevation (of which source?) for this session. 332 * 333 * @return the minimum acceptable elevation (of which source?) for this session, 334 * in degrees above the horizon. 335 */ 336 public double getMinimumElevation() 337 { 338 return minimumElevation; 339 } 340 341 /** 342 * Sets the scheduling constraints specified by a proposal's author 343 * for this session. These constraints are for human consumption; there 344 * is no required format for this text. 345 * 346 * @param constraint the scheduling constraints for this session. 347 */ 348 public void setSchedulingConstraint(String constraint) 349 { 350 this.schedulingConstraint = (constraint == null) ? NO_CONSTRAINT 351 : constraint; 352 } 353 354 /** 355 * Returns the scheduling constraints for this session. If there 356 * are no constraints, the empty string is returned. This method 357 * will never return <i>null</i>. 358 * 359 * @return this session's scheduling restraints. 360 */ 361 public String getSchedulingConstraint() 362 { 363 return schedulingConstraint; 364 } 365 366 //============================================================================ 367 // LENGTH OF OBSERVATION 368 //============================================================================ 369 370 /** 371 * Sets the number of times to repeat this session. 372 * 373 * @param repeats the number of times to repeat this session. 374 * If {@code repeats} is less than zero, it will be treated 375 * as zero. 376 */ 377 public void setRepeatCount(int repeats) 378 { 379 repeatCount = (repeats < 0) ? 0 : repeats; 380 } 381 382 /** 383 * Returns the number of times to repeat this session. 384 * 385 * @return the number of times to repeat this session. 386 */ 387 public int getRepeatCount() 388 { 389 return repeatCount; 390 } 391 392 /** 393 * Sets the separation in time between successive repeats of this session. 394 * 395 * @param separation the time duration between successive repeats of this 396 * session. If {@code separation} is <i>null</i>, it 397 * will be treated as a duration of no time. 398 */ 399 @SuppressWarnings("unused") 400 private void setSeparation(TimeDuration separation) 401 { 402 this.separation = (separation == null) ? new TimeDuration() : separation; 403 } 404 405 /** 406 * Returns the separation in time between successive repeats of this session. 407 * 408 * @return the separation in time between successive repeats of this session. 409 */ 410 public TimeDuration getSeparation() 411 { 412 return separation; 413 } 414 415 /** 416 * Sets the amount of time needed for one execution of this session. 417 * 418 * @param neededTime the amount of time needed for one execution of this 419 * session. If {@code neededTime} is <i>null</i>, it 420 * will be treated as a duration of no time. 421 */ 422 @SuppressWarnings("unused") 423 private void setSessionTime(TimeDuration neededTime) 424 { 425 sessionTime = (neededTime == null) ? new TimeDuration() : neededTime; 426 } 427 428 /** 429 * Returns the amount of time needed for one execution of this session. 430 * 431 * @return the amount of time needed for one execution of this session. 432 */ 433 public TimeDuration getSessionTime() 434 { 435 return sessionTime; 436 } 437 438 /** 439 * Returns the total time needed for this session after accounting for 440 * the desired number of executions. 441 * 442 * @return total time needed for this session. 443 */ 444 public TimeDuration getTotalTime() 445 { 446 TimeDuration totalTime = (TimeDuration)getSessionTime().clone(); 447 448 if (repeatCount > 1) 449 totalTime.multiplyBy(BigDecimal.valueOf(repeatCount)); 450 451 return totalTime; 452 } 453 454 //============================================================================ 455 // MISCELLANEOUS 456 //============================================================================ 457 458 /** 459 * Sets the proposer's comments for this observation session. 460 * 461 * @param comments the proposer's comments for this observation session. 462 * If {@code comments} is <i>null</i>, it will be treated 463 * as the empty string. 464 */ 465 public void setComments(String comments) 466 { 467 this.comments = (comments == null) ? NO_COMMENTS : comments; 468 } 469 470 /** 471 * Returns the proposer's comments for this observation session. 472 * 473 * @return the proposer's comments for this observation session. 474 */ 475 public String getComments() 476 { 477 return comments; 478 } 479 480 //TODO toXml 481 //TODO clone 482 //TODO equals 483 //TODO hashCode 484 }