001    package edu.nrao.sss.model.resource.evla;
002    
003    import java.io.FileNotFoundException;
004    import java.io.Reader;
005    import java.util.List;
006    
007    import javax.xml.bind.JAXBException;
008    import javax.xml.bind.annotation.XmlElement;
009    import javax.xml.bind.annotation.XmlRootElement;
010    import javax.xml.stream.XMLStreamException;
011    
012    import ca.nrc.widar.jaxb.vci.BaseBand;
013    import ca.nrc.widar.jaxb.vci.BbParams;
014    import edu.nrao.sss.astronomy.PolarizationType;
015    import edu.nrao.sss.electronics.DigitalSignal;
016    import edu.nrao.sss.measure.Frequency;
017    import edu.nrao.sss.measure.FrequencyRange;
018    import edu.nrao.sss.util.JaxbUtility;
019    
020    /**
021     * An unpaired baseband of the WIDAR correlator.
022     * <p>
023     * <b>Version Info:</b>
024     * <table style="margin-left:2em">
025     *   <tr><td>$Revision: 2271 $</td></tr>
026     *   <tr><td>$Date: 2009-04-28 12:02:17 -0600 (Tue, 28 Apr 2009) $</td></tr>
027     *   <tr><td>$Author: dharland $ (last person to modify)</td></tr>
028     * </table></p>
029     * 
030     * @author David M. Harland
031     * @since 2008-06-24
032     */
033    @XmlRootElement
034    public class WidarBasebandSinglet
035      extends WidarBaseband
036    {
037      @XmlElement private DigitalSignal inputSignal;
038      
039      //TODO Need to think about Hibernate & JAXB handling of this
040      private WidarBasebandSinglet partner;
041      
042      /**
043       * Helps create a new WIDAR baseband.
044       * @throws IllegalArgumentException
045       *   if {@code input} is <i>null</i>.
046       */
047      protected WidarBasebandSinglet(DigitalSignal input)
048      {
049        this();
050        initInput(input, true);
051      }
052      
053      //This is here only for persistence mechanisms
054      protected WidarBasebandSinglet()
055      {
056        super();
057      }
058    
059      /** Sets the input signal for this baseband. */
060      private void initInput(DigitalSignal input, boolean forceBwUpdate)
061      {
062        if (input == null)
063          throw new IllegalArgumentException(
064            "Cannot configure correlator baseband with a NULL input signal.");
065    
066        inputSignal = input;
067    
068        bandwidth = inputSignal.getCurrentRange().getWidth();
069      }
070      
071      /**
072       * Sets the input signal for this baseband.
073       * Classes that override this method should have
074       * <tt>super.setInput(input)</tt> as their first line.
075       */
076      protected void setInput(DigitalSignal input)
077      {
078        initInput(input, false);
079      }
080    
081      //============================================================================
082      // IDENTIFICATION
083      //============================================================================
084    
085      /* (non-Javadoc)
086       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getName()
087       */
088      public String getName()  { return inputSignal.getName(); }
089    
090      /* (non-Javadoc)
091       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#isSinglet()
092       */
093      public boolean isSinglet()  { return true; }
094    
095      //============================================================================
096      // FREQUENCY
097      //============================================================================
098      
099      Frequency getInputBandwidth()
100      {
101        return inputSignal.getCurrentRange().getWidth();
102      }
103    
104      /* (non-Javadoc)
105       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getProxiedRange()
106       */
107      public FrequencyRange getProxiedRange()
108      {
109        return getProxiedRange(inputSignal);
110      }
111    
112      /* (non-Javadoc)
113       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#proxiedRangeIsReversed()
114       */
115      public boolean proxiedRangeIsReversed()
116      {
117        return proxiedRangeIsReversed(inputSignal);
118      }
119      
120      //============================================================================
121      // QUANTIZATION & POLARIZATION
122      //============================================================================
123    
124      /* (non-Javadoc)
125       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getInitialQuantization()
126       */
127      public int getInitialQuantization()
128      {
129        return getInitialQuantization(inputSignal);
130      }
131      
132      /**
133       * Returns the polarization of the signal represented by this baseband.
134       * @return the polarization of the signal represented by this baseband.
135       */
136      public PolarizationType getPolarization()
137      {
138        return inputSignal.getPolarization();
139      }
140      
141      /* (non-Javadoc)
142       * @see edu.nrao.sss.model.resource.CorrelatorBaseband#getPolarizations()
143       */
144      public List<PolarizationType> getPolarizations()
145      {
146        return getPolarizations(inputSignal);
147      }
148    
149      //============================================================================
150      // PARTNERED BASEBANDS
151      //============================================================================
152      
153      public boolean isPartnerOf(WidarBaseband other)  { return other == partner; }
154      
155      public boolean hasPartner()  { return partner != null; }
156      
157      public WidarBaseband getPartner()  { return partner; }
158      
159      static void formPartnership(WidarBasebandSinglet bb1, WidarBasebandSinglet bb2)
160      {
161        if (bb1 != null)
162          bb1.setPartner(bb2);
163        
164        if (bb2 != null)
165          bb2.setPartner(bb1);
166      }
167      
168      private void setPartner(WidarBasebandSinglet newPartner)
169      {
170        //Intentionally dealing w/only ONE side of the partnership (unless new is null)
171        if (newPartner == null && this.partner != null)
172          this.partner.partner = null;
173        
174        this.partner = newPartner;
175        
176        //TODO think about anything else we should do here.
177      }
178    
179      /**
180       * @return
181       */
182      WidarBasebandPair toPairWithPartner()
183      {
184        DigitalSignal dsA = inputSignal;
185        DigitalSignal dsB = (partner == null) ? null : partner.inputSignal;
186        
187        WidarBasebandPair pair = null;
188        
189        //Can form pair only if we have two signals
190        if (dsA != null && dsB != null)
191        {
192          if (dsA.getName().compareTo(dsB.getName()) <= 0)
193            pair = new WidarBasebandPair(dsA,dsB);
194          else
195            pair = new WidarBasebandPair(dsB,dsA);
196          
197          pair.setEvlaWidarConfiguration(this.getEvlaWidarConfiguration());
198          //TODO pair needs to have its configuration based on THIS singlet, eg subbands
199        }
200        
201        return pair;
202      }
203      
204      //============================================================================
205      // SUBBAND
206      //============================================================================
207    
208      //============================================================================
209      // VCI ELEMENTS
210      //============================================================================
211      
212      void setWidarBbIds(BaseBand widarBB, boolean primary)
213      {
214        int[] idVciBbA = getVciBbIds(inputSignal.getName());
215        
216        int index = 0;
217        
218        if (idVciBbA.length == 2 && !primary)
219          index = 1;
220        
221        widarBB.setBbA(idVciBbA[index]);
222      }
223      
224      void addBbParams(List<BbParams> bbParamList, int stationId)
225      {
226        addBbParams(bbParamList, stationId, inputSignal);
227      }
228    
229      //============================================================================
230      // 
231      //============================================================================
232      
233      /**
234       * Creates a new baseband from the XML data in the given file.
235       * 
236       * @param xmlFile
237       *   the name of an XML file.  This method will attempt to locate
238       *   the file by using {@link Class#getResource(String)}.
239       *                
240       * @return
241       *   a new baseband from the XML data in the given file.
242       * 
243       * @throws FileNotFoundException
244       *   if the XML file cannot be found.
245       * 
246       * @throws JAXBException
247       *   if the schema file used (if any) is malformed, if the XML file cannot be
248       *   read, or if the XML file is not schema-valid.
249       * 
250       * @throws XMLStreamException
251       *   if there is a problem opening the XML file, if the XML is not well-formed,
252       *   or for some other "unexpected processing conditions".
253       */
254      public static WidarBasebandSinglet fromXml(String xmlFile)
255        throws JAXBException, XMLStreamException, FileNotFoundException
256      {
257        return JaxbUtility.getSharedInstance()
258                          .xmlFileToObject(xmlFile, WidarBasebandSinglet.class);
259      }
260    
261      /**
262       * Creates a new baseband based on the XML data read from {@code reader}.
263       * 
264       * @param reader
265       *   the source of the XML data.
266       *   If this value is <i>null</i>, <i>null</i> is returned.
267       *               
268       * @return
269       *  a new baseband based on the XML data read from {@code reader}.
270       * 
271       * @throws XMLStreamException
272       *   if the XML is not well-formed,
273       *   or for some other "unexpected processing conditions".
274       *           
275       * @throws JAXBException
276       *   if anything else goes wrong during the transformation.
277       */
278      public static WidarBasebandSinglet fromXml(Reader reader)
279        throws JAXBException, XMLStreamException
280      {
281        return JaxbUtility.getSharedInstance()
282                          .readObjectAsXmlFrom(reader, WidarBasebandSinglet.class, null);
283      }
284    
285      //============================================================================
286      // 
287      //============================================================================
288    
289      /**
290       *  Returns a copy of this baseband.
291       *  <p>
292       *  If anything goes wrong during the cloning procedure,
293       *  a {@code RuntimeException} will be thrown.</p>
294       */
295      @Override
296      public WidarBasebandSinglet clone()
297      {
298        WidarBasebandSinglet clone = cloneAllButPartner();
299    
300        if (this.partner != null)
301        {
302          clone.partner         = this.partner.cloneAllButPartner();
303          clone.partner.partner = clone;
304        }
305        
306        return clone;
307      }
308      
309      private WidarBasebandSinglet cloneAllButPartner()
310      {
311        WidarBasebandSinglet clone = null;
312        
313        try
314        {
315          clone = (WidarBasebandSinglet)super.clone();
316    
317          clone.inputSignal = this.inputSignal.clone();
318          clone.partner     = null;
319        }
320        catch (Exception ex)
321        {
322          throw new RuntimeException(ex);
323        }
324    
325        return clone;
326      }
327      
328      /** Returns <i>true</i> if {@code o} is equal to this baseband. */
329      @Override
330      public boolean equals(Object o)
331      {
332        //Quick exit if super class says not equal
333        if (!super.equals(o))
334          return false;
335       
336        //A safe cast if we got this far
337        WidarBasebandSinglet other = (WidarBasebandSinglet)o;
338    
339        return other.inputSignal.equals(this.inputSignal);
340      }
341    
342      /** Returns a hash code value for this baseband. */
343      @Override
344      public int hashCode()
345      {
346        //Taken from the Effective Java book by Joshua Bloch.
347        //The constants 17 & 37 are arbitrary & carry no meaning.
348        int result = super.hashCode();
349        
350        //You MUST keep this method in sync w/ the equals method
351        
352        result = 37 * result + inputSignal.hashCode();
353        
354        return result;
355      }
356      
357      //============================================================================
358      // 
359      //============================================================================
360      /*
361      public static void main(String[] args)
362      {
363        WidarBuilder builder = new WidarBuilder();
364        
365        WidarBasebandSinglet bb = builder.makeBasebandSinglet();
366    
367        try
368        {
369          bb.writeAsXmlTo(new java.io.PrintWriter(System.out));
370        }
371        catch (Exception ex)
372        {
373          System.out.println("Trouble w/ bb.toXml.  Msg:");
374          System.out.println(ex.getMessage());
375          ex.printStackTrace();
376          
377          System.out.println("Attempting to write XML w/out schema verification:");
378          JaxbUtility.getSharedInstance().setLookForDefaultSchema(false);
379          try
380          {
381            System.out.println(bb.toXml());
382          }
383          catch (JAXBException ex2)
384          {
385            System.out.println("Still had trouble w/ bb.toXml.  Msg:");
386            System.out.println(ex2.getMessage());
387            ex2.printStackTrace();
388          }
389        }
390        
391        BaseBand vciBB = bb.toVci();
392        System.out.println(); System.out.println("-------------"); System.out.println();
393        try
394        {
395          VciJaxbUtil.writeObjectAsXmlTo(new java.io.PrintWriter(System.out), vciBB);
396        }
397        catch (Exception ex)
398        {
399          throw new RuntimeException(ex);
400        }
401      }
402      */
403    }