001    /*
002     * $Id: AddeProfilerDataChooser.java,v 1.26 2012/02/19 17:35:35 davep Exp $
003     *
004     * This file is part of McIDAS-V
005     *
006     * Copyright 2007-2012
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    
031    package edu.wisc.ssec.mcidasv.chooser.adde;
032    
033    import static javax.swing.GroupLayout.DEFAULT_SIZE;
034    import static javax.swing.GroupLayout.PREFERRED_SIZE;
035    import static javax.swing.GroupLayout.Alignment.BASELINE;
036    import static javax.swing.GroupLayout.Alignment.LEADING;
037    import static javax.swing.LayoutStyle.ComponentPlacement.RELATED;
038    
039    import java.util.ArrayList;
040    import java.util.Hashtable;
041    import java.util.List;
042    
043    import javax.swing.GroupLayout;
044    import javax.swing.JComponent;
045    import javax.swing.JLabel;
046    import javax.swing.JPanel;
047    
048    import org.w3c.dom.Element;
049    
050    import ucar.unidata.data.AddeUtil;
051    import ucar.unidata.data.profiler.AddeProfilerDataSource;
052    import ucar.unidata.idv.chooser.IdvChooserManager;
053    import ucar.unidata.metdata.NamedStationTable;
054    import ucar.unidata.util.GuiUtils;
055    import ucar.unidata.util.Misc;
056    import ucar.unidata.util.TwoFacedObject;
057    import ucar.unidata.view.station.StationLocationMap;
058    import ucar.unidata.xml.XmlResourceCollection;
059    
060    import 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.26 $
074     */
075    public 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