Merge remote-tracking branch 'asm/asm_16.2.1' into master_16.2.1

Former-commit-id: 70338bff91bc02d5b0e2b2286164073afd85ed3c
This commit is contained in:
Shawn.Hooper 2016-04-26 07:21:57 -04:00
commit 44c2a22f93
6 changed files with 504 additions and 288 deletions

View file

@ -21,61 +21,84 @@ package com.raytheon.rcm.message;
import java.nio.ByteBuffer;
/**
* Represents the contents of an ORPG General Status Message.
*
* <pre>
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 2009 dfriedman Initial version
* 2016-04-22 DR 18909 dfriedman Read fields of expanded GSM.
* </pre>
*/
public class GSM extends Message {
public static final int OP_MODE_MAINTENANCE = 0;
public static final int OP_MODE_CLEAR_AIR = 1;
public static final int OP_MODE_STORM = 2;
public static final int OP_MODE_MAINTENANCE = 0;
public static final int OP_MODE_CLEAR_AIR = 1;
public static final int OP_MODE_STORM = 2;
public int opMode;
public int rdaOpStatus;
public int vcp;
public int[] cuts; // in tenths of degrees
public int rdaStatus;
public int rdaAlarms;
public int dataAvailability; // "DTE"
public int rpgOpStatus;
public int rpgAlarms;
public int rpgStatus;
public int rpgNarrowbandStatus;
public int rcc;
public int productAvailability;
public int superResCuts;
public int rdaVersion;
public int rdaChannel;
public int rpgVersion;
public int opMode;
public int rdaOpStatus;
public int vcp;
public int[] cuts; // in tenths of degrees
public int rdaStatus;
public int rdaAlarms;
public int dataAvailability; // "DTE"
public int rpgOpStatus;
public int rpgAlarms;
public int rpgStatus;
public int rpgNarrowbandStatus;
public int rcc;
public int productAvailability;
public int superResCuts;
public int rdaVersion;
public int rdaChannel;
public int rpgVersion;
public int vcpSupplemental;
public static GSM decode(byte[] msg) {
return (GSM) MD.decode(msg);
}
public static GSM decode(byte[] msg) {
return (GSM) MD.decode(msg);
}
protected void decodeBlock(int index, ByteBuffer buf) {
if (index != 1)
return;
opMode = buf.getShort();
rdaOpStatus = buf.getShort();
vcp = buf.getShort();
int nCuts = buf.getShort();
cuts = new int[nCuts];
for (int i = 0; i < 20; ++i) {
if (i < cuts.length)
cuts[i] = buf.getShort();
else
buf.getShort();
}
rdaStatus = buf.getShort();
rdaAlarms = buf.getShort();
dataAvailability = buf.getShort();
rpgOpStatus = buf.getShort();
rpgAlarms = buf.getShort();
rpgStatus = buf.getShort();
rpgNarrowbandStatus = buf.getShort();
rcc = buf.getShort();
productAvailability = buf.getShort();
superResCuts = buf.getShort();
buf.position(buf.position() + 4);
rdaVersion = buf.getShort();
rdaChannel = buf.getShort();
buf.position(buf.position() + 4);
rpgVersion = buf.getShort();
}
protected void decodeBlock(int index, ByteBuffer buf) {
if (index != 1)
return;
opMode = buf.getShort();
rdaOpStatus = buf.getShort();
vcp = buf.getShort();
int nCuts = buf.getShort();
cuts = new int[nCuts];
for (int i = 0; i < 20; ++i) {
short cut = buf.getShort();
if (i < cuts.length) {
cuts[i] = cut;
}
}
rdaStatus = buf.getShort();
rdaAlarms = buf.getShort();
dataAvailability = buf.getShort();
rpgOpStatus = buf.getShort();
rpgAlarms = buf.getShort();
rpgStatus = buf.getShort();
rpgNarrowbandStatus = buf.getShort();
rcc = buf.getShort();
productAvailability = buf.getShort();
superResCuts = buf.getShort();
buf.position(buf.position() + 4);
rdaVersion = buf.getShort();
rdaChannel = buf.getShort();
buf.position(buf.position() + 4);
rpgVersion = buf.getShort();
if (buf.remaining() < 12) {
return;
}
for (int i = 20; i < 25; ++i) {
short cut = buf.getShort();
if (i < cuts.length) {
cuts[i] = cut;
}
}
vcpSupplemental = buf.getShort();
}
}

View file

@ -22,10 +22,12 @@ package com.raytheon.rcm.otrmgr;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import com.raytheon.rcm.config.RadarConfig;
import com.raytheon.rcm.config.RadarType;
import com.raytheon.rcm.config.RcmUtil;
import com.raytheon.rcm.event.OtrEvent;
import com.raytheon.rcm.event.RadarEvent;
@ -39,6 +41,7 @@ import com.raytheon.rcm.message.MessageFormatException;
import com.raytheon.rcm.message.MessageInfo;
import com.raytheon.rcm.message.ProductRequest;
import com.raytheon.rcm.message.RequestResponse;
import com.raytheon.rcm.products.ElevationInfo;
import com.raytheon.rcm.request.Filter;
import com.raytheon.rcm.request.Request;
import com.raytheon.rcm.request.Sequence;
@ -55,9 +58,18 @@ import com.raytheon.rcm.server.RadarServer;
/**
* Manages One Time Requests for the RPGs.
* <p>
* Does not actually do much except provide a place to queue up requests while
* waiting to connect to the RPG. Does do some coalescing of duplicate
* requests.
* Implements a queue for pending requests to the RPGs. Performs some coalescing
* of duplicate requests.
*
* <pre>
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 2009 dfriedman Initial version
* 2016-04-22 DR 18909 dfriedman Accurately calculate the number of expected
* responses for multiple-elevation requests.
* </pre>
*/
public class OTRManager extends RadarEventAdapter {
@ -69,7 +81,7 @@ public class OTRManager extends RadarEventAdapter {
*/
protected boolean isReady;
protected List<Req> requests = new ArrayList<Req>();
protected List<Req> requests = new ArrayList<>();
protected GSM lastGSM;
@ -226,7 +238,7 @@ public class OTRManager extends RadarEventAdapter {
private void trySendingRequests() {
if (isReady()) {
ArrayList<Request> requestsToSend = new ArrayList<Request>();
ArrayList<Request> requestsToSend = new ArrayList<>();
long now = System.currentTimeMillis();
synchronized (this.requests) {
for (Req r : requests) {
@ -319,31 +331,55 @@ public class OTRManager extends RadarEventAdapter {
&& request.getElevationSelection() != Request.SPECIFIC_ELEVATION) {
if (lastGSM != null) {
if (request.getElevationSelection() == Request.ALL_ELEVATIONS) {
/*
* We do not get information about duplicate
* elevations. Could put in TDWR-specific knowledge.
* If vcp==80 && is-low-elevation...
*
* But probably needs something like.
* nExpectedUnknown = true and (if nExpectedUnknown
* then connMgr.idleDisconnectRadar(...)
*/
// if is tdwr and vcp80...
exactCountUnknown = true;
RadarType radarType = RcmUtil.getRadarType(getRadarConfig());
int[] completeElevationList;
nElevations = request.getElevationAngle() == 0 ? lastGSM.cuts.length
: 1;
if (radarType == RadarType.WSR
|| (radarType == RadarType.TDWR && lastGSM.rpgVersion >= 80)) {
/*
* When MESO-SAILS was added to WSR-88D, the
* expanded GSM was already available and it
* contained the complete list of elevations
* including extra SAILS elevations. Therefore,
* we can always rely on a WSR-88D's GSM for the
* list of elevation angles.
*
* Later version of the SPG contain the complete
* list of angles in an expected GSM.
*/
completeElevationList = lastGSM.cuts;
} else if (radarType == RadarType.TDWR && lastGSM.rpgVersion < 80) {
/*
* Earlier versions of the SPG do not list the
* extra low angle elevations scans. We can use
* the static elevation list instead.
*/
completeElevationList = ElevationInfo
.getInstance().getScanElevations(
radarID, lastGSM.vcp);
} else {
/*
* No choice but to guess based on the list of
* elevations from the GSM.
*/
completeElevationList = lastGSM.cuts;
exactCountUnknown = true;
}
int elevationAngle = request.getElevationAngle();
nElevations = elevationAngle == 0 ? uniqueCount(completeElevationList)
: matchCount(elevationAngle, completeElevationList);
} else if (request.getElevationSelection() == Request.N_ELEVATIONS) {
nElevations = Math.min(lastGSM.cuts.length,
nElevations = Math.min(uniqueCount(lastGSM.cuts),
request.getElevationAngle());
} else if (request.getElevationSelection() == Request.LOWER_ELEVATIONS) {
HashSet<Integer> seenAngles = new HashSet<>();
nElevations = 0;
int reqEA = request.getElevationAngle();
for (int ea : lastGSM.cuts) {
if (ea <= reqEA)
if (ea <= reqEA && !seenAngles.contains(ea)) {
++nElevations;
else
break;
seenAngles.add(ea);
}
}
} else
exactCountUnknown = true;
@ -356,9 +392,41 @@ public class OTRManager extends RadarEventAdapter {
nExpected = request.count * nElevations;
}
private int uniqueCount(int[] angles) {
HashSet<Integer> uniqueAngles = new HashSet<>();
for (int a : angles) {
uniqueAngles.add(a);
}
return uniqueAngles.size();
}
private int matchCount(int angle, int[] angles) {
int matchedAngle = findClosestAngle(angle, angles);
int count = 0;
for (int a : angles) {
if (a == matchedAngle) {
++count;
}
}
return count;
}
private int findClosestAngle(int angle, int[] angles) {
int result = Integer.MIN_VALUE;
int bestDiff = Integer.MAX_VALUE;
for (int a : angles) {
int diff = Math.abs(a - angle);
if (result == -1 || diff < bestDiff) {
result = a;
bestDiff = diff;
}
}
return result;
}
public void addHandler(OTRHandler handler) {
if (handlers == null)
handlers = new ArrayList<OTRHandler>();
handlers = new ArrayList<>();
handlers.add(handler);
}
@ -387,7 +455,7 @@ public class OTRManager extends RadarEventAdapter {
RadarServer radarServer;
// ArrayList<Req> requests = new ArrayList<Req>();
HashMap<String, RadarStatus> state = new HashMap<String, RadarStatus>();
HashMap<String, RadarStatus> state = new HashMap<>();
public OTRManager(RadarServer radarServer) {
this.radarServer = radarServer;

View file

@ -31,184 +31,198 @@ import com.raytheon.rcm.message.GraphicProduct.PDB;
/**
* A radar server component that logs various radar events.
*
* <pre>
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------ ---------- ----------- --------------------------
* 2009 dfriedma Initial version
* 2016-04-22 DR 18909 dfriedma Log fields of expanded GSM.
* </pre>
*/
public class EventLogger extends RadarEventAdapter {
public EventLogger() {
public EventLogger() {
}
}
@Override
public void handleRadarEvent(RadarEvent event) {
switch (event.getType()) {
case RadarEvent.CONNECTION_UP:
Log.eventf("%s: connected", event.getRadarID());
break;
case RadarEvent.CONNECTION_DOWN:
Log.eventf("%s: disconnected", event.getRadarID());
break;
case RadarEvent.MESSAGE_RECEIVED:
{
StringBuilder s = new StringBuilder();
byte[] msg = event.getMessageData();
int messageCode = Message.messageCodeOf(msg);
s.append("code=" + messageCode);
s.append(" size=" + msg.length);
if (messageCode == Message.GSM) {
s.append(' ');
GSM gsm = null;
try {
gsm = GSM.decode(msg);
} catch (Exception e) {
s.append("(Message decoding failed)");
}
if (gsm != null)
s.append(formatGSM(gsm));
} else if (messageCode == Message.REQUEST_RESPONSE) {
s.append(' ');
RequestResponse rr = null;
try {
rr = RequestResponse.decode(msg);
} catch (Exception e) {
s.append("(Message decoding failed)");
}
if (rr != null)
s.append(formatPRR(rr));
} else if (messageCode >= 16) {
PDB pdb = null;
@Override
public void handleRadarEvent(RadarEvent event) {
switch (event.getType()) {
case RadarEvent.CONNECTION_UP:
Log.eventf("%s: connected", event.getRadarID());
break;
case RadarEvent.CONNECTION_DOWN:
Log.eventf("%s: disconnected", event.getRadarID());
break;
case RadarEvent.MESSAGE_RECEIVED:
{
StringBuilder s = new StringBuilder();
byte[] msg = event.getMessageData();
int messageCode = Message.messageCodeOf(msg);
s.append("code=" + messageCode);
s.append(" size=" + msg.length);
if (messageCode == Message.GSM) {
s.append(' ');
GSM gsm = null;
try {
gsm = GSM.decode(msg);
} catch (Exception e) {
s.append("(Message decoding failed)");
}
if (gsm != null)
s.append(formatGSM(gsm));
} else if (messageCode == Message.REQUEST_RESPONSE) {
s.append(' ');
RequestResponse rr = null;
try {
rr = RequestResponse.decode(msg);
} catch (Exception e) {
s.append("(Message decoding failed)");
}
if (rr != null)
s.append(formatPRR(rr));
} else if (messageCode >= 16) {
PDB pdb = null;
s.append(' ');
try {
pdb = GraphicProduct.pdbOfMessage(msg);
} catch (Exception e) {
s.append("(Message decoding failed)");
}
if (pdb != null)
s.append(String.format("elev=%.1f sequence=%d"+
" vs=%3$tY-%3$tm-%3$td %3$tH:%3$tM:%3$tS #%4$d",
pdb.getElevationAngle() / 10.0, pdb.sequence,
pdb.volumeScanTime, pdb.volumeScan));
}
s.append(' ');
try {
pdb = GraphicProduct.pdbOfMessage(msg);
} catch (Exception e) {
s.append("(Message decoding failed)");
}
if (pdb != null)
s.append(String.format("elev=%.1f sequence=%d"+
" vs=%3$tY-%3$tm-%3$td %3$tH:%3$tM:%3$tS #%4$d",
pdb.getElevationAngle() / 10.0, pdb.sequence,
pdb.volumeScanTime, pdb.volumeScan));
}
Log.eventf("%s: message %s", event.getRadarID(), s.toString());
break;
}
}
}
Log.eventf("%s: message %s", event.getRadarID(), s.toString());
break;
}
}
}
protected final String[] rdaOpStatusStr = {
"auto-calib-disab", "online", "maint-req", "maint-mand", "cmd-shutdown",
"inoperable", null, "wideband-disconn"
};
protected final String[] rdaStatusStr = {
null, "startup", "standby", "restart", "operate", null, "offline-op"
};
protected final String[] rdaAlarmStr = {
"indeterminate", "tower", "pedestal", "transmitter", "receiver", "control", "comms"
};
protected final String[] dteStr = {
null, "none", "refl", "vel", "sw", "dual-pol"
};
protected final String[] rpgOpStr = {
"load-shed", "online", "maint-req", "maint-mand", "cmd-shutdown"
};
protected final String[] rpgAlarmStr = {
"none", "node-conn", null, "ctl-task-fail", "db-fail", null, "input-load-shed",
null, "store-load-shed", null, null, null, "link-fail", "redundant-channel-error",
"task-fail", "media-fail"
};
protected final String[] rpgStatusStr = {
"restart", "operate", "standby", null, "test-mode"
};
protected final String[] productAvailStr = {
"avail", "degraded", "not-avail"
};
protected final String[] prrStr = {
"no-such-msg", "no-such-prod", "not-gen", "proc-fault",
"narrowband-loadshed", "illegal-req", "mem-loadshed", "cpu-loadshed",
"slot-unavail", "task-failed", "task-unavail", "avail-next-scan",
"moment-disabled", "invalid-password", null, "aborted-scan",
"inval-prod-param", "data-seq-error", "task-term"
};
protected final String[] rdaOpStatusStr = {
"auto-calib-disab", "online", "maint-req", "maint-mand", "cmd-shutdown",
"inoperable", null, "wideband-disconn"
};
protected final String[] rdaStatusStr = {
null, "startup", "standby", "restart", "operate", null, "offline-op"
};
protected final String[] rdaAlarmStr = {
"indeterminate", "tower", "pedestal", "transmitter", "receiver", "control", "comms"
};
protected final String[] dteStr = {
null, "none", "refl", "vel", "sw", "dual-pol"
};
protected final String[] rpgOpStr = {
"load-shed", "online", "maint-req", "maint-mand", "cmd-shutdown"
};
protected final String[] rpgAlarmStr = {
"none", "node-conn", null, "ctl-task-fail", "db-fail", null, "input-load-shed",
null, "store-load-shed", null, null, null, "link-fail", "redundant-channel-error",
"task-fail", "media-fail"
};
protected final String[] rpgStatusStr = {
"restart", "operate", "standby", null, "test-mode"
};
protected final String[] productAvailStr = {
"avail", "degraded", "not-avail"
};
protected final String[] prrStr = {
"no-such-msg", "no-such-prod", "not-gen", "proc-fault",
"narrowband-loadshed", "illegal-req", "mem-loadshed", "cpu-loadshed",
"slot-unavail", "task-failed", "task-unavail", "avail-next-scan",
"moment-disabled", "invalid-password", null, "aborted-scan",
"inval-prod-param", "data-seq-error", "task-term"
};
protected final String[] vcpSupplementalStr = {
"AVSET", "SAILS", "site-specific-vcp", "RxRN", "CBT"
};
protected String formatBits(short bits, String[] strings) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < 16; i++) {
if ((bits & (1 << i)) != 0) {
if (result.length() > 0)
result.append(',');
String s = null;
if (i < strings.length)
s = strings[i];
if (s == null)
s = "unk" + Integer.toString(15 - i);
result.append(s);
}
}
return result.toString();
}
protected String formatBits(short bits, String[] strings) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < 16; i++) {
if ((bits & (1 << i)) != 0) {
if (result.length() > 0)
result.append(',');
String s = null;
if (i < strings.length)
s = strings[i];
if (s == null)
s = "unk" + Integer.toString(15 - i);
result.append(s);
}
}
return result.toString();
}
protected String formatPrrBits(int bits, String[] strings) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < 32; i++) {
// PRR bits are defined from the MSB on down, so
// note the (31-i)
if ((bits & (1 << (31-i))) != 0) {
if (result.length() > 0)
result.append(',');
String s = null;
if (i < strings.length)
s = strings[i];
if (s == null)
s = "unk" + Integer.toString(31 - i);
result.append(s);
}
}
return result.toString();
}
protected String formatPrrBits(int bits, String[] strings) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < 32; i++) {
// PRR bits are defined from the MSB on down, so
// note the (31-i)
if ((bits & (1 << (31-i))) != 0) {
if (result.length() > 0)
result.append(',');
String s = null;
if (i < strings.length)
s = strings[i];
if (s == null)
s = "unk" + Integer.toString(31 - i);
result.append(s);
}
}
return result.toString();
}
protected String formatGSM(GSM gsm) {
StringBuilder o = new StringBuilder();
String s;
protected String formatGSM(GSM gsm) {
StringBuilder o = new StringBuilder();
String s;
switch (gsm.opMode) {
case GSM.OP_MODE_CLEAR_AIR: s = "clear-air"; break;
case GSM.OP_MODE_STORM: s = "storm"; break;
case GSM.OP_MODE_MAINTENANCE: s = "maintenance"; break;
default: s = "(" +Integer.toString(gsm.opMode) + ")";
}
o.append("opMode=" + s);
switch (gsm.opMode) {
case GSM.OP_MODE_CLEAR_AIR: s = "clear-air"; break;
case GSM.OP_MODE_STORM: s = "storm"; break;
case GSM.OP_MODE_MAINTENANCE: s = "maintenance"; break;
default: s = "(" +Integer.toString(gsm.opMode) + ")";
}
o.append("opMode=" + s);
o.append(" vcp=" + gsm.vcp);
o.append(" cuts=" + Arrays.toString(gsm.cuts));
o.append(" vcp=" + gsm.vcp);
o.append(" cuts=" + Arrays.toString(gsm.cuts));
o.append(String.format(" rdaOp=%s rdaStat=%s rdaAlarm=%s dte=%s rpgOp=%s rpgStat=%s rpgAlarm=%s",
formatBits((short) gsm.rdaOpStatus, rdaOpStatusStr),
formatBits((short) gsm.rdaStatus, rdaStatusStr),
formatBits((short) gsm.rdaAlarms, rdaAlarmStr),
formatBits((short) gsm.dataAvailability, dteStr),
formatBits((short) gsm.rpgOpStatus, rpgOpStr),
formatBits((short) gsm.rpgStatus, rpgStatusStr),
formatBits((short) gsm.rpgAlarms, rpgAlarmStr)));
o.append(String.format(" rdaOp=%s rdaStat=%s rdaAlarm=%s dte=%s rpgOp=%s rpgStat=%s rpgAlarm=%s",
formatBits((short) gsm.rdaOpStatus, rdaOpStatusStr),
formatBits((short) gsm.rdaStatus, rdaStatusStr),
formatBits((short) gsm.rdaAlarms, rdaAlarmStr),
formatBits((short) gsm.dataAvailability, dteStr),
formatBits((short) gsm.rpgOpStatus, rpgOpStr),
formatBits((short) gsm.rpgStatus, rpgStatusStr),
formatBits((short) gsm.rpgAlarms, rpgAlarmStr)));
o.append(String.format(" avail=%s",
formatBits((short) gsm.productAvailability, productAvailStr)));
o.append(String.format(" avail=%s",
formatBits((short) gsm.productAvailability, productAvailStr)));
o.append(String.format(" rdaVer=%.1f rpgVer=%.1f", gsm.rdaVersion/10.0, gsm.rpgVersion/10.));
o.append(String.format(" suppl=%s",
formatBits((short) gsm.vcpSupplemental, vcpSupplementalStr)));
return o.toString();
}
o.append(String.format(" rdaVer=%.1f rpgVer=%.1f", gsm.rdaVersion/10.0, gsm.rpgVersion/10.));
protected String formatPRR(RequestResponse rr) {
StringBuilder o = new StringBuilder();
return o.toString();
}
o.append(String.format("productCode=%d sequence=%d elev=%d flags=%s",
rr.productCode,
rr.sequence,
rr.elevationAngle,
formatPrrBits(rr.errorCode, prrStr)));
protected String formatPRR(RequestResponse rr) {
StringBuilder o = new StringBuilder();
return o.toString();
}
o.append(String.format("productCode=%d sequence=%d elev=%d flags=%s",
rr.productCode,
rr.sequence,
rr.elevationAngle,
formatPrrBits(rr.errorCode, prrStr)));
return o.toString();
}
}

View file

@ -369,6 +369,7 @@ import com.raytheon.viz.ui.simulatedtime.SimulatedTimeOperations;
* 06Jan2016 5225 randerso Fix problem with mixed case not getting converted to upper case
* when multiple text editors are open on the same product.
* Mar 17, 2016 RM 18727 D. Friedman Fix use of verification listener when entering and exiting editor.
* Apr 15, 2016 RM 18870 D. Friedman Replace commas with ellipses only at start of edit and then word-wrap.
*
* </pre>
*
@ -4254,20 +4255,19 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
// section
setCurrentHeaderAndBody();
// if product is a WarnGen product and is not enabled for mixed case
// transmission, replace all commas with ellipses
if ((product != null) && warngenPils.contains(product.getNnnid())
&& !MixedCaseProductSupport.isMixedCase(product.getNnnid())) {
textEditor.setText(textEditor.getText()
.replaceAll(", {0,1}", "..."));
}
// Mark the uneditable warning text
if (markUneditableText(textEditor)) {
// Enable listener to monitor attempt to edit locked text
verifyUndeditableText = true;
}
// if product is a WarnGen product and is not enabled for mixed case
// transmission, replace all commas with ellipses
if ((product != null) && warngenPils.contains(product.getNnnid())
&& !MixedCaseProductSupport.isMixedCase(product.getNnnid())) {
replaceCommasWithEllipses(product);
}
// Set the menu buttons to reflect the edit mode.
editorButtonMenuStates(inEditMode);
@ -4295,6 +4295,60 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
editHeader("warning", true);
}
private void replaceCommasWithEllipses(StdTextProduct product) {
boolean wasVerifying = verifyUndeditableText;
try {
verifyUndeditableText = false;
/*
* Performing wrapping as few times as possible to reduce the
* chances of breaking the product format. Also, the location list
* does not wrap properly unless all commas in the paragraph have
* been changed to ellipses.
*/
Pattern p = Pattern.compile(", {0,1}");
int pendingParagraphLineStart = -1;
while (true) {
String text = textEditor.getText();
Matcher m = p.matcher(text);
if (! m.find())
break;
int line = textEditor.getLineAtOffset(m.start());
int paragraphLineStart = findParagraphStart(line);
String lineText = textEditor.getLine(line);
boolean lineNeedsWrap = lineText.length()
- (m.end() - m.start()) + 3 > charWrapCol;
if (pendingParagraphLineStart >= 0
&& paragraphLineStart != pendingParagraphLineStart
&& lineNeedsWrap) {
wrapWholeParagraphAtLine(pendingParagraphLineStart);
pendingParagraphLineStart = -1;
// Line numbers may have changed so restart.
continue;
}
textEditor.replaceTextRange(m.start(), m.end() - m.start(), "...");
if (lineNeedsWrap) {
pendingParagraphLineStart = paragraphLineStart;
}
}
if (pendingParagraphLineStart >= 0) {
wrapWholeParagraphAtLine(pendingParagraphLineStart);
}
} finally {
verifyUndeditableText = wasVerifying;
}
}
void wrapWholeParagraphAtLine(int paragraphLineStart) {
String line = textEditor.getLine(paragraphLineStart);
// Avoid rewrapInternal early bailout check.
if (line.length() < charWrapCol
&& line.indexOf("...") == line.lastIndexOf("...")) {
paragraphLineStart++;
}
int offset = textEditor.getOffsetAtLine(paragraphLineStart);
rewrap(offset, offset);
}
/**
* Cancel the editor mode.
*
@ -4402,16 +4456,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
textEditor.setText(originalText);
}
// if product is a WarnGen product and is not enabled for mixed case
// transmission, replace all commas with ellipses
StdTextProduct product = TextDisplayModel.getInstance()
.getStdTextProduct(token);
if ((product != null) && warngenPils.contains(product.getNnnid())
&& !MixedCaseProductSupport.isMixedCase(product.getNnnid())) {
textEditor.setText(textEditor.getText()
.replaceAll(", {0,1}", "..."));
}
markUneditableText(textEditor);
// Disable the lockable text listener since the application is no
@ -7109,14 +7153,6 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
textEditor.append(textProduct);
// if product is a WarnGen product and is not enabled for mixed case
// transmission, replace all commas with ellipses
if (warngenPils.contains(product.getNnnid())
&& !MixedCaseProductSupport.isMixedCase(product.getNnnid())) {
textEditor.setText(textEditor.getText()
.replaceAll(", {0,1}", "..."));
}
markUneditableText(textEditor);
// Update text display model with the product that was
@ -8038,7 +8074,10 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
paragraphStart = paragraphStart.toUpperCase();
// is this the locations paragraph?
if (paragraphStart.startsWith("* LOCATIONS")) {
if (paragraphStart.startsWith("* LOCATIONS")
|| paragraphStart.startsWith(("* SOME LOCATIONS"))
|| paragraphStart.startsWith(("LOCATIONS IMPACTED"))
|| paragraphStart.startsWith(("SOME LOCATIONS THAT"))) {
inLocations = true;
}
@ -8079,7 +8118,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
}
if (line.length() <= charWrapCol) {
extendShortLine(lineNumber, padding);
extendShortLine(lineNumber, padding, inLocations);
if (textEditor.getLine(lineNumber).length() <= charWrapCol) {
// extended line is still short enough do not wrap
if (lineNumber < endWrapLine) {
@ -8110,8 +8149,9 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
*
* @param lineNumber
* @param padding
* @param inLocations
*/
private void extendShortLine(int lineNumber, final String padding) {
private void extendShortLine(int lineNumber, final String padding, boolean inLocations) {
// if the line is too short move the next line up
// if there is a next line
String line = textEditor.getLine(lineNumber);
@ -8190,10 +8230,12 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
String wordSpace = "";
if (noSeparatorPattern.matcher(endLine).matches()
&& noSeparatorPattern.matcher(startNextLine)
.matches()) {
.matches()
&& (!inLocations || !line.endsWith("..."))) {
// Put a space between words when merging the lines.
wordSpace = " ";
}
textEditor.replaceTextRange(newlinePosition, deleteLen,
wordSpace);
String afterReplace = textEditor.getText();
@ -8207,7 +8249,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
// is this line still too short?
if (textEditor.getLine(lineNumber).length() <= charWrapCol) {
extendShortLine(lineNumber, padding);
extendShortLine(lineNumber, padding, inLocations);
}
}
}
@ -8460,7 +8502,7 @@ public class TextEditorDialog extends CaveSWTDialog implements VerifyListener,
private void recompileRegex() {
this.standardWrapRegex = Pattern.compile("( |..).{1,"
+ (charWrapCol - 3) + "}(\\s|-)");
this.locationsFirstRegex = Pattern.compile("^\\* LOCATIONS [^\\.]{1,"
this.locationsFirstRegex = Pattern.compile("^(?:\\* (?:SOME )?LOCATIONS|LOCATIONS IMPACTED|SOME LOCATIONS THAT) [^\\.]{1,"
+ (charWrapCol - 13) + "}\\s");
this.locationsBodyRegex = Pattern.compile("(( |..).{1,"
+ (charWrapCol - 5) + "}\\.\\.\\.)|(( |..).{1,"

View file

@ -1,19 +1,39 @@
package com.raytheon.viz.warnings.rsc;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.dataplugin.warning.AbstractWarningRecord;
import com.raytheon.uf.common.dataquery.requests.DbQueryRequest;
import com.raytheon.uf.common.dataquery.requests.RequestConstraint;
import com.raytheon.uf.common.dataquery.responses.DbQueryResponse;
import com.raytheon.uf.viz.core.RecordFactory;
import com.raytheon.uf.viz.core.alerts.AbstractAlertMessageParser;
import com.raytheon.uf.viz.core.alerts.AlertMessage;
import com.raytheon.uf.viz.core.exception.VizException;
import com.raytheon.uf.viz.core.requests.ThriftClient;
import com.raytheon.uf.viz.core.rsc.AbstractRequestableResourceData;
import com.raytheon.uf.viz.core.rsc.AbstractVizResource;
import com.raytheon.uf.viz.core.rsc.LoadProperties;
/**
* SOFTWARE HISTORY
*
* Date Ticket# Engineer Description
* ------------- -------- ----------- --------------------------
* Apr 21, 2016 DR 18905 Qinglu Lin Added code to handle no SPS auto-update issue.
*
*/
@XmlAccessorType(XmlAccessType.NONE)
public class CWASPSResourceData extends WWAResourceData {
private static AlertMessageToPDOParserSPS alertParser = new AlertMessageToPDOParserSPS();
/*
* (non-Javadoc)
*
@ -34,4 +54,42 @@ public class CWASPSResourceData extends WWAResourceData {
return new CWASPSResource(this, loadProperties);
}
@Override
public AbstractAlertMessageParser getAlertParser() {
return alertParser;
}
private static class AlertMessageToPDOParserSPS extends AbstractAlertMessageParser {
@Override
public Object parseAlertMessage(AlertMessage message,
AbstractRequestableResourceData reqResourceData) throws VizException {
Object objectToSend = null;
Map<String, Object> attribs = new HashMap<>(message.decodedAlert);
if (reqResourceData.isUpdatingOnMetadataOnly()) {
PluginDataObject record = RecordFactory.getInstance()
.loadRecordFromMap(attribs);
objectToSend = record;
} else {
/*
* TODO avoid requesting data that will not be used, for example
* when time matching won't allow the frame to be displayed.
*/
attribs.remove(PluginDataObject.DATAURI_ID);
DbQueryRequest request = new DbQueryRequest(
RequestConstraint.toConstraintMappingExcludeNull(attribs));
request.setLimit(1);
DbQueryResponse response = (DbQueryResponse) ThriftClient
.sendRequest(request);
PluginDataObject[] pdos = response
.getEntityObjects(PluginDataObject.class);
if (pdos.length > 0) {
objectToSend = pdos[0];
}
}
return objectToSend;
}
}
}

View file

@ -62,6 +62,7 @@ import com.raytheon.uf.common.wmo.WMOTimeParser;
* Jun 19, 2014 3226 bclement added validator callback
* Jul 07, 2015 4581 skorolev Corrected decodeStrikes to avoid BufferUnderflowException.
* Apr 07, 2016 DR18763 mgamazaychikov Switched to using LightningWMOHeader.
* Apr 21, 2016 DR18849 mgamazaychikov Decrypt all data in decrypt method.
*
* </pre>
*
@ -200,9 +201,19 @@ public class TotalLightningDecoder {
*/
private PluginDataObject[] decodeInternal(LightningWMOHeader wmoHdr,
String fileName, byte[] pdata) throws DecoderException {
if (!validFlashPacket(pdata, COMBINATION_PACKET_HEADER_SIZE)) {
/* assume data is encrypted if we can't understand it */
pdata = decrypt(wmoHdr, fileName, pdata);
byte[] pdataPreDecrypt = pdata;
// determine if the data is encrypted or not based on comparing
// checksums for flash packet
pdata = decrypt(wmoHdr, fileName, pdata);
boolean isDecryptedValid = validFlashPacket(pdata,
COMBINATION_PACKET_HEADER_SIZE);
boolean isPreDecryptedValid = validFlashPacket(pdataPreDecrypt,
COMBINATION_PACKET_HEADER_SIZE);
// assume that all data is encrypted, so decrypt it
if (!isDecryptedValid && isPreDecryptedValid) {
// this means that data is not encrypted, proceed without
// decryption
pdata = pdataPreDecrypt;
}
List<LightningStrikePoint> strikes = decodeStrikes(fileName, pdata);
if (!strikes.isEmpty()) {