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