Merge "Issue #2243 Prevented invalid follow ups." into omaha_13.5.1

Former-commit-id: c314bf2092 [formerly ef5a7fb83a] [formerly 69dd7b66fa] [formerly 69645f03dc [formerly 69dd7b66fa [formerly db71f51d18af219c2fdee6dcbe077be50d4e9e54]]]
Former-commit-id: 69645f03dc
Former-commit-id: e115b93102485b11368b55772e8726745f744ad8 [formerly d9e82e20fd]
Former-commit-id: 696ee07b3f
This commit is contained in:
Lee Venable 2013-08-08 16:40:59 -05:00 committed by Gerrit Code Review
commit b46745eebb
4 changed files with 162 additions and 55 deletions

View file

@ -37,6 +37,7 @@ import com.raytheon.uf.common.time.util.TimeUtil;
* ------------ ---------- ----------- --------------------------
* Initial creation
* May 7, 2013 1973 rferrel Changes to properly display Issue Time.
* Aug 7, 2013 2243 jsanchez Set all the attributes of an AbstractWarningRecord and added an expiration string.
*
* </pre>
*
@ -50,22 +51,25 @@ public class FollowupData extends WarningRecord {
/**
* String displayed in the drop down update list.
*/
public String displayString;
private String displayString;
/**
* String used to test if this object is equivalent to one of the updated
* items in the drop down.
*/
public String equvialentString;
private String equvialentString;
/**
* Information string used when the follow up is no longer valid or allowed.
*/
private String expirationString;
public FollowupData(WarningAction action, AbstractWarningRecord record) {
super((WarningRecord) record);
setAct(action.toString());
setOfficeid(record.getOfficeid());
setPhen(record.getPhen());
setSig(record.getSig());
setEtn(record.getEtn());
displayString = getDisplayString(action, record);
displayString = createDisplayString(action, record);
expirationString = createExpirationString(action);
}
/**
@ -76,7 +80,7 @@ public class FollowupData extends WarningRecord {
* @param record
* @return
*/
private String getDisplayString(WarningAction status,
private String createDisplayString(WarningAction status,
AbstractWarningRecord record) {
StringBuilder rval = new StringBuilder();
if (record.getProductClass().equals("T")) {
@ -98,6 +102,29 @@ public class FollowupData extends WarningRecord {
return rval.toString();
}
/**
* Creates the expiration string based on the action. The expiration string
* provides an explanation of why the follow up data is no longer valid.
*
* @param action
* @return
*/
private String createExpirationString(WarningAction action) {
String message = null;
if (action == WarningAction.NEW) {
message = "Reissue no longer allowed; after 30 minutes of warning expiration.";
} else if (action == WarningAction.COR) {
message = "Correction no longer allowed; after 10 minutes of warning issuance.";
} else if (action == WarningAction.CAN) {
message = "Cancellation no longer allowed; within 10 minutes of warning expiration.";
} else if (action == WarningAction.CON) {
message = "Continuation no longer allowed; within 5 minutes of warning expiration.";
} else if (action == WarningAction.EXP) {
message = "Expiration no longer allowed; after 10 minutes of warning expiration.";
}
return message;
}
/**
* Builds a string informing the user when a product was issued or when it
* will expire. This is appended to the product in the "Update List"
@ -143,4 +170,16 @@ public class FollowupData extends WarningRecord {
&& this.getEtn().equals(obj.getEtn());
}
public String getDisplayString() {
return displayString;
}
public String getEquvialentString() {
return equvialentString;
}
public String getExpirationString() {
return expirationString;
}
}

View file

@ -69,7 +69,6 @@ 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.viz.core.IDisplayPaneContainer;
import com.raytheon.uf.viz.core.VizApp;
import com.raytheon.uf.viz.core.exception.VizException;
@ -142,6 +141,7 @@ import com.vividsolutions.jts.geom.Polygon;
* Jun 24, 2013 DR 16317 D. Friedman Handle "motionless" track.
* Jul 16, 2013 DR 16387 Qinglu Lin Reset totalSegments for each followup product.
* Jul 29, 2013 DR 16352 D. Friedman Move 'result' to okPressed().
* Aug 6, 2013 2243 jsanchez Refreshed the follow up list every minute.
* </pre>
*
* @author chammack
@ -274,9 +274,9 @@ public class WarngenDialog extends CaveSWTDialog implements
private Group productType;
private IWarngenObserver wed = new WarningSender();
private boolean invalidFollowUpAction = false;
private TimeRange timeRange = null;
private IWarngenObserver wed = new WarningSender();
public WarngenDialog(Shell parentShell, WarngenLayer layer) {
super(parentShell, SWT.CLOSE | SWT.MODELESS | SWT.BORDER | SWT.TITLE,
@ -823,6 +823,9 @@ public class WarngenDialog extends CaveSWTDialog implements
|| warngenLayer.getPolygon().isEmpty()) {
str += WarngenConstants.INSTRUCTION_NO_SHADED_AREA;
createTextButtonEnabled = false;
} else if (invalidFollowUpAction) {
str += "Select a different follow up item";
createTextButtonEnabled = false;
}
if (okButton != null) {
okButton.setEnabled(createTextButtonEnabled);
@ -831,8 +834,8 @@ public class WarngenDialog extends CaveSWTDialog implements
if (warngenLayer.getWarningArea() == null) {
str = "Area selected has no overlap with current area of responsibility";
} else {
if (warngenLayer.getStormTrackState().isInitiallyMotionless() &&
! warngenLayer.getStormTrackState().isNonstationary()) {
if (warngenLayer.getStormTrackState().isInitiallyMotionless()
&& !warngenLayer.getStormTrackState().isNonstationary()) {
str += WarngenConstants.INSTRUCTION_DRAG_STORM + "\n";
} else if (warngenLayer.getStormTrackState().trackVisible) {
str += "Adjust Centroid in any Frame" + "\n";
@ -880,7 +883,7 @@ public class WarngenDialog extends CaveSWTDialog implements
if (FollowUpUtil.checkApplicable(site,
warngenLayer.getConfiguration(), warnings.get(i), act)) {
FollowupData data = new FollowupData(act, warnings.get(i));
updateListCbo.setData(data.displayString, data);
updateListCbo.setData(data.getDisplayString(), data);
if (act == WarningAction.NEW) {
newYes = true;
} else if (act == WarningAction.EXT) {
@ -892,7 +895,7 @@ public class WarngenDialog extends CaveSWTDialog implements
} else if (act == WarningAction.COR) {
corYes = true;
}
dropDownItems.add(data.displayString);
dropDownItems.add(data.getDisplayString());
}
}
}
@ -930,19 +933,54 @@ public class WarngenDialog extends CaveSWTDialog implements
updateListCbo.add(dropDownItems.get(i));
}
// Select the previously selected item.
invalidFollowUpAction = false;
if (currentSelection != null) {
boolean isValid = false;
for (int i = 0; i < updateListCbo.getItemCount(); i++) {
if (updateListCbo.getItem(i).startsWith(
currentSelection.equvialentString)) {
currentSelection.getEquvialentString())) {
updateListCbo.select(i);
isValid = true;
break;
}
}
if (!isValid) {
invalidFollowUpAction = true;
preventFollowUpAction(currentSelection);
}
} else {
updateListCbo.select(0);
}
}
/**
* Prevents the user from creating text when the current selection is no
* longer valid or available in the update list. The polygon will also be
* locked from being modified and return to it's last issued state if the
* polygon was temporarily modified.
*
* @param currentSelection
*/
private void preventFollowUpAction(FollowupData currentSelection) {
try {
warngenLayer.createPolygonFromRecord(currentSelection);
} catch (VizException e) {
statusHandler.handle(Priority.PROBLEM,
"Error resetting the polygon\n", e);
}
bulletList.setEnabled(false);
setPolygonLocked(true);
setTrackLocked(true);
refreshDisplay();
// Provide an info message when this situation occurs
statusHandler.handle(Priority.PROBLEM,
currentSelection.getExpirationString());
}
/**
* Set the possible durations
*
@ -995,11 +1033,11 @@ public class WarngenDialog extends CaveSWTDialog implements
return;
}
if (followupData != null && WarningAction.valueOf(followupData
.getAct()) == WarningAction.NEW) {
if (followupData != null
&& WarningAction.valueOf(followupData.getAct()) == WarningAction.NEW) {
redrawFromWarned();
}
if ((followupData == null || (WarningAction.valueOf(followupData
.getAct()) == WarningAction.CON && warngenLayer
.conWarnAreaChanged(followupData)))
@ -1021,9 +1059,10 @@ public class WarngenDialog extends CaveSWTDialog implements
try {
monitor.beginTask("Generating product", 1);
long t0 = System.currentTimeMillis();
String result = TemplateRunner.runTemplate(warngenLayer,
startTime.getTime(), endTime.getTime(),
selectedBullets, followupData, backupData);
String result = TemplateRunner.runTemplate(
warngenLayer, startTime.getTime(),
endTime.getTime(), selectedBullets,
followupData, backupData);
resultContainer[0] = result;
Matcher m = FollowUpUtil.vtecPtrn.matcher(result);
totalSegments = 0;
@ -1123,15 +1162,7 @@ public class WarngenDialog extends CaveSWTDialog implements
// again after a product was issued.AWIPS I does not auto update their
// update list, this is their solution.
if (followupData != null && totalSegments > 1) {
multiSegmentMessage(followupData.equvialentString);
return false;
}
if (timeRange != null
&& timeRange.contains(SimulatedTime.getSystemTime().getTime()) == false) {
// The action is no longer available in the follow up/update list
statusHandler.handle(Priority.PROBLEM,
"Follow up product has nothing to follow up.");
multiSegmentMessage(followupData.getEquvialentString());
return false;
}
@ -1188,7 +1219,6 @@ public class WarngenDialog extends CaveSWTDialog implements
bulletList.setEnabled(true);
recreateUpdates();
damBreakInstruct = null;
timeRange = null;
extEndTime = null;
totalSegments = 0;
bulletListManager.recreateBullets(warngenLayer.getConfiguration()
@ -1425,7 +1455,6 @@ public class WarngenDialog extends CaveSWTDialog implements
warngenLayer.state.followupData = null;
warngenLayer.getStormTrackState().endTime = null;
damBreakInstruct = null;
timeRange = null;
extEndTime = null;
totalSegments = 0;
@ -1448,6 +1477,8 @@ public class WarngenDialog extends CaveSWTDialog implements
changeBtn.setEnabled(!enableDuration);
recreateDurations(durationList);
// Current selection doesn't matter anymore
updateListCbo.select(0);
// update list
recreateUpdates();
@ -1571,7 +1602,8 @@ public class WarngenDialog extends CaveSWTDialog implements
.valueOf(warngenLayer.state.followupData
.getAct()) == WarningAction.CON
&& totalSegments > 1) {
sameProductMessage(warngenLayer.state.followupData.equvialentString);
sameProductMessage(warngenLayer.state.followupData
.getEquvialentString());
}
return;
}
@ -1581,7 +1613,8 @@ public class WarngenDialog extends CaveSWTDialog implements
// Sets the updatelist with the last selected vtec option
for (int i = 0; i < updateListCbo.getItemCount(); i++) {
String item = updateListCbo.getItem(i);
if (item.equals(warngenLayer.state.followupData.displayString)) {
if (item.equals(warngenLayer.state.followupData
.getDisplayString())) {
updateListCbo.select(i);
updateListCbo.setText(item);
data = warngenLayer.state.followupData;
@ -1823,6 +1856,32 @@ public class WarngenDialog extends CaveSWTDialog implements
}
timer.schedule(updateTimeTask, delay, delay);
TimerTask recreateUpdatesTask = new TimerTask() {
@Override
public void run() {
getDisplay().syncExec(new Runnable() {
public void run() {
try {
recreateUpdates();
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
"WarnGen Error", e);
}
}
});
}
};
// Update the follow up list every minute
long currentTimeInSeconds = SimulatedTime.getSystemTime().getMillis() / 1000;
long secondsToNextMinute = 0;
if (currentTimeInSeconds % 60 != 0) {
secondsToNextMinute = 60 - (currentTimeInSeconds % 60);
}
timer.schedule(recreateUpdatesTask, secondsToNextMinute * 1000,
60 * 1000);
}
/**
@ -1897,7 +1956,7 @@ public class WarngenDialog extends CaveSWTDialog implements
statusHandler.handle(Priority.PROBLEM,
"Error creating polygon from the record\n", e);
}
timeRange = FollowUpUtil.getTimeRange(WarningAction.CON, newWarn);
return newWarn;
}
@ -1943,7 +2002,7 @@ public class WarngenDialog extends CaveSWTDialog implements
"Error creating polygon from the record\n", e);
}
}
timeRange = FollowUpUtil.getTimeRange(WarningAction.COR, newWarn);
return newWarn;
}
@ -1981,7 +2040,7 @@ public class WarngenDialog extends CaveSWTDialog implements
statusHandler.handle(Priority.PROBLEM,
"Error creating polygon from the record\n", e);
}
timeRange = FollowUpUtil.getTimeRange(WarningAction.EXP, newWarn);
return newWarn;
}
@ -2019,7 +2078,7 @@ public class WarngenDialog extends CaveSWTDialog implements
statusHandler.handle(Priority.PROBLEM,
"Error creating polygon from the record\n", e);
}
timeRange = FollowUpUtil.getTimeRange(WarningAction.CAN, newWarn);
return newWarn;
}
@ -2044,7 +2103,7 @@ public class WarngenDialog extends CaveSWTDialog implements
statusHandler.handle(Priority.PROBLEM,
"Error creating polygon from the record\n", e);
}
timeRange = null;
return newWarn;
}
@ -2087,7 +2146,7 @@ public class WarngenDialog extends CaveSWTDialog implements
statusHandler.handle(Priority.PROBLEM,
"Error creating polygon from the record\n", e);
}
timeRange = FollowUpUtil.getTimeRange(WarningAction.EXT, newWarn);
return newWarn;
}

View file

@ -29,6 +29,7 @@ import com.raytheon.viz.warngen.text.ICommonPatterns;
* Jul 22, 2008 #1284 bwoodle Initial creation
* Oct 18, 2012 15332 jsanchez Fixed refactor bugs.
* Mar 13, 2013 DR 15892 D. Friedman Handle SMW format in canceledAreasFromText
* Aug 6, 2013 2243 jsanchez Updated the time ranges to be removed from the follow up list correctly.
*
* </pre>
*
@ -202,7 +203,8 @@ public class FollowUpUtil {
headline += line;
}
}
String[] ugcs = FipsUtil.getListCounties(ugcLine).toArray(new String[0]);
String[] ugcs = FipsUtil.getListCounties(ugcLine)
.toArray(new String[0]);
String[] names;
boolean smwAreas = false;
if (namesLine.length() > 0)
@ -233,7 +235,7 @@ public class FollowUpUtil {
areasNotation = "COUNTIES";
}
}
if (ugc.length() < 3)
continue; // TODO: log?
@ -242,7 +244,8 @@ public class FollowUpUtil {
if (i < names.length) {
if (!smwAreas && names[i].length() >= 3) {
name = names[i].substring(0, names[i].length() - 3);
stateAbbreviation = names[i].substring(names[i].length() - 2);
stateAbbreviation = names[i]
.substring(names[i].length() - 2);
} else {
name = names[i];
}
@ -314,48 +317,54 @@ public class FollowUpUtil {
TimeRange rval = null;
// The time ranges are offset by 1 minute so that after a refresh and on
// the final minute of the time range the follow up data will be
// removed. For example, if a CON is only a available until 5 minutes
// before a warnings expiration, when the time reaches 5 minutes the
// follow up data for a CON is correctly removed.
if (action == WarningAction.NEW) {
/* Calculate NEW Time Range */
start.setTime(record.getEndTime().getTime());
start.add(Calendar.MINUTE, -20);
start.add(Calendar.MINUTE, -21);
end.setTime(record.getEndTime().getTime());
end.add(Calendar.MINUTE, 30);
end.add(Calendar.MINUTE, 29);
rval = new TimeRange(start, end);
} else if (action == WarningAction.COR) {
/* Calculate COR Time Range */
end.setTime(record.getIssueTime().getTime());
end.add(Calendar.MINUTE, 10);
end.add(Calendar.MINUTE, 9);
rval = new TimeRange(record.getStartTime(), end);
} else if (action == WarningAction.CAN) {
/* Calculate CAN Time Range */
end.setTime(record.getEndTime().getTime());
end.add(Calendar.MINUTE, -10);
end.add(Calendar.MINUTE, -11);
rval = new TimeRange(record.getStartTime(), end);
} else if (action == WarningAction.CON) {
/* Calculate CON Time Range */
end.setTime(record.getEndTime().getTime());
end.add(Calendar.MINUTE, -5);
end.add(Calendar.MINUTE, -6);
rval = new TimeRange(record.getStartTime(), end);
} else if (action == WarningAction.EXP) {
/* Calculate EXP Time Range */
start.setTime(record.getEndTime().getTime());
start.add(Calendar.MINUTE, -10);
start.add(Calendar.MINUTE, -11);
end.setTime(record.getEndTime().getTime());
end.add(Calendar.MINUTE, 10);
end.add(Calendar.MINUTE, 9);
rval = new TimeRange(start, end);
} else if (action == WarningAction.EXT) {
/* Calculate EXT Time Range */
start.setTime(record.getStartTime().getTime());
end.setTime(record.getEndTime().getTime());
end.add(Calendar.MINUTE, -5);
end.add(Calendar.MINUTE, -6);
rval = new TimeRange(start, end);
}
return rval;
}
/** Parses the canceled areas of an SMW, which have a different format
* from other products.
/**
* Parses the canceled areas of an SMW, which have a different format from
* other products.
*/
private static String[] parseSMWCanceledAreas(String[] splitLines) {
StringBuilder text = new StringBuilder(64);

View file

@ -52,6 +52,7 @@ import com.vividsolutions.jts.geom.Geometry;
* 03/12/2007 1003 bwoodle initial creation
* 04/12/2013 1857 bgonzale Added SequenceGenerator annotation.
* 05/02/2013 1949 rjpeter Moved ugcZones to be a column inside table.
* 08/08/2013 2243 jsanchez Removed super method in copy constructor.
* </pre>
*
* @author bwoodle
@ -233,7 +234,6 @@ public abstract class AbstractWarningRecord extends PluginDataObject {
* The text of the message
*/
public AbstractWarningRecord(AbstractWarningRecord old) {
super((String) old.getMessageData());
this.setCountyheader(old.getCountyheader());
this.setDataTime(old.getDataTime());
this.setForecaster(old.getForecaster());