All Downloads are FREE. Search and download functionalities are using the official Maven repository.

decodes.dbimport.EmitImport Maven / Gradle / Ivy

Go to download

A collection of software for aggregatting and processing environmental data such as from NOAA GOES satellites.

The newest version!
/*
*  $Id$
*/
package decodes.dbimport;

import java.io.LineNumberReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.text.ParsePosition;
import java.util.Vector;
import java.util.Iterator;
import java.util.Date;
import ilex.util.*;
import ilex.cmdline.*;

import decodes.sql.DbKey;
import decodes.util.*;
import decodes.db.*;
import decodes.xml.XmlDatabaseIO;
import decodes.xml.TopLevelParser;

/**
Imports legacy database files from an EMIT or USGS-DECODES-C. This
program can handle the "sdf" (site device file) or "nl" (network list)
files generated by those packages.
*/
public class EmitImport
{
	private String curFileName;
	private Logger logger;
	private PlatformConfig platformConfig;    // PC we are parsing, null if we're not.
	private Database db;
	private DecodesScript selfTimedScript, randomScript, edlScript;
	private StringPair currentFormat;
	private Vector formats;
	private Platform platform;
	private String platformConfigName;
    private static final SimpleDateFormat emitDateFormat
        = new SimpleDateFormat("yyyyMMdd");
	private int messageTime;
	private String defaultStationNameType;
	private LineNumberReader reader;
	private StringBuffer configDescription;

	private boolean validateOnly;   // Switch - Validate only - do not modify DB
	private boolean keepOld;        // On conflict keep existing (old) DB records.
	private boolean euListChanged;
	private boolean platformListChanged;
	private boolean makeSiteNames;  // Make site names from network list entries.
	private boolean isEOF;
	private boolean skipToES;
	private boolean isUsgsFlag;  // Command line flag set meaning all files are USGS.
	private boolean isUsgsFile;  // This particular file is being parsed as a USGS file.

	private Vector newObjects;      // New DatabaseObject's to be saved.
	private PresentationGroup shefEnglishPG;

	private char dataOrderST;
	private char dataOrderRD;
	private char daylightFlag;
	private String statnum;

	/** Constructor. */
	public EmitImport()
	{
		curFileName = null;
		platformConfig = null;
		selfTimedScript = null;
		randomScript = null;
		edlScript = null;
		currentFormat = null;
		formats = new Vector();
		platform = null;
		defaultStationNameType = 
			DecodesSettings.instance().siteNameTypePreference;
		configDescription = null;

		validateOnly = false;
		keepOld = false;
		euListChanged = false;
		platformListChanged = false;
		makeSiteNames = false;

		// Store new object references for later merging with database:
		newObjects = new Vector();
		isEOF = true;
		shefEnglishPG = null;
		isUsgsFlag = false;
		isUsgsFile = false;
	}

	/** Called once at start of import to reset the staging database. */
	public void reset()
	{
		newObjects.clear();
		euListChanged = false;
	}

	/**
	  Parses a single file.
	  @param filename the file name
	*/
	public void parseFile(String filename)
		throws IOException
	{
		isUsgsFile = isUsgsFlag;  // Reset file-level flag to cmd-line arg 
		db = Database.getDb();
		logger = Logger.instance();
		curFileName = filename;
		logger.log(Logger.E_DEBUG1, "Attempting to parse '" + filename + "'");
		dataOrderST = 'D';
		dataOrderRD = 'D';
		daylightFlag = 'N';

		reader = new LineNumberReader(new FileReader(curFileName));

//		if (filename.endsWith(".tab"))
//		{
//			parseEqTable(filename, reader);
//			reader.close();
//			return;
//		}

		if (filename.endsWith(".nl"))
		{
			reader.close();
			parseNetworkList(filename);
			return;
		}

		String line;
		isEOF = false;
		while((line = reader.readLine()) != null)
		{
			debug(3, "Read line " + reader.getLineNumber() + " '" + line + "'");

			if (line.length() < 2)
				continue;
			String lineType = line.substring(0, 2).toLowerCase();
			if (lineType.equals("dv"))
				parseDV(line);
			else if (lineType.equals("dc"))
				parseDC(line);
			else if (lineType.equals("cd"))
				parseCD(line);
			else if (lineType.equals("cs"))
				parseCS(line);
			else if (lineType.equals("ca"))
				parseCA(line);
			else if (lineType.equals("cf"))
				parseCF(line);
			else if (lineType.equals("sf"))
				parseSF(line);
			else if (lineType.equals("ec"))
				parseEC(line);
			else if (lineType.equals("si"))
			{
				if (line.length() > 3 && line.charAt(2) == '1')
				{
					isUsgsFile = true; // These lines only exist in USGS files.
					parseSI1(line);
				}
				else
					parseSI(line);
			}
			else if (lineType.equals("sd"))
				parseSD(line);
			else if (lineType.equals("ss"))
			{
				if (line.length() > 3 && line.charAt(2) == '1')
				{
					isUsgsFile = true; // These lines only exist in USGS files.
					parseSS1(line);
				}
				else
					parseSS(line);
			}
			else if (lineType.equals("sa"))
			{
				isUsgsFile = false; // These lines only exist in EMIT files.
				parseSA(line);
			}
			else if (lineType.equals("se"))
				parseSE(line);
			else if (lineType.equals("sc"))
				parseSC(line);
			else if (lineType.equals("es"))
				parseES(line);

//			else if (lineType.equals("eq"))
//				parseEQ(line);
//			else if (lineType.equals("eo"))
//			{
//				isUsgsFile = false; // These lines only exist in EMIT files.
//				parseEO(line);
//			}
//			else if (lineType.equals("ea"))
//				parseEA(line);
//			else if (lineType.equals("ee"))
//				parseEE(line);
			else if (lineType.equals("qu"))
			{
				isUsgsFile = true; // These lines only exist in USGS files.
				debug(1, "Record '"
					+lineType + "' skipped - SATIN Queue Assignment not used.");
			}
			else if (lineType.equals("tz"))
                continue;
//                parseTZ(line);
			else
			{
				warning("Record '"
					+lineType + "' skipped - unrecognized line-type.");
			}

		}
		reader.close();
		isEOF = true;
	}

	/**
	  Parses DV record to create EquipmentModel.
	  @param line the line of data to parse
	*/
	public void parseDV(String line)
	{
		if (line.length() < 15)
		{
			failure("Invalid DV (device) record, length=" + line.length()
				+ ", skipped.");
			return;
		}

		String name = line.substring(3, 3+9).trim();
		if (name == null || name.length() == 0)
		{
			failure("DV record requires non-blank device ID, skipped.");
			return;
		}

		EquipmentModel em = db.equipmentModelList.get(name);
		if (em == null || !keepOld)
		{
			em = new EquipmentModel(name);
			db.equipmentModelList.add(em);
			newObjects.add(em);
		}

		em.equipmentType = Constants.eqType_dcp;
		String type = line.substring(12, 12+3).trim();
		try
		{
			if (type.length() == 0 || type.equalsIgnoreCase("DCP"))
			{
				selfTimedScript = DecodesScript.empty()
											.platformConfig(platformConfig)
											.scriptName(Constants.script_ST)
											.build();
				selfTimedScript.setDataOrder(dataOrderST);
				randomScript = DecodesScript.empty()
											.platformConfig(platformConfig)
											.scriptName(Constants.script_RD)
											.build();
				randomScript.setDataOrder(dataOrderRD);
				edlScript = null;
			}
			else if (type.equalsIgnoreCase("EDL"))
			{
				edlScript = DecodesScript.empty()
										.platformConfig(platformConfig)
										.scriptName(Constants.script_EDL)
										.build();
				edlScript.setDataOrder('A');
				selfTimedScript = randomScript = null;
			}
		}
		catch( DecodesScriptException | IOException ex)
		{
			throw new RuntimeException("Unable to prepare Decodes Scripts",ex);
		}
		formats.clear();
		currentFormat = null;

		if (type.length() != 0)
			em.properties.setProperty("EquipmentType", type);
//MJM 20031205			em.properties.setProperty("PlatformType", type);
		try
		{
			em.model = line.substring(15,15+20).trim();
			em.company = line.substring(35,35+20).trim();
			em.properties.setProperty("RetrievalMethod",
				line.substring(55,55+3).trim());
			em.properties.setProperty("TimeOrder", "" + line.charAt(58));
		}
		catch(Exception e) // These are optional fields, so ignore missing data
		{}
	}

	/**
	  Start of Device Config - Creates PlatformConfig record.
	  @param line the line of data to parse
	*/
	public void parseDC(String line)
	{
		if (line.length() < 19)
		{
			failure("Short DC (device) record, length=" + line.length()
				+ ", (need 19) skipped.");
			return;
		}

		String devId = line.substring(3, 3+9).trim();
		if (devId.length() == 0)
		{
			failure("DC record missing device ID - skipped.");
			return;
		}

		String name = PlatformConfig.makeConfigName(devId,
			line.substring(12,12+4), line.substring(16,16+3));

		if (platformConfig == null)
			startPlatformConfig(name);
		if (platformConfig == null)
			return;  // We're not going to process this one.

		platformConfig.configName = name;
		platformConfig.equipmentModel = db.equipmentModelList.get(devId);

		configDescription = new StringBuffer();

//		selfTimedScript = new DecodesScript(platformConfig,Constants.script_ST);
//		selfTimedScript.setDataOrder(dataOrderST);
//		randomScript = new DecodesScript(platformConfig,Constants.script_RD);
//		randomScript.setDataOrder(dataOrderRD);
//
//		formats.clear();
//		currentFormat = null;

		// Ignore last modified & last installed
		// New DECODES tracks last modified on Platform but not PlatformConfig
	}

	/**
	  Parse a CD (config description line.
	  @param line the line of data to parse
	*/
	public void parseCD(String line)
	{
		if (platformConfig == null || configDescription == null)
		{
			debug(2, "Skipped CD because not processing this PlatformConfig");
			return;
		}
		int len = line.length() - 3;
		if (len <= 0)
			return;
		if (len > 60)
			len = 60;

		String desc = line.substring(3, 3+len).trim();
		if (desc.length() > 0)
		{
			if (configDescription.length() + desc.length() + 1 > 400)
			{
				warning("Platform Config '" + platformConfig.configName
					+ "' description is too long (limit=400 chars)"
					+ ", ignoring CD line.");
			}
			else 
			{
				if (configDescription.length() > 0)
					configDescription.append(' ');
				configDescription.append(desc);
			}
		}
	}

	/**
	  Parses CS line, creates ConfigSensor inside current PlatformConfig.
	  @param line the line of data to parse
	*/
	public void parseCS(String line)
	{
		if (platformConfig == null)
		{
			debug(2, "Skipped CS because not processing this PlatformConfig");
			return;
		}
		if (line.length() < 21)
		{
			failure("CS missing required fields - PlatformConfig abandoned.");
			abandonPlatformConfig();
			return;
		}

		boolean dcpPerfMeasurement = false;
		char ch = line.charAt(3);
		if (ch == 'd' || ch == 'D')
		{
			dcpPerfMeasurement = true;
//			info("Default sensor skipped (not supported)");
//			return;
		}

		int sensorNum;
		String s = line.substring(4, 4+2).trim();
		try { sensorNum = Integer.parseInt(s); }
		catch (NumberFormatException e)
		{
			warning("Config Sensor skipped - cannot parse sensor number");
			return;
		}
		if (dcpPerfMeasurement)
			sensorNum += 100;

		String epaCode = line.substring(6, 6+5).trim();
		if (epaCode.length() > 0)
		{
			try { int i_epaCode = Integer.parseInt(epaCode); }
			catch (NumberFormatException e) { epaCode = null; }
		}

		String statCode = line.substring(11, 11+5).trim();
		if (statCode.length() == 0)
			statCode = null;

		// Ignore field length & # decimals - DECODES handles this with
		// the new Rounding Rules.

		char recordingType = line.charAt(19);
		char recordingMode = line.charAt(20);


		boolean convert = false;
		double a=1.0, b=0.0, c=1.0, d=0.0;

		if (line.length() >= 31)
		{
			s = line.substring(21,21+10).trim();
			if (s.length() > 0)
			{
				try { a = Double.parseDouble(s); }
				catch(NumberFormatException e)
				{
					warning("Sensor " + sensorNum
						+ " unparsable A coefficient (assumed to be 1.0)");
					a = 1.0;
				}
			}
		}

		if (line.length() >= 41)
		{
			s = line.substring(31,31+10).trim();
			if (s.length() > 0)
			{
				try { b = Double.parseDouble(s); }
				catch(NumberFormatException e)
				{
					warning("Sensor " + sensorNum
						+ " unparsable B coefficient (assumed to be 0.0)");
					b = 0.0;
				}
			}
		}

		if (line.length() >= 51)
		{
			s = line.substring(41,41+10).trim();
			if (s.length() > 0)
			{
				try { c = Double.parseDouble(s); }
				catch(NumberFormatException e)
				{
					warning("Sensor " + sensorNum
						+ " unparsable C coefficient (assumed to be 1.0)");
					c = 1.0;
				}
			}
		}

		if (line.length() >= 61)
		{
			s = line.substring(51,51+10).trim();
			if (s.length() > 0)
			{
				try { d = Double.parseDouble(s); }
				catch(NumberFormatException e)
				{
					warning("Sensor " + sensorNum
						+ " unparsable D coefficient (assumed to be 0.0)");
					d = 0.0;
				}
			}
		}

		convert = true;

		String name = "";
		if (line.length() > 61)
			name = line.substring(61).trim();
		if (name.length() == 0)
			name = epaCode;

		ConfigSensor cs = platformConfig.getSensor(sensorNum);
		if (cs == null)
		{
			cs = new ConfigSensor(platformConfig, sensorNum);
			platformConfig.addSensor(cs);
		}
		cs.sensorName = name;
		if (epaCode != null && epaCode.length() > 0)
		{
			int numcode = 0;
			try { numcode = Integer.parseInt(epaCode.trim()); }
			catch(NumberFormatException ex) {}

			// Don't add code if it is zero.
			if (numcode != 0)
				cs.addDataType(DataType.getDataType(Constants.datatype_EPA, 
					epaCode));
		}

		cs.setUsgsStatCode(statCode);

		// recordingType ???

		cs.recordingMode = recordingMode;

		// Add ScriptSensor objects for this sensor into both ST and RD scripts
		ScriptSensor stss = new ScriptSensor(selfTimedScript, sensorNum);
		if (selfTimedScript != null)
			selfTimedScript.scriptSensors.add(stss);
		ScriptSensor rdss = new ScriptSensor(randomScript, sensorNum);
		if (randomScript != null)
			randomScript.scriptSensors.add(rdss);
		ScriptSensor edlss = new ScriptSensor(edlScript, sensorNum);
		if (edlScript != null)
			edlScript.scriptSensors.add(edlss);

		// Try to set default for units from data type.
		// Note: EMIT files will have Units in the 'CA' record (parsed later).
		String units = "unknown";
		DataType shefDT = cs.getDataType(Constants.datatype_SHEF);
		if (shefEnglishPG != null && shefDT != null)
		{
			// Look up DataPresentation element for this SHEF code
			DataPresentation pres = 
				shefEnglishPG.findDataPresentation(shefDT);
			if (pres != null && pres.getUnitsAbbr() != null)
				units = pres.getUnitsAbbr();
		}

		UnitConverterDb rawcvt = new UnitConverterDb("raw", units);

		if (convert)
		{
			if (a == 1.0 && b == 0.0 && c == 1.0 && d == 0.0)
				rawcvt.algorithm = Constants.eucvt_none;
			else if (b == 0.0 && c == 1.0)
			{
				rawcvt.algorithm = Constants.eucvt_linear;
				rawcvt.coefficients[0] = a;
				rawcvt.coefficients[1] = d;
			}
			else
			{
				rawcvt.algorithm = Constants.eucvt_usgsstd;
				rawcvt.coefficients[0] = a;
				rawcvt.coefficients[1] = b;
				rawcvt.coefficients[2] = c;
				rawcvt.coefficients[3] = d;
			}
			stss.rawConverter = rawcvt;
			rdss.rawConverter = rawcvt.copy();
			rdss.rawConverter.clearId();
			edlss.rawConverter = rawcvt.copy();
			edlss.rawConverter.clearId();
		}
		else
			rawcvt.algorithm = Constants.eucvt_none;
	}

	/**
	  Parses a CA line, this contains additional information about a config
	  sensor, and is unique to EMIT.
	  @param line the line of data to parse
	*/
	public void parseCA(String line)
	{
		if (platformConfig == null)
		{
			debug(2, "Skipped CA because not processing this PlatformConfig");
			return;
		}
		if (line.length() < 14)
		{
			warning("CA missing required fields - skipped.");
			return;
		}

		int sensorNum;
		String s = line.substring(3, 3+2).trim();
		try { sensorNum = Integer.parseInt(s); }
		catch (NumberFormatException e)
		{
			warning("CA record skipped - cannot parse sensor number");
			return;
		}
		ConfigSensor cs = platformConfig.getSensor(sensorNum);
		if (cs == null)
		{
			warning(
				"CA record skipped - No matching CS record for sensor number "
				+ sensorNum);
			return;
		}

		String shef = line.substring(5, 5+2).trim();
		if (shef.length() != 0)
			cs.addDataType(DataType.getDataType(Constants.datatype_SHEF, shef));

		if (line.length() < 22)
			return;

		String units = line.substring(12, 12+10).trim();
		if (units.length() != 0)
		{
//			EngineeringUnit eu = db.engineeringUnitList.get(units);
//			if (eu == null)
//			{
//				warning("Unknown Engineering Unit '" + units + "'"
//					+ (validateOnly ? "" : " -- will be added."));
//				eu = EngineeringUnit.getEngineeringUnit(units);
//				euListChanged = true;
//			}

			if (selfTimedScript != null)
			{
				ScriptSensor ss = selfTimedScript.getScriptSensor(sensorNum);
				if (ss != null)
					ss.rawConverter.toAbbr = units;
			}
			if (randomScript != null)
			{
				ScriptSensor ss = randomScript.getScriptSensor(sensorNum);
				if (ss != null)
					ss.rawConverter.toAbbr = units;
			}
			if (edlScript != null)
			{
				ScriptSensor ss = edlScript.getScriptSensor(sensorNum);
				if (ss != null)
					ss.rawConverter.toAbbr = units;
			}
		}
	}

	/**
	  Parses a CF (config format) line.
	  @param line the line of data to parse
	*/
	public void parseCF(String line)
	{
		if (platformConfig == null)
		{
			debug(2, "Skipped CF because not processing this PlatformConfig");
			return;
		}
		if (line.length() < 11)
		{
			warning("CF (format statement) invalid or emtpy -- skipped.");
			return;
		}
		String lab = line.substring(3, 3+7).trim();
		String cmds = line.substring(10).trim();

		// If no label,  then this is a continuation of the previous CF line.
		if (lab.length() == 0)
		{
			if (currentFormat == null)
			{
				failure(
					"CF (format statement) missing required label - skipped");
				return;
			}
			currentFormat.second += cmds;
		}
		else // This is the start of a new format.
		{
			currentFormat = new StringPair(lab, cmds);
			formats.add(currentFormat);
		}
	}

	/**
	  Parses an SF (script file) line.
	  These lines were unique to C-DECODES (not used by emit). They
	  are ignored in Java DECODES.
	  @param line the line of data to parse
	*/
	public void parseSF(String line)
	{
		warning("SF (script file) unsupported -- skipped.");
		return;
	}

	/**
	  The EC line marks the end of a configuration record.
	  Validate the information collected in the config record and create
	  a DECODES PlatformConfig object.
	  @param line the line of data to parse
	*/
	public void parseEC(String line)
	{
		if (platformConfig == null)
		{
			debug(2, "Skipped EC because not processing this PlatformConfig");
			return;
		}

		if (configDescription.length() > 0)
			platformConfig.description = configDescription.toString();
		configDescription = null;

		for(int j=0; j 2 && line.charAt(2) == 'D')
		{
			failure("Site-Delete operation not supported (record ignored).");
			skipToES = true;
			return;
		}
		else 
			skipToES = false;

		if (line.length() < 10)
		{
			failure("SI record with no Station Number (site record ignored).");
			skipToES = true;
			return;
		}

		platform = new Platform();
		String agency = line.substring(3, 3+5).trim();
		if (agency.length() > 0)
			platform.agency = agency;
		
		statnum = line.substring(8);
		if (statnum.length() > 15)
			statnum = statnum.substring(0, 15);
		statnum = statnum.trim();
		if (statnum.length() > 0)
		{
			SiteName sn = new SiteName(null, Constants.snt_USGS, statnum);
			sn.setAgencyCode(platform.agency);
			sn.setUsgsDbno("01");
			Site existingSite = db.siteList.getSite(sn);
			if (existingSite != null)
			{
				sn.setSite(existingSite);
				platform.setSite(existingSite);
			}
			else
			{
				// Note 'explicitList' is false, so site will automatically
				// be added to the list by the constructor.
				Site site = new Site(platform);
				site.addName(sn);
				sn.setSite(site);
				platform.setSite(site);
			}
		}

		if (line.length() < 24)
			return;

		// Time Zone, daylight time flag:
		if (line.length() >= 29)
			daylightFlag = line.charAt(28);
		else
			daylightFlag = 'N';
		// MJM 20031209 As per convo with SED, ignore timezone in SI record.
		// SED 20070201 No, the offset on this line IS the offset to be used.
		// The TZ record simply provides the offset of the time zone where
		// the site that has the recorder is located, not the offset used
		// by the recorder.
		String tzstr = line.substring(23);
		if (tzstr.length() > 5)
			tzstr = tzstr.substring(0, 5);
		tzstr = tzstr.trim();
		if (tzstr.length() > 0 && platform.getSite() != null)
		{
			int min = 0;
			try 
			{
				min = Integer.parseInt(tzstr); 
				boolean dst = line.length() >= 29 && line.charAt(28) == 'Y';
//				platform.site.timeZoneAbbr = getSdfTZ(min, dst);
				platform.getSite().timeZoneAbbr = getSdfTZ(min, daylightFlag);
			}
			catch(NumberFormatException ex)
			{
				warning("SI line with illegal UTC offset '" + tzstr 
					+ "' -- ignored.");
			}
		}
		else if (platform.getSite() != null)
		{
			platform.getSite().timeZoneAbbr = "GMT";
		}
	}


	/**
	  Parse an SI1 record, unique to USGS-C-DECODES.
	  @param line the line of data to parse
	*/
	public void parseSI1(String line)
	{
		if (platform == null)
		{
			warning("SI1 can only occur inside Site block - ignored");
			return;
		}

		// Reset data order to default of Descending
		dataOrderST = 'D';
		dataOrderRD = 'D';

		int len = line.length();
		String s = line.substring(3, (len > 11 ? 11 : len)).trim();
		if (s.length() > 0)
		{
			SiteName sn = new SiteName(null, Constants.snt_NWSHB5, s);
			Site existingSite = db.siteList.getSite(sn);

			if (platform.getSite() == null)
			{
				if (existingSite != null)
					platform.setSite(existingSite);
				else
				{
					platform.setSite(new Site(platform));
					platform.getSite().addName(sn);
				}
			}
			else // platform.site already supplied by USGS number
			{
				/*
			  	  If this platform already has a site, e.g. from the SI record,
			  	  AND, this site name already refers to a different existing
			  	  site with a different USGS sitenume, then this is an error.
				*/
				if (existingSite == null)
					platform.getSite().addName(sn);
				else if (existingSite != platform.getSite())
					warning(
			"SI1 record contains HB5 name that is already used by a different"
			+ " site. HB5 name ignored.");
			}
		}
	}

	/**
	  Parse an SD (Site Device) record.
	  @param line the line of data to parse
	*/
	public void parseSD(String line)
	{
		if (skipToES)
			return;
		if (platform == null)
		{
			warning(
				"SD (Site Data) can only occur inside Site block - ignored");
			return;
		}
		if (line.length() < 20)
		{
			failure("SD too short (20 chars required) - platform abandoned.");
			abandonPlatform();
			return;
		}
		String devId = line.substring(3, 3+9).trim();
		if (devId.length() == 0)
		{
			failure("SD record missing device ID - skipped.");
			skipToES = true;
			return;
		}

		platformConfigName = PlatformConfig.makeConfigName(devId,
			line.substring(12, 12+4), line.substring(16, 16+3));

		startPlatformConfig(platformConfigName);

		String dcpAddr = null;
		if (line.length() >= 28)
		{
			String s = line.substring(20, 20+8);
			platform.lastModifyTime = emitDateFormat.parse(s, 
				new ParsePosition(0));

			if (line.length() >= 44)
			{
				dcpAddr = line.substring(36, 36+8).toUpperCase();
			}
		}

		if (dcpAddr == null || TextUtil.isAllWhitespace(dcpAddr))
		{
			/*
			  This is for an EDL. Construct transport ID as follows:
			  SiteNumber + "-" + DeviceName + "-" + DeviceNumber.
			*/
			TransportMedium edlTM = new TransportMedium(platform,
				Constants.medium_EDL, 
				statnum + "-" + devId + "-" + line.charAt(19));
			edlTM.scriptName = Constants.script_EDL;
			edlTM.setTimeZone(
				platform.getSite().timeZoneAbbr == null 
					|| platform.getSite().timeZoneAbbr.length() == 0
				? null : platform.getSite().timeZoneAbbr);
			platform.transportMedia.add(edlTM);
		}
		else
		{
			TransportMedium selfTimedTM = new TransportMedium(platform,
				Constants.medium_GoesST, dcpAddr);
			selfTimedTM.scriptName = Constants.script_ST;

			if (line.length() < 47)
				return;

			String s = line.substring(44, 44+3).trim();
			try { selfTimedTM.channelNum = Integer.parseInt(s); }
			catch(Exception e) {}

			if (line.length() < 53)
				return;

			s = line.substring(47, 47+6);
			try
			{
				selfTimedTM.assignedTime = IDateFormat.getSecondOfDay(s);
				// messageTime is assignedTime truncated to nearest minute 
				//- SED 2003/09/15
				messageTime = selfTimedTM.assignedTime 
					- ( selfTimedTM.assignedTime%60 );
			}
			catch(Exception e) {}

			if (line.length() < 59)
				return;

			s = line.substring(53, 53+6);
			try 
			{
				StringBuilder sb = new StringBuilder(s);
				for(int i=0; i 0)
			{
				randomTM = new TransportMedium(platform,
					Constants.medium_GoesRD, dcpAddr);
				randomTM.scriptName = Constants.script_RD;
				randomTM.channelNum = randomChannel;
				platform.transportMedia.add(randomTM);
			}

/*
* MJM 20031020 Ignore DRGS name - not guaranteed to be unique.
*		s = line.substring(62, 62+6).trim();
*		if (s.length() > 0)
*		{
*	  		if (platform.site == null)
*    			platform.site = new Site(platform);
*			SiteName sn = new SiteName(platform.site,Constants.snt_USGS_DRGS,s);
*			platform.site.addName(sn);
*		}
*/

			if (line.length() < 70)
				return;

			if (line.length() > 68)
				dataOrderST = Character.toUpperCase(line.charAt(68));
			if (line.length() > 69)
				dataOrderRD = Character.toUpperCase(line.charAt(69));
		}
	}

	/**
	  Parse an SS (Site Sensor) record.
	  In Java DECODES this info lives in a PlatformRecord.
	  @param line the line of data to parse
	*/
	public void parseSS(String line)
	{
		if (platform == null)
		{
			warning(
				"SS (Site Sensor) record not inside a Site (SI...ES) block "
				+ " - ignored");
			return;
		}

		// Difference in USGS and EMIT files for the SS record:
		String fields[];
		if (isUsgsFile)
			fields = TextUtil.getFixedFields(line, 
				new int[]{ 2,1,1,2,6,6,2,4,8,8,15,4,32 });
		else
			fields = TextUtil.getFixedFields(line,
				new int[]{ 2,1,1,2,6,6,2,4,10,10,15,4,32 });

		if (fields.length < 6)
		{
			warning("SS (Site Sensor) record empty - ignored");
			return;
		}

		boolean dcpPerfMeasurement = false;
		char c = fields[2].charAt(0);
		if (c == 'D' || c == 'd')
		{
			dcpPerfMeasurement = true;
//			info("SS (Site Sensor) Default Sensors not supported - ignored");
//			return;
		}

		int sensorNum = -1;
		try { sensorNum = Integer.parseInt(fields[3].trim()); }
		catch(NumberFormatException e)
		{
			failure("SS (Site Sensor) with invalid sensor number - ignored");
			return;
		}
		if (dcpPerfMeasurement)
			sensorNum += 100;

		PlatformSensor ps = new PlatformSensor(platform, sensorNum);
		int recordingInterval = -1;
		StringBuilder sb = new StringBuilder(fields[4]);
		for(int i=0; i 0)
				cs.timeOfFirstSample = 
					(messageTime - timeOffset) % recordingInterval;
			while (cs.timeOfFirstSample < 0)
			  cs.timeOfFirstSample += recordingInterval;
		}

		if (fields.length < 7)
			return;

		if (!fields[6].equals("  "))
		{
			char dbno[] = new char[2];
			dbno[0] = fields[6].charAt(0);
			if (dbno[0] == ' ')
				dbno[0] = '0';
			dbno[1] = fields[6].charAt(1);
			Site site = platform.getSite();
			if (site == null)
			{
				failure("SS Record with no Site -- skipped.");
				platform = null;
				skipToES = true;
				return;
			}
			SiteName sn = site.getName(Constants.snt_USGS);
			if (sn != null)
				sn.setUsgsDbno(new String(dbno));
		}

		if (fields.length >= 8)
		{
			int num = parseIntField(fields[7], 0, "DDNO", 0);
			if (num != 0)
				ps.setUsgsDdno(num);

			if (fields.length >= 9)
			{
				String s = fields[8].trim();
				if (s.length() != 0 && cs != null)
				if (cs != null && s.length() > 0)
				{
					try 
					{
						double d = Double.parseDouble(s); 
						ps.getProperties().setProperty("minimum", s);
					}
					catch (NumberFormatException e) {}
				}
		
				if (fields.length >= 10)
				{
					s = fields[9].trim();
					if (cs != null && s.length() > 0)
					{
						try 
						{ 
							double d = Double.parseDouble(s); 
							ps.getProperties().setProperty("maximum", s);
						}
						catch (NumberFormatException e) {}
					}
			
					if (fields.length >= 11)
					{
						s = fields[10].trim();
						if (s.length() > 0)
						{
							SiteName sn = new SiteName(null, 
								Constants.snt_USGS, s);
							ps.site = db.siteList.getSite(sn);
							if (ps.site == null)
							{
								ps.site = new Site();
								ps.site.addName(sn);
							}
						}
				
						if (fields.length >= 12)
						{
							num = parseIntField(fields[11], 0, 
								Constants.usgsprop_AlertNum, 0);
							if (num != 0)
								ps.getProperties().setProperty(
									Constants.usgsprop_AlertNum, ""+num);
					
							if (fields.length >= 13)
							{
								s = fields[12].trim();
								if (s.length() > 0 && !s.equals("0000"))
									ps.getProperties().setProperty(
										Constants.usgsprop_AlertUser, s);
							}
						}
					}
				}
			}
		}
		// Only add the PlatformSensor object if it contains useful data.
		if (!ps.isEmpty() )
			platform.platformSensors.add(ps);
	}

	/** 
	  USGS SS1 extensions to sensor records.
	  @param line the line of data to parse
	*/
	public void parseSS1(String line)
	{
		if (platform == null)
		{
			warning("SS1 (Site Sensor Extension) record not inside a Site "
				+ "(SI...ES) block - ignored");
			return;
		}
		if (platform.getConfig() == null)
		{
			warning("SS1 (Site Sensor Extension) without corresponding "
				+ "Device Config - ignored");
			return;
		}

		String f[] = TextUtil.getFixedFields(line, new int[]{3, 1, 2, 7, 8});
		if (f.length < 4)
		{
			warning("SS1 (Site Sensor Extension) record too short - ignored");
			return;
		}

		char c = f[1].charAt(0);
		if (c == 'D' || c == 'd')
		{
			info("SS1 (Site Sensor) Default Sensors not supported - ignored");
			return;
		}

		String s = f[2].trim();
		int sensorNum = -1;
		try { sensorNum = Integer.parseInt(s); }
		catch(NumberFormatException e)
		{
			failure(
			"SS1 (Site Sensor Extension) with invalid sensor number - ignored");
			return;
		}

		ConfigSensor cs = platform.getConfig().getSensor(sensorNum);
		if (cs == null)
		{
			failure("SS1 (Site Sensor Extension) with invalid sensor number "
				+ sensorNum);
			return;
		}

		String shefCode = f[3].trim();
		if (shefCode.length() > 0)
		{
			cs.addDataType(
				DataType.getDataType(Constants.datatype_SHEF, shefCode));
		}

		// get HB5 name, might be different from the one assigned to platform
		if (f.length < 5)
			return;
		String hb5 = f[4].trim();
		if (hb5.length() <= 0)
			return;

		SiteName sn = platform.getSite().getName(Constants.snt_NWSHB5);
		if (sn != null && sn.getNameValue().equalsIgnoreCase(hb5))
		{
			debug(1, "sensor site name '" + hb5 + "' same as site assigned to "
				     + "platform - ignored");
			return;
		}

		PlatformSensor ps = platform.getPlatformSensor(sensorNum);
		if (ps == null)
		{
			ps = new PlatformSensor(platform, sensorNum);
			platform.platformSensors.add(ps);
		}

		sn = new SiteName(null, Constants.snt_NWSHB5, hb5);
		Site site = db.siteList.getSite(sn);
		if (site == null)
		{
			site = new Site();
			site.addName(sn);
		}
		ps.site = site;
		info("Assigning sensor[" + sensorNum + "] to HB5 site '" + hb5 + "'");
	}

	/**
	  Parse an SA (Site Additional) record, containing Platform-SiteName
	  association.
	  @param line the line of data to parse
	*/
	public void parseSA(String line)
	{
		if (platform == null)
		{
			failure("SA record can only appear inside Site block");
			return;
		}

		if (line.length() < 4)
			return;
		String s = line.substring(3).trim();
		if (platform.getSite() == null)
			platform.setSite(new Site(platform));
		SiteName sn = new SiteName(platform.getSite(), defaultStationNameType, s);
		platform.getSite().addName(sn);
	}

	/**
	  Parse an SE record, containing a platform description.
	  @param line the line of data to parse
	*/
	public void parseSE(String line)
	{
		if (platform == null)
		{
			failure("SE record can only appear inside Site block");
			return;
		}

		if (line.length() < 4)
			return;
		String s = line.substring(3).trim();
		platform.description = s;
	}

	/**
	  Parse an SC record.
	  @param line the line of data to parse
	*/
	public void parseSC(String line)
	{
		if (platform == null)
		{
			failure("SC record can only appear inside Site block");
			return;
		}

		if (line.length() < 4)
			return;
		String s = line.substring(3).trim();
		if (platform.description == null)
			platform.description = s;
		else
			platform.description = platform.description + " -- " + s;
	}

	/**
	  Parses ES (End of Site) lines.
	  Finish construction of platform & save into database.
	  @param line the line of data to parse
	*/
	public void parseES(String line)
	{
		if (skipToES)
		{
			skipToES = false;
			return;
		}
		
		// Associate ST & RD transport media to scripts.
		TransportMedium st_tm =
			platform.getTransportMedium(Constants.medium_GoesST);
		TransportMedium rd_tm =
			platform.getTransportMedium(Constants.medium_GoesRD);
		TransportMedium edl_tm =
			platform.getTransportMedium(Constants.medium_EDL);

		// Add this platform to the global list.
		if (st_tm == null && rd_tm == null && edl_tm == null)
		{
			failure("A platform must have at least one transport medium "
				+ "(ST, RD, or EDL).");
			platform = null;
			return;
		}

		// Find out if this platform already exists.
		TransportMedium tm = st_tm != null ? st_tm : 
		                     rd_tm != null ? rd_tm : edl_tm;
		Platform oldPlatform = null;
		try
		{
			oldPlatform = db.platformList.getPlatform(
				tm.getMediumType(), tm.getMediumId(), new Date());
		}
		catch(DatabaseException ex) { oldPlatform = null; }

		if (oldPlatform != null && keepOld)
			failure("Discarding imported platform '" +
				tm.getMediumId() + "' - already exists in database.");
		else
		{	// Keeping new platform
			if (oldPlatform != null)
			{
                try {
					// Set new ID to the old one, forcing an overwrite.
                    DbKey id = oldPlatform.getId();
                    platform.setId(id);
                }
                catch (DatabaseException e) 
				{ /* Shouldn't happen. */ }
			}

			db.platformList.add(platform);
			if (platform.getSite() != null)
				newObjects.add(platform.getSite());
			newObjects.add(platform);
			platformListChanged = true;
		}

		// Set temporaries to null
		platform = null;
		platformConfig = null;
	}

//	public void parseEQ(String line)
//	{
//		if (line.length() < 18)
//		{
//			failure("EQ record too short - Must have at least name and scope.");
//			return;
//		}
//		String nm = line.substring(3, 3+14).trim();
//		if (nm.length() == 0)
//		{
//			failure("EQ spec name cannot be blank");
//			return;
//		}
//		if (nm.endsWith(".eq"))
//			nm = nm.substring(0, nm.length()-3);
//
//		char c = line.charAt(17);
//		String scope = null;
//		switch(c)
//		{
//		case 'G': scope = Constants.eqSpecScopeALL; break;
//		case 'D': scope = Constants.eqSpecScopeDCP; break;
//		case 'C': scope = Constants.eqSpecScopeDCF; break;
//		case 'L': scope = Constants.eqSpecScopeNL; break;
//		}
//		if (scope == null)
//		{
//			failure("EQ spec with invalid scope - skipped");
//			return;
//		}
//
//		eqSpec = null;
//
//		EquationSpec old = db.equationSpecList.get(nm);
//		if (old != null)
//		{
//			if (keepOld)
//			{
//				warning("EQ Spec '" + nm + "' already exists - skipping.");
//				return;
//			}
//			else
//			{
//				warning("EQ spec '" + nm + "' already exists"
//					+ (validateOnly ? "" : " - overwriting with new definition"));
//				eqSpec = new EquationSpec(nm);
//			}
//		}
//		else
//			eqSpec = new EquationSpec(nm);
//
//		debug(1, "Created EquationSpec '" + nm + "'");
//
//		eqSpec.scope = scope;
//		if (line.length() <= 18)
//			return;
//		String s = line.substring(18).trim();
//		if (s.length() > 0)
//		eqSpec.applyTo = s;
//	}
//
//	public void parseEO(String line)
//	{
//		if (eqSpec == null)
//		{
//			warning("Skipping EO record");
//			return;
//		}
//		if (line.length() < 40)
//		{
//			failure("EO record too short (must be 40 chars at least)");
//			return;
//		}
//		eqSpec.outputName = line.substring(3, 3+8).trim();
//
//		String s = line.substring(12, 12+5).trim();
//		if (s.length() > 0)
//		{
//			int code = 0;
//			try { code = Integer.parseInt(s); }
//			catch(NumberFormatException e) {}
//			if (code != 0)
//			{
//				eqSpec.dataType = DataType.getDataType(
//					Constants.datatype_EPA, s);
//			}
//		}
//		s = line.substring(17, 17+7).trim();
//		if (s.length() > 0)
//			eqSpec.dataType = DataType.getDataType(Constants.datatype_SHEF, s);
//
//		s = line.substring(29, 29+10);
//		if (s.length() > 0)
//			eqSpec.unitsAbbr = s;
//	}
//
//	public void parseEA(String line)
//	{
//		if (eqSpec == null)
//		{
//			warning("Skipping EA record");
//			return;
//		}
//		if (line.length() < 11)
//		{
//			failure("EA record too short");
//			return;
//		}
//		String varname = line.substring(3, 3+8).trim();
//		String expr = line.substring(11);
//		int idx = expr.indexOf('#');
//		if (idx != -1)
//			expr = expr.substring(0, idx);
//		expr = expr.trim();
//		if (expr.length() > 0)
//		{
//			if (varname.length() > 0)  // New varname - start new statement.
//			{
//				eqStatement = new EqStatement(eqSpec);
//				eqStatement.varName = varname;
//				eqStatement.expression = expr;
//				eqSpec.statements.add(eqStatement);
//			}
//			else // continuation of previous EA
//			{
//				eqStatement.expression = eqStatement.expression + " " + expr;
//			}
//		}
//	}
//
//	public void parseEE(String line)
//	{
//		if (eqSpec != null)
//			newObjects.add(eqSpec);
//		eqSpec = null;
//	}

//	public void parseEqTable(String filename, LineNumberReader reader)
//		throws IOException
//	{
//		// Strip extension off of filename - this is the table name.
//		int idx = filename.lastIndexOf('.');
//		if (idx != -1)
//			filename = filename.substring(0, idx);
//
//		// Also strip off directory prefix, if any.
//		idx = filename.lastIndexOf(File.separatorChar);
//		if (idx != -1)
//			filename = filename.substring(idx+1);
//
//		EqTable old = db.eqTableList.get(filename);
//		if (old != null)
//		{
//			if (keepOld)
//			{
//				warning("EQ Table '" + filename + "' already exists - skipping.");
//				return;
//			}
//			else
//			{
//				warning("EQ table '" + filename + "' already exists"
//					+ (validateOnly ? "" : " - overwriting with new definition"));
//			}
//		}
//
//		EqTable eqTable = new EqTable(filename);
//		db.eqTableList.add(eqTable);
//		newObjects.add(eqTable);
//
//		boolean bounded = false;
//
//		String line;
//		while((line = reader.readLine()) != null)
//		{
//			debug(3, "Read line " + reader.getLineNumber()
//				+ " '" + line + "'");
//			line = line.trim();
//			if (line.length() == 0 || line.charAt(0) == '#')
//				continue;
//			int colon = line.indexOf(':');
//			if (colon == -1 || line.length() < colon+2)
//			{
//				warning("Table line too short - skipped");
//				continue;
//			}
//
//			String first = line.substring(0, colon).trim();
//			String second = line.substring(colon+1).trim();
//			char c;
//			double x, y;
//			double minX = Double.MAX_VALUE;
//			double maxX = Double.NEGATIVE_INFINITY;
//
//			switch(line.charAt(0))
//			{
//			case 'D':
//			case 'd':	/* table description */
//				eqTable.description = second;
//				break;
//			case 'X':
//			case 'x':	/* X params>> x:name:type */
//				idx = second.indexOf(':');
//				if (idx != -1)
//					second = second.substring(0, idx);
//				eqTable.inputName = second;
//				break;
//			case 'Y':
//			case 'y':	/* Y params>> y:name:type */
//				idx = second.indexOf(':');
//				if (idx != -1)
//					second = second.substring(0, idx);
//				eqTable.outputName = second;
//				break;
//			case 'R':
//			case 'r':	/* out-of-range option: 'i'=interpolate, 'f'=fail */
//				c = second.charAt(0);
//				if (c == 'i' || c == 'I')
//					bounded = false;
//				else if (c == 'f' || c == 'F')
//					bounded = true;
//				break;
//			case 'L':
//			case 'l':	/* Lookup: i=interpolate, r=round, t=trunc, m=match */
//				c = second.charAt(0);
//
//				// Here we have to assume: Most tables in EMIT were used for
//				// stage to flow conversion. The appropriate algorithm for
//				// that is logarithmic (with interpolation).
//				if (c == 'i' || c == 'I')
//					eqTable.lookupAlgorithm = Constants.lookup_logarithmic;
//				else if (c == 'r' || c == 'R')
//					eqTable.lookupAlgorithm = Constants.lookup_rounding;
//				else if (c == 't' || c == 'T')
//					eqTable.lookupAlgorithm = Constants.lookup_truncating;
//				else if (c == 'm' || c == 'M')
//					eqTable.lookupAlgorithm = Constants.lookup_exact;
//				break;
//			default:
//				try
//				{
//					x = Double.parseDouble(first);
//					y = Double.parseDouble(second);
//				}
//				catch(NumberFormatException e)
//				{
//					failure("Illegal table values - must be numbers");
//					continue;
//				}
//				if (x > maxX) maxX = x;
//				if (x < minX) minX = x;
//				eqTable.addPoint(x, y);
//				break;
//			}
//		}
//		reader.close();
//	}

	/**
	  Parses an EMIT/LRGS/DRS-style ASCII network list file.
	  @param filename the network list file name.
	*/
	public void parseNetworkList(String filename)
		throws IOException
	{
		// Use LRGS object to parse the file.
		lrgs.common.NetworkList lnl =
			new lrgs.common.NetworkList(new File(filename));
		int sz = lnl.size();
		if (sz <= 0)
		{
			failure("Network list '" + filename
				+ "' is either empty or unparsable -- skipped.");
			return;
		}

		// Strip extension & dir prefix from filename - this will be list name.
		int idx = filename.lastIndexOf('.');
		if (idx != -1)
			filename = filename.substring(0, idx);
        idx = filename.lastIndexOf('/');
        if (idx == -1)
            idx = filename.lastIndexOf('\\');
//		idx = filename.lastIndexOf(File.separatorChar);
		if (idx != -1)
			filename = filename.substring(idx+1);

		// Make a new DECODES network list
		decodes.db.NetworkList dnl = new decodes.db.NetworkList(filename);
		dnl.transportMediumType = Constants.medium_Goes;
		dnl.siteNameTypePref = DecodesSettings.instance().siteNameTypePreference;

		db.networkListList.add(dnl);
		newObjects.add(dnl);

		// Copy legacy netlist data into DECODES network list.
		for(Iterator it = lnl.iterator(); it.hasNext(); )
		{
			lrgs.common.NetworkListItem lnli =
				(lrgs.common.NetworkListItem)it.next();
			decodes.db.NetworkListEntry nle =
				new decodes.db.NetworkListEntry(dnl, lnli.addr.toString());
			nle.setPlatformName(lnli.name);
			nle.setDescription(lnli.description);
			dnl.addEntry(nle);
			if (makeSiteNames && nle.getPlatformName() != null
			 && !TextUtil.isAllWhitespace(nle.getPlatformName()))
			{
				Platform p = db.platformList.findPlatform(
					Constants.medium_Goes, nle.transportId, new Date());
				if (p != null && p.getSite() != null)
				{
					SiteName sn = new SiteName(p.getSite(), defaultStationNameType,
						nle.getPlatformName().trim());
					p.getSite().addName(sn);
					newObjects.add(p.getSite());
				}
			}
		}
	}

	/**
	  The TZ line contains a minute offset to assign a time zone to the
	  site record.
	  @param line the line of data to parse
	*/
	private void parseTZ(String line)
	{
		if (platform == null || platform.getSite() == null)
		{
			warning("TZ can only occur inside Site block - ignored");
			return;
		}
		line = line.substring(2).trim();
		if (line.length() == 0)
			return;

		try
		{
			int min = Integer.parseInt(line);
			platform.getSite().timeZoneAbbr = getSdfTZ(min, daylightFlag);
		}
		catch(NumberFormatException ex)
		{
			warning("TZ line must have integer # minutes -- ignored.");
		}
	}

	private String getSdfTZ(int min, char daylightFlag)
	{
	String tzcode;
		if ( daylightFlag == 'M' ||
			daylightFlag == 'A' ) {
			switch (min)
			{
			case 0:     tzcode = "GMT"; break;
			case -240:  tzcode = "America/Puerto_Rico"; break;
			case -300:  tzcode = "EST"; break;
			case -360:  tzcode = "CST"; break;
			case -420:  tzcode = "MST"; break;
			case -480:  tzcode = "PST"; break;
			default:
			   tzcode = "none";
			}
			if ( daylightFlag == 'M' )
			  tzcode+=" M";
		} else {
			int ohr = min/60;
			int omin = min%60;
			tzcode = "GMT";
			if ( ohr != 0 || omin != 0  ) {
			  if ( ohr > 0 ) { 
			    if ( ohr < 10 )
			      tzcode+="+0"+ohr+":";
			    else
			      tzcode+="+"+ohr+":";
			  } else {
			    ohr *= -1;
			    if ( ohr < 10 )
			      tzcode+="-0"+ohr+":";
			    else
			      tzcode+="+"+ohr+":";
			  }
			  if ( omin < 10 )
			    tzcode += "0";
			  tzcode += omin;
			}
		}
		return(tzcode);
	}
	
	/**
	  Parses an integer field, returning a default value if the field
	  is blank, or an error value if it is unparsable.
	  @param s the field data
	  @param dflt the default returned if the field is blank
	  @param nm the name of the field used in log messages
	  @param err the error value returned if the field is unparsable
	*/
	public int parseIntField(String s, int dflt, String nm, int err)
	{
		s = s.trim();
		if (s.length() == 0)
			return dflt;
		try
		{
			return Integer.parseInt(s.trim());
		}
		catch(NumberFormatException nfe)
		{
			warning("Expected number in field '" + nm + "' -- ignored.");
			return err;
		}
	}

	static CmdLineArgs cmdLineArgs = new CmdLineArgs(false, "util.log");
	static StringToken nameTypeArg = new StringToken("t", "Station-Name-Type",
		"", TokenOptions.optSwitch, "");
	static BooleanToken outputAsExportArg = new BooleanToken("x",
		"Output as XML Export File", "", TokenOptions.optSwitch, false);
	static BooleanToken validateOnlyArg = new BooleanToken("v",
		"Validate Only", "", TokenOptions.optSwitch, false);
	static BooleanToken keepOldArg = new BooleanToken("o",
		"Keep old records on conflict", "", TokenOptions.optSwitch, false);
	static StringToken fileArgs = new StringToken("", "EmitFiles", "",
		TokenOptions.optArgument|TokenOptions.optMultiple
		|TokenOptions.optRequired, "");
	static BooleanToken makeSiteNamesArg = new BooleanToken("s",
		"Make site names from network list entries", "", 
		TokenOptions.optSwitch, false);
	static BooleanToken usgsFileArg = new BooleanToken("u",
		"Default to USGS-generated SDF files", "", 
		TokenOptions.optSwitch, false);
	static
	{
		cmdLineArgs.addToken(nameTypeArg);
		cmdLineArgs.addToken(outputAsExportArg);
		cmdLineArgs.addToken(validateOnlyArg);
		cmdLineArgs.addToken(keepOldArg);
		cmdLineArgs.addToken(fileArgs);
		cmdLineArgs.addToken(makeSiteNamesArg);
		cmdLineArgs.addToken(usgsFileArg);
	}

	/**
	Main method.
	

Usage: [java] decodes.import.EmitImport [file list] @param args the command line arguments. */ public static void main(String args[]) throws IOException, DecodesException { Logger.setLogger(new StderrLogger("EmitImport")); // Parse command line arguments. cmdLineArgs.parseArgs(args); // Send WARNING & higher messages to stderr, file logger set by args. Logger fileLogger = Logger.instance(); String procname = fileLogger.getProcName(); Logger stderrLogger = new StderrLogger(procname); stderrLogger.setMinLogPriority(Logger.E_WARNING); stderrLogger.setUseDateTime(false); Logger teeLogger = new TeeLogger(procname, fileLogger, stderrLogger); Logger.setLogger(teeLogger); Logger.instance().log(Logger.E_INFORMATION, "EmitImport Starting (" + DecodesVersion.startupTag() + ") ====================="); DecodesSettings settings = DecodesSettings.instance(); // Construct the database and the interface specified by properties. Database db = new decodes.db.Database(); Database.setDb(db); Logger.instance().log(Logger.E_DEBUG1, "Instantiating Database IO of type '" + settings.editDatabaseType + "' at location '" + settings.editDatabaseLocation + "'"); DatabaseIO dbio = null; try { dbio = DatabaseIO.makeDatabaseIO( settings.editDatabaseTypeCode, settings.editDatabaseLocation); } catch(Exception ex) { System.err.println("Cannot instantiate database: " + ex); ex.printStackTrace(System.err); } // Standard Database Initialization for all Apps: Site.explicitList = false; // YES Sites automatically added to SiteList // Don't update dependents when writing records. We will ensure // consistency internally. XmlDatabaseIO.writeDependents = false; db.setDbIo(dbio); // Initialize standard collections: db.enumList.read(); db.dataTypeSet.read(); db.engineeringUnitList.read(); db.siteList.read(); db.equipmentModelList.read(); db.platformConfigList.read(); db.platformList.read(); db.presentationGroupList.read(); EmitImport importer = new EmitImport(); importer.isUsgsFlag = usgsFileArg.getValue(); String s = nameTypeArg.getValue(); if (s != null && s.length() > 0) importer.defaultStationNameType = s; importer.validateOnly = validateOnlyArg.getValue(); importer.keepOld = keepOldArg.getValue(); importer.makeSiteNames = makeSiteNamesArg.getValue(); importer.shefEnglishPG = db.presentationGroupList.find("SHEF-English"); if (importer.shefEnglishPG != null) importer.shefEnglishPG.prepareForExec(); // Process all filenames on the command line. importer.reset(); for(int i = 0; i < fileArgs.NumberOfValues(); i++) { importer.parseFile(fileArgs.getValue(i)); } // If outputting to an XML export file, write Database object. if (outputAsExportArg.getValue()) { TopLevelParser.write(System.out, importer.db); } else // Else importing into existing database. { for(Iterator it = importer.newObjects.iterator(); it.hasNext(); ) { DatabaseObject dbob = (DatabaseObject)it.next(); if (dbob instanceof Platform) { Platform p = (Platform)dbob; importer.info("Writing Platform '" + p.makeFileName() + "' config=" + p.getConfigName()); } else if (dbob instanceof PlatformConfig) { PlatformConfig pc = (PlatformConfig)dbob; importer.info("Writing PlatformConfig '" + pc.configName + "'"); } else if (dbob instanceof Site) { Site site = (Site)dbob; importer.info("Writing Site '" + site.getDisplayName() + "'"); } else importer.info("Writing " + dbob.getObjectType()); dbob.write(); } if (importer.platformListChanged) db.platformList.write(); } } /** @return a log message prefix containing the current file name and line number. */ private String logpfx() { if (isEOF) return ""; else return curFileName + "(" + reader.getLineNumber() + ") "; } /** Convenience method to print a log message. @param msg the message */ private void info(String msg) { logger.log(Logger.E_INFORMATION, logpfx() + msg); } /** Convenience method to print a log message. @param msg the message */ private void warning(String msg) { logger.log(Logger.E_WARNING, logpfx() + msg); } /** Convenience method to print a log message. @param msg the message */ private void failure(String msg) { logger.log(Logger.E_FAILURE, logpfx() + msg); } /** Convenience method to print a log message. @param lev the debug level (1, 2, or 3) @param msg the message */ private void debug(int lev, String msg) { logger.log(lev == 1 ? Logger.E_DEBUG1 : lev == 2 ? Logger.E_DEBUG2 : Logger.E_DEBUG3, logpfx() + msg); } /** Called when unrecoverable error seen in a platform record. Causes parse to discard any data collected for this platform and skip ahead to the next platform record. */ private void abandonPlatform() { failure("Abandoning platform"); platform = null; skipToES = true; } /** Called when unrecoverable error seen in a platform config record. Causes parse to discard any data collected for this platform and skip ahead to the next platform record. */ private void abandonPlatformConfig() { failure("Abandoning platform config"); platformConfig = null; if (platform != null) abandonPlatform(); } /** @return true if this object newly created within this import session. */ private boolean isNewObject(DatabaseObject ob) { for(Iterator it = newObjects.iterator(); it.hasNext(); ) { DatabaseObject test = (DatabaseObject)it.next(); if (test == ob) return true; } return false; } /** Starts a new PlatformConfig object with the given name. @param name platform config name. */ private void startPlatformConfig(String name) { if (platform != null) platform.setConfigName(name); platformConfig = db.platformConfigList.get(platformConfigName); if (platformConfig == null) { // not defined yet, create one to be filled in later: platformConfig = new PlatformConfig(name); if (platform != null) platform.setConfig(platformConfig); } else if (isNewObject(platformConfig)) { // This object already created from previous rec in this // import session. We don't want to process this one also. if (platform != null) // establish link to previously parsed DC. platform.setConfig(platformConfig); platformConfig = null; // but don't process this one. } else { // This PC exists previously in my database. if (keepOld) { warning("Platform config '" + name + "' already exists -- records of this PC will be skipped."); if (platform != null) // establish link to existing DC. platform.setConfig(platformConfig); platformConfig = null; // but don't process this one. } else // Overwrite old with new { warning("Platform config '" + name + "' already exists " + (validateOnly ? "" : " - will be overwritten.")); db.platformConfigList.remove(platformConfig); platformConfig = new PlatformConfig(name); if (platform != null) platform.setConfig(platformConfig); } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy