001    package edu.nrao.sss.model.resource;
002    
003    import java.math.BigDecimal;
004    import java.util.*;
005    
006    import edu.nrao.sss.astronomy.SpectralLine;
007    import edu.nrao.sss.astronomy.StokesParameter;
008    import edu.nrao.sss.measure.Frequency;
009    import edu.nrao.sss.measure.FrequencyRange;
010    import edu.nrao.sss.measure.FrequencyUnits;
011    import edu.nrao.sss.measure.LinearVelocity;
012    import edu.nrao.sss.measure.LinearVelocityUnits;
013    import edu.nrao.sss.measure.TimeDuration;
014    import edu.nrao.sss.measure.TimeUnits;
015    import edu.nrao.sss.model.resource.evla.EvlaWidarConfiguration;
016    import edu.nrao.sss.model.resource.evla.WidarBaseband;
017    import edu.nrao.sss.model.resource.evla.WidarSubband;
018    import edu.nrao.sss.util.*;
019    
020    /**
021     * Helper for test classes; builds resources and their components.
022     * <p>
023     * <b>Version Info:</b>
024     * <table style="margin-left:2em">
025     *   <tr><td>$Revision: 1791 $</td></tr>
026     *   <tr><td>$Date: 2008-12-10 17:56:36 -0700 (Wed, 10 Dec 2008) $</td></tr>
027     *   <tr><td>$Author: dharland $</td></tr>
028     * </table></p>
029     * 
030     * @author David M. Harland
031     * @since 2006-10-30
032     */
033    public class ResourceBuilder
034    {
035      private static final EnumerationUtility ENUM_UTIL =
036        EnumerationUtility.getSharedInstance();
037    
038      private Random random = new Random(System.currentTimeMillis());
039    
040      private boolean setId          = false;
041      private Long    nextResourceId = 1L;
042    
043      private TelescopeType teleType;
044      
045      private static final HashSet<TelescopeType> VALID_TELESCOPES = new HashSet<TelescopeType>();
046      
047      static
048      {
049        VALID_TELESCOPES.add(TelescopeType.EVLA);
050    //    VALID_TELESCOPES.add(TelescopeType.VLA);    TODO restore
051    //    VALID_TELESCOPES.add(TelescopeType.GBT);    TODO restore
052      }
053      
054      //============================================================================
055      // PUBLIC METHODS
056      //============================================================================
057      
058      /**
059       * Tells the factory methods whether or not they should set the object
060       * identifiers.
061       */
062      public void setIdentifiers(boolean setIds)
063      {
064        setId = setIds;
065      }
066    
067      public Resource makeResource(String name)
068      {
069        return makeResource(name, null);
070      }
071      
072      public Resource makeResource(String name, TelescopeType telescopeType)
073      {
074        Resource resource = new Resource(name == null ? makeName() : name);
075        
076        teleType = telescopeType;
077        
078        setTelescopeFor(resource);
079    
080        if (setId)
081          resource.setId(nextResourceId++);
082        
083        Date now = new Date();
084        resource.setCreatedOn(now);
085        resource.setLastUpdatedOn(now);
086    
087        long id = 1L + (long)(1000.0 * Math.random());
088        resource.setCreatedBy(id);
089        resource.setLastUpdatedBy(id);
090        
091        if (random.nextDouble() < 2)  //TODO restore: 0.75)
092        {
093          makeReceiversFor(resource);
094          makeBackendsFor(resource);
095        }
096        else
097        {
098          resource.setScienceSpecification(makeResourceSpecification());
099          if (teleType != null)
100          {
101            List<ReceiverBand> receivers =
102              teleType.selectReceivers(resource.getScienceSpecification())
103                      .get(0).getReceivers();
104            resource.getAntennaElectronics().configureFor(new HashSet<ReceiverBand>(receivers));
105            //TODO: use resource spec to select/configure backends, only after making XML element for backends
106          }
107        }
108        
109        int count = random.nextInt(3);
110        for (int n=0; n < count; n++)
111          resource.getNotes().add("Random note #"+n);
112        
113        teleType = null;
114    
115        return resource;
116      }
117      
118      public ResourceGroup makeGroup(String name)
119      {
120        ResourceGroup group = new ResourceGroup(null, name == null ? makeName() : name);
121        
122        //Add resources
123        final int MIN_RSRC_COUNT = 5;
124        int rsrcCount = MIN_RSRC_COUNT + (int)(15.0 * Math.random());
125        for (int r=0; r < rsrcCount; r++)
126          group.add(makeResource(null));
127        
128        int count = random.nextInt(3);
129        for (int n=0; n < count; n++)
130          group.getNotes().add("Random note #"+n);
131    
132        return group;
133      }
134      
135      public ResourceCatalog makeCatalog(String name)
136      {
137        ResourceCatalog catalog =
138          new ResourceCatalog(name == null ? makeName() : name);
139        
140        Date now = new Date();
141        catalog.setCreatedOn(now);
142        catalog.setLastUpdatedOn(now);
143    
144        long id = 1L + (long)(1000.0 * Math.random());
145        catalog.setCreatedBy(id);
146        catalog.setLastUpdatedBy(id);
147        catalog.setOwner(id);
148    
149        //Add resources
150        int rsrcCount = 20 + (int)(20.0 * Math.random());
151        for (int r=0; r < rsrcCount; r++)
152          catalog.addItem(makeResource(null));
153        
154        //Add groups
155        int grpCount = (int)(5.0 * Math.random());
156        for (int g=0; g < grpCount; g++)
157          catalog.addGroup(makeGroup(null));
158        
159        int count = random.nextInt(3);
160        for (int n=0; n < count; n++)
161          catalog.getNotes().add("Random note #"+n);
162    
163        return catalog;
164      }
165    
166      //============================================================================
167      // HARDWARE
168      //============================================================================
169    
170      private void setTelescopeFor(Resource resource)
171      {
172        while (teleType == null || !VALID_TELESCOPES.contains(teleType))
173          teleType = ENUM_UTIL.getRandomValueFor(TelescopeType.class);
174        
175        resource.setTelescope(teleType);
176      }
177    
178      private void makeReceiversFor(Resource resource)
179      {
180        int count = Math.random() < 0.9 ? 1 : 2;
181        
182        Set<ReceiverBand> receivers = new HashSet<ReceiverBand>();
183        
184        for (int r=0; r < count; r++)
185          receivers.add(makeReceiver());
186        
187        resource.getAntennaElectronics().configureFor(receivers);
188      }
189      
190      public ReceiverBand makeReceiver()
191      {
192        ReceiverBand receiver;
193        
194        ReceiverBand[] receivers = new ReceiverBand[0];
195          
196        receivers = teleType.getReceivers().toArray(receivers);
197          
198        receiver = receivers[random.nextInt(receivers.length)];
199        
200        return receiver;
201      }
202    
203      private void makeBackendsFor(Resource resource)
204      {
205        int count = 1; //Math.random() < 0.9 ? 1 : 2;  TODO handle multiple backends
206        
207        for (int b=0; b < count; b++)
208          makeBackend(resource);
209      }
210      
211      private void makeBackend(Resource resource)
212      {
213        TelescopeBackend backend = resource.getBackend(CorrelatorName.WIDAR); //TODO restore: VLA);
214        resource.getAntennaElectronics().execute();
215        configure((EvlaWidarConfiguration)backend);
216        
217        /* TODO Remove above & restore below
218        List<CorrelatorName> types = resource.getTelescope().getBackendTypes();
219    
220        if (types.size() > 0)
221        {
222          resource.getBackend(types.get(random.nextInt(types.size())));
223         
224          add code here to configure particular correlator
225        } 
226        */
227      }
228      
229      private void configure(EvlaWidarConfiguration correlator)
230      {
231        for (CorrelatorBaseband baseband : correlator.getBasebands())
232        {
233          //TODO move BB building to sep builder, eg WidarBuilder.
234          //     MIght want to back form generic BackendBuilder.
235          WidarBaseband bb = (WidarBaseband)baseband;
236          bb.setSinglePhaseCenter(random.nextBoolean());
237          
238          //TODO replace below w/ code that makes random #s of SBs
239          addSubbandTo(bb);
240        }
241      }
242      
243      private void addSubbandTo(WidarBaseband baseband)
244      {
245        WidarSubband sb = baseband.makeNewSubband();
246        
247        //TODO use random values
248        sb.setBandwidth(new Frequency("128.0", FrequencyUnits.MEGAHERTZ));
249        sb.setCentralFrequency(new Frequency("512.0", FrequencyUnits.MEGAHERTZ));
250        
251        //TODO value the other properties
252        
253        baseband.addSubband(sb);
254      }
255    
256      //============================================================================
257      // SCIENCE SPECIFICATIONS
258      //============================================================================
259    
260      public ResourceSpecification makeResourceSpecification()
261      {
262        ResourceSpecification spec = new ResourceSpecification();
263        
264        int count = random.nextInt(5) + 1;
265        List<SkyFrequencySpecification> sfsList = spec.getSkyFrequencySpecs();
266        for (int s=0; s < count; s++)
267          sfsList.add(makeSkyFrequencySpecification());
268        
269        count = random.nextInt(5);
270        List<SpectralLineSpecification> slsList = spec.getSpectralLineSpecs();
271        for (int s=0; s < count; s++)
272          slsList.add(makeSpectralLineSpecification());
273      
274        count = random.nextInt(2);
275        List<PulsarSpecification> psList = spec.getPulsarSpecs();
276        for (int s=0; s < count; s++)
277          psList.add(makePulsarSpecification());
278        
279        return spec;
280      }
281      
282      public SkyFrequencySpecification makeSkyFrequencySpecification()
283      {
284        SkyFrequencySpecification spec = new SkyFrequencySpecification();
285        
286        spec.setFrequencyRange(makeFrequencyRange());
287        spec.setTimeResolution(makeTimeResolution());
288        spec.setFrequencyResolution(new Frequency(new BigDecimal(10.0 + random.nextDouble() * 80.0),
289                                    FrequencyUnits.MEGAHERTZ));
290        
291        int count = 1 + random.nextInt(2);
292        SortedSet<StokesParameter> polarizations = spec.getPolarizationProducts();
293        for (int p=0; p < count; p++)
294          polarizations.add(ENUM_UTIL.getRandomValueFor(StokesParameter.class));
295        
296        return spec;
297      }
298      
299      private static final BigDecimal PCT25 = new BigDecimal("0.25");
300      private static final BigDecimal PCT05 = new BigDecimal("0.05");
301    
302      public SpectralLineSpecification makeSpectralLineSpecification()
303      {
304        SpectralLineSpecification spec = new SpectralLineSpecification();
305    
306        SpectralLine specLine = spec.getLine();
307        
308        specLine.setSpecies(makeName());
309        specLine.setTransition(makeName());
310        specLine.setSourceOfInformation(makeName());
311        specLine.setFrequency(makeFrequency());
312        specLine.setUncertainty(new Frequency());
313        
314        LinearVelocity sourceVelocity = makeVelocity();
315        spec.setSourceVelocity(sourceVelocity);
316        
317        LinearVelocity bandwidth = sourceVelocity.clone().multiplyBy(PCT25);
318        spec.setVelocityBandwidth(bandwidth);
319        
320        LinearVelocity resolution = sourceVelocity.clone().multiplyBy(PCT05);
321        spec.setVelocityResolution(resolution);
322        
323        spec.setTimeResolution(makeTimeResolution());
324        
325        int count = 1 + random.nextInt(2);
326        SortedSet<StokesParameter> polarizations = spec.getPolarizationProducts();
327        for (int p=0; p < count; p++)
328          polarizations.add(ENUM_UTIL.getRandomValueFor(StokesParameter.class));
329        
330        return spec;
331      }
332      
333      public PulsarSpecification makePulsarSpecification()
334      {
335        PulsarSpecification spec = new PulsarSpecification();
336    
337        //TODO
338        
339        return spec;
340      }
341      
342      //============================================================================
343      // HELPERS
344      //============================================================================
345      
346      private String makeName()
347      {
348        StringBuilder srcName = new StringBuilder();
349    
350        int numChars = random.nextInt(3)+3;
351        for (int i=0; i < numChars; i++)
352          srcName.append((char)('a'+random.nextInt(25)));
353    
354        return srcName.toString();
355      }
356      
357      private Frequency makeFrequency()
358      {
359        return new Frequency(new BigDecimal(0.010 + 99.990 * random.nextDouble()),
360                             FrequencyUnits.GIGAHERTZ);
361      }
362      
363      private FrequencyRange makeFrequencyRange()
364      {
365        return new FrequencyRange(makeFrequency(), makeFrequency());
366      }
367      
368      private TimeDuration makeTimeResolution()
369      {
370        long ms = Math.round(10.0 + 490.0 * random.nextDouble());
371        
372        return new TimeDuration(new BigDecimal(ms), TimeUnits.MILLISECOND);
373      }
374      
375      private LinearVelocity makeVelocity()
376      {
377        LinearVelocity velocity = new LinearVelocity();
378        
379        if (random.nextDouble() < 0.5)
380        {
381          velocity.setUnits(LinearVelocityUnits.KILOMETERS_PER_SECOND);
382          velocity.setValue(BigDecimal.valueOf(100.0 + 199900.0 * random.nextDouble()));
383        }
384        else
385        {
386          velocity.setUnits(LinearVelocityUnits.Z);
387          velocity.setValue(BigDecimal.valueOf(0.5 + 4.5 * random.nextDouble()));
388        }
389        
390        return velocity;
391      }
392    }