Omaha #4806: Create method so GFE smart tools and procedures can transmit text products.

Change-Id: Iada380912df9cabf744eb004d1f260713a62db7b

Former-commit-id: b96f462d21b1483e34b36533abfb27e2fb9e5f74
This commit is contained in:
David Gillingham 2015-08-28 13:32:53 -05:00
parent e16ebbae02
commit 534d43b455
3 changed files with 245 additions and 101 deletions

View file

@ -72,6 +72,7 @@
# Aug 26, 2015 4809 randerso Added option group parameter to editAreaList()
# Aug 26, 2015 4804 dgilling Added callTextFormatter().
# Aug 27, 2015 4805 dgilling Added saveCombinationsFile().
# Aug 27, 2015 4806 dgilling Added transmitTextProduct().
########################################################################
import types, string, time, sys
from math import *
@ -108,6 +109,7 @@ from com.raytheon.viz.gfe.dialogs.formatterlauncher import ConfigData
ProductStateEnum = ConfigData.ProductStateEnum
from com.raytheon.viz.gfe.textformatter import FormatterUtil
from com.raytheon.viz.gfe.textformatter import TextProductFinishWaiter
from com.raytheon.viz.gfe.textformatter import TextProductTransmitter
class SmartScript(BaseTool.BaseTool):
@ -2640,7 +2642,6 @@ class SmartScript(BaseTool.BaseTool):
raise RuntimeError(msg)
return product
def saveCombinationsFile(self, name, combinations):
"""
Save the specified zone combinations to the localization data store.
@ -2665,3 +2666,27 @@ class SmartScript(BaseTool.BaseTool):
combo_list = JUtil.pyValToJavaObj([[str(zone) for zone in group] for group in combinations])
CombinationsFileUtil.generateAutoCombinationsFile(combo_list, str(name))
def transmitTextProduct(self, product, wanPil, wmoType):
"""
Transmit the specified product. Will automatically detect if GFE is
operating in OPERATIONAL or PRACTICE mode and send using the appropriate
route.
Args:
product: the text or body of the product to transmit.
wanPil: the AWIPS WAN PIL for the product
wmoType: The WMO type of the product.
Returns:
The status of the transmission request as a ProductStateEnum.
"""
wanPil = str(wanPil)
product = str(product)
wmoType = str(wmoType)
transmitter = TextProductTransmitter(product, wanPil, wmoType)
practice = self.gfeOperatingMode()=="PRACTICE"
status = transmitter.transmitProduct(practice)
return status

View file

@ -19,11 +19,9 @@
**/
package com.raytheon.viz.gfe.dialogs.formatterlauncher;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
@ -40,23 +38,15 @@ import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import com.raytheon.uf.common.activetable.SendPracticeProductRequest;
import com.raytheon.uf.common.activetable.response.GetNextEtnResponse;
import com.raytheon.uf.common.dissemination.OUPRequest;
import com.raytheon.uf.common.dissemination.OUPResponse;
import com.raytheon.uf.common.dissemination.OfficialUserProduct;
import com.raytheon.uf.common.serialization.comm.IServerRequest;
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.time.SimulatedTime;
import com.raytheon.uf.common.time.TimeRange;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.viz.core.auth.UserController;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.viz.core.mode.CAVEMode;
import com.raytheon.viz.gfe.product.TextDBUtil;
import com.raytheon.viz.gfe.textformatter.TextProductTransmitter;
import com.raytheon.viz.gfe.vtec.GFEVtecUtil;
import com.raytheon.viz.texteditor.util.VtecObject;
import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
@ -89,6 +79,8 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog;
* Feb 26, 2015 4126 randerso Ensure transmit/store is properly cancelled if dialog is closed
* Code cleanup
* Apr 20, 2015 4027 randerso Renamed ProductStateEnum with an initial capital
* Aug 28, 2015 4806 dgilling Extract code for product transmission into
* its own class.
*
* </pre>
*
@ -102,8 +94,6 @@ public class StoreTransmitDlg extends CaveSWTDialog {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(StoreTransmitDlg.class);
private static int SEQ_NUMBER = 0;
/**
* Product ID text control.
*/
@ -529,93 +519,14 @@ public class StoreTransmitDlg extends CaveSWTDialog {
* true if we are transmitting a practice product
*/
private void transmitProduct(boolean practice) {
IServerRequest req = null;
if (practice) {
SendPracticeProductRequest practiceReq = new SendPracticeProductRequest();
practiceReq.setNotifyGFE(true);
practiceReq.setProductText(productText);
if (!SimulatedTime.getSystemTime().isRealTime()) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(
"yyyyMMdd_HHmm");
dateFormatter.setTimeZone(TimeZone.getTimeZone("GMT"));
practiceReq.setDrtString(dateFormatter.format(SimulatedTime
.getSystemTime().getTime()));
}
req = practiceReq;
} else {
OUPRequest oupReq = new OUPRequest();
OfficialUserProduct oup = new OfficialUserProduct();
// make sure the awipsWanPil is exactly 10 characters space-padded
// long
String awipsWanPil = String.format("%-10s", productIdText.getText()
.trim());
oup.setAwipsWanPil(awipsWanPil);
oup.setProductText(productText);
String tempName = awipsWanPil + "-" + SEQ_NUMBER + "-"
+ (System.currentTimeMillis() / TimeUtil.MILLIS_PER_SECOND);
oup.setFilename(tempName);
String type = parentEditor.getProductType();
if (!type.equals("rou") && !type.equals("res")) {
oup.setWmoType(type);
}
// oup.setAddress(parentEditor.getAutoSendAddress());
oup.setNeedsWmoHeader(false);
oup.setSource("GFE");
oupReq.setProduct(oup);
oupReq.setUser(UserController.getUserObject());
req = oupReq;
}
try {
Object response = ThriftClient.sendRequest(req);
// TODO need a response on the other one?
// it's going async....
if (response instanceof OUPResponse) {
OUPResponse resp = (OUPResponse) response;
Priority p = null;
if (!resp.hasFailure()) {
p = Priority.EVENTA;
sendTransmissionStatus(ConfigData.ProductStateEnum.Transmitted);
} else {
// determine the failure type and priority
ConfigData.ProductStateEnum state = null;
if (resp.isSendLocalSuccess()) {
state = ConfigData.ProductStateEnum.Transmitted;
} else {
state = ConfigData.ProductStateEnum.Failed;
}
p = Priority.EVENTA;
if (!resp.isAttempted()) {
// if was never attempted to send or store even locally
p = Priority.CRITICAL;
} else if (!resp.isSendLocalSuccess()) {
// if send/store locally failed
p = Priority.CRITICAL;
} else if (!resp.isSendWANSuccess()) {
// if send to WAN failed
if (resp.getNeedAcknowledgment()) {
// if ack was needed, if it never sent then no ack
// was recieved
p = Priority.CRITICAL;
} else {
// if no ack was needed
p = Priority.EVENTA;
}
} else if (resp.getNeedAcknowledgment()
&& !resp.isAcknowledged()) {
// if sent but not acknowledged when acknowledgment is
// needed
p = Priority.CRITICAL;
}
sendTransmissionStatus(state);
}
statusHandler.handle(p, resp.getMessage());
}
TextProductTransmitter transmitter = new TextProductTransmitter(
productText, productIdText.getText(),
parentEditor.getProductType());
ConfigData.ProductStateEnum state = transmitter
.transmitProduct(practice);
sendTransmissionStatus(state);
this.parentEditor.setProductText(productText, false);
this.parentEditor.brain();
} catch (VizException e) {
@ -623,8 +534,6 @@ public class StoreTransmitDlg extends CaveSWTDialog {
sendTransmissionStatus(ConfigData.ProductStateEnum.Failed);
this.parentEditor.revive();
}
SEQ_NUMBER++;
}
private void sendTransmissionStatus(ConfigData.ProductStateEnum status) {

View file

@ -0,0 +1,210 @@
/**
* 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.viz.gfe.textformatter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicInteger;
import com.raytheon.uf.common.activetable.SendPracticeProductRequest;
import com.raytheon.uf.common.dataplugin.text.db.MixedCaseProductSupport;
import com.raytheon.uf.common.dissemination.OUPRequest;
import com.raytheon.uf.common.dissemination.OUPResponse;
import com.raytheon.uf.common.dissemination.OfficialUserProduct;
import com.raytheon.uf.common.serialization.comm.IServerRequest;
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.time.SimulatedTime;
import com.raytheon.uf.common.time.util.TimeUtil;
import com.raytheon.uf.viz.core.auth.UserController;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.viz.gfe.dialogs.formatterlauncher.ConfigData;
import com.raytheon.viz.gfe.dialogs.formatterlauncher.ConfigData.ProductStateEnum;
/**
* Handles product transmission for GFE text products, using handleOUP for
* operational products and the {@code SendPracticeProduct} thrift request for
* practice products.
*
* <pre>
*
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* Aug 28, 2015 #4806 dgilling Initial creation
*
* </pre>
*
* @author dgilling
* @version 1.0
*/
public final class TextProductTransmitter {
private static final transient IUFStatusHandler statusHandler = UFStatus
.getHandler(TextProductTransmitter.class);
private static final AtomicInteger SEQ_NUMBER = new AtomicInteger();
private final String productText;
private final String pil;
private final String wmoType;
/**
* Constructor
*
* @param productText
* Product text to transmit
* @param pil
* AWIPS WAN PIL of the product to transmit
* @param wmoType
* WMO type for the product.
*/
public TextProductTransmitter(String productText, String pil, String wmoType) {
this.pil = pil;
this.productText = MixedCaseProductSupport.conditionalToUpper(
this.pil.substring(4, 7), productText);
this.wmoType = wmoType;
}
/**
* Transmit the product.
*
* @param practice
* Whether to transmit the product as an operational or practice
* product.
* @return Product transmission status.
* @throws VizException
* If the transmission request threw an exception during
* server-side processing.
*/
public ProductStateEnum transmitProduct(boolean practice)
throws VizException {
IServerRequest req = (!practice) ? constructOperationalRequest()
: constructPracticeRequest();
Object response = ThriftClient.sendRequest(req);
/*
* Currently processing of the practice product happens async, so as
* long as the request didn't throw an exception, we can only assume it
* succeeded.
*/
ProductStateEnum status = (response instanceof OUPResponse) ? processOupResponse((OUPResponse) response)
: ProductStateEnum.Transmitted;
return status;
}
private SendPracticeProductRequest constructPracticeRequest() {
SendPracticeProductRequest practiceReq = new SendPracticeProductRequest();
practiceReq.setNotifyGFE(true);
practiceReq.setProductText(productText);
practiceReq.setDrtString(getDRTString());
return practiceReq;
}
private OUPRequest constructOperationalRequest() {
OfficialUserProduct oup = new OfficialUserProduct();
oup.setProductText(productText);
/*
* ensure the awipsWanPil is exactly 10 characters space-padded long
*/
String awipsWanPil = String.format("%-10s", pil.trim());
oup.setAwipsWanPil(awipsWanPil);
String tempName = awipsWanPil + "-" + SEQ_NUMBER.incrementAndGet()
+ "-"
+ (System.currentTimeMillis() / TimeUtil.MILLIS_PER_SECOND);
oup.setFilename(tempName);
if (!wmoType.equals("rou") && !wmoType.equals("res")) {
oup.setWmoType(wmoType);
}
oup.setNeedsWmoHeader(false);
oup.setSource("GFE");
OUPRequest oupReq = new OUPRequest();
oupReq.setProduct(oup);
oupReq.setUser(UserController.getUserObject());
return oupReq;
}
private ProductStateEnum processOupResponse(OUPResponse response) {
ProductStateEnum retVal = null;
if (response instanceof OUPResponse) {
OUPResponse resp = response;
Priority p = null;
if (!resp.hasFailure()) {
p = Priority.EVENTA;
retVal = ConfigData.ProductStateEnum.Transmitted;
} else {
// determine the failure type and priority
if (resp.isSendLocalSuccess()) {
retVal = ConfigData.ProductStateEnum.Transmitted;
} else {
retVal = ConfigData.ProductStateEnum.Failed;
}
p = Priority.EVENTA;
if (!resp.isAttempted()) {
// if was never attempted to send or store even locally
p = Priority.CRITICAL;
} else if (!resp.isSendLocalSuccess()) {
// if send/store locally failed
p = Priority.CRITICAL;
} else if (!resp.isSendWANSuccess()) {
// if send to WAN failed
if (resp.getNeedAcknowledgment()) {
// if ack was needed, if it never sent then no ack
// was recieved
p = Priority.CRITICAL;
} else {
// if no ack was needed
p = Priority.EVENTA;
}
} else if (resp.getNeedAcknowledgment()
&& !resp.isAcknowledged()) {
// if sent but not acknowledged when acknowledgment is
// needed
p = Priority.CRITICAL;
}
}
statusHandler.handle(p, resp.getMessage());
}
return retVal;
}
private static String getDRTString() {
String time = null;
if (!SimulatedTime.getSystemTime().isRealTime()) {
DateFormat gmtFormatter = new SimpleDateFormat("yyyyMMdd_HHmm");
gmtFormatter.setTimeZone(TimeZone.getTimeZone("GMT"));
time = gmtFormatter.format(SimulatedTime.getSystemTime().getTime());
}
return time;
}
}