//
// AddePointDataReader.java
//

/*
This source file is part of the edu.wisc.ssec.mcidas package and is
Copyright (C) 1998 - 2017 by Tom Whittaker, Tommy Jasmin, Tom Rink,
Don Murray, James Kelly, Bill Hibbard, Dave Glowacki, Curtis Rueden
and others.
 
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Library General Public License for more details.

You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
MA 02111-1307, USA
*/

package edu.wisc.ssec.mcidas.adde;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Vector;
import edu.wisc.ssec.mcidas.McIDASUtil;

/** 
 * AddePointDataReader interface for McIDAS ADDE point data sets.   Simulates a
 * McIDAS PTLIST output using an ADDE URL if toString() method is used.
 * 
 * Note that units are ignored by this client, default units are used.
 *
 * 
 * URLs must all have the following format   
 *   adde://host/point?keyword_1=value_1&keyword_2=value_2
 *
 * there can be any valid combination of the following supported keywords:
 *
 *   group=<groupname>         ADDE group name
 *   descr=<descriptor>        ADDE descriptor name
 *   pos=<position>            request an absolute or relative ADDE 
 *                               position number
 *   select=<select clause>    to specify which data is required
 *   param=<param list>        what parameters to return
 *   num=<max>                 maximum number of obs to return
 *   user=<user_id>            ADDE user identification
 *   proj=<proj #>             a valid ADDE project number
 *   trace=<0/1>               setting to 1 tells server to write debug 
 *                               trace file (imagedata, imagedirectory)
 *   version=1                 ADDE version number, currently 1 
 *   
 * the following keywords are required:
 *
 *   group
 *   descr
 *
 * an example URL might look like:
 *   adde://rtds/point?group=neons&type=metar
 * 
* * @author Don Murray - Unidata and James Kelly - BoM * */ public class AddePointDataReader { // load protocol for ADDE URLs // See java.net.URL for explanation of URL handling static { try { String handlers = System.getProperty("java.protocol.handler.pkgs"); String newProperty = null; if (handlers == null) newProperty = "edu.wisc.ssec.mcidas"; else if (handlers.indexOf("edu.wisc.ssec.mcidas") < 0) newProperty = "edu.wisc.ssec.mcidas | " + handlers; if (newProperty != null) // was set above System.setProperty("java.protocol.handler.pkgs", newProperty); } catch (Exception e) { System.out.println( "Unable to set System Property: java.protocol.handler.pkgs"); } } /** * Key for getting data in param order [numParams][numObs] */ public static final int PARAM_ORDER = 0; /** * Key for getting data in obs order [numObs][numParams] */ public static final int OB_ORDER = 1; /** * Maximum number of parameters - used as a sanity check */ public static final int MAXNUMPARM = 402; // number of parameters private int status=0; // read status //private URLConnection urlc; // URL connection private String[] params; // parameters returned from server private int[] ScalingFactors; // scaling factors returned from server private String[] units; // units returned from server private int[][] iData = null; // data returned from server as array of ints private int[][] oData = null; // data returned from server as array of ints private Vector data = null; // holds the obs private int numParams = 0; // number of parameters private boolean debug = false; // set to true for debugging /** * creates an AddePointDataReader object that allows reading ADDE point * datasets. * * @param request ADDE URL to read from. See class javadoc. * *
     * an example URL might look like:
     *   adde://rtds.ho.bom.gov.au/point?group=neons&descr=metar
     * 
* * @exception AddeException if there are no datasets of the particular * type or there is an error reading data * */ public AddePointDataReader(String request) throws AddeException { DataInputStream dataInputStream; URLConnection urlc; try { URL url = new URL(request); urlc = url.openConnection(); //InputStream is = urlc.getInputStream(); dataInputStream = new DataInputStream( new BufferedInputStream( urlc.getInputStream())); } catch (AddeURLException ae) { throw new AddeException("No datasets found", ae); } catch (Exception e) { throw new AddeException("Error opening connection", e); } // // first get number of bytes for Parameter Names // int numParamBytes; if(urlc instanceof AddeURLConnection) { numParamBytes = ((AddeURLConnection) urlc).getInitialRecordSize(); } else { try { numParamBytes = dataInputStream.readInt(); } catch (IOException e) { throw new AddeException("Error reading data", e); } } if (debug) System.out.println("numParamBytes = " + numParamBytes); if (numParamBytes == 0) { status = -1; throw new AddeException("No data found"); } else if (numParamBytes/4 > MAXNUMPARM) { status = -1; throw new AddeException("Not an ADDE Point Data set"); } else { byte[] bParamNames = new byte[numParamBytes]; numParams = numParamBytes/4; params = new String[numParams]; try { // // read Parameter names into paramNames // dataInputStream.readFully(bParamNames, 0, numParamBytes); String sParamNames = new String(bParamNames); if (debug) System.out.println(" sParamNames = " + sParamNames); for (int i = 0; i < numParams; i++) params[i] = sParamNames.substring(i*4, (i+1)*4).trim(); } catch (IOException e) { status = -1; throw new AddeException("Error reading parameters", e); } } // // next get number of bytes for Unit Names // try { int numUnitBytes = dataInputStream.readInt(); units = new String[numUnitBytes/4]; if (debug) System.out.println("numUnitBytes = " + numUnitBytes); byte[] bUnitNames = new byte[numUnitBytes]; dataInputStream.readFully(bUnitNames, 0, numUnitBytes); String sUnitNames = new String(bUnitNames); if (debug) System.out.println("sUnitNames = " + sUnitNames); for (int i = 0; i < numUnitBytes/4; i++) units[i] = sUnitNames.substring(i*4, (i+1)*4).trim(); } catch (IOException e) { status = -1; throw new AddeException("Error reading units", e); } // // next get number of bytes for Scaling Factors // try { int numScalingBytes = dataInputStream.readInt(); if (debug) System.out.println("numScalingBytes = " + numScalingBytes); ScalingFactors = new int[(int)(numScalingBytes/4)]; for (int i=0; i < (int) (numScalingBytes/4); i++) { ScalingFactors[i] = dataInputStream.readInt(); } } catch (IOException e) { status = -1; throw new AddeException("Error reading scaling factors", e); } // // next get number of bytes for the actual data // data = new Vector(); byte[] bThisUnitName = new byte[4]; try { int numDataBytes = dataInputStream.readInt(); while (numDataBytes !=0) { if (debug) System.out.println(" i, Param, Unit, Value " ); int[] dataArray = new int[numParams]; for (int i=0; i < (int) (numDataBytes/4); i++) { dataArray[i] = dataInputStream.readInt(); } data.addElement(dataArray); numDataBytes = dataInputStream.readInt(); if (debug) System.out.println("numDataBytes = " + numDataBytes); } } catch (IOException e) { status = -1; throw new AddeException("Error reading data", e); } } /** * Return the data sent by the server * * @return array of the data. Data is in the format of an integer array * of unscaled integers as returned from the server in parameter * order ([numParams][numObs]). * * @exception AddeException if there was an error reading data */ public int[][] getData() throws AddeException { return getData(PARAM_ORDER); } /** * Return the data sent by the server in a particular order * (PARAM_ORDER, OB_ORDER). * @param order order of the data. (PARAM_ORDER, OB_ORDER) * * @return array of the data. Data is in the format of an integer array * of unscaled integers in the specified order * (PARAM_ORDER = [numParams][numObs], * OB_ORDER = [numObs][numParams]) * * @exception AddeException if there was an error reading data */ public int[][] getData(int order) throws AddeException { if (status < 0) throw new AddeException("No data available"); return (order == PARAM_ORDER) ? getParamOrderData() : getObOrderData(); } /** * Get the list of parameters * * @return array of the parameter names. The names will be in the same * order as the array of data values in the getData() * method. * * @exception AddeException if there was an error reading data */ public String[] getParams() throws AddeException { if (status < 0) throw new AddeException("No data available"); return params; } /** * Get the list of units * * @return array of the unit names. The names will be in the same * order as the array of data values in the getData() * method. * * @exception AddeException if there was an error reading data */ public String[] getUnits() throws AddeException { if (status < 0) throw new AddeException("No data available"); return units; } /** * Get the list of scaling factors * * @return array of the scaling factors (powers of 10). The scaling * factors will be in the same order as the array of data * values in the getData() method. * * @exception AddeException if there was an error reading data */ public int[] getScales() throws AddeException { if (status < 0) throw new AddeException("No data available"); return ScalingFactors; } /** * return the number of parameters * * @return number of parameters returned from the server */ public int getNumParams() throws AddeException { if (status < 0) throw new AddeException("No data available"); return numParams; } /** * Return an array of data for the particular parameter. * * @return array of values for the particular parameter or * null if an invalid parameter was entered. This * will return String[] for parameters with units of CHAR, * float[1][] for an array of non scaled data, and double[1][] for */ public Object[] getData(String parameter) throws AddeException { if (status < 0) throw new AddeException("No data available"); for (int i = 0; i < numParams; i++) { if (parameter.equalsIgnoreCase(params[i])) { iData = getParamOrderData(); if (units[i].equalsIgnoreCase("CHAR")) { String[] vals = new String[iData[i].length]; for (int j = 0; j < iData[i].length; j++) { vals[j] = McIDASUtil.intBitsToString(iData[i][j]); } return vals; } else if (ScalingFactors[i] != 0) { double[][] vals = new double[1][iData[i].length]; for (int j = 0; j < iData[i].length; j++) { vals[0][j] = iData[i][j]/Math.pow(10.0, (double) ScalingFactors[i]); } return vals; } else { float[][] vals = new float[1][iData[i].length]; for (int j = 0; j < iData[i].length; j++) { vals[0][j] = (float) iData[i][j]; } return vals; } } } return null; } /** * Create an array of data in parameter order [numParams][numobs]. * @return array of data in parameter order */ private int[][] getParamOrderData() { if (iData == null) { // Convert to in array iData = new int[numParams][data.size()]; if (debug) { System.out.println("number of data records = " + data.size()); } for (int i = 0; i < data.size(); i++) { int[] values = (int[]) data.get(i); for (int j = 0; j < numParams; j++) iData[j][i] = values[j]; } } return iData; } /** * Create an array of data in observation order [numObs][numParams]. * @return array of data in obs order */ private int[][] getObOrderData() { if (oData == null) { // Convert to in array oData = new int[data.size()][numParams]; if (debug) { System.out.println("number of data records = " + data.size()); } for (int i = 0; i < data.size(); i++) { oData[i] = (int[]) data.get(i); } } return oData; } /** * Return a formated string of the returned data * * @return formatted representation of the data ala McIDAS PTLIST command. */ public String toString() { if (status < 0) return new String("No data Available"); StringBuffer buf = new StringBuffer(); for (int i = 0; i < numParams; i++) { buf.append(params[i]); buf.append("["); buf.append(units[i]); buf.append("] "); buf.append("\t"); } buf.append("\n"); iData = getParamOrderData(); for (int i = 0; i < iData[0].length; i++) { for (int j = 0; j < numParams; j++) { if (units[j].equalsIgnoreCase("CHAR")) { buf.append(McIDASUtil.intBitsToString(iData[j][i])); } else if (ScalingFactors[j] != 0) { buf.append( iData[j][i] == McIDASUtil.MCMISSING ? " " : Double.toString( iData[j][i]/Math.pow(10.0, (double) ScalingFactors[j] ))); } else { buf.append( iData[j][i] == McIDASUtil.MCMISSING ? " " : Integer.toString(iData[j][i])); } buf.append("\t"); } buf.append("\n"); } return buf.toString(); } /** test by running 'java edu.wisc.ssec.mcidas.adde.AddePointDataReader' */ public static void main (String[] args) throws Exception { System.out.println("\nData Requested:"); String request = (args.length == 0) // ? "adde://servb.ho.bom.gov.au/point?group=neons&descr=metar&num=2&select='id ymml; time 22 24; day 1999317'&parm=id dir spd t[c] td[c] psl&pos=ALL&version=1" // Unidata server ? "adde://adde.ucar.edu/point?group=rtptsrc&descr=sfchourly&num=2&select='id ypph'&parm=id dir spd t[c] td[c] psl&pos=0&version=1&trace=1" : args[0]; AddePointDataReader ptlist = new AddePointDataReader(request); System.out.println(ptlist.toString()); } }

Ads help maintain this website.