001    package edu.nrao.sss.model.resource;
002    
003    import java.util.EnumSet;
004    import java.util.HashMap;
005    import java.util.Set;
006    
007    import edu.nrao.sss.util.EnumerationUtility;
008    
009    /**
010     * A particular configuration of a telescope.
011     * <p>
012     * A telescope configuration is typically most appropriate for telescopes
013     * that consist of multiple antennas or mirrors, such as the VLA.
014     * More information about the VLA's configurations, and a schedule for when the
015     * array is in a given configuration, can be found at the
016     * <a href="http://www.vla.nrao.edu/genpub/configs/">
017     * VLA Configurations page</a>.</p>
018     * <p>
019     * <i>(This class replaces the old {@code VlaConfiguration} class.)</i></p>
020     * <p>
021     * <b>Version Info:</b>
022     * <table style="margin-left:2em">
023     *   <tr><td>$Revision: 2258 $</td></tr>
024     *   <tr><td>$Date: 2009-04-24 13:25:38 -0600 (Fri, 24 Apr 2009) $</td></tr>
025     *   <tr><td>$Author: dharland $</td></tr>
026     * </table></p>
027     * 
028     * @author David M. Harland
029     * @since 2006-11-13
030     */
031    public enum TelescopeConfiguration
032    {
033      /** The <i>A</i> configuration of the Very Large Array.
034       *  <p>
035       *  This is the configuration where the antennas are most widely separated.
036       *  Each arm of the array is 21 kilometers long.</p>
037       */
038      VLA_A("VLA A", "A", "A"), 
039    
040      /** The <i>B</i> configuration of the Very Large Array.
041       *  <p>
042       *  This is the second-most widely separated configuration of the array.</p>
043       */
044      VLA_B("VLA B", "B", "B"), 
045    
046      /** The <i>C</i> configuration of the Very Large Array.
047       *  <p>
048       *  This is the second-most tightly spaced configuration of the array.</p>
049       */
050      VLA_C("VLA C", "C", "C"), 
051    
052      /** The <i>D</i> configuration of the Very Large Array.
053       *  <p>
054       *  This is the configuration where the antennas are most tightly spaced.
055       *  Each antenna is within 0.6 kilometers of the center.</p>
056       */
057      VLA_D("VLA D", "D", "D"), 
058    
059      /** A hybrid of the VLA <i>B</i> and <i>A</i> configurations.
060       *  <p>
061       *  In this configuration the east and west arms are in the <i>B</i>
062       *  configuration, but the north arm is still in the <i>A</i> configuration.</p>
063       */
064      VLA_BnA("VLA B/A Hybrid", "B/A", "BNA"), 
065    
066      /** A hybrid of the VLA <i>C</i> and <i>B</i> configurations.
067       *  <p>
068       *  In this configuration the east and west arms are in the <i>C</i>
069       *  configuration, but the north arm is still in the <i>B</i> configuration.</p>
070       */
071      VLA_CnB("VLA C/B Hybrid", "C/B", "CNB"),
072    
073      /** A hybrid of the VLA <i>D</i> and <i>C</i> configurations.
074       *  <p>
075       *  In this configuration the east and west arms are in the <i>D</i>
076       *  configuration, but the north arm is still in the <i>C</i> configuration.</p>
077       */
078      VLA_DnC("VLA D/C Hybrid", "D/C", "DNC"), 
079    
080      /** Represents the VLA as it is being moved
081       *  from the <i>A</i> to the <i>B/A Hybrid</i> configuration.
082       */
083      VLA_AtoBnA("VLA A to B/A Hybrid", "A->B/A", "A=>BNA"), 
084    
085      /** Represents the VLA as it is being moved
086       *  from the <i>B/A Hybrid</i> to the <i>B</i> configuration.
087       */
088      VLA_BnAtoB("VLA B/A Hybrid to B", "B/A->B", "BNA=>B"), 
089    
090      /** Represents the VLA as it is being moved
091       *  from the <i>B</i> to the <i>C/B Hybrid</i> configuration.
092       */
093      VLA_BtoCnB("VLA B to C/B Hybrid", "B->C/B", "B=>CNB"), 
094    
095      /** Represents the VLA as it is being moved
096       *  from the <i>C/B Hybrid</i> to the <i>C</i> configuration.
097       */
098      VLA_CnBtoC("VLA C/B Hybrid to C", "C/B->C", "B=>CNB"), 
099    
100      /** Represents the VLA as it is being moved
101       *  from the <i>C</i> to the <i>D/C Hybrid</i> configuration.
102       */
103      VLA_CtoDnC("VLA C to D/C Hybrid", "C->D/C", "CNB=>C"),
104    
105      /** Represents the VLA as it is being moved
106       *  from the <i>D/C Hybrid</i> to the <i>D</i> configuration.
107       */
108      VLA_DnCtoD("VLA D/C Hybrid to D", "D/C->D", "DNC=>D"),
109    
110      /** Represents the VLA as it is being moved
111       *  from the <i>D</i> to the <i>A</i> configuration.
112       */
113      VLA_DtoA("VLA D to A", "D->A", "D=>A"),
114    
115      /** An unspecified configuration applicable to all telescopes.
116       *  <p>
117       *  Clients use the <i>ANY</i> configuration when they are not concerned
118       *  with the particular arrangement of the telescope.
119       *  This element is also used to implement the
120       *  <i>Null Object Pattern</i>.  In situations where a method might
121       *  be tempted to return <i>null</i>, this element is returned instead.</p>
122       */
123      ANY("Any Configuration", "Any", "Any");
124    
125      //============================================================================
126      //
127      //============================================================================
128    
129      private static final EnumSet<TelescopeConfiguration> VLA_SET =
130        EnumSet.of(VLA_A, VLA_B, VLA_C, VLA_D,
131                   VLA_BnA, VLA_CnB, VLA_DnC,
132                   VLA_AtoBnA, VLA_BnAtoB, VLA_BtoCnB, VLA_CnBtoC,
133                   VLA_CtoDnC, VLA_DnCtoD, VLA_DtoA,
134                   ANY);
135    
136      private static final EnumSet<TelescopeConfiguration> GBT_SET =
137        EnumSet.of(ANY);
138      
139      private static HashMap<TelescopeType, EnumSet<TelescopeConfiguration>> 
140        TELESCOPE_SETS = new HashMap<TelescopeType,
141                                     EnumSet<TelescopeConfiguration>>();
142      
143      static
144      {
145        TELESCOPE_SETS.put(TelescopeType.VLA,  VLA_SET);
146        TELESCOPE_SETS.put(TelescopeType.EVLA, VLA_SET);
147        TELESCOPE_SETS.put(TelescopeType.GBT,  GBT_SET);
148      }
149      
150      //============================================================================
151      //
152      //============================================================================
153      
154      private final String name;
155      private final String code;
156      private final String histCode;
157      
158      private TelescopeConfiguration(String name, String code, String histCode)
159      {
160        this.name     = name;
161        this.code     = code;
162        this.histCode = histCode;
163      }
164    
165      /** Returns a text representation of this configuration. */
166      @Override
167      public String toString()
168      {
169        return name;
170      }
171      
172      /**
173       * Returns a short code for this configuration.
174       * <p>
175       * Examples: "A", "A->B/A" (for A to B/A hybrid),
176       *           "B/A" (for B-north-A hybrid).</p>
177       * 
178       * @return a short code for this configuration.
179       * 
180       * @since 2008-07-25
181       * @see #getHistoricalCode()
182       */
183      public String getCode()
184      {
185        return code;
186      }
187      
188      /**
189       * Returns another {@link #getCode() code} for this configuration.
190       * 
191       * @return
192       *   a historical code for this configuration.
193       *   
194       * @since 2009-04-24
195       */
196      public String getHistoricalCode()
197      {
198        return histCode;
199      }
200      
201      /**
202       * Returns <i>true</i> if this configuration is compatible with {@code other}.
203       * <p>
204       * The best way to understand compatibility is to imagine that the telescope
205       * is currently in the {@code other} configuration and that some specification
206       * says we may only use the telescope if it is in {@code this} configuration.
207       * In general, two configurations are compatible if either they are the same
208       * configuration or if one of them is the {@code ANY} configuration.</p>
209       *   
210       * @param other the configuration to be tested for compatibility.
211       * 
212       * @return <i>true<i> if this configuration is compatible with {@code other}.
213       */
214      public boolean isCompatibleWith(TelescopeConfiguration other)
215      {
216        return (this == other) || (this == ANY) || (other == ANY);
217      }
218    
219      /**
220       * Returns a default telescope configuration.
221       * @return a default telescope configuration.
222       */
223      public static TelescopeConfiguration getDefault()
224      {
225        return ANY;
226      }
227    
228      /**
229       * Returns the telescope configuration represented by {@code text}.
230       * <p>
231       * For details about the transformation, see
232       * {@link EnumerationUtility#enumFromString(Class, String)}.</p>
233       * 
234       * @param text a text representation of a telescope configuration.
235       * 
236       * @return the telescope configuration represented by {@code text}.
237       */
238      public static TelescopeConfiguration fromString(String text)
239      {
240        TelescopeConfiguration result =
241          EnumerationUtility.getSharedInstance()
242                            .enumFromString(TelescopeConfiguration.class, text);
243        
244        if (result == null)
245        {
246          for (TelescopeConfiguration tc : TelescopeConfiguration.values())
247          {
248            if (text.equalsIgnoreCase(tc.getCode()))
249            {
250              result = tc;
251              break;
252            }
253          }
254        }
255        
256        return result;
257      }
258      
259      /**
260       * Returns the subset of elements that are appropriate for the
261       * given telescope.
262       * 
263       * @param telescope the telescope for which a set of configurations
264       *                  is desired.
265       *                  
266       * @return a set of configurations for {@code telescope}.
267       */
268      public static
269        Set<TelescopeConfiguration> getElementsFor(TelescopeType telescope)
270      {
271        EnumSet<TelescopeConfiguration> answer = TELESCOPE_SETS.get(telescope);
272        
273        return (answer == null) ? EnumSet.of(ANY) : answer.clone(); 
274      }
275    
276      //============================================================================
277      //
278      //============================================================================
279      
280      //This is here for quick manual testing
281      /*
282      public static void main(String[] args)
283      {
284        for (TelescopeType telescope : TelescopeType.values())
285        {
286          System.out.println("TELESCOPE: " + telescope);
287          for (TelescopeConfiguration config :
288               TelescopeConfiguration.getElementsFor(telescope))
289          {
290            System.out.print("  |  " + config);
291          }
292          System.out.println();
293          System.out.println();
294        }
295      }
296      */
297      /*
298      public static void main(String[] args)
299      {
300        for (TelescopeConfiguration tc : TelescopeConfiguration.values())
301        {
302          System.out.println("variable = " + tc.name() + ";    display = " + tc.toString());
303        }
304      }
305      */ 
306    }