001/*
002 * $Id: AddeProfilerDataChooser.java,v 1.25 2011/03/24 16:06:32 davep Exp $
003 *
004 * This file is part of McIDAS-V
005 *
006 * Copyright 2007-2011
007 * Space Science and Engineering Center (SSEC)
008 * University of Wisconsin - Madison
009 * 1225 W. Dayton Street, Madison, WI 53706, USA
010 * https://www.ssec.wisc.edu/mcidas
011 * 
012 * All Rights Reserved
013 * 
014 * McIDAS-V is built on Unidata's IDV and SSEC's VisAD libraries, and
015 * some McIDAS-V source code is based on IDV and VisAD source code.  
016 * 
017 * McIDAS-V is free software; you can redistribute it and/or modify
018 * it under the terms of the GNU Lesser Public License as published by
019 * the Free Software Foundation; either version 3 of the License, or
020 * (at your option) any later version.
021 * 
022 * McIDAS-V is distributed in the hope that it will be useful,
023 * but WITHOUT ANY WARRANTY; without even the implied warranty of
024 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
025 * GNU Lesser Public License for more details.
026 * 
027 * You should have received a copy of the GNU Lesser Public License
028 * along with this program.  If not, see http://www.gnu.org/licenses.
029 */
030
031package edu.wisc.ssec.mcidasv.chooser.adde;
032
033import static javax.swing.GroupLayout.DEFAULT_SIZE;
034import static javax.swing.GroupLayout.PREFERRED_SIZE;
035import static javax.swing.GroupLayout.Alignment.BASELINE;
036import static javax.swing.GroupLayout.Alignment.LEADING;
037import static javax.swing.LayoutStyle.ComponentPlacement.RELATED;
038
039import java.util.ArrayList;
040import java.util.Hashtable;
041import java.util.List;
042
043import javax.swing.GroupLayout;
044import javax.swing.JComponent;
045import javax.swing.JLabel;
046import javax.swing.JPanel;
047
048import org.w3c.dom.Element;
049
050import ucar.unidata.data.AddeUtil;
051import ucar.unidata.data.profiler.AddeProfilerDataSource;
052import ucar.unidata.idv.chooser.IdvChooserManager;
053import ucar.unidata.metdata.NamedStationTable;
054import ucar.unidata.util.GuiUtils;
055import ucar.unidata.util.Misc;
056import ucar.unidata.util.TwoFacedObject;
057import ucar.unidata.view.station.StationLocationMap;
058import ucar.unidata.xml.XmlResourceCollection;
059
060import edu.wisc.ssec.mcidasv.util.McVGuiUtils;
061
062/**
063 * Selection widget for specifing data sources of
064 * NOAA National Profiler Network data.
065 * For selecting Profiler data source; user selects ADDE server,
066 * profiler station(s),
067 * and choice of data interval such as hourly or 6 minute.
068 *
069 * Metadata about the station (lat, lon. elevation)
070 * and about the request is made available by "get" methods.
071 *
072 * @author Unidata IDV Development Team
073 * @version $Revision: 1.25 $
074 */
075public class AddeProfilerDataChooser extends AddePointDataChooser {
076    
077    /** collection of station tables */
078    private XmlResourceCollection stationResources;
079
080    /**
081     * ctor
082     *
083     * @param mgr The chooser manager
084     * @param root The chooser.xml node
085     */
086    public AddeProfilerDataChooser(IdvChooserManager mgr, Element root) {
087        super(mgr, root);
088                    
089        descriptorsAllowPrefix = "PROF";
090                
091    }
092    
093    /**
094     * Tell the AddeChooser our name
095     *
096     * @return  The name
097     */
098    public String getDataName() {
099        return "Profiler Data";
100    }
101
102    /**
103     * Get the descriptor widget label.
104     *
105     * @return  label for the descriptor  widget
106     */
107    public String getDescriptorLabel() { 
108        return "Profiler Type"; 
109    }
110        
111    /**
112     * Overwrite base class method to create the station map
113     * with the appropriate properties.
114     *
115     * @return The new station map
116     */
117    protected StationLocationMap createStationMap() {
118        return new StationLocationMap(true, (String) null, StationLocationMap.TEMPLATE_NAME) {
119            public void setDeclutter(boolean declutter) {
120                super.setDeclutter(declutter);
121                updateStatus();
122            }
123        };
124    }
125
126    /**
127     * Initialize  the  station map
128     *
129     * @param stationMap The station map to initialize
130     */
131    protected void initStationMap(StationLocationMap stationMap) {
132        super.initStationMap(stationMap);
133
134        // get station information from the xml file listed
135        if (stationResources == null) {
136            List resources =
137                Misc.newList(
138                    "/ucar/unidata/idv/resources/stations/profilerstns.xml");
139            stationResources = new XmlResourceCollection("", resources);
140        }
141
142        // create an object to hold the station info
143        NamedStationTable stationTable =
144            NamedStationTable.createStationTable(stationResources.getRoot(0));
145
146
147        List listOfTables =
148            NamedStationTable.createStationTables(stationResources);
149        if (listOfTables.size() > 0) {
150            NamedStationTable profStations =
151                (NamedStationTable) listOfTables.get(0);
152            // Take this out if we only want to init stations 
153            // when we connect to the server. 
154            //   each "value" is a full Station object, not the name string
155            stationMap.setStations(new ArrayList(profStations.values()));
156        } else {
157            //What to do if there are no stations
158        }
159    }
160
161    /**
162     * Get any extra key=value pairs that are appended to all requests.
163     *
164     * @param buff The buffer to append onto
165     */
166    protected void appendMiscKeyValues(StringBuffer buff) {
167        appendKeyValue(buff, PROP_POS, getDoRelativeTimes() ? "ALL" : "0");
168        super.appendMiscKeyValues(buff);
169    }
170
171    /**
172     * Override this to determine how to select sample
173     */
174    protected void appendTimesRequest(StringBuffer buf) {
175        appendKeyValue(buf, PROP_SELECT, "'IDA BLMM'");
176    }
177    
178    /**
179     * Do we have times selected. Either we are doing absolute
180     * times and there are some selected in the list. Or we
181     * are doing relative times and we have done a connect to the
182     * server
183     *
184     * @return Do we have times
185     */
186    public boolean timesOk() {
187        if (usingStations() && (stationMap.getStations().size() > 0)
188                && (getSelectedStations().size() == 0)) {
189            return false;
190        }
191        return super.timesOk();
192    }
193    
194    /**
195     * Get the selection event from the profiler data chooser
196     * and process it, creating a ADDE.PROFILER data source
197     *
198     */
199    public void doLoadInThread() {
200        showWaitCursor();
201        try {
202            List selectedStations = getSelectedStations();
203
204            // make properties Hashtable to hand some 
205            //  data selection metadata
206            // to the AddeProfilerDataSource where it helps process 
207            // the data from the server into data format this IDV
208            // needs for this request.
209
210            Hashtable profilersourceHT = new Hashtable();
211
212            profilersourceHT.put(AddeProfilerDataSource.PROFILER_INT,
213                    getRelBoxString());
214            profilersourceHT.put(AddeProfilerDataSource.PROFILER_DATAINT,
215                    getDescriptor());
216            profilersourceHT.put(AddeProfilerDataSource.PROFILER_SERVER,
217                    getServer());
218            profilersourceHT.put(AddeProfilerDataSource.PROFILER_TIMES,
219                    getDayTimeSelectString());
220            profilersourceHT.put(AddeUtil.NUM_RELATIVE_TIMES,
221                    getRelativeTimeIndices());
222            profilersourceHT.put(AddeUtil.RELATIVE_TIME_INCREMENT,
223                    new Float(getRelativeTimeIncrement()));
224            profilersourceHT.put(AddeUtil.MISC_KEYWORDS,
225                    getMiscKeywords());
226
227
228            //System.out.println("   pc time list "+getSelectedTimes());
229            //System.out.println
230            // ("   pc data display interval "+getSelectedDataInterval());
231            //System.out.println
232            // ("  pc data source interval  "+getDataSourceInterval());
233
234            // hard-coded "ADDE.PROFILER" is in idv/resources/datasource.xml,
235            // which tells IDV to use code 
236            // ucar.unidata.data.profiler.AddeProfilerDataSource
237            makeDataSource(selectedStations, "ADDE.PROFILER",
238                           profilersourceHT);
239            saveServerState();
240        } catch (Exception excp) {
241            logException("Unable to open Profiler dataset", excp);
242        }
243        showNormalCursor();
244    }
245        
246    /**
247     * Get the extra time widget, but built in a different way.
248     * Designed to be put into a GroupLayout
249     */
250    protected JComponent getExtraTimeComponent() {
251        TwoFacedObject[] intervals = { 
252                new TwoFacedObject(AddeProfilerDataSource.PROFILER_6MIN, .2f),
253                new TwoFacedObject(AddeProfilerDataSource.PROFILER_12MIN, .1f),
254                new TwoFacedObject(AddeProfilerDataSource.PROFILER_30MIN, .5f),
255                new TwoFacedObject(AddeProfilerDataSource.PROFILER_1HR, 1f)
256        };
257
258        GuiUtils.setListData(relTimeIncBox, intervals);
259        if (relTimeIncBox.getItemCount()>=4) relTimeIncBox.setSelectedIndex(3);
260        
261        return McVGuiUtils.makeLabeledComponent(relTimeIncLabel, relTimeIncBox, McVGuiUtils.Position.LEFT);
262    }
263        
264    /**
265     * Make the UI for this selector.
266     *
267     * @return The gui
268     */
269    public JComponent doMakeContents() {      
270        JPanel myPanel = new JPanel();
271                        
272        JLabel stationLabel = McVGuiUtils.makeLabelRight("Stations:");
273        addServerComp(stationLabel);
274
275        JComponent stationPanel = getStationMap();
276        registerStatusComp("stations", stationPanel);
277        addServerComp(stationPanel);
278        
279        JLabel timesLabel = McVGuiUtils.makeLabelRight("Times:");
280        addDescComp(timesLabel);
281        
282        JPanel timesPanel = makeTimesPanel();
283        timesPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());
284        addDescComp(timesPanel);
285        
286        enableWidgets();
287        updateStatus();
288
289        GroupLayout layout = new GroupLayout(myPanel);
290        myPanel.setLayout(layout);
291        layout.setHorizontalGroup(
292            layout.createParallelGroup(LEADING)
293            .addGroup(layout.createSequentialGroup()
294                .addGroup(layout.createParallelGroup(LEADING)
295                    .addGroup(layout.createSequentialGroup()
296                        .addComponent(descriptorLabel)
297                        .addGap(GAP_RELATED)
298                        .addComponent(descriptorComboBox))
299                    .addGroup(layout.createSequentialGroup()
300                        .addComponent(stationLabel)
301                        .addGap(GAP_RELATED)
302                        .addComponent(stationPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))
303                    .addGroup(layout.createSequentialGroup()
304                        .addComponent(timesLabel)
305                        .addGap(GAP_RELATED)
306                        .addComponent(timesPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))))
307        );
308        layout.setVerticalGroup(
309            layout.createParallelGroup(LEADING)
310            .addGroup(layout.createSequentialGroup()
311                .addGroup(layout.createParallelGroup(BASELINE)
312                    .addComponent(descriptorLabel)
313                    .addComponent(descriptorComboBox))
314                .addPreferredGap(RELATED)
315                .addGroup(layout.createParallelGroup(LEADING)
316                    .addComponent(stationLabel)
317                    .addComponent(stationPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))
318                .addPreferredGap(RELATED)
319                .addGroup(layout.createParallelGroup(LEADING)
320                    .addComponent(timesLabel)
321                    .addComponent(timesPanel, PREFERRED_SIZE, DEFAULT_SIZE, Short.MAX_VALUE))
322                .addPreferredGap(RELATED))
323        );
324        
325        setInnerPanel(myPanel);
326        return super.doMakeContents(true);
327    }
328
329}
330