diff --git a/edexOsgi/build.edex/deploy-common/deploy-gfesuite.xml b/edexOsgi/build.edex/deploy-common/deploy-gfesuite.xml index e1789b9ce4..0d0876c744 100644 --- a/edexOsgi/build.edex/deploy-common/deploy-gfesuite.xml +++ b/edexOsgi/build.edex/deploy-common/deploy-gfesuite.xml @@ -24,6 +24,10 @@ + + + + diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/config/gfe/doConfig.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/config/gfe/doConfig.py index 0345db90d6..deee7c6c03 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/config/gfe/doConfig.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/config/gfe/doConfig.py @@ -405,16 +405,16 @@ def parseSat(satdirs): def otherParse(serverhost, mhsid, port, initmodules, accumElem, initskips, d2ddbver, logfilepurge, prddir, home, - extraWEPrec, autoConfigureNotifyTextProd, + extraWEPrec, vtecRequestTime, autoConfigureNotifyTextProd, iscRoutingTableAddress, requestedISCsites, requestISC, sendiscOnSave, sendiscOnPublish, requestedISCparms, transmitScript): if type(serverhost) != str: raise TypeError, "GFESUITE_HOST not an str: " + `serverhost` if type(mhsid) != str: raise TypeError, "GFESUITE_MHSID not an str: " + `mhsid` -# if type(vtecRequestTime) != int: -# raise TypeError, "VTECPartners: VTEC_REMOTE_TABLE_FETCH_TIME " + \ -# "not an int: " + `vtecRequestTime` + if type(vtecRequestTime) != int: + raise TypeError, "VTECPartners: VTEC_REMOTE_TABLE_FETCH_TIME " + \ + "not an int: " + `vtecRequestTime` if type(port) != int: raise TypeError, "GFESUITE_PORT not an int: " + `port` initmodules = dictCheck(initmodules, list, str, "INITMODULES") @@ -490,7 +490,7 @@ def otherParse(serverhost, mhsid, port, return serverhost, mhsid, \ port, initmodules, accumElem, \ initskips, d2ddbver, logfilepurge, prddir, home,\ - extraWEPrecision, \ + extraWEPrecision, vtecRequestTime, \ autoConfigureNotifyTextProd, \ iscRoutingTableAddress, reqISCsites, requestISC, sendiscOnSave, \ sendiscOnPublish, reqISCparms, transmitScript diff --git a/edexOsgi/build.edex/esb/data/utility/edex_static/base/config/gfe/serverConfig.py b/edexOsgi/build.edex/esb/data/utility/edex_static/base/config/gfe/serverConfig.py index 3acf5633db..dc1a688c3a 100644 --- a/edexOsgi/build.edex/esb/data/utility/edex_static/base/config/gfe/serverConfig.py +++ b/edexOsgi/build.edex/esb/data/utility/edex_static/base/config/gfe/serverConfig.py @@ -1885,7 +1885,7 @@ IFPConfigServer.allowTopoBelowZero = 1 def doIt(): # Import the local site configuration file (if it exists) import doConfig -# import VTECPartners + import VTECPartners (models, projections, vis, wx, desDef, allSites, domain, siteId, timeZone,officeTypes) = \ doConfig.parse(GFESUITE_SITEID, DATABASES, types, visibilities, SITES, allProjections) @@ -1910,6 +1910,7 @@ def doIt(): logFilePurgeAfter, \ prdDir, baseDir, \ extraWEPrecision, \ + tableFetchTime, \ autoConfigureNotifyTextProd, \ iscRoutingTableAddress, \ requestedISCsites, requestISC, \ @@ -1922,7 +1923,8 @@ def doIt(): D2DAccumulativeElements, INITSKIPS, D2DDBVERSIONS, LOG_FILE_PURGE_AFTER, GFESUITE_PRDDIR, GFESUITE_HOME, - ExtraWEPrecision, AUTO_CONFIGURE_NOTIFYTEXTPROD, ISC_ROUTING_TABLE_ADDRESS, + ExtraWEPrecision, VTECPartners.VTEC_REMOTE_TABLE_FETCH_TIME, + AUTO_CONFIGURE_NOTIFYTEXTPROD, ISC_ROUTING_TABLE_ADDRESS, REQUESTED_ISC_SITES, REQUEST_ISC, SEND_ISC_ON_SAVE, SEND_ISC_ON_PUBLISH, REQUESTED_ISC_PARMS, TRANSMIT_SCRIPT) IFPConfigServer.serverHost = serverHost @@ -1936,6 +1938,7 @@ def doIt(): IFPConfigServer.prdDir = prdDir IFPConfigServer.baseDir = baseDir IFPConfigServer.extraWEPrecision = extraWEPrecision + IFPConfigServer.tableFetchTime = tableFetchTime IFPConfigServer.autoConfigureNotifyTextProd = autoConfigureNotifyTextProd IFPConfigServer.iscRoutingTableAddress = iscRoutingTableAddress IFPConfigServer.requestedISCsites = requestedISCsites diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/.pydevproject b/edexOsgi/com.raytheon.edex.plugin.gfe/.pydevproject index faf12629d9..f4a659751e 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/.pydevproject +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/.pydevproject @@ -2,6 +2,6 @@ -python 2.5 +python 2.7 Default diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtServer.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtServer.py index 014d4d31a0..3757e514a9 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtServer.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/IrtServer.py @@ -18,7 +18,9 @@ # further licensing information. ## -import LogStream, siteConfig, tempfile, os, sys, JUtil, subprocess +import cPickle + +import LogStream, siteConfig, tempfile, os, sys, JUtil, subprocess, traceback import time, copy, string, iscUtil from com.raytheon.edex.plugin.gfe.isc import IRTManager @@ -34,6 +36,9 @@ from com.raytheon.edex.plugin.gfe.isc import IRTManager # Date Ticket# Engineer Description # ------------ ---------- ----------- -------------------------- # 07/14/09 1995 bphillip Initial Creation. +# 01/25/13 1447 dgilling Implement routines needed by +# iscDataRec for VTEC table +# sharing. # # # @@ -55,7 +60,121 @@ def logVerbose(*msg): def logDebug(*msg): logVerbose(iscUtil.tupleToString(*msg)) + +# called by iscDataRec when another site has requested the active table +# returns the active table, filtered, pickled. +def getVTECActiveTable(siteAndFilterInfo, xmlPacket): + import VTECPartners + if VTECPartners.VTEC_RESPOND_TO_TABLE_REQUESTS: + return #respond is disabled + #decode the data (pickled) + info = cPickle.loads(siteAndFilterInfo) + (mhsSite, reqsite, filterSites, countDict, issueTime) = info + + #get the active table, and write it to a temporary file + from com.raytheon.uf.common.site import SiteMap + from com.raytheon.uf.edex.activetable import ActiveTable + from com.raytheon.uf.common.activetable import ActiveTableMode + site4Id = SiteMap.getInstance().getSite4LetterId(siteConfig.GFESUITE_SITEID) + javaTable = ActiveTable.getActiveTable(site4Id, ActiveTableMode.OPERATIONAL) + dictTable = ActiveTable.convertToDict(javaTable, siteConfig.GFESUITE_SITEID) + + # we must convert this to a python hash using the A1 field naming conventions + # for cross-version compatibility + table = [] + for i in xrange(dictTable.size()): + convRecord = JUtil.javaObjToPyVal(dictTable.get(i)) + convRecord['oid'] = convRecord['officeid'] + convRecord['vstr'] = convRecord['vtecstr'] + convRecord['end'] = convRecord['endTime'] + convRecord['start'] = convRecord['startTime'] + convRecord['key'] = convRecord['phensig'] + # remove new fields so we don't pickle two copies + del convRecord['officeid'] + del convRecord['vtecstr'] + del convRecord['endTime'] + del convRecord['phensig'] + del convRecord['startTime'] + if convRecord.has_key('segText'): + convRecord['text'] = convRecord['segText'] + del convRecord['segText'] + table.append(convRecord) + + # additionally, we'll need to pickle our output to match the A1 file + # format + pickledTable = cPickle.dumps(table) + outDir = os.path.join(siteConfig.GFESUITE_PRDDIR, "ATBL") + with tempfile.NamedTemporaryFile(suffix='.ato', dir=outDir, delete=False) as fp: + fname = fp.name + fp.write(pickledTable) + + #write the xmlpacket to a temporary file, if one was passed + if xmlPacket is not None: + with tempfile.NamedTemporaryFile(suffix='.xml', delete=False) as fp: + fnameXML = fp.name + fp.write(xmlPacket) + + #call sendAT to send the table to the requestor + pid = os.fork() + if pid == 0: + cmd = os.path.join(siteConfig.GFESUITE_HOME, "bin", "sendAT") + args = [cmd, '-s', reqsite, '-a', mhsSite, '-H', ServerHost, + '-P', ServerPort, '-L', ServerProtocol, '-M', ServerMHS, + '-S', ServerSite, '-x', XmtScript] + if filterSites is not None: + for fs in filterSites: + args.append('-f') + args.append(fs) + if countDict is not None: + args.append('-c') + args.append(`countDict`) + if issueTime is not None: + args.append('-t') + args.append(`issueTime`) + args.append('-v') + args.append(fname) + if xmlPacket is not None: + args.append('-X') + args.append(fnameXML) + try: + os.execvp(cmd, args) + except: + logProblem("Error executing sendAT: ", traceback.format_exc()) + finally: + os._exit(0) + +#when we receive a requested active table from another site, this function +#is called from iscDataRec +def putVTECActiveTable(strTable, xmlPacket): + #write the xmlpacket to a temporary file, if one was passed + if xmlPacket is not None: + with tempfile.NamedTemporaryFile(suffix='.xml', delete=False) as fp: + fnameXML = fp.name + fp.write(xmlPacket) + + inDir = os.path.join(siteConfig.GFESUITE_PRDDIR, "ATBL") + with tempfile.NamedTemporaryFile(suffix='.ati', dir=inDir, delete=False) as fp: + fname = fp.name + fp.write(strTable) + + pid = os.fork() + if pid == 0: + cmd = os.path.join(siteConfig.GFESUITE_HOME, "bin", "ingestAT") + args = [] + args.append(cmd) + args.append("-f") + args.append(fname) + if xmlPacket is not None: + args.append('-X') + args.append(fnameXML) + try: + os.execvp(cmd, args) + except: + logProblem("Error executing ingestAT: ", traceback.format_exc()) + finally: + os._exit(0) + def initIRT(ancfURL, bncfURL, mhsid, serverHost, serverPort, serverProtocol, site, parmsWanted, gridDims, gridProj, gridBoundBox, iscWfosWanted): global IRTthread diff --git a/edexOsgi/com.raytheon.uf.common.activetable/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.activetable/META-INF/MANIFEST.MF index 7b81012aed..82082d6931 100644 --- a/edexOsgi/com.raytheon.uf.common.activetable/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.common.activetable/META-INF/MANIFEST.MF @@ -14,6 +14,8 @@ Import-Package: com.raytheon.uf.common.dataplugin.annotations, javax.persistence, org.hibernate.annotations, org.springframework.beans.factory.annotation -Export-Package: com.raytheon.uf.common.activetable +Export-Package: com.raytheon.uf.common.activetable, + com.raytheon.uf.common.activetable.request, + com.raytheon.uf.common.activetable.response Require-Bundle: com.raytheon.uf.common.serialization, com.raytheon.uf.common.message;bundle-version="1.12.1174" diff --git a/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/ActiveTableRecord.java b/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/ActiveTableRecord.java index 098ea3b13e..3328c3d31c 100644 --- a/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/ActiveTableRecord.java +++ b/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/ActiveTableRecord.java @@ -51,6 +51,7 @@ import com.vividsolutions.jts.geom.Geometry; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Mar 24, 2009 njensen Initial creation + * Feb 26, 2013 1447 dgilling Implement equals(). * * * @@ -217,6 +218,258 @@ public abstract class ActiveTableRecord extends PersistableDataObject { @Override public abstract Object clone(); + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ActiveTableRecord other = (ActiveTableRecord) obj; + if (act == null) { + if (other.act != null) { + return false; + } + } else if (!act.equals(other.act)) { + return false; + } + if (countyheader == null) { + if (other.countyheader != null) { + return false; + } + } else if (!countyheader.equals(other.countyheader)) { + return false; + } + if (endTime == null) { + if (other.endTime != null) { + return false; + } + } else if (!endTime.equals(other.endTime)) { + return false; + } + if (etn == null) { + if (other.etn != null) { + return false; + } + } else if (!etn.equals(other.etn)) { + return false; + } + if (floodBegin == null) { + if (other.floodBegin != null) { + return false; + } + } else if (!floodBegin.equals(other.floodBegin)) { + return false; + } + if (floodCrest == null) { + if (other.floodCrest != null) { + return false; + } + } else if (!floodCrest.equals(other.floodCrest)) { + return false; + } + if (floodEnd == null) { + if (other.floodEnd != null) { + return false; + } + } else if (!floodEnd.equals(other.floodEnd)) { + return false; + } + if (floodRecordStatus == null) { + if (other.floodRecordStatus != null) { + return false; + } + } else if (!floodRecordStatus.equals(other.floodRecordStatus)) { + return false; + } + if (floodSeverity == null) { + if (other.floodSeverity != null) { + return false; + } + } else if (!floodSeverity.equals(other.floodSeverity)) { + return false; + } + if (forecaster == null) { + if (other.forecaster != null) { + return false; + } + } else if (!forecaster.equals(other.forecaster)) { + return false; + } + if (geometry == null) { + if (other.geometry != null) { + return false; + } + } else if (!geometry.equalsExact(other.geometry)) { + return false; + } + if (immediateCause == null) { + if (other.immediateCause != null) { + return false; + } + } else if (!immediateCause.equals(other.immediateCause)) { + return false; + } + if (issueTime == null) { + if (other.issueTime != null) { + return false; + } + } else if (!issueTime.equals(other.issueTime)) { + return false; + } + if (loc == null) { + if (other.loc != null) { + return false; + } + } else if (!loc.equals(other.loc)) { + return false; + } + if (locationID == null) { + if (other.locationID != null) { + return false; + } + } else if (!locationID.equals(other.locationID)) { + return false; + } + if (motdir == null) { + if (other.motdir != null) { + return false; + } + } else if (!motdir.equals(other.motdir)) { + return false; + } + if (motspd == null) { + if (other.motspd != null) { + return false; + } + } else if (!motspd.equals(other.motspd)) { + return false; + } + if (officeid == null) { + if (other.officeid != null) { + return false; + } + } else if (!officeid.equals(other.officeid)) { + return false; + } + if (overviewText == null) { + if (other.overviewText != null) { + return false; + } + } else if (!overviewText.equals(other.overviewText)) { + return false; + } + if (phen == null) { + if (other.phen != null) { + return false; + } + } else if (!phen.equals(other.phen)) { + return false; + } + if (phensig == null) { + if (other.phensig != null) { + return false; + } + } else if (!phensig.equals(other.phensig)) { + return false; + } + if (pil == null) { + if (other.pil != null) { + return false; + } + } else if (!pil.equals(other.pil)) { + return false; + } + if (productClass == null) { + if (other.productClass != null) { + return false; + } + } else if (!productClass.equals(other.productClass)) { + return false; + } + if (purgeTime == null) { + if (other.purgeTime != null) { + return false; + } + } else if (!purgeTime.equals(other.purgeTime)) { + return false; + } + if (rawmessage == null) { + if (other.rawmessage != null) { + return false; + } + } else if (!rawmessage.equals(other.rawmessage)) { + return false; + } + if (region == null) { + if (other.region != null) { + return false; + } + } else if (!region.equals(other.region)) { + return false; + } + if (seg != other.seg) { + return false; + } + if (segText == null) { + if (other.segText != null) { + return false; + } + } else if (!segText.equals(other.segText)) { + return false; + } + if (sig == null) { + if (other.sig != null) { + return false; + } + } else if (!sig.equals(other.sig)) { + return false; + } + if (startTime == null) { + if (other.startTime != null) { + return false; + } + } else if (!startTime.equals(other.startTime)) { + return false; + } + if (ufn != other.ufn) { + return false; + } + if (ugcZone == null) { + if (other.ugcZone != null) { + return false; + } + } else if (!ugcZone.equals(other.ugcZone)) { + return false; + } + if (vtecstr == null) { + if (other.vtecstr != null) { + return false; + } + } else if (!vtecstr.equals(other.vtecstr)) { + return false; + } + if (wmoid == null) { + if (other.wmoid != null) { + return false; + } + } else if (!wmoid.equals(other.wmoid)) { + return false; + } + if (xxxid == null) { + if (other.xxxid != null) { + return false; + } + } else if (!xxxid.equals(other.xxxid)) { + return false; + } + return true; + } + /** * @return the wmoid */ diff --git a/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/UpdateActiveTableRequest.java b/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/UpdateActiveTableRequest.java deleted file mode 100644 index c2506060eb..0000000000 --- a/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/UpdateActiveTableRequest.java +++ /dev/null @@ -1,118 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.uf.common.activetable; - -import java.util.Map; - -import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; -import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; -import com.raytheon.uf.common.serialization.comm.IServerRequest; - -/** - * TODO Add Description - * - *
- * 
- * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Sep 13, 2010            wldougher     Initial creation
- * 
- * 
- * - * @author wldougher - * @version 1.0 - */ - -@DynamicSerialize -public class UpdateActiveTableRequest implements IServerRequest { - - @DynamicSerializeElement - private Map[] activeTable; - - @DynamicSerializeElement - private String xmlSource; - - @DynamicSerializeElement - private ActiveTableMode mode = ActiveTableMode.PRACTICE; - - @DynamicSerializeElement - private float timeOffset = 0.0f; - - /** - * @return the activeTable - */ - public Map[] getActiveTable() { - return activeTable; - } - - /** - * @param activeTable - * the activeTable to set - */ - public void setActiveTable(Map[] activeTable) { - this.activeTable = activeTable; - } - - /** - * @param xmlSource - */ - public void setXmlSource(String xmlSource) { - this.xmlSource = xmlSource; - } - - /** - * @return - */ - public String getXmlSource() { - return xmlSource; - } - - /** - * @param mode - * the mode to set - */ - public void setMode(ActiveTableMode mode) { - this.mode = mode; - } - - /** - * @return the mode - */ - public ActiveTableMode getMode() { - return mode; - } - - /** - * @param timeOffset - * the timeOffset to set - */ - public void setTimeOffset(float timeOffset) { - this.timeOffset = timeOffset; - } - - /** - * @return the timeOffset - */ - public float getTimeOffset() { - return timeOffset; - } - -} diff --git a/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/UpdateActiveTableResponse.java b/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/UpdateActiveTableResponse.java deleted file mode 100644 index 18c27b48fb..0000000000 --- a/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/UpdateActiveTableResponse.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.raytheon.uf.common.activetable; - -import java.util.List; - -import com.raytheon.uf.common.serialization.ISerializableObject; -import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; -import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; - -@DynamicSerialize -public class UpdateActiveTableResponse implements ISerializableObject { - - @DynamicSerializeElement - private List sourceInfo; - - @DynamicSerializeElement - private String message; - - /** - * @param sourceInfo - */ - public void setSourceInfo(List sourceInfo) { - this.sourceInfo = sourceInfo; - } - - /** - * @return - */ - public List getSourceInfo() { - return sourceInfo; - } - - /** - * @param message - * the message to set - */ - public void setMessage(String message) { - this.message = message; - } - - /** - * @return the message - */ - public String getMessage() { - return message; - } -} diff --git a/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/request/MergeActiveTableRequest.java b/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/request/MergeActiveTableRequest.java new file mode 100644 index 0000000000..81679804c3 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/request/MergeActiveTableRequest.java @@ -0,0 +1,191 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.activetable.request; + +import java.util.Map; + +import com.raytheon.uf.common.activetable.ActiveTableMode; +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; +import com.raytheon.uf.common.serialization.comm.IServerRequest; + +/** + * Request to merge in a provided collection of new active table entries to the + * specified active table using the legacy MergeVTEC logic. Used by CLI + * utilities ingestAT/MergeVTEC for active table sharing. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Sep 13, 2010            wldougher     Initial creation
+ * Feb 13, 2013   1447     dgilling     Added additional fields to 
+ *                                      better support VTEC table sharing.
+ * 
+ * 
+ * + * @author wldougher + * @version 1.0 + */ + +@DynamicSerialize +public class MergeActiveTableRequest implements IServerRequest { + + @DynamicSerializeElement + private Map[] incomingRecords; + + @DynamicSerializeElement + private String site; + + @DynamicSerializeElement + private ActiveTableMode tableName; + + @DynamicSerializeElement + private float timeOffset; + + @DynamicSerializeElement + private String xmlSource; + + @DynamicSerializeElement + private boolean fromIngestAT; + + @DynamicSerializeElement + private boolean makeBackups; + + /** + * No argument constructor. Not intended to be used by anyone, except + * DynamicSerialize. + */ + public MergeActiveTableRequest() { + this(null, ActiveTableMode.PRACTICE, null, 0.0f, null, false, true); + } + + /** + * Builds a MergeActiveTableRequest. + * + * @param incomingRecords + * Array containing active table entries in the python-style dict + * or Map format. + * @param tableName + * Table the new records will be merged into. + * @param site + * 3-char site id to perform the merge operation as. + * @param timeOffset + * For DRT; the number of seconds away from current time to use + * as the base time for the merge. + * @param xmlSource + * MHS XML data that contains who sent these active table + * records. + * @param fromIngestAT + * Whether to run ingestAT or MergeVTEC to perform the merge. + * @param makeBackups + * Whether to save a backup copy of the active table prior to the + * merge operation. + */ + public MergeActiveTableRequest(Map[] incomingRecords, + ActiveTableMode tableName, String site, float timeOffset, + String xmlSource, boolean fromIngestAT, boolean makeBackups) { + this.incomingRecords = incomingRecords; + this.tableName = tableName; + this.site = site; + this.timeOffset = timeOffset; + this.xmlSource = xmlSource; + this.fromIngestAT = fromIngestAT; + this.makeBackups = makeBackups; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("MergeActiveTableRequest [incomingRecords="); + builder.append(incomingRecords); + builder.append(", tableName="); + builder.append(tableName); + builder.append(", site="); + builder.append(site); + builder.append(", timeOffset="); + builder.append(timeOffset); + builder.append(", xmlSource="); + builder.append(xmlSource); + builder.append(", fromIngestAT="); + builder.append(fromIngestAT); + builder.append(", makeBackups="); + builder.append(makeBackups); + builder.append("]"); + return builder.toString(); + } + + public Map[] getIncomingRecords() { + return incomingRecords; + } + + public void setIncomingRecords(Map[] incomingRecords) { + this.incomingRecords = incomingRecords; + } + + public ActiveTableMode getTableName() { + return tableName; + } + + public void setTableName(ActiveTableMode tableName) { + this.tableName = tableName; + } + + public float getTimeOffset() { + return timeOffset; + } + + public void setTimeOffset(float timeOffset) { + this.timeOffset = timeOffset; + } + + public String getXmlSource() { + return xmlSource; + } + + public void setXmlSource(String xmlSource) { + this.xmlSource = xmlSource; + } + + public void setFromIngestAT(boolean fromIngestAT) { + this.fromIngestAT = fromIngestAT; + } + + public boolean isFromIngestAT() { + return fromIngestAT; + } + + public void setMakeBackups(boolean makeBackups) { + this.makeBackups = makeBackups; + } + + public boolean isMakeBackups() { + return makeBackups; + } + + public void setSite(String site) { + this.site = site; + } + + public String getSite() { + return site; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/request/RetrieveRemoteActiveTableRequest.java b/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/request/RetrieveRemoteActiveTableRequest.java new file mode 100644 index 0000000000..84526a9637 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/request/RetrieveRemoteActiveTableRequest.java @@ -0,0 +1,199 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.activetable.request; + +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; +import com.raytheon.uf.common.serialization.comm.IServerRequest; + +/** + * Request to run the requestAT utility, which will send messages over the MHS + * to neighboring sites for their active table entries that are relevant to this + * site. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 6, 2013            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +@DynamicSerialize +public class RetrieveRemoteActiveTableRequest implements IServerRequest { + + @DynamicSerializeElement + private String serverHost; + + @DynamicSerializeElement + private int serverPort; + + @DynamicSerializeElement + private String serverProtocol; + + @DynamicSerializeElement + private String mhsId; + + @DynamicSerializeElement + private String siteId; + + @DynamicSerializeElement + private String ancfAddress; + + @DynamicSerializeElement + private String bncfAddress; + + @DynamicSerializeElement + private String transmitScript; + + /** + * No argument constructor. Not intended to be used by anyone, except + * DynamicSerialize. + */ + public RetrieveRemoteActiveTableRequest() { + // no-op + } + + /** + * Build a RetrieveRemoteActiveTableRequest. + * + * @param serverHost + * Host name of system running requestAT. + * @param serverPort + * Port upon which system runs. + * @param serverProtocol + * MHS protocol string for server. + * @param mhsId + * MHS ID of this system. + * @param siteId + * Site ID of this system. + * @param ancfAddress + * Configured ANCF URL. + * @param bncfAddress + * Configured BNCF URL. + * @param transmitScript + * Command to run to transmit requestAT output over MHS. + */ + public RetrieveRemoteActiveTableRequest(String serverHost, int serverPort, + String serverProtocol, String mhsId, String siteId, + String ancfAddress, String bncfAddress, String transmitScript) { + this.serverHost = serverHost; + this.serverPort = serverPort; + this.serverProtocol = serverProtocol; + this.mhsId = mhsId; + this.siteId = siteId; + this.ancfAddress = ancfAddress; + this.bncfAddress = bncfAddress; + this.transmitScript = transmitScript; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("RetrieveRemoteActiveTableRequest [serverHost="); + builder.append(serverHost); + builder.append(", serverPort="); + builder.append(serverPort); + builder.append(", serverProtocol="); + builder.append(serverProtocol); + builder.append(", mhsId="); + builder.append(mhsId); + builder.append(", siteId="); + builder.append(siteId); + builder.append(", ancfAddress="); + builder.append(ancfAddress); + builder.append(", bncfAddress="); + builder.append(bncfAddress); + builder.append(", transmitScript="); + builder.append(transmitScript); + builder.append("]"); + return builder.toString(); + } + + public String getServerHost() { + return serverHost; + } + + public void setServerHost(String serverHost) { + this.serverHost = serverHost; + } + + public int getServerPort() { + return serverPort; + } + + public void setServerPort(int serverPort) { + this.serverPort = serverPort; + } + + public String getServerProtocol() { + return serverProtocol; + } + + public void setServerProtocol(String serverProtocol) { + this.serverProtocol = serverProtocol; + } + + public String getMhsId() { + return mhsId; + } + + public void setMhsId(String mhsId) { + this.mhsId = mhsId; + } + + public String getSiteId() { + return siteId; + } + + public void setSiteId(String siteId) { + this.siteId = siteId; + } + + public String getAncfAddress() { + return ancfAddress; + } + + public void setAncfAddress(String ancfAddress) { + this.ancfAddress = ancfAddress; + } + + public String getBncfAddress() { + return bncfAddress; + } + + public void setBncfAddress(String bncfAddress) { + this.bncfAddress = bncfAddress; + } + + public String getTransmitScript() { + return transmitScript; + } + + public void setTransmitScript(String transmitScript) { + this.transmitScript = transmitScript; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/request/SendActiveTableRequest.java b/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/request/SendActiveTableRequest.java new file mode 100644 index 0000000000..d84b6c9f35 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/request/SendActiveTableRequest.java @@ -0,0 +1,286 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.activetable.request; + +import java.util.List; +import java.util.Map; + +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; +import com.raytheon.uf.common.serialization.comm.IServerRequest; + +/** + * Request to run the utility sendAT, which will send active table entries + * relevant to the specified sites via MHS. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 6, 2013            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +@DynamicSerialize +public class SendActiveTableRequest implements IServerRequest { + + @DynamicSerializeElement + private String serverHost; + + @DynamicSerializeElement + private Integer serverPort; + + @DynamicSerializeElement + private String serverProtocol; + + @DynamicSerializeElement + private String serverSite; + + @DynamicSerializeElement + private String mhsId; + + @DynamicSerializeElement + private List sites; + + @DynamicSerializeElement + private List filterSites; + + @DynamicSerializeElement + private List mhsSites; + + @DynamicSerializeElement + private Float issueTime; + + @DynamicSerializeElement + private Map countDict; + + @DynamicSerializeElement + private String fileName; + + @DynamicSerializeElement + private String xmlIncoming; + + @DynamicSerializeElement + private String transmitScript; + + /** + * No argument constructor. Not intended to be used by anyone, except + * DynamicSerialize. + */ + public SendActiveTableRequest() { + // no-op + } + + /** + * Builds a SendActiveTableRequest. + * + * @param serverHost + * Host name of system running sendAT. + * @param serverPort + * Port upon which system runs. + * @param serverProtocol + * MHS protocol string for server. + * @param serverSite + * Site ID of this system. + * @param mhsId + * MHS ID of this system. + * @param sites + * Sites to collect active table entries for. + * @param filterSites + * Sites to filter out of active table entries. + * @param mhsSites + * optional field for legacy systems. MHS IDs of server to send + * results to. + * @param issueTime + * Time request was made. Epoch time in seconds. + * @param countDict + * Counts of records requesting server has for each site in + * sites. + * @param fileName + * File name containing records to send out. + * @param xmlIncoming + * MHS XML data about the request. + * @param transmitScript + * Command to run to send results via MHS. + */ + public SendActiveTableRequest(String serverHost, int serverPort, + String serverProtocol, String serverSite, String mhsId, + List sites, List filterSites, + List mhsSites, float issueTime, + Map countDict, String fileName, + String xmlIncoming, String transmitScript) { + this.serverHost = serverHost; + this.serverPort = serverPort; + this.serverProtocol = serverProtocol; + this.serverSite = serverSite; + this.mhsId = mhsId; + this.sites = sites; + this.filterSites = filterSites; + this.mhsSites = mhsSites; + this.issueTime = issueTime; + this.countDict = countDict; + this.fileName = fileName; + this.xmlIncoming = xmlIncoming; + this.transmitScript = transmitScript; + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("SendActiveTableRequest [serverHost="); + builder.append(serverHost); + builder.append(", serverPort="); + builder.append(serverPort); + builder.append(", serverProtocol="); + builder.append(serverProtocol); + builder.append(", serverSite="); + builder.append(serverSite); + builder.append(", mhsId="); + builder.append(mhsId); + builder.append(", sites="); + builder.append(sites); + builder.append(", filterSites="); + builder.append(filterSites); + builder.append(", mhsSites="); + builder.append(mhsSites); + builder.append(", issueTime="); + builder.append(issueTime); + builder.append(", countDict="); + builder.append(countDict); + builder.append(", fileName="); + builder.append(fileName); + builder.append(", xmlIncoming="); + builder.append(xmlIncoming); + builder.append(", transmitScript="); + builder.append(transmitScript); + builder.append("]"); + return builder.toString(); + } + + public String getServerHost() { + return serverHost; + } + + public void setServerHost(String serverHost) { + this.serverHost = serverHost; + } + + public Integer getServerPort() { + return serverPort; + } + + public void setServerPort(Integer serverPort) { + this.serverPort = serverPort; + } + + public String getServerProtocol() { + return serverProtocol; + } + + public void setServerProtocol(String serverProtocol) { + this.serverProtocol = serverProtocol; + } + + public String getServerSite() { + return serverSite; + } + + public void setServerSite(String serverSite) { + this.serverSite = serverSite; + } + + public String getMhsId() { + return mhsId; + } + + public void setMhsId(String mhsId) { + this.mhsId = mhsId; + } + + public List getSites() { + return sites; + } + + public void setSites(List sites) { + this.sites = sites; + } + + public List getFilterSites() { + return filterSites; + } + + public void setFilterSites(List filterSites) { + this.filterSites = filterSites; + } + + public List getMhsSites() { + return mhsSites; + } + + public void setMhsSites(List mhsSites) { + this.mhsSites = mhsSites; + } + + public Float getIssueTime() { + return issueTime; + } + + public void setIssueTime(Float issueTime) { + this.issueTime = issueTime; + } + + public Map getCountDict() { + return countDict; + } + + public void setCountDict(Map countDict) { + this.countDict = countDict; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getXmlIncoming() { + return xmlIncoming; + } + + public void setXmlIncoming(String xmlIncoming) { + this.xmlIncoming = xmlIncoming; + } + + public String getTransmitScript() { + return transmitScript; + } + + public void setTransmitScript(String transmitScript) { + this.transmitScript = transmitScript; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/response/ActiveTableSharingResponse.java b/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/response/ActiveTableSharingResponse.java new file mode 100644 index 0000000000..0ca0a54290 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.activetable/src/com/raytheon/uf/common/activetable/response/ActiveTableSharingResponse.java @@ -0,0 +1,86 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.activetable.response; + +import com.raytheon.uf.common.serialization.ISerializableObject; +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + +/** + * Response for the following active table sharing request types: + *
    + *
  • MergeActiveTableRequest + *
  • RetrieveRemoteActiveTableRequest + *
  • SendActiveTableRequest + *
+ * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 27, 2013            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +@DynamicSerialize +public class ActiveTableSharingResponse implements ISerializableObject { + + @DynamicSerializeElement + private boolean taskSuccess; + + @DynamicSerializeElement + private String errorMessage; + + /** + * Build an ActiveTableSharingResponse. + * + * @param taskSuccess + * Whether the task tied to the request succeeded. + * @param errorMessage + * Any status/error messages that could be returned relevant to + * the task. + */ + public ActiveTableSharingResponse(boolean taskSuccess, String errorMessage) { + this.taskSuccess = taskSuccess; + this.errorMessage = errorMessage; + } + + public boolean isTaskSuccess() { + return taskSuccess; + } + + public void setTaskSuccess(boolean taskSuccess) { + this.taskSuccess = taskSuccess; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/python/GfePyIncludeUtil.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/python/GfePyIncludeUtil.java index 697a3f3566..3b157e7abe 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/python/GfePyIncludeUtil.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/python/GfePyIncludeUtil.java @@ -19,16 +19,13 @@ **/ package com.raytheon.uf.common.dataplugin.gfe.python; -import java.util.HashMap; -import java.util.Map; -import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.LocalizationContext; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; import com.raytheon.uf.common.localization.LocalizationFile; -import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.python.PyUtil; +import com.raytheon.uf.common.python.PythonIncludePathUtil; import com.raytheon.uf.common.util.FileUtil; /** @@ -40,15 +37,14 @@ import com.raytheon.uf.common.util.FileUtil; * ------------ ---------- ----------- -------------------------- * Oct 9, 2008 njensen Initial creation * Sep 18, 2012 #1091 randerso added base directory to getGfeConfigIncludePath + * Feb 27, 2013 #1447 dgilling Re-factor based on PythonPathIncludeUtil. * * * @author njensen * @version 1.0 */ -public class GfePyIncludeUtil { - - public static final String PYTHON = "python"; +public class GfePyIncludeUtil extends PythonIncludePathUtil { public static final String GFE = "gfe"; @@ -99,33 +95,6 @@ public class GfePyIncludeUtil { public static final String VCMOD_UTILS = FileUtil .join(VCMODULES, "utility"); - private static final IPathManager PATH_MANAGER = PathManagerFactory - .getPathManager(); - - private static Map> pathMap = new HashMap>(); - - private static String getPath(LocalizationContext ctx, String locPath) { - Map ctxMap = pathMap.get(ctx); - if (ctxMap == null) { - ctxMap = new HashMap(); - pathMap.put(ctx, ctxMap); - } - String fsPath = ctxMap.get(locPath); - if (fsPath == null) { - LocalizationFile file = PATH_MANAGER.getLocalizationFile(ctx, - locPath); - fsPath = file.getFile().getAbsolutePath(); - ctxMap.put(locPath, fsPath); - } - return fsPath; - } - - // LocalizationFile getters - - public static LocalizationFile getCommonPythonLF(LocalizationContext ctx) { - return PATH_MANAGER.getLocalizationFile(ctx, PYTHON); - } - public static LocalizationFile getCommonGfeLF(LocalizationContext ctx) { return PATH_MANAGER.getLocalizationFile(ctx, COMMON_GFE); } @@ -189,11 +158,6 @@ public class GfePyIncludeUtil { // Include Path getters - public static String getCommonPythonIncludePath() { - return getPath(PATH_MANAGER.getContext(LocalizationType.COMMON_STATIC, - LocalizationLevel.BASE), PYTHON); - } - public static String getCommonGfeIncludePath() { String pythonDir = getCommonPythonIncludePath(); String gfeDir = getPath(PATH_MANAGER.getContext( diff --git a/edexOsgi/com.raytheon.uf.common.python/src/com/raytheon/uf/common/python/PythonIncludePathUtil.java b/edexOsgi/com.raytheon.uf.common.python/src/com/raytheon/uf/common/python/PythonIncludePathUtil.java new file mode 100644 index 0000000000..9e7a37f487 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.python/src/com/raytheon/uf/common/python/PythonIncludePathUtil.java @@ -0,0 +1,83 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.common.python; + +import java.util.HashMap; +import java.util.Map; + +import com.raytheon.uf.common.localization.IPathManager; +import com.raytheon.uf.common.localization.LocalizationContext; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; +import com.raytheon.uf.common.localization.LocalizationFile; +import com.raytheon.uf.common.localization.PathManagerFactory; + +/** + * Utility for getting python directories to include. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 27, 2013            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class PythonIncludePathUtil { + + protected static final IPathManager PATH_MANAGER = PathManagerFactory + .getPathManager(); + + private static Map> pathMap = new HashMap>(); + + public static final String PYTHON = "python"; + + protected static String getPath(LocalizationContext ctx, String locPath) { + Map ctxMap = pathMap.get(ctx); + if (ctxMap == null) { + ctxMap = new HashMap(); + pathMap.put(ctx, ctxMap); + } + String fsPath = ctxMap.get(locPath); + if (fsPath == null) { + LocalizationFile file = PATH_MANAGER.getLocalizationFile(ctx, + locPath); + fsPath = file.getFile().getAbsolutePath(); + ctxMap.put(locPath, fsPath); + } + return fsPath; + } + + public static LocalizationFile getCommonPythonLF(LocalizationContext ctx) { + return PATH_MANAGER.getLocalizationFile(ctx, PYTHON); + } + + public static String getCommonPythonIncludePath() { + return getPath(PATH_MANAGER.getContext(LocalizationType.COMMON_STATIC, + LocalizationLevel.BASE), PYTHON); + } + +} diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/.pydevproject b/edexOsgi/com.raytheon.uf.edex.activetable/.pydevproject index faf12629d9..f4a659751e 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/.pydevproject +++ b/edexOsgi/com.raytheon.uf.edex.activetable/.pydevproject @@ -2,6 +2,6 @@ -python 2.5 +python 2.7 Default diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/res/spring/activetable-request.xml b/edexOsgi/com.raytheon.uf.edex.activetable/res/spring/activetable-request.xml index 8191ddb92f..f6a991af5d 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/res/spring/activetable-request.xml +++ b/edexOsgi/com.raytheon.uf.edex.activetable/res/spring/activetable-request.xml @@ -46,16 +46,28 @@ - - - - - - + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTable.java b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTable.java index fe00585ac8..a07cdd55fd 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTable.java +++ b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTable.java @@ -51,6 +51,7 @@ import com.raytheon.uf.common.site.SiteMap; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.util.FileUtil; import com.raytheon.uf.edex.core.EDEXUtil; import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.cluster.ClusterLockUtils; @@ -75,7 +76,9 @@ import com.vividsolutions.jts.geom.Geometry; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Mar 17, 2009 njensen Initial creation - * Dec 21, 2009 4055 njensen Queued thread for updates + * Dec 21, 2009 4055 njensen Queued thread for updates + * Feb 26, 2013 1447 dgilling Add routine to use MergeVTEC as basis + * for merge logic. * * * @@ -290,7 +293,7 @@ public class ActiveTable { updateTable(siteId, result, mode); if (result.changeList.size() > 0) { - sendNotification(mode, result.changeList); + sendNotification(mode, result.changeList, "VTECDecoder"); } } } @@ -339,12 +342,13 @@ public class ActiveTable { return result; } - private void sendNotification(ActiveTableMode mode, List changes) { + private static void sendNotification(ActiveTableMode mode, + List changes, String source) { Date modTime = new Date(); // VTECTableChangeNotifier.send(mode, modTime, "VTECDecoder", changes); try { VTECTableChangeNotification notification = new VTECTableChangeNotification( - mode, modTime, "VTECDecoder", + mode, modTime, source, changes.toArray(new VTECChange[changes.size()])); // System.out.println("Sending VTECTableChangeNotification:" // + notification); @@ -427,7 +431,7 @@ public class ActiveTable { * @param changes * the updated table followed by the purged records */ - private void updateTable(String siteId, MergeResult changes, + private static void updateTable(String siteId, MergeResult changes, ActiveTableMode mode) { synchronized (ActiveTable.class) { List updated = changes.updatedList; @@ -468,6 +472,99 @@ public class ActiveTable { return exc; } + /** + * Merges the specified new active table records into the active table using + * the legacy MergeVTEC logic (which is different than the legacy logic in + * ActiveTable.py used elsewhere). + * + * @param siteId + * Site ID to perform the merge as. + * @param tableName + * Table to merge the records into. + * @param newRecords + * The incoming new records to merge. + * @param timeOffset + * For DRT; number of seconds from current time to use as base + * time for the merge. + * @param makeBackup + * Whether or not to make a backup of the active table prior to + * the merge. + * @param runIngestAT + * Whether this merge will be performed as ingestAT or MergeVTEC + * (has minor logging effects). + * @param xmlSource + * Only required when runIngestAT is true; XML data + * from MHS about source of new records. + * @throws JepException + * If an unhandled exception is encountered in the python code + * executed. + */ + public static void mergeRemoteTable(String siteId, + ActiveTableMode tableName, List newRecords, + float timeOffset, boolean makeBackup, boolean runIngestAT, + String xmlSource) throws JepException { + MergeResult result = null; + PythonScript script = null; + try { + String scriptName = runIngestAT ? "ingestAT.py" : "MergeVTEC.py"; + IPathManager pathMgr = PathManagerFactory.getPathManager(); + LocalizationContext commonCx = pathMgr.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.BASE); + String scriptPath = pathMgr.getFile(commonCx, + FileUtil.join(ActiveTablePyIncludeUtil.VTEC, scriptName)) + .getPath(); + String pythonIncludePath = PyUtil.buildJepIncludePath( + ActiveTablePyIncludeUtil.getCommonPythonIncludePath(), + ActiveTablePyIncludeUtil.getVtecIncludePath(siteId), + ActiveTablePyIncludeUtil.getGfeConfigIncludePath(siteId), + ActiveTablePyIncludeUtil.getIscScriptsIncludePath()); + + try { + script = new PythonScript(scriptPath, pythonIncludePath, + ActiveTable.class.getClassLoader()); + } catch (JepException e) { + statusHandler.handle(Priority.PROBLEM, + "Error initializing ingestAT or MergeVTEC python", e); + throw e; + } + + try { + String site4Char = SiteMap.getInstance().getSite4LetterId( + siteId); + List activeTable = getActiveTable(site4Char, + tableName); + HashMap args = new HashMap(); + args.put("activeTable", activeTable); + args.put("activeTableMode", tableName.toString()); + args.put("newRecords", newRecords); + args.put("drt", timeOffset); + args.put("makeBackups", makeBackup); + if (runIngestAT) { + args.put("xmlIncoming", xmlSource); + } + + String methodName = runIngestAT ? "runFromJava" : "merge"; + result = (MergeResult) script.execute(methodName, args); + } catch (JepException e) { + statusHandler.handle(Priority.PROBLEM, + "Error merging active table", e); + throw e; + } + } finally { + if (script != null) { + script.dispose(); + script = null; + } + } + + if (result != null) { + updateTable(siteId, result, tableName); + if (!result.changeList.isEmpty()) { + sendNotification(tableName, result.changeList, "MergeVTEC"); + } + } + } + public void dispose() { python.dispose(); } diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTablePyIncludeUtil.java b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTablePyIncludeUtil.java new file mode 100644 index 0000000000..624e1c668b --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/ActiveTablePyIncludeUtil.java @@ -0,0 +1,77 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.edex.activetable; + +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; +import com.raytheon.uf.common.python.PyUtil; +import com.raytheon.uf.common.python.PythonIncludePathUtil; +import com.raytheon.uf.common.util.FileUtil; + +/** + * Utility for getting python directories to include. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 27, 2013            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class ActiveTablePyIncludeUtil extends PythonIncludePathUtil { + + public static final String GFE = "gfe"; + + public static final String GFE_CONFIG = FileUtil.join("config", GFE); + + public static final String ISC = FileUtil.join(GFE, "isc"); + + public static final String VTEC = "vtec"; + + public static String getGfeConfigIncludePath(String siteId) { + String baseConfigDir = getPath(PATH_MANAGER.getContext( + LocalizationType.EDEX_STATIC, LocalizationLevel.BASE), + GFE_CONFIG); + String siteConfigDir = getPath(PATH_MANAGER.getContextForSite( + LocalizationType.EDEX_STATIC, siteId), GFE_CONFIG); + return PyUtil.buildJepIncludePath(siteConfigDir, baseConfigDir); + } + + public static String getIscScriptsIncludePath() { + return getPath(PATH_MANAGER.getContext(LocalizationType.EDEX_STATIC, + LocalizationLevel.BASE), ISC); + } + + public static String getVtecIncludePath(String siteId) { + String baseDir = getPath(PATH_MANAGER.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.BASE), VTEC); + String siteDir = getPath(PATH_MANAGER.getContextForSite( + LocalizationType.COMMON_STATIC, siteId), VTEC); + return PyUtil.buildJepIncludePath(siteDir, baseDir); + } + +} diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/UpdateActiveTableHandler.java b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/handler/MergeActiveTableHandler.java similarity index 68% rename from edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/UpdateActiveTableHandler.java rename to edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/handler/MergeActiveTableHandler.java index 0857594e9e..a91b39d7cb 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/UpdateActiveTableHandler.java +++ b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/handler/MergeActiveTableHandler.java @@ -17,34 +17,36 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.uf.edex.activetable; +package com.raytheon.uf.edex.activetable.handler; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Calendar; -import java.util.Collections; -import java.util.Comparator; import java.util.GregorianCalendar; import java.util.List; import java.util.Map; +import jep.JepException; + import com.raytheon.uf.common.activetable.ActiveTableMode; import com.raytheon.uf.common.activetable.ActiveTableRecord; import com.raytheon.uf.common.activetable.OperationalActiveTableRecord; import com.raytheon.uf.common.activetable.PracticeActiveTableRecord; -import com.raytheon.uf.common.activetable.UpdateActiveTableRequest; -import com.raytheon.uf.common.activetable.UpdateActiveTableResponse; +import com.raytheon.uf.common.activetable.request.MergeActiveTableRequest; +import com.raytheon.uf.common.activetable.response.ActiveTableSharingResponse; import com.raytheon.uf.common.serialization.comm.IRequestHandler; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.edex.activetable.ActiveTable; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.io.ParseException; import com.vividsolutions.jts.io.WKTReader; /** - * Handler for UpdateActiveTableRequests. This is the server-side portion of the - * ingestAT application. + * Handler for + * MergeActiveTableRequests. This is the server-side portion of the + * ingestAT/MergeVTEC applications. * *
  * 
@@ -54,6 +56,8 @@ import com.vividsolutions.jts.io.WKTReader;
  * Sep 13, 2010            wldougher     Initial creation
  * Aug 20, 2012  #1084     dgilling      Properly zero pad incoming
  *                                       ETN values.
+ * Feb 26, 2013  #1447     dgilling      Rewrite based on MergeActiveTableRequest
+ *                                       and use MergeVTEC.py to perform merge.
  * 
  * 
* @@ -61,10 +65,10 @@ import com.vividsolutions.jts.io.WKTReader; * @version 1.0 */ -public class UpdateActiveTableHandler implements - IRequestHandler { +public class MergeActiveTableHandler implements + IRequestHandler { private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(UpdateActiveTableHandler.class); + .getHandler(MergeActiveTableHandler.class); /** * Handle a request to update the active table with a list of records. The @@ -74,100 +78,39 @@ public class UpdateActiveTableHandler implements * @see com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest(com.raytheon.uf.common.serialization.comm.IServerRequest) */ @Override - public Object handleRequest(UpdateActiveTableRequest request) - throws Exception { - StringBuilder sb = new StringBuilder(); - Float timeOffset = request.getTimeOffset(); - - Map[] activeTableMap = request.getActiveTable(); - ActiveTableMode mode = request.getMode(); + public ActiveTableSharingResponse handleRequest( + MergeActiveTableRequest request) throws Exception { + Map[] activeTableMap = request.getIncomingRecords(); + ActiveTableMode mode = request.getTableName(); statusHandler.handle(Priority.INFO, "Received UpdateActiveTable request containing " + activeTableMap.length + " maps."); - List records = null; + List records; try { records = mapToRecords(activeTableMap, mode); } catch (Exception e) { - statusHandler.handle(Priority.PROBLEM, - "The mapToRecords() call failed.", e); - sb.append(e.getLocalizedMessage()); - for (StackTraceElement ste : e.getStackTrace()) { - sb.append(ste.toString() + "\n"); - } + // already logged this below, just returning failed status + return new ActiveTableSharingResponse(false, + "Error executing converting incoming records: " + + e.getLocalizedMessage()); } - if (sb.length() == 0) { - - // Records may have entries for more than one site ID (officeid). - // However, the merge() method of ActiveTable assumes it will only - // get records for a single site. So some sorting and slicing of the - // list has to be done. - class OidComparator implements Comparator { - /** - * Comparator for sorting ActiveTableRecords by office id. - * - * @see java.util.Comparator#compare(java.lang.Object, - * java.lang.Object) - */ - @Override - public int compare(ActiveTableRecord o1, ActiveTableRecord o2) { - return o1.getOfficeid().compareTo(o2.getOfficeid()); - } - } - OidComparator comparator = new OidComparator(); - Collections.sort(records, comparator); - - // Create an active table instance to perform the merge - ActiveTable table = new ActiveTable(); - // A sublist of records, all for the same site - List siteRecords = null; - // A dummy record for use with binarySearch - ActiveTableRecord key = new PracticeActiveTableRecord(); - // The index of the first record with a different site ID - int nextIdx = -1; - - while (records.size() > 0) { - // Get a sublist with identical site IDs - key.setOfficeid(records.get(0).getOfficeid() + " "); - nextIdx = Collections.binarySearch(records, key, comparator); - if (nextIdx < 0) { - nextIdx = -(nextIdx + 1); - } - siteRecords = records.subList(0, nextIdx); - // Merge all the records for the site - Exception exc = table.merge(siteRecords, timeOffset); - if (exc != null) { - statusHandler.handle(Priority.PROBLEM, - "table.merge() returned an error.", exc); - sb.append(exc.getLocalizedMessage()); - for (StackTraceElement ste : exc.getStackTrace()) { - sb.append(ste.toString() + "\n"); - } - break; - } - // Remove the processed records - records = records.subList(nextIdx, records.size()); - } - + String xmlSource = request.isFromIngestAT() ? request.getXmlSource() + : null; + try { + ActiveTable.mergeRemoteTable(request.getSite(), + request.getTableName(), records, request.getTimeOffset(), + request.isMakeBackups(), request.isFromIngestAT(), + xmlSource); + } catch (JepException e) { + // already logged this in ActiveTable, just returning failed status + return new ActiveTableSharingResponse(false, + "Error performing merge: " + e.getLocalizedMessage()); } - String xmlSource = request.getXmlSource(); - List sourceInfo = null; - if (xmlSource != null && !("".equals(xmlSource.trim()))) { - ServerInfoExtractor infoExtractor = new ServerInfoExtractor(); - sourceInfo = infoExtractor.extract(xmlSource); - } - - // Tell the user we finished processing. - // The merge() method handles its own error reporting, we get no status - UpdateActiveTableResponse response = new UpdateActiveTableResponse(); - response.setSourceInfo(sourceInfo); - if (sb.length() > 0) { - response.setMessage(sb.toString()); - } - return response; + return new ActiveTableSharingResponse(true, null); } /** @@ -178,9 +121,11 @@ public class UpdateActiveTableHandler implements * @param activeTableMap * @param mode * @return + * @throws Exception */ protected List mapToRecords( - Map[] activeTableMap, ActiveTableMode mode) { + Map[] activeTableMap, ActiveTableMode mode) + throws Exception { List records = new ArrayList( activeTableMap.length); if (activeTableMap != null) { @@ -214,16 +159,20 @@ public class UpdateActiveTableHandler implements atr.setAct(template.get("act").toString()); atr.setSeg((Integer) template.get("seg")); Calendar start = GregorianCalendar.getInstance(); - start.setTimeInMillis(((Integer) template.get("startTime")) * 1000L); + start.setTimeInMillis(((Number) template.get("startTime")) + .longValue() * 1000L); atr.setStartTime(start); Calendar end = GregorianCalendar.getInstance(); - end.setTimeInMillis(((Integer) template.get("endTime")) * 1000L); + end.setTimeInMillis(((Number) template.get("endTime")) + .longValue() * 1000L); atr.setEndTime(end); Calendar purge = GregorianCalendar.getInstance(); - purge.setTimeInMillis(((Integer) template.get("purgeTime")) * 1000L); + purge.setTimeInMillis(((Number) template.get("purgeTime")) + .longValue() * 1000L); atr.setPurgeTime(purge); Calendar issue = GregorianCalendar.getInstance(); - issue.setTimeInMillis(((Integer) template.get("issueTime")) * 1000L); + issue.setTimeInMillis(((Number) template.get("issueTime")) + .longValue() * 1000L); atr.setIssueTime(issue); atr.setUfn((Boolean) template.get("ufn")); atr.setOfficeid(template.get("officeid").toString()); @@ -273,7 +222,7 @@ public class UpdateActiveTableHandler implements } catch (Exception e) { statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); - + throw e; } } } diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/handler/RetrieveRemoteActiveTableHandler.java b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/handler/RetrieveRemoteActiveTableHandler.java new file mode 100644 index 0000000000..fb8f256024 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/handler/RetrieveRemoteActiveTableHandler.java @@ -0,0 +1,127 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.edex.activetable.handler; + +import java.util.HashMap; +import java.util.Map; + +import jep.JepException; + +import com.raytheon.uf.common.activetable.request.RetrieveRemoteActiveTableRequest; +import com.raytheon.uf.common.activetable.response.ActiveTableSharingResponse; +import com.raytheon.uf.common.localization.IPathManager; +import com.raytheon.uf.common.localization.LocalizationContext; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; +import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.common.python.PyUtil; +import com.raytheon.uf.common.python.PythonScript; +import com.raytheon.uf.common.serialization.comm.IRequestHandler; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.util.FileUtil; +import com.raytheon.uf.edex.activetable.ActiveTablePyIncludeUtil; + +/** + * Handler for RetrieveRemoteActiveTableRequest. Runs the requestAT + * application using the parameters from the request as arguments to the + * PythonScript. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 6, 2013            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class RetrieveRemoteActiveTableHandler implements + IRequestHandler { + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(RetrieveRemoteActiveTableHandler.class); + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest + * (com.raytheon.uf.common.serialization.comm.IServerRequest) + */ + @Override + public ActiveTableSharingResponse handleRequest( + RetrieveRemoteActiveTableRequest request) throws Exception { + IPathManager pathMgr = PathManagerFactory.getPathManager(); + LocalizationContext commonBaseCx = pathMgr.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.BASE); + String scriptPath = pathMgr.getFile(commonBaseCx, + FileUtil.join(ActiveTablePyIncludeUtil.VTEC, "requestAT.py")) + .getPath(); + final String siteId = request.getSiteId(); + String pythonIncludePath = PyUtil.buildJepIncludePath( + ActiveTablePyIncludeUtil.getCommonPythonIncludePath(), + ActiveTablePyIncludeUtil.getVtecIncludePath(siteId), + ActiveTablePyIncludeUtil.getGfeConfigIncludePath(siteId), + ActiveTablePyIncludeUtil.getIscScriptsIncludePath()); + + PythonScript script = null; + try { + script = new PythonScript(scriptPath, pythonIncludePath, + RetrieveRemoteActiveTableHandler.class.getClassLoader()); + + try { + Map argMap = new HashMap(); + argMap.put("serverHost", request.getServerHost()); + argMap.put("serverPort", request.getServerPort()); + argMap.put("serverProtocol", request.getServerProtocol()); + argMap.put("mhsid", request.getMhsId()); + argMap.put("siteID", siteId); + argMap.put("ancf", request.getAncfAddress()); + argMap.put("bncf", request.getBncfAddress()); + argMap.put("xmtScript", request.getTransmitScript()); + script.execute("runFromJava", argMap); + } catch (JepException e) { + statusHandler.handle(Priority.PROBLEM, + "Error executing requestAT.", e); + return new ActiveTableSharingResponse(false, + "Error executing requestAT: " + e.getLocalizedMessage()); + } + } catch (JepException e) { + statusHandler.handle(Priority.PROBLEM, + "Unable to instantiate requestAT python script object.", e); + return new ActiveTableSharingResponse(false, + "Unable to instantiate requestAT python script object: " + + e.getLocalizedMessage()); + } finally { + if (script != null) { + script.dispose(); + } + } + + return new ActiveTableSharingResponse(true, null); + } +} diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/handler/SendActiveTableHandler.java b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/handler/SendActiveTableHandler.java new file mode 100644 index 0000000000..3caad2606a --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/handler/SendActiveTableHandler.java @@ -0,0 +1,131 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.uf.edex.activetable.handler; + +import java.util.HashMap; +import java.util.Map; + +import jep.JepException; + +import com.raytheon.uf.common.activetable.request.SendActiveTableRequest; +import com.raytheon.uf.common.activetable.response.ActiveTableSharingResponse; +import com.raytheon.uf.common.localization.IPathManager; +import com.raytheon.uf.common.localization.LocalizationContext; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; +import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.common.python.PyUtil; +import com.raytheon.uf.common.python.PythonScript; +import com.raytheon.uf.common.serialization.comm.IRequestHandler; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.util.FileUtil; +import com.raytheon.uf.edex.activetable.ActiveTablePyIncludeUtil; + +/** + * Handler for SendActiveTableRequest. Runs the sendAT application + * using the parameters from the request as arguments to the PythonScript. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 6, 2013            dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class SendActiveTableHandler implements + IRequestHandler { + + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(SendActiveTableHandler.class); + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest + * (com.raytheon.uf.common.serialization.comm.IServerRequest) + */ + @Override + public ActiveTableSharingResponse handleRequest( + SendActiveTableRequest request) throws Exception { + IPathManager pathMgr = PathManagerFactory.getPathManager(); + LocalizationContext commonBaseCx = pathMgr.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.BASE); + String scriptPath = pathMgr.getFile(commonBaseCx, + FileUtil.join(ActiveTablePyIncludeUtil.VTEC, "sendAT.py")) + .getPath(); + final String siteId = request.getServerSite(); + String pythonIncludePath = PyUtil.buildJepIncludePath( + ActiveTablePyIncludeUtil.getCommonPythonIncludePath(), + ActiveTablePyIncludeUtil.getVtecIncludePath(siteId), + ActiveTablePyIncludeUtil.getGfeConfigIncludePath(siteId), + ActiveTablePyIncludeUtil.getIscScriptsIncludePath()); + + PythonScript script = null; + try { + script = new PythonScript(scriptPath, pythonIncludePath, + RetrieveRemoteActiveTableHandler.class.getClassLoader()); + + try { + Map argMap = new HashMap(); + argMap.put("myServerHost", request.getServerHost()); + argMap.put("myServerPort", request.getServerPort()); + argMap.put("myServerProtocol", request.getServerProtocol()); + argMap.put("myServerMHSID", request.getMhsId()); + argMap.put("myServerSite", siteId); + argMap.put("sites", request.getSites()); + argMap.put("filterSites", request.getFilterSites()); + argMap.put("mhsSites", request.getMhsSites()); + argMap.put("issueTime", request.getIssueTime()); + argMap.put("countDict", request.getCountDict()); + argMap.put("fname", request.getFileName()); + argMap.put("xmlIncoming", request.getXmlIncoming()); + argMap.put("xmtScript", request.getTransmitScript()); + script.execute("runFromJava", argMap); + } catch (JepException e) { + statusHandler.handle(Priority.PROBLEM, + "Error executing sendAT.", e); + return new ActiveTableSharingResponse(false, + "Error executing sendAT: " + e.getLocalizedMessage()); + } + } catch (JepException e) { + statusHandler.handle(Priority.PROBLEM, + "Unable to instantiate sendAT python script object.", e); + return new ActiveTableSharingResponse(false, + "Unable to instantiate sendAT python script object: " + + e.getLocalizedMessage()); + } finally { + if (script != null) { + script.dispose(); + } + } + + return new ActiveTableSharingResponse(true, null); + } +} diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/ActiveTableRecord.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/ActiveTableRecord.py index b740a00dac..1b6b86af59 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/ActiveTableRecord.py +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/ActiveTableRecord.py @@ -27,6 +27,8 @@ # Date Ticket# Engineer Description # ------------ ---------- ----------- -------------------------- # 12/20/09 njensen Initial Creation. +# 02/26/13 1447 dgilling Implement __eq__() and +# __ne__(). # # # @@ -35,7 +37,7 @@ import ActiveTableVtec from java.util import Calendar -class ActiveTableRecord: +class ActiveTableRecord(object): def __init__(self, javaRecord, state="Decoded"): self.atr = javaRecord @@ -150,7 +152,12 @@ class ActiveTableRecord: def __deepcopy__(self, memo): return ActiveTableRecord(self.atr.clone(), self.state) - + + def __eq__(self, other): + return self.javaRecord().equals(other.javeRecord()) + + def __ne__(self, other): + return not self.__eq__(other) def javaRecord(self): return self.atr diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/MergeVTEC.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/MergeVTEC.py new file mode 100644 index 0000000000..c03acde673 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/MergeVTEC.py @@ -0,0 +1,430 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# MergeVTEC - merges two "active" tables together. +# Originally written by Mark Mathewson FSL + +# +# Port of MergeVTEC code from AWIPS1 +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 01/25/13 1447 dgilling Initial Creation. +# +# + + +import copy +import cPickle +import gzip +import logging +import os +import sys +import time + +import ActiveTableRecord +import siteConfig +import VTECPartners +import VTECTableSqueeze +import VTECTableUtil + +from java.util import ArrayList +from com.raytheon.uf.common.activetable import MergeResult +from com.raytheon.uf.common.activetable import VTECChange +from com.raytheon.uf.common.localization import PathManagerFactory +from com.raytheon.uf.common.localization import LocalizationContext_LocalizationType as LocalizationType +from com.raytheon.uf.common.site import SiteMap + + +class MergeVTEC(VTECTableUtil.VTECTableUtil): + + def __init__(self, activeTable, activeTableMode, newRecords, offsetSecs=0.0, + makeBackups=True, logger=None): + # activeTable - current activeTable records + # activeTableMode - which table is being modified--OPERATIONAL or PRACTICE + # newRecords - records to merge in to activeTable + # inputIsGZIP (0,1) - remote input file is gzipped + # offsetSecs - Number of seconds +/- current time + # makeBackups (False, True) - make backups of previous table + # logger - python logging object to send all logs to + if logger is not None: + self._log = logger + else: + self._log = self.__initLogging() + + # create a dummy name to simplify the file access code in VTECTableUtil + pathMgr = PathManagerFactory.getPathManager() + commonSiteCx = pathMgr.getContextForSite( + LocalizationType.COMMON_STATIC, siteConfig.GFESUITE_SITEID) + filePath = pathMgr.getFile(commonSiteCx,"vtec").getPath() + self._activeTableFilename = os.path.join(filePath, activeTableMode + ".tbl") + + # to ensure time calls are based on Zulu + os.environ['TZ'] = "GMT0" + self._time = time.time() + offsetSecs #present time + + self._makeBackups = makeBackups + + VTECTableUtil.VTECTableUtil.__init__(self, self._activeTableFilename) + + # get the SPC site id from the configuration file + self._spcSite = getattr(VTECPartners, "VTEC_SPC_SITE", "KWNS") + self._tpcSite = getattr(VTECPartners, "VTEC_TPC_SITE", "KNHC") + + # get our site + siteid = siteConfig.GFESUITE_SITEID + self._ourSite = self._get4ID(siteid) + + self._siteFilter = self._getFilterSites() + + self._log.info("MergeVTEC Starting") + self._log.info("localFN= " + self._activeTableFilename + " sites= " + + repr(self._siteFilter)) + + #read table to merge + otherTable = newRecords + self._log.info("Remote Table size: %d", len(otherTable)) + + #read active table + self._log.info("Active Table size: %d", len(activeTable)) + + #save a copy for later backup purposes + oldActiveTable = copy.deepcopy(activeTable) + + #delete "obsolete" records from our table and the other table + vts = VTECTableSqueeze.VTECTableSqueeze(self._time) + activeTable, tossRecords = vts.squeeze(activeTable) + self._log.info("Active Table squeezed size: %d", len(activeTable)) + self._log.info("Other Table size: %d", len(otherTable)) + otherTable, tossRecordsOther = vts.squeeze(otherTable) + self._log.info("Other Table squeezed size: %d", len(otherTable)) + + #merge the tables + updatedTable, toDelete, changes = self._mergeTable(activeTable, otherTable) + self._log.info("Updated Active Table size: %d", len(updatedTable)) + updatedTable, tossRecordsMerged = vts.squeeze(updatedTable) + self._log.info("Updated Active Table squeeze size: %d", + len(updatedTable)) + del vts + + self._updatedTable = [] + self._purgedTable = [] + self._changes = [] + + #notify the ifpServer of changes, save a backup copy + if tossRecords or tossRecordsMerged or changes: + self._log.debug("#tossRecords: %d", len(tossRecords)) + self._log.debug("#tossRecordsMerged: %d", len(tossRecordsMerged)) + self._log.debug("#changes: %d", len(changes)) + + # save lists for later retrieval + self._updatedTable = updatedTable + self._purgedTable.extend(tossRecords) + self._purgedTable.extend(toDelete) + self._purgedTable.extend([rec for rec in tossRecordsMerged if rec in oldActiveTable]) + self._changes = changes + + #save backup copy + if self._makeBackups: + oldActiveTable = self._convertTableToPurePython(oldActiveTable, siteid) + self.saveOldActiveTable(oldActiveTable) + pTime = getattr(VTECPartners, "VTEC_BACKUP_TABLE_PURGE_TIME", + 168) + self.purgeOldSavedTables(pTime) + + self._log.info("MergeVTEC Finished") + + # merges the active and other table together and returns the merged + # table along with the list of changes that occurred. + def _mergeTable(self, activeTable, otherTable): + changes = [] + purges = [] + compare = ['id', 'phen', 'sig', 'officeid', 'etn', 'pil'] + compare1 = ['phen', 'sig', 'officeid'] + compare2 = ['officeid', 'pil', 'phen', 'sig', 'etn'] + missingEntriesPast = [] + missingEntriesAct = [] + newReplaceEntriesPast = [] + oldReplaceEntriesPast = [] + newReplaceEntriesAct = [] + oldReplaceEntriesAct = [] + ignoredNewReplaceAct = [] + ignoredOldReplaceAct = [] + + currentYear = time.gmtime(self._time)[0] + terminations = ('CAN', 'EXP', 'UPG') + + # we process each entry in the other (received) table + for othRec in otherTable: + # filter out all other sites we aren't interested in + if self._siteFilter is not None and \ + othRec['officeid'] not in self._siteFilter: + continue + + # filter out ROU and COR codes + if othRec['act'] in ["ROU","COR"]: + continue + + othRecYear = time.gmtime(othRec['issueTime'])[0] + + # check our active table for this event. if there is only one record + # and it is a canceled event, then we keep it that way. + + matches = [] + for rec in activeTable: + if self.hazardCompare(rec, othRec, compare2): + atRecYear = time.gmtime(rec['issueTime'])[0] + if othRecYear == atRecYear: + matches.append(rec) + + if len(matches) == 1 and matches[0]['act'] in terminations: + # done with this remote record + continue + + # if the remote table has a single canceled record, + # copy the record if needed and remove the rest for the event + + canceled = othRec['act'] in terminations + if canceled: + # determine if the remote table has a single record + for othRec2 in otherTable: + if self.hazardCompare(othRec2, othRec, compare2): + recYear = time.gmtime(othRec2['issueTime'])[0] + if recYear == othRecYear and othRec2['id'] != othRec['id']: + canceled = False + break + + if canceled: + # find all the record in our active table for this event + matches = [] + for i, rec in enumerate(activeTable): + if self.hazardCompare(rec, othRec, compare2): + atRecYear = time.gmtime(rec['issueTime'])[0] + if othRecYear == atRecYear: + matches.append(i) + + changed = False + + found = False + matches.reverse() + for i in matches: + rec = activeTable[i] + if rec['id'] == othRec['id']: + found = True + # replace record if not the same + if rec != othRec: + newReplaceEntriesAct.append(othRec) + oldReplaceEntriesAct.append(rec) + activeTable[i] = othRec + changed = True + else: + # remove other records for this event + oldReplaceEntriesAct.append(rec) + del activeTable[i] + changed = True + + if not found: + # add the remote record + if len(matches) > 0: + newRplaceEntriesAct.append(othRec) + else: + missingEntriesAct.append(othRec) + activeTable.append(othRec) + changed = True + + if changed: + chgRec = (othRec['officeid'], othRec['pil'], othRec['phensig']) + if chgRec not in changes: + changes.append(chgRec) + + # done with this remote record + continue + + + # currently active events + if othRec['endTime'] >= self._time: + + # find a match in otherTable that is in our active table + # and replace it if newer, but only if it is from the same + # issuance year. + found = 0 + for i in xrange(len(activeTable)): + if self.hazardCompare(activeTable[i], othRec, compare): + found = 1 + atRecYear = time.gmtime(activeTable[i]['issueTime'])[0] + if othRec['issueTime'] > activeTable[i]['issueTime']: + if othRecYear == atRecYear: + newReplaceEntriesAct.append(othRec) + oldReplaceEntriesAct.append(activeTable[i]) + activeTable[i] = othRec #replace the record + chgRec = (activeTable[i]['officeid'], + activeTable[i]['pil'], activeTable[i]['phensig']) + if chgRec not in changes: + changes.append(chgRec) + else: + ignoredNewReplaceAct.append(othRec) + ignoredOldReplaceAct.append(activeTable[i]) + break + + # if a match wasn't found, then we may need to add the record + # into our active table + if found == 0: + activeTable.append(othRec) #add the record + missingEntriesAct.append(othRec) + chgRec = (othRec['officeid'], othRec['pil'], othRec['phensig']) + if chgRec not in changes: + changes.append(chgRec) + + # past events + else: + + othRecYear = time.gmtime(othRec['issueTime'])[0] + if currentYear != othRecYear: + continue #only care about this years + + # find the highest ETN for the current year per phen/sig + # in active table and compare to the other table. If found + # higher 'remote' record, replace the record. + maxETN = None + maxETNIndex = None + for i in xrange(len(activeTable)): + a = activeTable[i] + if self.hazardCompare(a, othRec, compare1) and \ + time.gmtime(a['issueTime'])[0] == currentYear: + if maxETN is None or a['etn'] > maxETN: + maxETN = a['etn'] #save maxETN + maxETNIndex = i #save the index + + if maxETN is not None and othRec['etn'] > maxETN: + newReplaceEntriesPast.append(othRec) + oldReplaceEntriesPast.append(activeTable[maxETNIndex]) + activeTable[maxETNIndex] = othRec #replace record + chgRec = (othRec['officeid'], othRec['pil'], othRec['phensig']) + if chgRec not in changes: + changes.append(chgRec) + + #if phen/sig not found, then add it + if maxETN is None: + activeTable.append(othRec) #add the record + missingEntriesPast.append(othRec) + chgRec = (othRec['officeid'], othRec['pil'], othRec['phensig']) + if chgRec not in changes: + changes.append(chgRec) + + # log the changes + if len(missingEntriesAct): + self._log.debug("Active Missing entries added: %s", + self.printActiveTable(missingEntriesAct, 1)) + if len(newReplaceEntriesAct): + self._log.debug("Active Replacement entries (new): %s", + self.printActiveTable(newReplaceEntriesAct, 1)) + if len(oldReplaceEntriesAct): + self._log.debug("Active Entries Replaced (old): %s", + self.printActiveTable(oldReplaceEntriesAct, 1)) + if len(missingEntriesPast): + self._log.debug("Past Missing entries added %s", + self.printActiveTable(missingEntriesPast, 1)) + if len(newReplaceEntriesPast): + self._log.debug("Past Replacement entries (new): %s", + self.printActiveTable(newReplaceEntriesPast, 1)) + if len(oldReplaceEntriesPast): + self._log.debug("Past Entries Replaced (old): %s", + self.printActiveTable(oldReplaceEntriesPast, 1)) + if len(ignoredNewReplaceAct): + self._log.debug("Ignored Different Year Issuance (new): %s", + self.printActiveTable(ignoredNewReplaceAct, 1)) + self._log.debug("Ignored Different Year Issuance (old): %s", + self.printActiveTable(ignoredOldReplaceAct, 1)) + self._log.debug("Table Changes: %s", changes) + + purges.extend(oldReplaceEntriesAct) + purges.extend(oldReplaceEntriesPast) + return activeTable, purges, changes + + def getMergeResults(self): + if not self._updatedTable and not self._purgedTable and not self._changes: + return None + + updatedList = ArrayList() + for rec in self._updatedTable: + updatedList.add(rec.javaRecord()) + + purgedList = ArrayList() + for rec in self._purgedTable: + purgedList.add(rec.javaRecord()) + + changeList = ArrayList() + for c in self._changes: + changeList.add(VTECChange(c[0],c[1],c[2])) + + result = MergeResult(updatedList, purgedList, changeList) + return result + + def _getFilterSites(self): + #gets the list of filter sites, which is the list specified, plus + #SPC plus our own site. Returns None for no-filtering. + sites = getattr(VTECPartners, "VTEC_MERGE_SITES", []) + if sites is None: + return None + sites.append(self._spcSite) + sites.append(self._tpcSite) + sites.append(self._ourSite) + self._log.debug("Filter Sites: %s", sites) + return sites + + #convert 3 letter to 4 letter site ids + def _get4ID(self, id): + return SiteMap.getInstance().getSite4LetterId(id) + + def __initLogging(self): + logPath = os.path.join(siteConfig.GFESUITE_LOGDIR, + time.strftime("%Y%m%d", time.gmtime()), 'MergeVTEC.log') + try: + os.makedirs(os.path.dirname(logPath)) + except OSError as e: + if e.errno != errno.EEXIST: + sys.stderr.write("Could not create log directory " + os.path.dirname(logPath)) + sys.exit(-1) + + logging.basicConfig(filename=logPath, + format="%(levelname)s %(asctime)s [%(process)d:%(thread)d] %(filename)s: %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO) + return logging.getLogger("MergeVTEC") + +def merge(activeTable, activeTableMode, newRecords, drt=0.0, makeBackups=True, + logger=None): + pyActive = [] + for i in range(activeTable.size()): + pyActive.append(ActiveTableRecord.ActiveTableRecord(activeTable.get(i))) + + pyNew = [] + for i in range(newRecords.size()): + pyNew.append(ActiveTableRecord.ActiveTableRecord(newRecords.get(i))) + + decoder = MergeVTEC(pyActive, activeTableMode, pyNew, drt, makeBackups, logger) + mergeResults = decoder.getMergeResults() + decoder = None + + return mergeResults + diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECPartners.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECPartners.py index 2e99b85ee4..e690405267 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECPartners.py +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECPartners.py @@ -17,6 +17,7 @@ # See the AWIPS II Master Rights File ("Master Rights File.pdf") for # further licensing information. ## + #VTEC_Partners.py - configuration file to control filtering and merging #of VTEC active table. @@ -46,7 +47,7 @@ VTEC_DECODER_SITES = [] # The following list is a set of product categories (e.g., ZFP, WOU) that # when decoded, the text for each segment is captured. The text is not # normally needed to be captured except for warning-style products. -VTEC_CAPTURE_TEXT_CATEGORIES = []#['WSW', 'NPW', 'RFW', 'FFA', 'CFW', 'MWS', 'HLS', 'MWW'] +VTEC_CAPTURE_TEXT_CATEGORIES = ['WSW', 'NPW', 'RFW', 'FFA', 'CFW', 'MWS', 'HLS', 'MWW'] # Remapping of product pils. This is required for certain VTEC events # if a hazard is created in one pil and then updated or cancelled in another diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECTableSqueeze.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECTableSqueeze.py index 4010fd54fa..94e12be3c3 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECTableSqueeze.py +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECTableSqueeze.py @@ -213,7 +213,8 @@ class VTECTableSqueeze: for ps in phensig: issueYears = d[o][ps].keys() for iy in issueYears: - etns = d[o][ps][iy].keys() + dd = d[o][ps][iy] + etns = dd.keys() #get two maxetn for tropicalPhen (one for site created and the other #for NHC created. The etn will be more than 100 for NHC hazards), @@ -227,50 +228,75 @@ class VTECTableSqueeze: else: maxetn2 = maxetn1 - ids1 = d[o][ps][iy][maxetn1] + ids1 = dd[maxetn1] minid1 = min(ids1) ids2 = ids1 minid2 = minid1 if maxetn2 > 0 and maxetn2 != maxetn1: - ids2 = d[o][ps][iy][maxetn2] + ids2 = dd[maxetn2] minid2 = min(ids2) #determine what to keep and what to toss - for etn in d[o][ps][iy].keys(): - for id in d[o][ps][iy][etn].keys(): - for rec in d[o][ps][iy][etn][id]: + for etn in etns: + all_hourOld = True + all_cancelled = True + all_twoWeeksOld = True + ufn = None - ufn = rec.get('ufn',0) + for id in dd[etn].keys(): + for rec in dd[etn][id]: + if ufn is None: + ufn = rec.get('ufn', False) hourOld = self.__ctime > rec['endTime'] + (1*3600) twoWeeksOld = self.__ctime > rec['issueTime'] + (14*86400) cancelled = rec['act'] in ['CAN','UPG','EXP'] - # keep records that are: - # 1. are UFN, not cancelled, and not older then two weeks. - # 2. not UFN, and not ended in the last hour - # 3. cancelled, from this year, are minid, and are maxetn - if ufn and not cancelled and not twoWeeksOld: # 1 + all_hourOld &= hourOld + all_cancelled &= cancelled + all_twoWeeksOld &= twoWeeksOld + + # keep records if the event: + # 1. is UFN, not cancelled, and not older then two weeks. + # 2. not UFN, and not ended in the last hour + # 3. cancelled, from this year, keep only records that are minid, and maxetn + + if ufn and not all_cancelled and not all_twoWeeksOld: # 1 + for id in dd[etn].keys(): + for rec in dd[etn][id]: saveRec.append(rec) - elif not ufn and not hourOld: # 2 + + elif not ufn and not all_hourOld: # 2 + for id in dd[etn].keys(): + for rec in dd[etn][id]: saveRec.append(rec) - elif iy == self.__thisYear and \ - rec['id'] == minid1 and \ - rec['etn'] == maxetn1: - if rec['officeid'] in ['KNHC'] and twoWeeksOld: - LogStream.logDebug("******** WILL PURGE *******", rec['vtecstr']) - else: - saveRec.append(rec) - elif iy == self.__thisYear and \ - maxetn1 != maxetn2 and \ - rec['phen'] in tropicalPhen and \ - rec['id'] == minid2 and \ - rec['etn'] == maxetn2: # 3 - saveRec.append(rec) - # otherwise, remove them + + elif iy == self.__thisYear and etn == maxetn1: # 3 + for id in dd[etn].keys(): + if (id == minid1): + for rec in dd[etn][id]: + saveRec.append(rec) else: + for rec in dd[etn][id]: + LogStream.logDebug("******** WILL PURGE *******", rec['vtecstr']) + purgeRec.append(rec) + + elif (iy == self.__thisYear) and (etn == maxetn2): # 3 + for id in dd[etn].keys(): + if (id == minid2): + for rec in dd[etn][id]: + saveRec.append(rec) + else: + for rec in dd[etn][id]: + LogStream.logDebug("******** WILL PURGE *******", rec['vtecstr']) + purgeRec.append(rec) + + else: + for id in dd[etn].keys(): + for rec in dd[etn][id]: LogStream.logDebug("******** WILL PURGE *******", rec['vtecstr']) purgeRec.append(rec) + return saveRec, purgeRec #prints the dictionary organized by oid, phensig, issueYear, etn, id diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECTableUtil.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECTableUtil.py index 26239c2923..092dba5f71 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECTableUtil.py +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/VTECTableUtil.py @@ -19,10 +19,22 @@ ## # Utility classes for the VTEC active table -import time, copy, types +import copy +import cPickle +import errno +import glob +import gzip +import os +import stat +import time +import types + import LogStream import JUtil +from java.util import ArrayList +from com.raytheon.uf.edex.activetable import ActiveTable + class VTECTableUtil: @@ -290,4 +302,85 @@ class VTECTableUtil: return "K" + id +#------------------------------------------------------------------ +# Table lock/unlock read/write utility +#------------------------------------------------------------------ + def saveOldActiveTable(self, oldActiveTable): + #saves off the specified table and time stamps it + + if self._activeTableFilename is None: + raise Exception, "saveOldActiveTable without filename" + + #determine filename + directory = os.path.join(os.path.dirname(self._activeTableFilename), "backup") + try: + os.makedirs(directory) + except OSError as e: + if e.errno != errno.EEXIST: + LogStream.logProblem("Could not create active table backup directory:", + directory, LogStream.exc()) + raise e + + gmtime = time.gmtime(time.time()) + format = "%Y%m%d_%H%M%S" + baseN = os.path.basename(self._activeTableFilename) + fn = time.strftime(format, gmtime) + "_" + baseN + filename = os.path.join(directory, fn + ".gz") + + t = time.time() + try: + os.chmod(filename, 0666) + os.remove(filename) + except: + pass + + #output file + #gzip it to save space + with gzip.GzipFile(filename, 'wb', 9) as fd: + buf = cPickle.dumps(oldActiveTable) + fd.write(buf) + os.chmod(filename, 0664) + + t1 = time.time() + tstr = "%.3f" % (t1-t) + LogStream.logVerbose("Saved Previous Active Table: ", fn, "t=", + tstr, "sec.") + + def purgeOldSavedTables(self, purgeTime): + #purges old saved tables + + if self._activeTableFilename is None: + raise Exception, "purgeOldSavedTables without filename" + + #calculate purge time + purgeTime = time.time() - (purgeTime * 3600) + + #directory and files + directory = os.path.join(os.path.dirname(self._activeTableFilename), "backup") + baseN = os.path.basename(self._activeTableFilename) + idx = baseN.find(".") + if idx != -1: + baseN = baseN[0:idx] + files = glob.glob(directory + "/*" + baseN + "*.gz") + + #delete files older than purgeTime + for f in files: + try: + modTime = os.stat(f)[stat.ST_MTIME] + if modTime < purgeTime: + os.remove(f) + LogStream.logDebug("Removing old file: ", f) + except: + LogStream.logProblem("Problem Removing old backup file: ", f, + LogStream.exc()) + + def _convertTableToPurePython(self, table, siteId): + javaRecList = ArrayList() + for rec in table: + javaRecList.add(rec.javaRecord()) + + javaDictFormat = ActiveTable.convertToDict(javaRecList, siteId) + + return JUtil.javaObjToPyVal(javaDictFormat) + diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/ingestAT.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/ingestAT.py new file mode 100644 index 0000000000..b09ea99b81 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/ingestAT.py @@ -0,0 +1,103 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# +# Port of ingestAT code from AWIPS1 +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 02/13/13 1447 dgilling Initial Creation. +# +# + + +import errno +import logging +import os +import sys +import time +import xml.etree.ElementTree as ET + +import IrtAccess +import MergeVTEC +import siteConfig + + +log = None + +def init_logging(): + logPath = os.path.join(siteConfig.GFESUITE_LOGDIR, + time.strftime("%Y%m%d", time.gmtime()), 'ingestAT.log') + try: + os.makedirs(os.path.dirname(logPath)) + except OSError as e: + if e.errno != errno.EEXIST: + sys.stderr.write("Could not create log directory " + os.path.dirname(logPath)) + sys.exit(-1) + + logging.basicConfig(filename=logPath, + format="%(levelname)s %(asctime)s [%(process)d:%(thread)d] %(filename)s: %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO) + global log + log = logging.getLogger("ingestAT") + + +def execute_ingest_at(incomingRecords, activeTable, atName, ztime, makeBackups, xmlIncoming): + # log the source of this data + if xmlIncoming is not None: + irt = IrtAccess.IrtAccess("") + xmlTree = ET.ElementTree(ET.XML(xmlIncoming)) + sourceE = xmlTree.find('source') + for addressE in sourceE.getchildren(): + sourceServer = irt.decodeXMLAddress(addressE) + if sourceServer is None: + continue + log.info("Source Server: " + irt.printServerInfo(sourceServer)) + + results = None + try: + results = MergeVTEC.merge(activeTable, atName, incomingRecords, ztime, makeBackups, + logging.getLogger('MergeVTEC')) + except: + log.exception("MergeVTEC fail:") + return results + +def runFromJava(activeTable, activeTableMode, newRecords, drt, makeBackups, + xmlIncoming): + init_logging() + + log.info('************* ingestAT ************************') + startT = time.time() + + results = execute_ingest_at(newRecords, activeTable, activeTableMode, drt, + makeBackups, xmlIncoming) + + #-------------------------------------------------------------------- + # Finish + #-------------------------------------------------------------------- + endT = time.time() + log.info("Final: wctime: {0:-6.2f}, cputime: {1:-6.2f}".format(endT - startT, time.clock())) + + return results + diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/requestAT.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/requestAT.py new file mode 100644 index 0000000000..5e348f549f --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/requestAT.py @@ -0,0 +1,268 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# +# Port of requestAT code from AWIPS1 +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 02/06/13 1447 dgilling Initial Creation. +# +# + +import cPickle +import errno +import logging +import os +import sys +import tempfile +import time +import xml.etree.ElementTree as ET + +import IrtAccess +import siteConfig +import VTECPartners + +from com.raytheon.uf.common.activetable import ActiveTableMode +from com.raytheon.uf.edex.activetable import ActiveTable + + + +log = None + +def init_logging(): + logPath = os.path.join(siteConfig.GFESUITE_LOGDIR, + time.strftime("%Y%m%d", time.gmtime()), 'requestAT.log') + try: + os.makedirs(os.path.dirname(logPath)) + except OSError as e: + if e.errno != errno.EEXIST: + sys.stderr.write("Could not create log directory " + os.path.dirname(logPath)) + sys.exit(-1) + + logging.basicConfig(filename=logPath, + format="%(levelname)s %(asctime)s [%(process)d:%(thread)d] %(filename)s: %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO) + global log + log = logging.getLogger("requestAT") + +def execute_request_at(serverHost, serverPort, serverProtocol, mhsid, siteID, ancf, + bncf, xmtScript): + #-------------------------------------------------------------------- + # Create a message - pickled + # (MHSsiteID, mySiteID, listOfVTECMergeSites, countDict, issueTime) + # Note that VTEC_MERGE_SITES does not contain our site or SPC, TPC. + #-------------------------------------------------------------------- + + # determine my 4 letter siteid + if siteID in ['SJU']: + mysite4 = "TJSJ" + elif siteID in ['AFG','AJK','HFO','GUM']: + mysite4 = "P" + siteID + elif siteID in ['AER','ALU']: + mysite4 = "PAFC" + else: + mysite4 = "K" + siteID + otherSites = [mysite4, VTECPartners.VTEC_SPC_SITE, + VTECPartners.VTEC_TPC_SITE] + + # determine the MHS WMO id for this message + wmoid = "TTAA00 " + mysite4 + wmoid += " " + time.strftime("%d%H%M", time.gmtime(time.time())) + + # connect to ifpServer and retrieve active table + actTab = ActiveTable.getActiveTable(mysite4, ActiveTableMode.OPERATIONAL) + + # analyze active table to get counts + countDict = {} + issueTime = 0 + for i in xrange(actTab.size()): + rec = actTab.get(i) + # only care about our own sites that we merge + if rec.getOfficeid() not in VTECPartners.VTEC_MERGE_SITES and \ + rec.getOfficeid() not in otherSites: + continue + + recIssueTime = rec.getIssueTime().getTimeInMillis() / 1000 + #track latest + issueTime = max(recIssueTime, issueTime) + + cnt = countDict.get(rec.getOfficeid(), 0) #get old count + countDict[rec.getOfficeid()] = cnt + 1 + + data = (mhsid, siteID, VTECPartners.VTEC_MERGE_SITES, countDict, issueTime) + log.info("Data: " + repr(data)) + + tempdir = os.path.join(siteConfig.GFESUITE_HOME, "products", "ATBL") + with tempfile.NamedTemporaryFile(suffix='.reqat', dir=tempdir, delete=False) as fp: + fname = fp.name + buf = cPickle.dumps(data) + fp.write(buf) + + #-------------------------------------------------------------------- + # Assemble XML source/destination document + #-------------------------------------------------------------------- + msgSendDest = [] #list of mhs sites to send request + + irt = IrtAccess.IrtAccess(ancf, bncf) + iscE = ET.Element('isc') + # this is the requestor of the data + sourceServer = {'mhsid': mhsid, 'host': serverHost, 'port': serverPort, + 'protocol': serverProtocol, 'site': siteID} + irt.addSourceXML(iscE, sourceServer) + log.info("Requesting Server: " + irt.printServerInfo(sourceServer)) + + # who is running the domains requested? + sites = VTECPartners.VTEC_TABLE_REQUEST_SITES + if not sites: + log.error('No sites defined for VTEC_TABLE_REQUEST_SITES') + sys.exit(1) + + status, xml = irt.getServers(sites) + if not status: + log.error('Failure to getServers from IRT') + sys.exit(1) + + # decode the XML + try: + serverTree = ET.ElementTree(ET.XML(xml)) + serversE = serverTree.getroot() + except: + log.exception("Malformed XML on getServers()") + sys.exit(1) + + if serversE.tag != "servers": + log.error("Servers packet missing from web server") + sys.exit(1) + + # process each requested domain returned to us + chosenServers = [] + matchingServers = [] + for domainE in serversE: + if domainE.tag != "domain": + continue + servers = [] #list of servers for this domain + + # decode each server in the domain + for addressE in domainE.getchildren(): + info = irt.decodeXMLAddress(addressE) + if info is None: + continue #not address tag + servers.append(info) + matchingServers.append(info) + + # server search list in priority. The px3 entries are used for + # dual domain for AFC. + hp = [('dx4','98000000'),('px3', '98000000'), ('dx4','98000001'), + ('px3', '98000001')] + + # choose one server from this domain, find first dx4, 98000000 + # try to use one with the same mhsidDest as the site, which + # would be the primary operational GFE. Note that the px3 entries + # are for AFC. + found = False + for matchServer, matchPort in hp: + for server in servers: + if server['host'][0:3] == matchServer and \ + server['port'] == matchPort and server['mhsid'] == siteID: + chosenServers.append(server) + if server['mhsid'] not in msgSendDest: + msgSendDest.append(server['mhsid']) + found = True + break + + # find first dx4, 98000000, but perhaps a different mhsid + # this is probably not the primary operational GFE + if not found: + for matchServer, matchPort in hp: + for server in servers: + if server['host'][0:3] == matchServer and \ + server['port'] == matchPort: + chosenServers.append(server) + if server['mhsid'] not in msgSendDest: + msgSendDest.append(server['mhsid']) + found = True + break + + # if didn't find standard one, then take the first one, but don't + # take ourselves unless we are the only one. + if not found and servers: + for server in servers: + if server['mhsid'] != mhsid and server['host'] != serverHost \ + and server['port'] != serverPort and \ + server['mhsid'] != siteID: + chosenServers.append(server) + if server['mhsid'] not in msgSendDest: + msgSendDest.append(server['mhsid']) + found = True + if not found: + chosenServers.append(servers[0]) + if servers[0]['mhsid'] not in msgSendDest: + msgSendDest.append(servers[0]['mhsid']) + + # Display the set of matching servers + s = "Matching Servers:" + for x in matchingServers: + s += "\n" + irt.printServerInfo(x) + log.info(s) + + # Display the chosen set of servers + s = "Chosen Servers:" + for x in chosenServers: + s += "\n" + irt.printServerInfo(x) + log.info(s) + + irt.addDestinationXML(iscE, chosenServers) + + # create the XML file + with tempfile.NamedTemporaryFile(suffix='.xml', dir=tempdir, delete=False) as fd: + fnameXML = fd.name + fd.write(ET.tostring(iscE)) + + #-------------------------------------------------------------------- + # Now send the message + #-------------------------------------------------------------------- + irt.transmitFiles("GET_ACTIVE_TABLE2", msgSendDest, mhsid, + [fname, fnameXML], xmtScript) + + +def runFromJava(serverHost, serverPort, serverProtocol, mhsid, siteID, ancf, + bncf, xmtScript): + init_logging() + + log.info('*********** requestAT ******************') + startT = time.time() + + try: + execute_request_at(serverHost, serverPort, serverProtocol, mhsid, + siteID, ancf, bncf, xmtScript) + except: + log.exception('Error requesting active table') + + #-------------------------------------------------------------------- + # Finish + #-------------------------------------------------------------------- + endT = time.time() + log.info("Final: wctime: {0:-6.2f}, cputime: {1:-6.2f}".format(endT - startT, time.clock())) + diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/sendAT.py b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/sendAT.py new file mode 100644 index 0000000000..3411781652 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.activetable/utility/common_static/base/vtec/sendAT.py @@ -0,0 +1,300 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# +# Port of sendAT code from AWIPS1 +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 02/08/13 1447 dgilling Initial Creation. +# +# + + +import cPickle +import errno +import gzip +import logging +import os +import sys +import time +import tempfile +import stat +import xml.etree.ElementTree as ET + +import IrtAccess +import JUtil +import siteConfig +import VTECPartners +import VTECTableSqueeze + +# Configuration Item for Test Purposes +FORCE_SEND = False #Set to True to always send even if no updates required. + +log = None + +def init_logging(): + logPath = os.path.join(siteConfig.GFESUITE_LOGDIR, + time.strftime("%Y%m%d", time.gmtime()), 'sendAT.log') + try: + os.makedirs(os.path.dirname(logPath)) + except OSError as e: + if e.errno != errno.EEXIST: + sys.stderr.write("Could not create log directory " + os.path.dirname(logPath)) + sys.exit(-1) + + logging.basicConfig(filename=logPath, + format="%(levelname)s %(asctime)s [%(process)d:%(thread)d] %(filename)s: %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO) + global log + log = logging.getLogger("sendAT") + +def execute_send_at(myServerHost, myServerPort, myServerProtocol, + myServerMHSID, myServerSite, sites, filterSites, mhsSites, + issueTime, countDict, fname, xmlIncoming, xmtScript): + log.info('reqSite= ' + repr(sites)) + log.info('filterSites= ' + repr(filterSites)) + log.info('mhsSite= ' + repr(mhsSites)) + log.info('reqCountDict= ' + repr(countDict)) + if issueTime is None: + log.info('reqIssueTime= None') + else: + log.info('reqIssueTime= ' + str(issueTime) + ' ' + + time.asctime(time.gmtime(issueTime))) + + irt = IrtAccess.IrtAccess("") + myServer = {'mhsid': myServerMHSID, 'host': myServerHost, 'port': myServerPort, + 'protocol': myServerProtocol, 'site': myServerSite} + log.info('MyServer: ' + irt.printServerInfo(myServer)) + + #-------------------------------------------------------------------- + # Prepare the file for sending + #-------------------------------------------------------------------- + with open(fname, 'rb') as fd: + buf = fd.read() + os.remove(fname) + table = cPickle.loads(buf) #unpickle it + log.info("Local Table Length= " + str(len(table))) + + filtTable = [] + # filter by sites listing + if filterSites: + for t in table: + if t['oid'] in filterSites or t['oid'][1:4] in sites or \ + t['oid'] == VTECPartners.VTEC_SPC_SITE or \ + t['oid'] == VTECPartners.VTEC_TPC_SITE: + filtTable.append(t) + else: + filtTable = table #no filtering + log.info("Site Filtered Table Length= " + str(len(filtTable))) + + # eliminate obsolete records + ctime = time.time() #now time + vts = VTECTableSqueeze.VTECTableSqueeze(ctime) + filtTable = rename_fields_for_A2(filtTable) + actTable, tossRecords = vts.squeeze(filtTable) + actTable = rename_fields_for_A1(actTable) + log.info("Squeezed Table Length= " + str(len(actTable))) + + # check issuance time - any times newer in remote table (this table) than + # the local table (requesting site)? + if issueTime is not None: + newerRec = False + newestRec = 0.0 + for t in actTable: + if newestRec < t['issueTime']: + newestRec = t['issueTime'] + if issueTime < newestRec: + newerRec = True + + log.info("NewestFound= " + str(newestRec) + ' ' + + time.asctime(time.gmtime(newestRec))) + log.info("IssueTime check. Newer record found= " + str(newerRec)) + else: + newerRec = True #just assume there are newer records + + # check "counts" for number of records. Any more records means that + # we may be missing some records. + if countDict: + missingRec = False + localCountDict = {} + for t in actTable: + if localCountDict.has_key(t['oid']): + localCountDict[t['oid']] = localCountDict[t['oid']] + 1 + else: + localCountDict[t['oid']] = 1 + for site in localCountDict: + reqCount = countDict.get(site, 0) #number in requesting site + if reqCount != localCountDict[site]: #records different in request site + missingRec = True + break + log.info("MissingRec check. Missing record found= " + str(missingRec)) + log.info("lclCountBySite= " + repr(localCountDict)) + log.info("reqCountBySite= " + repr(countDict)) + else: + missingRec = True #just assume there are + + #should we send? + if missingRec or newerRec or FORCE_SEND: + sendIt = True + else: + sendIt = False + + if sendIt: + actTablePickled = cPickle.dumps(actTable) #repickle it + rawSize = len(actTablePickled) + + #output it as gzipped + fname = fname + ".gz" + with gzip.open(fname, 'wb', 6) as fd: + fd.write(actTablePickled) + + gzipSize = os.stat(fname)[stat.ST_SIZE] + log.info('#dataSize: ' + str(rawSize) + ', #gzipSize: ' + str(gzipSize)) + + #-------------------------------------------------------------------- + # Create the destination XML file + #-------------------------------------------------------------------- + iscOut = Element('isc') + irt.addSourceXML(iscOut, myServer) + + destServers = [] + + if xmlIncoming is not None: + with open(xmlIncoming,'rb') as fd: + xml = fd.read() + os.remove(xmlIncoming) + reqTree = ET.ElementTree(ET.XML(xml)) + sourceE = reqTree.find('source') + for addressE in sourceE.getchildren(): + destServer = irt.decodeXMLAddress(addressE) + if destServer is None: + continue + destServers.append(destServer) + break + + # no XML received on request, this is probably from an older site. + # create a dummy response XML file. Try all combinations. Only + # the mhsid is important for older sites. + else: + servers = [] + for mhss in mhsSites: + for port in xrange(98000000, 98000002): + for site in sites: + for host in ['dx4f','px3']: + destServer = {'mhsid': mhss, 'host': host, + 'port': port, 'protocol': "20070723", + 'site': site} + destServers.append(destServer) + + irt.addDestinationXML(iscOut, destServers) #add the dest server xml + + # print out destinations + s = "Destinations:" + for destServer in destServers: + s += "\n" + irt.printServerInfo(destServer) + log.info(s) + + # create XML file + tempdir = os.path.join(siteConfig.GFESUITE_HOME, "products", "ATBL") + with tempfile.NamedTemporaryFile(suffix='.xml', dir=tempdir, delete=False) as fd: + fnameXML = fd.name + fd.write(ET.tostring(iscOut)) + + #-------------------------------------------------------------------- + # Send it + #-------------------------------------------------------------------- + irt.transmitFiles("PUT_ACTIVE_TABLE2", mhsSites, myServerSite, + [fname, fnameXML], xmtScript) + + else: + log.info("Send has been skipped") + +def rename_fields_for_A1(table): + newTable = [] + for record in table: + record['oid'] = record['officeid'] + del record['officeid'] + record['vstr'] = record['vtecstr'] + del record['vtecstr'] + record['end'] = record['endTime'] + del record['endTime'] + record['start'] = record['startTime'] + del record['startTime'] + record['key'] = record['phensig'] + del record['phensig'] + if record.has_key('segText'): + record['text'] = record['segText'] + del record['segText'] + newTable.append(record) + + return newTable + +def rename_fields_for_A2(table): + newTable = [] + for record in table: + record['officeid'] = record['oid'] + del record['oid'] + record['vtecstr'] = record['vstr'] + del record['vstr'] + record['endTime'] = record['end'] + del record['end'] + record['startTime'] = record['start'] + del record['start'] + record['phensig'] = record['key'] + del record['key'] + if record.has_key('text'): + record['segText'] = record['text'] + del record['text'] + newTable.append(record) + + return newTable + +def runFromJava(myServerHost, myServerPort, myServerProtocol, myServerMHSID, + myServerSite, sites, filterSites, mhsSites, issueTime, + countDict, fname, xmlIncoming, xmtScript): + init_logging() + + log.info('*********** sendAT ****************') + startT = time.time() + + try: + sites = JUtil.javaObjToPyVal(sites) + filterSites = JUtil.javaObjToPyVal(filterSites) + mhsSites = JUtil.javaObjToPyVal(mhsSites) + countDict = JUtil.javaObjToPyVal(countDict) + + execute_send_at(myServerHost, myServerPort, myServerProtocol, + myServerMHSID, myServerSite, sites, filterSites, + mhsSites, issueTime, countDict, fname, xmlIncoming, + xmtScript) + except: + log.exception('Error in sendAT:') + sys.exit(1) + + #-------------------------------------------------------------------- + # Finish + #-------------------------------------------------------------------- + endT = time.time() + log.info("Final: wctime: {0:-6.2f}, cputime: {1:-6.2f}".format(endT - startT, time.clock())) \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/MergeVTEC b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/MergeVTEC new file mode 100644 index 0000000000..32319a41eb --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/MergeVTEC @@ -0,0 +1,40 @@ +#!/bin/sh +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# this allows you to run this script from outside of ./bin +path_to_script=`readlink -f $0` +RUN_FROM_DIR=`dirname $path_to_script` + +GFESUITE_DIR=`dirname $RUN_FROM_DIR` + +# get the base environment +source ${RUN_FROM_DIR}/setup.env + +# setup the environment needed to run the the Python +export LD_LIBRARY_PATH=${GFESUITE_DIR}/src/lib:${PYTHON_INSTALL}/lib +export PYTHONPATH=${RUN_FROM_DIR}/src:${RUN_FROM_DIR}/activeTable:$PYTHONPATH + +# execute the Python module +_PYTHON="${PYTHON_INSTALL}/bin/python" +_MODULE="${RUN_FROM_DIR}/src/activeTable/MergeVTEC.py" + +# quoting of '$@' is used to prevent command line interpretation +$_PYTHON $_MODULE -h ${DEFAULT_HOST} -p ${DEFAULT_PORT} -a OPERATIONAL "$@" diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/requestAT b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/requestAT new file mode 100644 index 0000000000..479faf516d --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/requestAT @@ -0,0 +1,40 @@ +#!/bin/sh +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# this allows you to run this script from outside of ./bin +path_to_script=`readlink -f $0` +RUN_FROM_DIR=`dirname $path_to_script` + +GFESUITE_DIR=`dirname $RUN_FROM_DIR` + +# get the base environment +source ${RUN_FROM_DIR}/setup.env + +# setup the environment needed to run the the Python +export LD_LIBRARY_PATH=${GFESUITE_DIR}/src/lib:${PYTHON_INSTALL}/lib +export PYTHONPATH=${RUN_FROM_DIR}/src:${RUN_FROM_DIR}/activeTable:$PYTHONPATH + +# execute the Python module +_PYTHON="${PYTHON_INSTALL}/bin/python" +_MODULE="${RUN_FROM_DIR}/src/activeTable/requestAT.py" + +# quoting of '$@' is used to prevent command line interpretation +$_PYTHON $_MODULE "$@" diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/sendAT b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/sendAT new file mode 100644 index 0000000000..12aec0f415 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/sendAT @@ -0,0 +1,40 @@ +#!/bin/sh +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# this allows you to run this script from outside of ./bin +path_to_script=`readlink -f $0` +RUN_FROM_DIR=`dirname $path_to_script` + +GFESUITE_DIR=`dirname $RUN_FROM_DIR` + +# get the base environment +source ${RUN_FROM_DIR}/setup.env + +# setup the environment needed to run the the Python +export LD_LIBRARY_PATH=${GFESUITE_DIR}/src/lib:${PYTHON_INSTALL}/lib +export PYTHONPATH=${RUN_FROM_DIR}/src:${RUN_FROM_DIR}/activeTable:$PYTHONPATH + +# execute the Python module +_PYTHON="${PYTHON_INSTALL}/bin/python" +_MODULE="${RUN_FROM_DIR}/src/activeTable/sendAT.py" + +# quoting of '$@' is used to prevent command line interpretation +$_PYTHON $_MODULE "$@" diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/MergeVTEC.py b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/MergeVTEC.py index 11123b11b7..a39f3a7053 100644 --- a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/MergeVTEC.py +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/MergeVTEC.py @@ -17,207 +17,224 @@ # See the AWIPS II Master Rights File ("Master Rights File.pdf") for # further licensing information. ## -import gzip + +# +# MergeVTEC - merges two "active" tables together. +# Ported from AWIPS1 code, originally written by Mark Mathewson FSL +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# ??/??/?? wldougher Initial Creation. +# 02/22/13 1447 dgilling Re-ported to better match +# requestAT/sendAT. +# +# + +import argparse +import collections import cPickle -import os -import stat -import time +import gzip import logging -import getAT -#import JUtil -import dynamicserialize.dstypes.com.raytheon.uf.common.activetable.UpdateActiveTableRequest as UpdateActiveTableRequest +import os +import re +import sys + +from dynamicserialize.dstypes.com.raytheon.uf.common.activetable.request import MergeActiveTableRequest + from ufpy import ThriftClient from ufpy import TimeUtil -from getVtecAttribute import getVtecAttribute -from getFourCharSites import getFourCharSites +from ufpy import UsageArgumentParser -logging.basicConfig(level=logging.DEBUG) -log = logging.getLogger("MergeVTEC") -def merge(removeRemote, remoteATName, atName, inputIsGZIP=False, drt=None, - makeBackups=True, xmlIncoming=None, ourSites=None, host='localhost', port=9581): - oldTable = None - siteFilter = _getFilterSites(ourSites, host, port) +logging.basicConfig(format="%(asctime)s %(name)s %(levelname)s: %(message)s", + datefmt="%H:%M:%S", + level=logging.DEBUG) +log = logging.getLogger('MergeVTEC') + + +class CaseInsensitiveStringSet(collections.Set): + def __init__(self, iterable): + self.__internalSet = frozenset(iterable) + + def __contains__(self, x): + return x.upper() in (item.upper() for item in self.__internalSet) - if drt is None: - drtOffset = 0.0; - else: - drtOffset = TimeUtil.determineDrtOffset(drt)[0] - - atName = atName.upper() - if "PRACTICE" != atName: - atName = "OPERATIONAL" - - try: - oldTable = getAT.getActiveTable(atName, siteFilter, host=host, port=port) - except: - log.error('Error getting old table for backup :', exc_info=True) + def __len__(self): + return len(self.__internalSet) - log.info("Active Table size: %d", len(oldTable)) - - if inputIsGZIP: - fd = gzip.open(remoteATName) - else: - fd = open(remoteATName) + def __iter__(self): + return iter(self.__internalSet) - try: - newTable = cPickle.load(fd) - finally: +class StoreDrtTimeAction(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + drtInfoTuple = TimeUtil.determineDrtOffset(values) + setattr(namespace, self.dest, drtInfoTuple[0]) + +class MergeVTEC(object): + def __init__(self, serverHost, serverPort, site, removeRemote, + remoteATName, atName, inputIsGZIP, drt=0, makeBackups=True, + xmlIncoming=None, fromIngestAT=False): + # serverHost - host name to send merge request to + # serverPort - port EDEX is running on + # site - site to perform merge operation as + # removeRemote (False, True) to remove remote table file upon completion + # remoteATName - name of remote active table file + # atName (OPERATIONAL, PRACTICE) - name of active table name + # inputIsGZIP (False, True) - remote input file is gzipped + # drt mode - None, or number of seconds +/- current time + # makeBackups (False, True) - make backups of table changes + # xmlIncoming - None, or XML data from MHS, only used in ingestAT mode + # fromIngestAT (False, True) - run in ingestAT mode, only affects logging + self._thriftClient = ThriftClient.ThriftClient(serverHost, serverPort, '/services') + self._site = site + self._deleteAfterProcessing = removeRemote + self._remoteTableFilename = remoteATName + self._activeTableFilename = atName + drt = 0 if drt is None else drt + self._drtInfo = float(drt) + self._makeBackups = makeBackups + self._xmlIncoming = xmlIncoming + self._fromIngestAT = fromIngestAT + + log.info("MergeVTEC Starting") + log.info("remoteFN= " + self._remoteTableFilename + + " localFN= " + self._activeTableFilename + + " siteID= " + self._site) + + # read table to merge + otherTable = self._readActiveTable(self._remoteTableFilename, + inputIsGZIP) + log.info("Remote Table size: %d", len(otherTable)) + + self._mergeTable(otherTable) + + # delete remote file, if desired + if self._deleteAfterProcessing: + os.remove(self._remoteTableFilename) + + log.info("MergeVTEC Finished") + + def _mergeTable(self, otherTable): + # Send the new active table to the server. + # The real merge is done server-side. + request = MergeActiveTableRequest(otherTable, self._activeTableFilename, + self._site, self._drtInfo, self._xmlIncoming, + self._fromIngestAT, self._makeBackups) + response = self._thriftClient.sendRequest(request) + if not response.getTaskSuccess(): + raise RuntimeError("Error performing merge: " + response.getErrorMessage()) + + def _readActiveTable(self, filename, inputIsGZIP=False): + # reads the active table and returns the list of records + + records = [] + + # get the file and unpickle it + if not inputIsGZIP: + fd = open(filename, 'rb') + else: + fd = gzip.open(filename, 'rb') + + buf = fd.read() fd.close() - - log.info("Other Table size: %d", len(newTable)) - - if len(newTable) > 0 and newTable[0].has_key('oid'): - convertToNewFormat(newTable) + log.debug("read active table, size: %d", len(buf)) + records = cPickle.loads(buf) + log.debug("cPickle.loads, #records: %d", len(records)) - # Filter out any extra sites in the new table. - if siteFilter is not None: - newTable = [x for x in newTable if x['officeid'] in siteFilter] + if records and records[0].has_key('oid'): + self._convertToNewFormat(records) - log.info("Other Table filtered size: %d", len(newTable)) - - # Send the new active table to the server. - # The real merge is done server-side. - request = UpdateActiveTableRequest() - request.setActiveTable(newTable) - request.setMode(atName) - request.setXmlSource(xmlIncoming) - request.setTimeOffset(drtOffset) - response = None + return records - thriftClient = ThriftClient.ThriftClient(host, port, "/services") - try: - response = thriftClient.sendRequest(request) - log.info('Other table merged.') - except: - log.error("Error sending other table to server:", exc_info=True) - - if response is None: - log.error("No response was received from the server.") - return - - errMsg = response.getMessage() - if errMsg is not None and "" != errMsg: - log.error("Error on server: %s", errMsg) - return - - sourceInfo = response.getSourceInfo() - if sourceInfo is not None: - if type(sourceInfo) != list: - log.info("Converting sourceInfo from " + str(type(sourceInfo))) - # sourceInfo = JUtil.javaStringListToPylist(sourceInfo) - for source in sourceInfo: - log.info("Source Server: %s", str(source)) - else: - log.info("sourceInfo is None") - - if makeBackups and oldTable: - convertToOldFormat(oldTable) - dirname = os.path.dirname(os.path.abspath(remoteATName)) - format = "%Y%m%d_%H%M%S" - gmtime = time.gmtime(time.time() + drtOffset) - bname = time.strftime(format, gmtime) + 'activeTable.gz' - bdirName = os.path.join(dirname, "backup") - - if not os.path.exists(bdirName): - # create the dir and give everyone R/W access - os.mkdir(bdirName, stat.S_IRWXU | stat.S_IRWXG | stat.S_IROTH | - stat.S_IWOTH) - - fname = os.path.join(bdirName, bname) - saveFile = gzip.open(fname, "wb") - save_start = time.time() - try: - cPickle.dump(oldTable, saveFile) - finally: - saveFile.close() + def _convertToNewFormat(self, table): + '''Convert an AWIPS I table to AWIPS 2 internally''' + + maxFutureTime = long(float(2**31-1)) + for entry in table: + entry['officeid'] = entry['oid'] + entry['vtecstr'] = entry['vstr'] + entry['endTime'] = int(entry['end']) + entry['startTime'] = int(entry['start']) + entry['purgeTime'] = int(entry['purgeTime']) + entry['issueTime'] = int(entry['issueTime']) + entry['phensig'] = entry['key'] + entry['state'] = 'Decoded' + if entry['endTime'] >= maxFutureTime: + entry['ufn'] = True + else: + entry['ufn'] = False + entry['productClass'] = entry['vtecstr'][1] + if not entry.has_key('rawMessage'): + entry['rawMessage'] = '' - # Give the user and user's group all access, others read access - os.chmod(fname, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IWGRP | stat.S_IROTH) - tdiff = time.time() - save_start - log.info('Saved Previous Active Table: %s t=%.3f sec. ', fname, tdiff) - elif makeBackups: - log.info('No old active table to back up.') - - if removeRemote: - os.remove(remoteATName) - log.info('Input file ' + remoteATName + ' deleted.') + # Note: this is not always correct + entry['xxxid'] = entry['officeid'][1:] + + if entry.has_key('text'): + entry['segText'] = entry['text'] + # adapted from WarningDecoder... + lines = entry['segText'].split('\n') + for count in xrange(len(lines)-1): + dtg_search = re.search(r' ([0123][0-9][012][0-9][0-5][0-9])', + lines[count]) + if dtg_search: + pil_search = re.search(r'^([A-Z]{3})(\w{3}|\w{2}|\w{1})', + lines[count+1]) + if pil_search: + entry['xxxid'] = pil_search.group(2) + break -def _getFilterSites(ourSites, host, port): - if ourSites is None: - ourSite = os.getenv('GFESUITE_SITEID') - if ourSite is None: - raise Exception("Specify at least one site or set GFESUITE_SITEID.") - else: - ourSite = ourSites[0] - sites = getVtecAttribute('VTEC_MERGE_SITES', [], ourSite, host, port) - if sites is not None: - spcSite = getVtecAttribute("VTEC_SPC_SITE", "KWNS", ourSite, host, port) - tpcSite = getVtecAttribute("VTEC_TPC_SITE", "KNHC", ourSite, host, port) - sites.extend([spcSite, tpcSite]) - if ourSites is None: - sites.append(ourSite) - else: - sites.extend(ourSites) - sites = getFourCharSites(sites, host, port) +def process_command_line(): + parser = UsageArgumentParser.UsageArgumentParser(prog='MergeVTEC', conflict_handler="resolve") + parser.add_argument("-h", action="store", dest="serverHost", + required=True, metavar="serverHost", + help="host name of the EDEX server") + parser.add_argument("-p", action="store", type=int, dest="serverPort", + required=True, metavar="serverPort", + help="port number for the EDEX server") + parser.add_argument("-d", action="store_true", + dest="removeRemote", + help="delete remote active table when done") + parser.add_argument("-a", action="store", dest="atName", + choices=CaseInsensitiveStringSet(['OPERATIONAL', 'PRACTICE']), + required=True, metavar="atName", default="OPERATIONAL", + help="name of the active table (OPERATIONAL or PRACTICE)") + parser.add_argument("-r", action="store", dest="remoteATName", + required=True, metavar="rmtATName", + help="location of the active table (remote)") + parser.add_argument("-z", action=StoreDrtTimeAction, dest="drt", + metavar="drtMode", help="Run in DRT mode") + parser.add_argument("-n", action="store_false", dest="makeBackups", + help="Don't make backups of vtec table") + parser.add_argument("-g", action="store_true", + dest="inputIsGZIP", + help="Remote active table is compressed") + parser.add_argument("-s", action="store", dest="site", metavar="siteID", + required=True, + help="site to merge AT records into") + return vars(parser.parse_args()) - log.debug("Filter Sites: %s", str(sites)) - return sites +def merge(serverHost, serverPort, site, removeRemote, remoteATName, + atName, inputIsGZIP=False, drt=0, makeBackups=True, xmlIncoming=None, + fromIngestAT=False): + decoder = MergeVTEC(serverHost, serverPort, site, removeRemote, + remoteATName, atName, inputIsGZIP, drt, makeBackups, xmlIncoming, + fromIngestAT) + decoder = None + return -def convertToNewFormat(newTable): - '''Convert an AWIPS I table to AWIPS 2 internally''' - import re - maxFutureTime = long(float(2**31-1)) - for dct in newTable: - dct['officeid'] = dct['oid'] - dct['vtecstr'] = dct['vstr'] - dct['endTime'] = int(dct['end']) - dct['startTime'] = int(dct['start']) - dct['purgeTime'] = int(dct['purgeTime']) - dct['issueTime'] = int(dct['issueTime']) - dct['phensig'] = dct['key'] - dct['state'] = 'Decoded' - if dct['endTime'] >= maxFutureTime: - dct['ufn'] = True - else: - dct['ufn'] = False - dct['productClass'] = dct['vtecstr'][1] - if not dct.has_key('rawMessage'): - dct['rawMessage'] = '' - - # Note: this is not always correct - dct['xxxid'] = dct['officeid'][1:] +def main(): + args = process_command_line() + try: + merge(**args) + sys.exit(0) + except: + log.exception("Caught Exception: ") + sys.exit(1) - if dct.has_key('text'): - dct['segText'] = dct['text'] - # adapted from WarningDecoder... - lines = dct['segText'].split('\n') - for count in xrange(len(lines)-1): - dtg_search = re.search(r' ([0123][0-9][012][0-9][0-5][0-9])', - lines[count]) - if dtg_search: - pil_search = re.search(r'^([A-Z]{3})(\w{3}|\w{2}|\w{1})', - lines[count+1]) - if pil_search: - dct['xxxid'] = pil_search.group(2) - break - -def convertToOldFormat(backupTable): - 'Convert an AWIPS 2 table to a table usable by AWIPS 1, in-place.' - for dct in backupTable: - dct['oid'] = dct['officeid'] - dct['vstr'] = dct['vtecstr'] - dct['end'] = dct['endTime'] - dct['start'] = dct['startTime'] - dct['key'] = dct['phensig'] - # remove new fields so we don't pickle two copies - del dct['officeid'] - del dct['vtecstr'] - del dct['endTime'] - del dct['phensig'] - del dct['startTime'] - - if dct.has_key('segText'): - dct['text'] = dct['segText'] - del dct['segText'] +if __name__ == "__main__": + main() diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/ingestAT.py b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/ingestAT.py index 40adafd9ea..8abd3b4d21 100644 --- a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/ingestAT.py +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/ingestAT.py @@ -17,81 +17,113 @@ # See the AWIPS II Master Rights File ("Master Rights File.pdf") for # further licensing information. ## -import tempfile, os, stat, getopt, sys -import logging, time, traceback, string, MergeVTEC -logging.basicConfig() -log = logging.getLogger("ingestAT") -log.info('************* ingestAT ************************') +# +# Port of ingestAT code from AWIPS1 +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# ??/??/?? wldougher Initial Creation. +# 02/13/13 1447 dgilling Re-ported to better match +# requestAT/sendAT. +# +# -startT = time.time() + +import argparse +import collections +import logging +import os +import sys + +import MergeVTEC +from ufpy import TimeUtil +from ufpy import UsageArgumentParser + + + +logging.basicConfig(format="%(asctime)s %(name)s %(levelname)s: %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO) +log = logging.getLogger('ingestAT') + + + +class CaseInsensitiveStringSet(collections.Set): + def __init__(self, iterable): + self.__internalSet = frozenset(iterable) + + def __contains__(self, x): + return x.upper() in (item.upper() for item in self.__internalSet) + + def __len__(self): + return len(self.__internalSet) + + def __iter__(self): + return iter(self.__internalSet) + +class StoreDrtTimeAction(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + drtInfoTuple = TimeUtil.determineDrtOffset(values) + setattr(namespace, self.dest, drtInfoTuple[0]) + +class ReadDeleteFileAction(argparse.Action): + def __call__(self, parser, namespace, values, option_string=None): + with open(values, 'rb') as fd: + fileData = fd.read() + setattr(namespace, self.dest, fileData) + os.remove(values) #-------------------------------------------------------------------- # decode command line ingestAT -f remoteActiveTable [-z drtMode] -# -a activeTableName [-n] -X xmlInfo -# -s site +# -a activeTableName [-n] -X xmlInfo +# -s site #-------------------------------------------------------------------- -log.info('Cmd: %s', str(sys.argv[1:])) -fname = None -ztime = None -atName = 'OPERATIONAL' -xmlIncoming = None -makeBackups = 1 -ourSites = None -host = 'localhost' -port = 9581 +def process_command_line(): + parser = UsageArgumentParser.UsageArgumentParser(prog='ingestAT', conflict_handler="resolve") + parser.add_argument("-h", action="store", dest="serverHost", + required=True, metavar="serverHost") + parser.add_argument("-p", action="store", type=int, dest="serverPort", + required=True, metavar="serverPort") + parser.add_argument("-f", action="store", dest="fname", + required=True, metavar="remoteActiveTable") + parser.add_argument("-z", action=StoreDrtTimeAction, dest="ztime", + metavar="drtMode") + parser.add_argument("-a", action="store", dest="atName", + choices=CaseInsensitiveStringSet(['OPERATIONAL', 'PRACTICE']), + default='OPERATIONAL') + parser.add_argument("-n", action="store_false", dest="makeBackups") + parser.add_argument("-X", action=ReadDeleteFileAction, dest="xmlIncoming", + metavar="xmlInfo") + parser.add_argument("-s", action="store", dest="site", metavar="siteID", + required=True) + return parser.parse_args() -try: - optlist, args = getopt.getopt(sys.argv[1:], 'f:z:a:nX:s:h:p:') - for opt in optlist: - if opt[0] == "-f": - fname = opt[1] - elif opt[0] == "-z": - ztime = opt[1] - elif opt[0] == "-a": - atName = opt[1] - elif opt[0] == "-n": - makeBackups = 0 - elif opt[0] == "-X": - fd = open(opt[1], 'rb') #open the xml source file - xmlIncoming = fd.read() - fd.close() - os.remove(opt[1]) #delete the incoming xml file - elif opt[0] == "-s": - if ourSites is None: - ourSites = [] - ourSites.append(opt[1]) - elif opt[0] == "-h": - host = opt[1] - elif opt[0] == "-p": - port = int(opt[1]) -except: - t, v, tb = sys.exc_info() - tstr = string.join(traceback.format_exception(t, v, tb)) - log.error('Error parsing command line args: %s %s', str(sys.argv), tstr) - sys.exit(1) +def main(): + options = process_command_line() + log.debug("Command-line options: " + repr(options)) + + try: + inputIsGZIP = True + removeRemoteFile = False + fromIngestAT = True + MergeVTEC.merge(options.serverHost, options.serverPort, options.site, + removeRemoteFile, options.fname, options.atName, inputIsGZIP, + options.ztime, options.makeBackups, options.xmlIncoming, + fromIngestAT) + except: + log.exception("MergeVTEC fail: ") + + try: + os.remove(options.fname) + except OSError: + pass -try: - inputIsGZIP = 1 - removeRemoteFile = False - MergeVTEC.merge(removeRemoteFile, fname, atName, inputIsGZIP, drt=ztime, - makeBackups=makeBackups, xmlIncoming=xmlIncoming, ourSites=ourSites, - host=host, port=port) - removeRemoteFile = True -except: - t, v, tb = sys.exc_info() - tstr = string.join(traceback.format_exception(t, v, tb)) - log.error("MergeVTEC fail: " + tstr) -try: - if removeRemoteFile: - os.remove(fname) -except OSError: - pass +if __name__ == '__main__': + main() -#-------------------------------------------------------------------- -# Finish -#-------------------------------------------------------------------- -endT = time.time() -log.info('Final: wctime: %-0.2f, cputime: %-0.2f',(endT - startT), time.clock()) diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/requestAT.py b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/requestAT.py new file mode 100644 index 0000000000..31442a69c4 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/requestAT.py @@ -0,0 +1,98 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# +# Port of requestAT code from AWIPS1 +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 01/28/13 1447 dgilling Initial Creation. +# +# + + +import logging +import sys + +from dynamicserialize.dstypes.com.raytheon.uf.common.activetable.request import RetrieveRemoteActiveTableRequest + +from ufpy import ThriftClient +from ufpy import UsageArgumentParser + + +logging.basicConfig(format="%(asctime)s %(name)s %(levelname)s: %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO) +log = logging.getLogger('requestAT') + + +#-------------------------------------------------------------------- +# command line: requestAT -H ourHost -P ourPort -L ourProto -M mhsid -s siteID +# -t irtServiceAddr -x xmtScript +#-------------------------------------------------------------------- +def process_command_line(): + parser = UsageArgumentParser.UsageArgumentParser(prog='requestAT', conflict_handler="resolve") + parser.add_argument("-H", action="store", dest="serverHost", + required=True, metavar="ourHost") + parser.add_argument("-P", action="store", type=int, dest="serverPort", + required=True, metavar="ourPort") + parser.add_argument("-L", action="store", dest="serverProtocol", + required=True, metavar="ourProto") + parser.add_argument("-M", action="store", dest="mhsid", + required=True, metavar="mhsid") + parser.add_argument("-S", action="store", dest="siteID", + required=True, metavar="siteID") + parser.add_argument("-a", action="store", dest="ancf") + parser.add_argument("-b", action="store", dest="bncf") + parser.add_argument("-x", action="store", dest="xmtScript", + metavar="xmtScript") + return parser.parse_args() + +def build_request(args): + req = RetrieveRemoteActiveTableRequest(args.serverHost, args.serverPort, + args.serverProtocol, args.mhsid, + args.siteID, args.ancf, args.bncf, + args.xmtScript) + return req + +def main(): + options = process_command_line() + log.debug("Command-line options: " + repr(options)) + + req = build_request(options) + log.debug("Request: " + repr(req)) + + thriftClient = ThriftClient.ThriftClient(host=options.serverHost) + try: + response = thriftClient.sendRequest(req) + except: + log.exception("Error posting request.") + sys.exit(1) + + if not response.getTaskSuccess(): + log.error("Error executing requestAT: " + response.getErrorMessage()) + sys.exit(1) + + +if __name__ == '__main__': + main() diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/sendAT.py b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/sendAT.py new file mode 100644 index 0000000000..64dd3aa565 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/cli/src/activeTable/sendAT.py @@ -0,0 +1,122 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# sendAT - sends active table to remote site +# sendAT -s reqSite -a mhsSite -f filterSite -f filterSite -f filterSite... +# [-c countDict] [-t timeStamp] -v vtecData [-X serverXMLInfo] +# -H serverhost -P serverPort -L serverProtocol -M serverMHS -S serverSite +# -x xmtScript + +# +# Port of sendAT code from AWIPS1 +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 01/28/13 1447 dgilling Initial Creation. +# +# + + +import logging +import sys + +from dynamicserialize.dstypes.com.raytheon.uf.common.activetable.request import SendActiveTableRequest +from ufpy import ThriftClient +from ufpy import UsageArgumentParser + + +logging.basicConfig(format="%(asctime)s %(name)s %(levelname)s: %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO) +log = logging.getLogger('sendtAT') + + +#-------------------------------------------------------------------- +# decode command line, -s siteToSend -f filterSite -a mhsSite +# -c countDict (siteid:records) -t issueTime +# -v vtecData [-X serverXMLInfo] -x transmitScript +#-------------------------------------------------------------------- +def process_command_line(): + parser = UsageArgumentParser.UsageArgumentParser(prog='sendAT', conflict_handler="resolve") + parser.add_argument("-s", action="append", dest="sites", + metavar="siteToSend") + parser.add_argument("-f", action="append", dest="filterSites", + metavar="filterSite") + parser.add_argument("-a", action="append", dest="mhsSites", + metavar="mhsSite") + parser.add_argument("-t", action="store", type=float, dest="issueTime", + metavar="issueTime") + parser.add_argument("-c", action="store", dest="countDict", + metavar="countDict") + parser.add_argument("-v", action="store", dest="fname", + metavar="vtecData") + parser.add_argument("-X", action="store", dest="xmlIncoming", + metavar="serverXMLInfo") + parser.add_argument("-H", action="store", dest="myServerHost", + metavar="ourHost") + parser.add_argument("-P", action="store", type=int, dest="myServerPort", + metavar="ourPort") + parser.add_argument("-L", action="store", dest="myServerProtocol", + metavar="ourProto") + parser.add_argument("-M", action="store", dest="myServerMHSID", + metavar="ourMHSID") + parser.add_argument("-S", action="store", dest="myServerSite", + metavar="ourSiteID") + parser.add_argument("-x", action="store", dest="xmtScript", + metavar="transmitScript") + + args = parser.parse_args() + if args.countDict is not None: + exec "countDict = " + args.countDict + setattr(args, "countDict", countDict) + return args + +def build_request(args): + req = SendActiveTableRequest(args.myServerHost, args.myServerPort, + args.myServerProtocol, args.myServerSite, + args.myServerMHSID, args.sites, + args.filterSites, args.mhsSites, + args.issueTime, args.countDict, args.fname, + args.xmlIncoming, args.xmtScript) + return req + +def main(): + options = process_command_line() + log.debug("Command-line options: " + repr(options)) + + req = build_request(options) + log.debug("Request: " + repr(req)) + + thriftClient = ThriftClient.ThriftClient(host=options.myServerHost) + try: + response = thriftClient.sendRequest(req) + except: + log.exception("Error posting request.") + sys.exit(1) + + if not response.getTaskSuccess(): + log.error("Error executing sendAT: " + response.getErrorMessage()) + sys.exit(1) + +if __name__ == '__main__': + main() diff --git a/edexOsgi/com.raytheon.uf.tools.gfesuite/deploy.xml b/edexOsgi/com.raytheon.uf.tools.gfesuite/deploy.xml index 505ae6f152..dc101c42f9 100644 --- a/edexOsgi/com.raytheon.uf.tools.gfesuite/deploy.xml +++ b/edexOsgi/com.raytheon.uf.tools.gfesuite/deploy.xml @@ -83,7 +83,7 @@ - + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/__init__.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/__init__.py index 2a51112ae2..d6497323a0 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/__init__.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/__init__.py @@ -33,10 +33,11 @@ __all__ = [ 'OperationalActiveTableRecord', 'PracticeActiveTableRecord', 'PracticeProductOfftimeRequest', - 'UpdateActiveTableRequest', - 'UpdateActiveTableResponse', + 'SendPracticeProductRequest', 'VTECChange', - 'VTECTableChangeNotification' + 'VTECTableChangeNotification', + 'request', + 'response' ] from ActiveTableMode import ActiveTableMode @@ -52,8 +53,6 @@ from OperationalActiveTableRecord import OperationalActiveTableRecord from PracticeActiveTableRecord import PracticeActiveTableRecord from PracticeProductOfftimeRequest import PracticeProductOfftimeRequest from SendPracticeProductRequest import SendPracticeProductRequest -from UpdateActiveTableRequest import UpdateActiveTableRequest -from UpdateActiveTableResponse import UpdateActiveTableResponse from VTECChange import VTECChange from VTECTableChangeNotification import VTECTableChangeNotification diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/request/MergeActiveTableRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/request/MergeActiveTableRequest.py new file mode 100644 index 0000000000..9ffde5404b --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/request/MergeActiveTableRequest.py @@ -0,0 +1,94 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# File auto-generated against equivalent DynamicSerialize Java class + +class MergeActiveTableRequest(object): + + def __init__(self, incomingRecords=[], tableName='PRACTICE', site=None, + timeOffset=0.0, xmlSource=None, fromIngestAT=False, + makeBackups=True): + self.incomingRecords = incomingRecords + self.site = site + self.tableName = tableName.upper() if tableName.upper() in ['OPERATIONAL', 'PRACTICE'] else 'PRACTICE' + self.timeOffset = float(timeOffset) + self.xmlSource = xmlSource + self.fromIngestAT = bool(fromIngestAT) + self.makeBackups = bool(makeBackups) + + def __repr__(self): + retVal = "MergeActiveTableRequest(" + retVal += repr(self.incomingRecords) + ", " + retVal += repr(self.tableName) + ", " + retVal += repr(self.site) + ", " + retVal += repr(self.timeOffset) + ", " + retVal += repr(self.xmlSource) + ", " + retVal += repr(self.fromIngestAT) + ", " + retVal += repr(self.makeBackups) + ")" + return retVal + + def __str__(self): + return self.__repr__() + + def getIncomingRecords(self): + return self.incomingRecords + + def setIncomingRecords(self, incomingRecords): + self.incomingRecords = incomingRecords + + def getTableName(self): + return self.tableName + + def setTableName(self, tableName): + value = tableName.upper() + if value not in ['OPERATIONAL', 'PRACTICE']: + raise ValueError("Invalid value " + tableName + " specified for ActiveTableMode.") + self.tableName = value + + def getSite(self): + return self.site + + def setSite(self, site): + self.site = site + + def getTimeOffset(self): + return self.timeOffset + + def setTimeOffset(self, timeOffset): + self.timeOffset = float(timeOffset) + + def getXmlSource(self): + return self.xmlSource + + def setXmlSource(self, xmlSource): + self.xmlSource = xmlSource + + def getFromIngestAT(self): + return self.fromIngestAT + + def setFromIngestAT(self, fromIngestAT): + self.fromIngestAT = bool(fromIngestAT) + + def getMakeBackups(self): + return self.makeBackups + + def setMakeBackups(self, makeBackups): + self.makeBackups = bool(makeBackups) + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/request/RetrieveRemoteActiveTableRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/request/RetrieveRemoteActiveTableRequest.py new file mode 100644 index 0000000000..5cc18757d7 --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/request/RetrieveRemoteActiveTableRequest.py @@ -0,0 +1,99 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# File auto-generated against equivalent DynamicSerialize Java class + +class RetrieveRemoteActiveTableRequest(object): + + def __init__(self, serverHost=None, serverPort=0, serverProtocol=None, + mhsId=None, siteId=None, ancfAddress=None, bncfAddress=None, + transmitScript=None): + self.serverHost = serverHost + self.serverPort = int(serverPort) + self.serverProtocol = serverProtocol + self.mhsId = mhsId + self.siteId = siteId + self.ancfAddress = ancfAddress + self.bncfAddress = bncfAddress + self.transmitScript = transmitScript + + def __repr__(self): + retVal = "RetrieveRemoteActiveTableRequest(" + retVal += repr(self.serverHost) + ", " + retVal += repr(self.serverPort) + ", " + retVal += repr(self.serverProtocol) + ", " + retVal += repr(self.mhsId) + ", " + retVal += repr(self.siteId) + ", " + retVal += repr(self.ancfAddress) + ", " + retVal += repr(self.bncfAddress) + ", " + retVal += repr(self.transmitScript) + ")" + return retVal + + def __str__(self): + return self.__repr__() + + def getServerHost(self): + return self.serverHost + + def setServerHost(self, serverHost): + self.serverHost = serverHost + + def getServerPort(self): + return self.serverPort + + def setServerPort(self, serverPort): + self.serverPort = int(serverPort) + + def getServerProtocol(self): + return self.serverProtocol + + def setServerProtocol(self, serverProtocol): + self.serverProtocol = serverProtocol + + def getMhsId(self): + return self.mhsId + + def setMhsId(self, mhsId): + self.mhsId = mhsId + + def getSiteId(self): + return self.siteId + + def setSiteId(self, siteId): + self.siteId = siteId + + def getAncfAddress(self): + return self.ancfAddress + + def setAncfAddress(self, ancfAddress): + self.ancfAddress = ancfAddress + + def getBncfAddress(self): + return self.bncfAddress + + def setBncfAddress(self, bncfAddress): + self.bncfAddress = bncfAddress + + def getTransmitScript(self): + return self.transmitScript + + def setTransmitScript(self, transmitScript): + self.transmitScript = transmitScript + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/request/SendActiveTableRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/request/SendActiveTableRequest.py new file mode 100644 index 0000000000..cb4d4f4241 --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/request/SendActiveTableRequest.py @@ -0,0 +1,140 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# File auto-generated against equivalent DynamicSerialize Java class + +class SendActiveTableRequest(object): + + def __init__(self, serverHost=None, serverPort=None, serverProtocol=None, + serverSite=None, mhsId=None, sites=None, filterSites=None, + mhsSites=None, issueTime=None, countDict=None, fileName=None, + xmlIncoming=None, transmitScript=None): + self.serverHost = serverHost + self.serverPort = None if serverPort is None else int(serverPort) + self.serverProtocol = serverProtocol + self.serverSite = serverSite + self.mhsId = mhsId + self.sites = sites if sites is not None else [] + self.filterSites = filterSites if filterSites is not None else [] + self.mhsSites = mhsSites if mhsSites is not None else [] + self.issueTime = None if issueTime is None else float(issueTime) + self.countDict = countDict if countDict is not None else {} + self.fileName = fileName + self.xmlIncoming = xmlIncoming + self.transmitScript = transmitScript + + def __repr__(self): + retVal = "SendActiveTableRequest(" + retVal += repr(self.serverHost) + ", " + retVal += repr(self.serverPort) + ", " + retVal += repr(self.serverProtocol) + ", " + retVal += repr(self.serverSite) + ", " + retVal += repr(self.mhsId) + ", " + retVal += repr(self.sites) + ", " + retVal += repr(self.filterSites) + ", " + retVal += repr(self.mhsSites) + ", " + retVal += repr(self.issueTime) + ", " + retVal += repr(self.countDict) + ", " + retVal += repr(self.fileName) + ", " + retVal += repr(self.xmlIncoming) + ", " + retVal += repr(self.transmitScript) + ")" + return retVal + + def __str__(self): + return self.__repr__() + + def getServerHost(self): + return self.serverHost + + def setServerHost(self, serverHost): + self.serverHost = serverHost + + def getServerPort(self): + return self.serverPort + + def setServerPort(self, serverPort): + self.serverPort = serverPort + + def getServerProtocol(self): + return self.serverProtocol + + def setServerProtocol(self, serverProtocol): + self.serverProtocol = serverProtocol + + def getServerSite(self): + return self.serverSite + + def setServerSite(self, serverSite): + self.serverSite = serverSite + + def getMhsId(self): + return self.mhsId + + def setMhsId(self, mhsId): + self.mhsId = mhsId + + def getSites(self): + return self.sites + + def setSites(self, sites): + self.sites = sites + + def getFilterSites(self): + return self.filterSites + + def setFilterSites(self, filterSites): + self.filterSites = filterSites + + def getMhsSites(self): + return self.mhsSites + + def setMhsSites(self, mhsSites): + self.mhsSites = mhsSites + + def getIssueTime(self): + return self.issueTime + + def setIssueTime(self, issueTime): + self.issueTime = issueTime + + def getCountDict(self): + return self.countDict + + def setCountDict(self, countDict): + self.countDict = countDict + + def getFileName(self): + return self.fileName + + def setFileName(self, fileName): + self.fileName = fileName + + def getXmlIncoming(self): + return self.xmlIncoming + + def setXmlIncoming(self, xmlIncoming): + self.xmlIncoming = xmlIncoming + + def getTransmitScript(self): + return self.transmitScript + + def setTransmitScript(self, transmitScript): + self.transmitScript = transmitScript + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/UpdateActiveTableResponse.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/request/__init__.py similarity index 64% rename from pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/UpdateActiveTableResponse.py rename to pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/request/__init__.py index 9aea6cc366..86acf1ad9e 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/UpdateActiveTableResponse.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/request/__init__.py @@ -18,19 +18,15 @@ # further licensing information. ## -class UpdateActiveTableResponse(object): - def __init__(self): - self.sourceInfo = None - self.message = None - - def getSourceInfo(self): - return self.sourceInfo - - def getMessage(self): - return self.message - - def setSourceInfo(self, sourceInfo): - self.sourceInfo = sourceInfo - - def setMessage(self, message): - self.message = message +# File auto-generated by PythonFileGenerator + +__all__ = [ + 'MergeActiveTableRequest', + 'RetrieveRemoteActiveTableRequest', + 'SendActiveTableRequest' + ] + +from MergeActiveTableRequest import MergeActiveTableRequest +from RetrieveRemoteActiveTableRequest import RetrieveRemoteActiveTableRequest +from SendActiveTableRequest import SendActiveTableRequest + diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/UpdateActiveTableRequest.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/response/ActiveTableSharingResponse.py similarity index 55% rename from pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/UpdateActiveTableRequest.py rename to pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/response/ActiveTableSharingResponse.py index 07f606d056..db10d0e969 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/UpdateActiveTableRequest.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/response/ActiveTableSharingResponse.py @@ -20,35 +20,21 @@ # File auto-generated against equivalent DynamicSerialize Java class -class UpdateActiveTableRequest(object): +class ActiveTableSharingResponse(object): def __init__(self): - self.activeTable = None - self.xmlSource = None - self.mode = None - self.timeOffset = None + self.taskSuccess = None + self.errorMessage = None - def getActiveTable(self): - return self.activeTable + def getTaskSuccess(self): + return self.taskSuccess - def setActiveTable(self, activeTable): - self.activeTable = activeTable + def setTaskSuccess(self, taskSuccess): + self.taskSuccess = bool(taskSuccess) - def getXmlSource(self): - return self.xmlSource + def getErrorMessage(self): + return self.errorMessage - def setXmlSource(self, xmlSource): - self.xmlSource = xmlSource - - def getMode(self): - return self.mode - - def setMode(self, mode): - self.mode = mode - - def getTimeOffset(self): - return self.timeOffset - - def setTimeOffset(self, timeOffset): - self.timeOffset = timeOffset + def setErrorMessage(self, errorMessage): + self.errorMessage = errorMessage diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/response/__init__.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/response/__init__.py new file mode 100644 index 0000000000..9a6076619f --- /dev/null +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/activetable/response/__init__.py @@ -0,0 +1,28 @@ +## +# This software was developed and / or modified by Raytheon Company, +# pursuant to Contract DG133W-05-CQ-1067 with the US Government. +# +# U.S. EXPORT CONTROLLED TECHNICAL DATA +# This software product contains export-restricted data whose +# export/transfer/disclosure is restricted by U.S. law. Dissemination +# to non-U.S. persons whether in the United States or abroad requires +# an export license or other authorization. +# +# Contractor Name: Raytheon Company +# Contractor Address: 6825 Pine Street, Suite 340 +# Mail Stop B8 +# Omaha, NE 68106 +# 402.291.0100 +# +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +# File auto-generated by PythonFileGenerator + +__all__ = [ + 'ActiveTableSharingResponse' + ] + +from ActiveTableSharingResponse import ActiveTableSharingResponse +