001    package edu.nrao.sss.model.project.scan;
002    
003    import java.util.ArrayList;
004    import java.util.List;
005    
006    import edu.nrao.sss.model.resource.Resource;
007    import edu.nrao.sss.model.resource.TelescopeBackend;
008    import edu.nrao.sss.model.resource.CorrelatorName;
009    import edu.nrao.sss.model.resource.vla.CorrelatorMode;
010    import edu.nrao.sss.model.resource.vla.IFPair;
011    import edu.nrao.sss.model.resource.vla.VlaConfiguration;
012    import edu.nrao.sss.validation.AbstractValidator;
013    import edu.nrao.sss.validation.DataNotEnteredValidation;
014    import edu.nrao.sss.validation.FailureSeverity;
015    import edu.nrao.sss.validation.Validation;
016    import edu.nrao.sss.validation.ValidationPurpose;
017    import edu.nrao.sss.validation.Validator;
018    
019    /**
020     * A validator of {@link TippingScan tipping scans}.
021     * <p>
022     * <u>Validations Performed for All Purposes</u>
023     * <ol>
024     *   <li>All validations performed by {@link SimpleScanValidator}.</li>
025     *   <li>Scan has at least one position.</li>
026     *   <li>Contained positions are valid.<sup>1</sup></li>
027     * </ol>
028     * <sup>1</sup><i>The particular validations performed depend on the
029     * validator used by this one to operate on those contained positions.
030     * </ol>
031     * <p>
032     * <b>Version Info:</b>
033     * <table style="margin-left:2em">
034     *   <tr><td>$Revision: 1971 $</td></tr>
035     *   <tr><td>$Date: 2009-02-13 09:30:50 -0700 (Fri, 13 Feb 2009) $</td></tr>
036     *   <tr><td>$Author: btruitt $</td></tr>
037     * </table></p>
038     * 
039     * @author David M. Harland
040     * @since 2007-02-13
041     */
042    public class TippingScanValidator
043      extends ScanValidator<TippingScan>
044    {
045      private Validator tippingPositionValidator;
046      
047      /** Creates a new instance. */
048      public TippingScanValidator()
049      {
050        super(TippingScanValidator.class.getName(), TippingScan.class);
051      }
052      
053      /* (non-Javadoc)
054       * @see AbstractValidator#makeValidationList(ValidationPurpose)
055       */
056      @Override
057      protected List<Validation<TippingScan>>
058        makeValidationList(ValidationPurpose purpose)
059      {
060        List<Validation<TippingScan>> validations = new ArrayList<Validation<TippingScan>>();
061        
062        validations.add(new HasName           (this, purpose));
063        validations.add(new HasIntent         (this, purpose));
064        validations.add(new HasResource       (this, purpose));
065        validations.add(new UsesSkyFrequencies(this, purpose));
066        validations.add(new HasValidTimeType  (this, purpose));
067        validations.add(new HasDurationOrTime (this, purpose));
068    
069        // TODO: re-enable when we fully enable our tipping scan support!
070        // validations.add(new HasPosition(this, purpose));
071    
072        return validations; 
073      }
074    
075      /* (non-Javadoc)
076       * @see edu.nrao.sss.model.validation.AbstractValidator#validate()
077       */
078      @Override
079      protected void validate()
080      {
081        super.validate();
082    
083        //Validate the contained settings
084        Validator tpVal = getTippingPositionValidator();
085        
086        for (TippingPosition tp : target.getElevations())
087          failures.addAll(tpVal.validate(tp, purpose));
088      }
089      
090      //============================================================================
091      // COMPONENT VALIDATORS
092      //============================================================================
093    
094      /**
095       * Sets the validator to use for the tipping positions of the target scan.
096       * It is acceptable to use a <i>null</i> parameter, in which case
097       * this validator will contact its manager for a tipping-position validator
098       * or create one itself.
099       * 
100       * @param newValidator a validator to use on the tipping positions of this
101       *                     validator's target scan.
102       */
103      public void setTippingPositionValidator(Validator newValidator)
104      {
105        tippingPositionValidator = newValidator;
106      }
107    
108      /** Returns a validator for delay settings. */
109      public Validator getTippingPositionValidator()
110      {
111        Validator validator = tippingPositionValidator;
112        
113        if (validator == null)
114        {
115          if (manager != null)
116            validator = manager.getValidator(TippingPosition.class);
117          
118          if (validator == null)
119            validator = new TippingPositionValidator();
120        }
121        
122        return validator;
123      }
124      
125      //============================================================================
126      // UNITIALIZED FIELD VALIDATIONS
127      //============================================================================
128      
129      class HasPosition extends DataNotEnteredValidation<TippingScan>
130      {
131        protected HasPosition(AbstractValidator<TippingScan> validationContainer,
132                              ValidationPurpose              reasonForValidation)
133        {
134          super(validationContainer, reasonForValidation,
135                "tipping scan", "tipping position", "0");
136        }
137        
138        @Override
139        protected String getCurrentValue()
140        {
141          specificTargetName = target.getName();
142    
143          return Integer.toString(target.getElevations().size());
144        }
145      }
146    
147      // TODO: This is Vla correlator specific!!  Must update for widar!
148      class UsesSkyFrequencies extends Validation<TippingScan>
149      {
150        protected UsesSkyFrequencies(AbstractValidator<TippingScan> validationContainer, ValidationPurpose reasonForValidation)
151        {
152          super(validationContainer, reasonForValidation);
153          severity = (reasonForValidation == ValidationPurpose.CERTIFY_READY_TO_USE)? FailureSeverity.ERROR : FailureSeverity.WARNING;
154        }
155        
156        @Override
157        public boolean passesTest()
158        {
159          Resource rsrc = target.getResource();
160    
161          if (rsrc != null)
162          {
163            List<TelescopeBackend> backEnds = rsrc.getBackends();
164            if (backEnds != null && !backEnds.isEmpty())
165            {
166              // We only care about/look at the first back end.
167              TelescopeBackend be = backEnds.get(0);
168              if (be.getName().equals(CorrelatorName.VLA))
169              {
170                VlaConfiguration conf = (VlaConfiguration)be;
171                CorrelatorMode mode = conf.getCorrelatorMode();
172                if ((mode.uses(IFPair.AC) && !conf.isSkyFrequency(IFPair.AC)) ||
173                    (mode.uses(IFPair.BD) && !conf.isSkyFrequency(IFPair.BD)))
174                {
175                  return false;
176                }
177              }
178            }
179          }
180          
181          return true;
182        }
183    
184        @Override
185        public String debugMessage()
186        {
187          return displayMessage();
188        }
189    
190        @Override
191        public String displayMessage()
192        {
193          StringBuilder msg = new StringBuilder("Tipping scan: ");
194          msg.append(target.getName());
195          msg.append(" is using a rest frequency as opposed to a sky frequency in its hardware configuration.");
196          msg.append("  Rest frequencies are not allowed in tipping and pointing scans.");
197    
198          if (severity != FailureSeverity.ERROR)
199            msg.append("  This is ok for now, but you will not be able to observe with this configuration.");
200    
201          return msg.toString();
202        }
203      }
204    }