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

decodes.tsdb.xml.CompXio 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$
*  
*  Open Source Software
*  
*  $Log$
*  Revision 1.5  2016/11/03 19:07:16  mmaloney
*  Don't reread group members. The cache already has complete groups.
*
*  Revision 1.4  2016/03/24 19:22:56  mmaloney
*  Added support for algorithm scripts.
*
*  Revision 1.3  2015/05/14 13:52:18  mmaloney
*  RC08 prep
*
*  Revision 1.2  2014/12/15 20:39:10  mmaloney
*  writeTsGrp for Site List, must use site.getUniqueName, not getDisplayName.
*
*  Revision 1.1.1.1  2014/05/19 15:28:59  mmaloney
*  OPENDCS 6.0 Initial Checkin
*
*  Revision 1.18  2013/07/12 13:06:24  mmaloney
*  Fix bug whereby LoadingApplication nodes was not saving or reading properties.
*
*  Revision 1.17  2013/03/21 18:27:40  mmaloney
*  DbKey Implementation
*
*/
package decodes.tsdb.xml;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.Iterator;

import opendcs.dai.TsGroupDAI;

import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;

import ilex.util.HasProperties;
import ilex.util.Logger;
import ilex.util.TextUtil;
import ilex.xml.DomHelper;
import ilex.xml.TaggedStringOwner;
import ilex.xml.TaggedStringSetter;
import ilex.xml.XmlHierarchyParser;
import ilex.xml.XmlObjectParser;
import ilex.xml.XmlOutputStream;
import decodes.sql.DbKey;
import decodes.tsdb.*;
import decodes.db.Constants;
import decodes.db.SiteName;
import decodes.db.DataType;

/**
XML Input/Output for Computational Meta Data.
*/
public class CompXio
	implements XmlObjectParser, TaggedStringOwner
{
	private static final org.slf4j.Logger log = LoggerFactory.getLogger(CompXio.class);
	private String module;
	private String filename;
	private TimeSeriesDb theDb = null;
	private static final int propertyTag = 0;
	private static final int commentTag = 1;
	
	private CompAppInfo workingObject = null;
	private String propName = null;

	/** Default constructor. */
	public CompXio(String module, TimeSeriesDb theDb)
	{
		this.module = module;
		this.theDb = theDb;
	}

	public ArrayList readStream(InputStream stream) throws DbXmlException
	{
		this.filename = "Provided Stream";
		Document doc;
		try
		{
			doc = DomHelper.readStream(module, stream);
		}
		catch(ilex.util.ErrorException ex)
		{
			throw new DbXmlException(ex.toString());
		}
		ArrayList metadata = new ArrayList();

		Node rootel = doc.getDocumentElement();
		if (rootel.getNodeName().equalsIgnoreCase(CompXioTags.loadingApplication))
		{
			addLoadingApplication(metadata, rootel);
			return metadata;
		}
		else if (!rootel.getNodeName().equalsIgnoreCase(CompXioTags.compMetaData))
		{
			String s = module 
				+ ": Wrong type of configuration file -- Cannot initialize. "
				+ "Root element is not '" + CompXioTags.compMetaData + "'.";
			Logger.instance().failure(s);
			throw new DbXmlException(s);
		}

		NodeList children = rootel.getChildNodes();
		for(int i=0; children != null && i readFile(String filename) throws DbXmlException
	{
		Logger.instance().info("CompXio.readFile(" + filename + ")");
		this.filename = filename;
		File file = new File(filename);
		try (InputStream in = new FileInputStream(file))
		{
			return this.readStream(in);
		}
		catch(IOException ex)
		{
			throw new DbXmlException("Unable to process " + filename, ex);
		}
	}

	private void addAlgorithm(ArrayList metadata, Node node)
	{
		// Get number and host attributes.
		Element elem = (Element)node;
//System.out.println("addAlgorithm nodename=" + node.getNodeName());
		String name = DomHelper.findAttr(elem, CompXioTags.name);
		if (name == null)
		{
			Logger.instance().warning(module + ": " + filename
				+ " Algorithm element without name attribute -- ignored.");
			return;
		}
		DbCompAlgorithm algo = new DbCompAlgorithm(Constants.undefinedId,
			name, null, null);

		NodeList children = node.getChildNodes();
		for(int i=0; children != null && i 0)
									lineb.insert(0, ' ');
								scriptBuilder.append(lineb);
								scriptBuilder.append("\n");
								// Add the indent
							}	
							else
							{
								Logger.instance().warning("Algorithm '" + name
									+ "' has an " + CompXioTags.algoScriptLine 
									+ " element with null content -- ignored.");
							}
						}
					}
					DbCompAlgorithmScript newScript = new DbCompAlgorithmScript(algo, 
						ScriptType.fromDbChar(scriptTypeStr.charAt(0)));
					newScript.addToText(scriptBuilder.toString());
					algo.putScript(newScript);
				}
				else
					Logger.instance().warning("Unrecognized element '"
						+ nn + "' ignored DRGS Config.");
			}
		}

		Logger.instance().debug2(module + " Adding algorithm " + name);
		metadata.add(algo);
	}

	private void addComputation(ArrayList metadata, Node node)
	{
		// Get number and host attributes.
		Element elem = (Element)node;
		String name = DomHelper.findAttr(elem, CompXioTags.name);
		if (name == null)
		{
			Logger.instance().warning(module + ": " + filename
				+ " Computation element without name attribute -- ignored.");
			return;
		}
		DbComputation comp = new DbComputation(Constants.undefinedId, name);

		NodeList children = node.getChildNodes();
		for(int i=0; children != null && i 0 ) 
//					{
//						for (DbKey j: tsGrp.getDataTypeIdList()) 
//						{
//							DataType dataType = DataType.getDataType(j);
//							if ((dataType.getStandard() == DomHelper.findAttr((Element)childNode, CompXioTags.standard)) &&
//									(dataType.getCode() == DomHelper.findAttr((Element)childNode, CompXioTags.code))) {
//								foundDataTypeId = true;
//								break;
//							}
//						}
//					}
//					if (!foundDataTypeId) {
//						String dataTypeStd = DomHelper.findAttr((Element)childNode, CompXioTags.standard);
//						String dataTypeCod = DomHelper.findAttr((Element)childNode, CompXioTags.code);
//						if (dataTypeCod == null) {
//							dataTypeCod = DomHelper.getTextContent((Element)childNode);
//						}
//						DataType dataType = DataType.getDataType(dataTypeStd, dataTypeCod);
//						
//						tsGrp.addDataTypeId(dataType.getId());
//					}
//				}
//				else if (nodeName.equalsIgnoreCase(CompXioTags.member)) {
//					String memberTyp = DomHelper.findAttr((Element)childNode, CompXioTags.type);
//					String memberVal = DomHelper.findAttr((Element)childNode, CompXioTags.value);
//					if (memberVal == null) {
//						memberVal = DomHelper.getTextContent((Element)childNode);
//					}
//					
//					tsGrp.addOtherMember(memberTyp, memberVal);
//				}
//			}
//		}
//		
//		// Load TsGroup to theDb
//		if (tsGrp.getGroupId() == Constants.undefinedId) 
//		{
//			TsGroupDAI groupDAO = theDb.makeTsGroupDAO();
//			try 
//			{
//				groupDAO.writeTsGroup(tsGrp);
//			}
//			catch (Exception E) 
//			{
//				System.out.println(E.toString());
//			}
//			finally
//			{
//				groupDAO.close();
//			}
//		}
//
//		// Set TsGroup to the computation 
//		comp.setGroup(tsGrp);
//	}
	
	/**
	 * @param metadata
	 * @param node
	 */
	private void addTsGroup(ArrayList metadata, Node node)
	{
		// Find the Group Name
		Element elem = (Element)node;
		String groupName = DomHelper.findAttr(elem, CompXioTags.name);
		if (groupName == null)
		{
			Logger.instance().warning(module + ": " + filename
				+ " " + CompXioTags.tsGroup + " element without " 
				+ CompXioTags.name + " attribute -- ignored.");
			return;
		}

		// Declare the tsGrp object
		TsGroup tsGrp = new TsGroup();
		tsGrp.setGroupName(groupName);
		
		// Reset the parameters of the tsGrp
		String nodeName;
		Node childNode;
		NodeList children = elem.getChildNodes();
		for(int i=0; children != null && i metadata, Node node)
	{
		// Get name attribute.
		Element elem = (Element)node;
		String name = DomHelper.findAttr(elem, CompXioTags.name);
		if (name == null)
		{
			Logger.instance().warning(module + ": " + filename
				+ " " + CompXioTags.loadingApplication
				+ " element without name attribute -- ignored.");
			return;
		}
		CompAppInfo info = new CompAppInfo(Constants.undefinedId);
		info.setAppName(name);
		Node commentNode = DomHelper.findNode(elem, CompXioTags.comment,
			Node.ELEMENT_NODE);
		if (commentNode != null)
			info.setComment(
				TextUtil.collapseWhitespace(
					DomHelper.getTextContent(commentNode)));

		NodeList children = node.getChildNodes();
		for(int i=0; children != null && i metadata, 
		String algoName)
	{
		for(CompMetaData obj : metadata)
		{
			if (obj instanceof DbCompAlgorithm)
			{
				DbCompAlgorithm algo = (DbCompAlgorithm)obj;
				if (algoName.equalsIgnoreCase(algo.getName()))
					return algo;
			}
		}
		return null;
	}

	/**
	 * Creates or overwrites the specified file, writing all of the objects
	 * found in 'metadata'.
	 * @param metadata the computational meta-data objects to write.
	 * @param filename the file name to write to.
	 */
	public void writeFile(ArrayList metadata, String filename)
		throws IOException
	{
		// Open an output stream wrapped by an XmlOutputStream
		FileOutputStream fos = new FileOutputStream(filename);
		XmlOutputStream xos = 
			new XmlOutputStream(fos, CompXioTags.compMetaData);
		xos.writeXmlHeader();

		xos.startElement(CompXioTags.compMetaData);
		for(CompMetaData mdObject : metadata)
		{
			if (mdObject instanceof DbComputation)
				writeComp(xos, (DbComputation)mdObject);
			else if (mdObject instanceof DbCompAlgorithm)
				writeAlgo(xos, (DbCompAlgorithm)mdObject);
			else if (mdObject instanceof CompAppInfo)
				writeApp(xos, (CompAppInfo)mdObject);
			else if (mdObject instanceof TsGroup)
				writeTsGrp(xos, (TsGroup)mdObject);
		}
		xos.endElement(CompXioTags.compMetaData);
		fos.close();
	}

	private void writeAlgo(XmlOutputStream xos, DbCompAlgorithm algo)
		throws IOException
	{
		xos.startElement(CompXioTags.algorithm, 
			CompXioTags.name, algo.getName());

		String s = algo.getComment();
		if (s != null)
			xos.writeElement(CompXioTags.comment, s);

		s = algo.getExecClass();
		if (s != null)
			xos.writeElement(CompXioTags.execClass, s);

		for(Enumeration en = algo.getPropertyNames(); en.hasMoreElements(); )
		{
			String propname = (String)en.nextElement();
			xos.writeElement(CompXioTags.algoProperty,
				CompXioTags.name, propname, algo.getProperty(propname));
		}

		for(Iterator it = algo.getParms(); it.hasNext(); )
		{
			DbAlgoParm dap = it.next();
			xos.startElement(CompXioTags.algoParm, 
				CompXioTags.roleName, dap.getRoleName());
			xos.writeElement(CompXioTags.parmType, dap.getParmType());
			xos.endElement(CompXioTags.algoParm);
		}
		
		for(ScriptType st : ScriptType.values())
		{
			DbCompAlgorithmScript script = algo.getScript(st);
			// Temporarily set width very wide to prevent script lines from wrapping
			// and inserting awkward spacing when read back in.
			int w = xos.width;
			xos.width = 200;
			if (script != null)
			{
				xos.startElement(CompXioTags.algoScript, CompXioTags.algoScriptType, ""+st.getDbChar());
				String scriptText = script.getText();
				BufferedReader bufReader = new BufferedReader(new StringReader(scriptText));
				String line = null;
				while((line = bufReader.readLine()) != null)
				{
					int indent = 0;
					for(int idx=0; idx it = comp.getParms(); it.hasNext(); )
		{
			DbCompParm dcp = it.next();
			xos.startElement(CompXioTags.compParm, 
				CompXioTags.roleName, dcp.getRoleName());

			xos.startElement(CompXioTags.siteDataType);
			for(SiteName sn : dcp.getSiteNames())
				xos.writeElement(CompXioTags.siteName,
					CompXioTags.nameType,  sn.getNameType(), 
					sn.getNameValue());
			DataType dataType = dcp.getDataType();
			if (dataType != null)
			{
				xos.writeElement(CompXioTags.dataType,
					CompXioTags.standard, dataType.getStandard(), 
					CompXioTags.code, dataType.getCode(), null);
			}
			else Logger.instance().warning("Role '" 
				+ dcp.getRoleName() + "' has no data type.");
			xos.endElement(CompXioTags.siteDataType);
	
			s = dcp.getInterval();
			if (s != null)
				xos.writeElement(CompXioTags.interval, s);

			s = dcp.getTableSelector();
			if (s != null)
				xos.writeElement(CompXioTags.tableSelector, s);

			int dt = dcp.getDeltaT();
			xos.writeElement(CompXioTags.deltaT, "" + dt);
			String dtu = dcp.getDeltaTUnits();
			if (dtu != null && dtu.trim().length() > 0)
				xos.writeElement(CompXioTags.deltaTUnits, dtu);

			int mid = dcp.getModelId();
			if (mid != Constants.undefinedIntKey)
				xos.writeElement(CompXioTags.modelId, "" + mid);

			xos.endElement(CompXioTags.compParm);
		}
		
		xos.endElement(CompXioTags.computation);
	}
	
	/**
	 * Write the TsGroup block into XML file if it exists
	 * 
	 * @param xos
	 * @param tsgrp
	 */
	private void writeTsGrp(XmlOutputStream xos, TsGroup tsgrp)
		throws IOException
	{
		if (tsgrp == null) { return; }

		//Expand the group members for each TS group
//		try
//		{
//			theDb.readTsGroupMembers(tsgrp);
//		}
//		catch (Exception E) {
//			System.out.println(E.toString());
//		}
		
		//Write the group elements for each TS group
		xos.startElement(CompXioTags.tsGroup, CompXioTags.name, tsgrp.getGroupName());
		xos.writeElement(CompXioTags.groupType, tsgrp.getGroupType());
		xos.writeElement(CompXioTags.description, tsgrp.getDescription());
//		xos.writeElement(CompXioTags.officeId, tsgrp.getDbOfficeId());
		for (TimeSeriesIdentifier tsId: tsgrp.getTsMemberList()) 
			xos.writeElement(CompXioTags.timeSeries, tsId.getUniqueString());
		for (DbKey i: tsgrp.getSiteIdList()) 
		{
			try 
			{
			  xos.writeElement(CompXioTags.siteName, (theDb.getSiteById(i)).getUniqueName());
			}
			catch (Exception E) {
				System.out.println(E.toString());
			}
		}
		DataType dataType;
		for (DbKey j: tsgrp.getDataTypeIdList()) 
		{
			dataType = DataType.getDataType(j);
			xos.writeElement(CompXioTags.dataType,
					CompXioTags.standard, dataType.getStandard(), 
					CompXioTags.code, dataType.getCode(), null);
		}
		for (TsGroupMember mem: tsgrp.getOtherMembers()) 
		{
			xos.writeElement(CompXioTags.member,
		  		CompXioTags.type, mem.getMemberType(),
		  		CompXioTags.value, mem.getMemberValue(), null);
		}
		for (TsGroup tsGrpId: tsgrp.getIncludedSubGroups()) 
		  xos.writeElement(CompXioTags.subGroup,
		  		CompXioTags.combine, "add", tsGrpId.getGroupName());
		for (TsGroup tsGrpId: tsgrp.getExcludedSubGroups()) 
		  xos.writeElement(CompXioTags.subGroup,
		  		CompXioTags.combine, "subtract", tsGrpId.getGroupName());
		for (TsGroup tsGrpId: tsgrp.getIntersectedGroups()) 
			  xos.writeElement(CompXioTags.subGroup,
			  		CompXioTags.combine, "intersect", tsGrpId.getGroupName());
		xos.endElement(CompXioTags.tsGroup);
	}

	@Override
	public void characters(char[] ch, int start, int length)
		throws SAXException
	{
		if (!TextUtil.isAllWhitespace(new String(ch, start, length)))
			throw new SAXException(
				"No character data expected within LoadingApplication");
	}

	@Override
	public void startElement(XmlHierarchyParser hier, String namespaceURI,
		String localName, String qname, Attributes atts) throws SAXException
	{
		if (localName.equalsIgnoreCase(CompXioTags.comment))
			hier.pushObjectParser(new TaggedStringSetter(this, commentTag));
		else if (localName.equalsIgnoreCase(CompXioTags.appProperty))
		{
			propName = atts.getValue(CompXioTags.name);
			if (propName == null)
				throw new SAXException(CompXioTags.appProperty
					+ " without " + CompXioTags.name +" attribute");
			hier.pushObjectParser(new TaggedStringSetter(this, propertyTag));
		}
	}

	@Override
	public void endElement(XmlHierarchyParser hier, String namespaceURI,
		String localName, String qname) throws SAXException
	{
		if (localName.equalsIgnoreCase(CompXioTags.loadingApplication))
			hier.popObjectParser();
		else
			throw new SAXException(
				"Parse stack corrupted: got end tag for " + localName
				+ ", expected " + CompXioTags.loadingApplication);
	}

	@Override
	public void ignorableWhitespace(char[] ch, int start, int length)
		throws SAXException
	{
	}

	@Override
	public void set(int tag, String value) throws SAXException
	{
		switch(tag)
		{
		case propertyTag:
			workingObject.getProperties().setProperty(propName, value);
			break;
		case commentTag:
			workingObject.setComment(value);
			break;
		}
	}

	/**
	 * When parsing a decodes database image with embedded LoadingApplication elements,
	 * the caller must set a working object for the SAX methods above.
	 * @param workingObject
	 */
	public void setWorkingObject(CompAppInfo workingObject)
	{
		this.workingObject = workingObject;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy