001    package edu.nrao.sss.model.resource;
002    
003    import java.util.ArrayList;
004    import java.util.List;
005    
006    /**
007     * A selection of receivers, typically created by a {@link ReceiverSelector}.
008     * Instances of this class are immutable.
009     * <p>
010     * <b>Version Info:</b>
011     * <table style="margin-left:2em">
012     *   <tr><td>$Revision: 1096 $</td></tr>
013     *   <tr><td>$Date: 2008-02-12 11:01:13 -0700 (Tue, 12 Feb 2008) $</td></tr>
014     *   <tr><td>$Author: dharland $</td></tr>
015     * </table></p>
016     * 
017     * @author David M. Harland
018     * @since 2007-01-11
019     */
020    public class ReceiverSelection
021    {
022      private List<ReceiverBand>    receivers;
023      private ResourceSpecification originalSpecifications;
024      private ResourceSpecification modifiedSpecifications;
025      
026      private transient double fractionalCoverage = -1.0;
027      
028      /**
029       * Creates a new selection of receivers.
030       * 
031       * @param selections the selected receivers.  If no receivers were selected,
032       *                   send either an empty list, or <i>null</i>, which will
033       *                   be converted to an empty list by this constructor.
034       *                   
035       * @param original the resource specifications used to select the receivers.
036       *                 This parameter may not be <i>null</i>.
037       * 
038       * @param modified the intersection of the original specifications and the
039       *                 frequency ranges of the selected receivers.
040       *                 This parameter may not be <i>null</i>.
041       */
042      ReceiverSelection(List<ReceiverBand>    selections,
043                        ResourceSpecification original,
044                        ResourceSpecification modified)
045      {
046        originalSpecifications = original.clone();
047        modifiedSpecifications = modified.clone();
048    
049        receivers = new ArrayList<ReceiverBand>();
050        
051        //We're not adding clones of the Receivers in selections because
052        //Receiver instances are immutable.
053        if (selections != null)
054          receivers.addAll(selections);
055      }
056      
057      /**
058       * Returns the selected receivers.
059       * The returned list is a copy, but the references to the receivers in the
060       * returned list are the same as those held by this object's list.
061       *  
062       * @return the selected receivers.
063       */
064      public List<ReceiverBand> getReceivers()
065      {
066        return new ArrayList<ReceiverBand>(receivers);
067      }
068      
069      /**
070       * Returns the resource specifications that were used to create this
071       * selection.
072       * <p>
073       * Note that the returned specification is a copy of that held by
074       * this receiver selection.  That means that any changes made to the
075       * returned specification will not be reflected in this object.</p>
076       * 
077       * @return the specifications that were used to create this selection.
078       */
079      public ResourceSpecification getOriginalSpecifications()
080      {
081        return originalSpecifications.clone();
082      }
083      
084      /**
085       * Returns the resource specifications that represent the intersection
086       * between the original specifications and the bandwidth covered by the
087       * selected receivers.
088       * <p>
089       * Note that the returned specification is a copy of that held by
090       * this receiver selection.  That means that any changes made to the
091       * returned specification will not be reflected in this object.</p>
092       * 
093       * @return a modification to the original resource specifications that
094       *         reflects the capabilities of the selected receivers.
095       */
096      public ResourceSpecification getModifiedSpecifications()
097      {
098        return modifiedSpecifications.clone();
099      }
100      
101      /**
102       * Returns the fraction of the bandwidth requested in the original
103       * specifications that can be satisfied by the selected receivers.
104       * The value will returned will be between zero and one, inclusive.
105       * 
106       * @return the fraction of the requested bandwidth covered by the
107       *         selected receivers.
108       */
109      public double getFractionalBandwidthCoverage()
110      {
111        if (fractionalCoverage < 0.0)
112          calculateFractionalBandwidthCoverage();
113        
114        return fractionalCoverage;
115      }
116      
117      private void calculateFractionalBandwidthCoverage()
118      {
119        //We can divide the amt covered by the modified specs by the amt
120        //covered by the original specs only because we know that each
121        //range of the modified specs is a subset (including being the
122        //complete range) of a corresponding range in the original specs.
123        fractionalCoverage =
124          modifiedSpecifications.getSpectrum().getAmountCovered().dividedBy(
125          originalSpecifications.getSpectrum().getAmountCovered()).doubleValue();
126      }
127    }