001    package edu.nrao.sss.model.project;
002    
003    import javax.xml.bind.annotation.XmlType;
004    
005    import edu.nrao.sss.measure.TimeDuration;
006    import edu.nrao.sss.model.project.scan.ScanIntent;
007    
008    /**
009     * A calibration of a telescope that is typically performed just
010     * before, or just after, a scheduling block is executed.
011     * <p>
012     * <b>CVS Info:</b>
013     * <table style="margin-left:2em">
014     *   <tr><td>$Revision: 897 $</td></tr>
015     *   <tr><td>$Date: 2007-09-20 11:39:07 -0600 (Thu, 20 Sep 2007) $</td></tr>
016     *   <tr><td>$Author: dharland $</td></tr>
017     * </table></p>
018     *  
019     * @author David M. Harland
020     * @since 2006-07-27
021     */
022    @XmlType(propOrder= {"type", "timing", "allowableSeparation"})
023    public class ServiceCalibration
024      implements Cloneable
025    {
026      private ScanIntent               type;
027      private ServiceCalibrationTiming timing;
028      private TimeDuration             allowableSeparation;
029      
030      /** Creates a new instance. */
031      public ServiceCalibration()
032      {
033        type = ScanIntent.OTHER;
034        timing = ServiceCalibrationTiming.getDefault();
035        allowableSeparation = new TimeDuration();
036      }
037      
038      /**
039       * Sets the type of calibration to be performed.
040       * @param calibrationType the type of calibration to be performed.
041       */
042      public void setType(ScanIntent calibrationType)
043      {
044        type = (calibrationType == null) ? ScanIntent.OTHER : calibrationType;
045      }
046      
047      /**
048       * Returns the type of calibration to be performed.
049       * @return the type of calibration to be performed.
050       */
051      public ScanIntent getType()
052      {
053        return type;
054      }
055      
056      /**
057       * Sets a value that indicates whether this service calibration should
058       * be performed before or after execution of a scheduling block.
059       * 
060       * @param newTiming the timing of calibration to be performed.
061       */
062      public void setTiming(ServiceCalibrationTiming newTiming)
063      {
064        timing = (newTiming == null) ? ServiceCalibrationTiming.getDefault()
065                                     : newTiming;
066      }
067      
068      /**
069       * Returns a value that indicates whether this service calibration should
070       * be performed before or after execution of a scheduling block.
071       * 
072       * @return the timing of calibration to be performed.
073       */
074      public ServiceCalibrationTiming getTiming()
075      {
076        return timing;
077      }
078    
079      /**
080       * Sets the time duration during which a prior calibration of the
081       * same type would be acceptable for reuse.
082       * 
083       * @param separation a period of time after which a prior calibration
084       *                   of this type will no longer be acceptable for reuse.
085       *                   Once this period has elapsed, a new calibration will
086       *                   be required.
087       */
088      public void setAllowableSeparation(TimeDuration separation)
089      {
090        allowableSeparation = (separation == null) ? new TimeDuration()
091                                                   : separation;
092      }
093      
094      /**
095       * Returns the time duration during which a prior calibration of the
096       * same type would be acceptable for reuse.
097       * 
098       * @return an expiration period for a calibration of this type.  Once this
099       *         period has elapsed, the prior calibration is not to be used for
100       *         new observations. 
101       */
102      public TimeDuration getAllowableSeparation()
103      {
104        return allowableSeparation;
105      }
106    
107      //============================================================================
108      // 
109      //============================================================================
110      
111      /**
112       *  Returns a copy of this service calibration.
113       *  <p>
114       *  If anything goes wrong during the cloning procedure,
115       *  a {@code RuntimeException} will be thrown.</p>
116       */
117      public ServiceCalibration clone()
118      {
119        ServiceCalibration clone = null;
120        
121        try
122        {
123          //This line takes care of the primitive & immutable fields properly
124          clone = (ServiceCalibration)super.clone();
125          
126          clone.allowableSeparation = this.allowableSeparation.clone();
127        }
128        catch (Exception ex)
129        {
130          throw new RuntimeException(ex);
131        }
132        
133        return clone;
134      }
135      
136      /**
137       * Returns <i>true</i> if {@code o} is equal to this service calibration.
138       * <p>
139       * In order to be equal to this service calibration, {@code o} must be
140       * non-null and of the same class as this calibration.  Equality is
141       * determined by examining the equality of corresponding attributes.</p>
142       */
143      public boolean equals(Object o)
144      {
145        //Quick exit if o is null
146        if (o == null)
147          return false;
148        
149        //Quick exit if o is this
150        if (o == this)
151          return true;
152        
153        //Quick exit if classes are different
154        if (!o.getClass().equals(this.getClass()))
155          return false;
156    
157        ServiceCalibration other = (ServiceCalibration)o;
158        
159        return (other.type.equals(this.type) &&
160                other.timing.equals(this.timing) &&
161                other.allowableSeparation.equals(this.allowableSeparation));
162      }
163      
164      /* (non-Javadoc)
165       * @see java.lang.Object#hashCode()
166       */
167      public int hashCode()
168      {
169        //Taken from the Effective Java book by Joshua Bloch.
170        //The constants 17 & 37 are arbitrary & carry no meaning.
171        int result = 17;
172        
173        //You MUST keep this method in sync w/ the equals method
174    
175        //Names
176        result = 37 * result + type.hashCode();
177        result = 37 * result + timing.hashCode();
178        result = 37 * result + allowableSeparation.hashCode();
179    
180        return result;
181      }
182    }