From 68911edc7fb63a29be7f0c786263d03758e8409d Mon Sep 17 00:00:00 2001 From: Matt Nash Date: Tue, 15 Jan 2013 16:05:25 -0600 Subject: [PATCH 01/10] Issue #1481 slight clean up of radar, make alphanumeric values empty for any products that do not matter Change-Id: I88847a609e57e8057a480653add74f0c5c5b4934 Former-commit-id: 3f8cf19d7173d06bcd11bd3c0bc9efea82cf52d4 [formerly 79e95d787c2844c0d51ca7e24d8fecb6e26c6b55] [formerly 3f8cf19d7173d06bcd11bd3c0bc9efea82cf52d4 [formerly 79e95d787c2844c0d51ca7e24d8fecb6e26c6b55] [formerly db1dfd3001a1c3bef751aa439caf78906e973b9f [formerly 1ac8a6d7320254f4f69160f764c86e8bd4b35d66]]] Former-commit-id: db1dfd3001a1c3bef751aa439caf78906e973b9f Former-commit-id: a78f914b92fcfd32e9c855e8a48ab8faddd2ee21 [formerly 9f8cc4ec5daecaaa1fd1ff3bf686f1c25bc0db23] Former-commit-id: 47de98d4d7f12392cec8f30580abc95bd9556fa5 --- .../edex/plugin/radar/RadarDecoder.java | 77 ++++++++++++------- .../plugin/radar/level3/Level3BaseRadar.java | 37 ++++++--- 2 files changed, 77 insertions(+), 37 deletions(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecoder.java b/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecoder.java index 55dcefe7b6..c7f7bba8f4 100644 --- a/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/RadarDecoder.java @@ -22,6 +22,7 @@ package com.raytheon.edex.plugin.radar; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; import java.util.List; @@ -95,6 +96,30 @@ public class RadarDecoder extends AbstractDecoder { private static final IUFStatusHandler theHandler = UFStatus .getHandler(RadarDecoder.class); + // radar server sends messages from edex to cave, handle that here + private final String EDEX = "EDEX"; + + /* + * Constants having to do with certain products + */ + + private final List LEVEL_TWO_IDENTS = new ArrayList( + Arrays.asList("ARCH", "AR2V")); + + private final String NOUS = "NOUS"; + + private final int USER_ALERT_MESSAGE = 73; + + private final int FREE_TEXT_MESSAGE = 75; + + private final int USER_SELECT_ACCUM = 173; + + private final int CLUTTER_FILTER_CONTROL = 34; + + /* + * End constants + */ + private String traceId = ""; private RadarInfoDict infoDict; @@ -103,9 +128,6 @@ public class RadarDecoder extends AbstractDecoder { private final String RADAR = "RADAR"; - // radar server sends messages from edex to cave, handle that here - private final String EDEX = "EDEX"; - public RadarDecoder() throws DecoderException { String dir = ""; @@ -146,11 +168,11 @@ public class RadarDecoder extends AbstractDecoder { String arch = new String(messageData, 0, 4); try { // for level2 data, this does not happen very often - if ("ARCH".equals(arch) || "AR2V".equals(arch)) { + if (LEVEL_TWO_IDENTS.contains(arch)) { decodeLevelTwoData(messageData, recordList); } // for free text messages, which come in with the following wmo - else if ("NOUS".equals(arch)) { + else if (NOUS.equals(arch)) { decodeFreeTextMessage(messageData, headers); } else { if (headers.get("header") != null) { @@ -208,24 +230,19 @@ public class RadarDecoder extends AbstractDecoder { // -- some product specific decode functionality -- // the general status message product - if (l3Radar.getMessageCode() == 2) { + if (l3Radar.getMessageCode() == l3Radar.GSM_MESSAGE) { record.setGsmMessage(l3Radar.getGsmBlock().getMessage()); record.setPrimaryElevationAngle(0.0); record.setTrueElevationAngle(0.0f); handleRadarStatus(record); } // the product request response product - else if (l3Radar.getMessageCode() == 3) { + else if (l3Radar.getMessageCode() == l3Radar.PRODUCT_REQUEST_RESPONSE_MESSAGE) { // do nothing with this, it will get excessive otherwise! - // EDEXUtil.sendMessageAlertViz(Priority.VERBOSE, - // RadarConstants.PLUGIN_ID, EDEX, RADAR, - // record.getIcao() - // + ": Response Request Message Received", - // l3Radar.getRequestResponseMessage(), null); return new PluginDataObject[0]; } // the user alert message product - else if (l3Radar.getMessageCode() == 73) { + else if (l3Radar.getMessageCode() == USER_ALERT_MESSAGE) { EDEXUtil.sendMessageAlertViz(Priority.VERBOSE, RadarConstants.PLUGIN_ID, EDEX, RADAR, record.getIcao() + ": User Alert Message Received", @@ -233,21 +250,19 @@ public class RadarDecoder extends AbstractDecoder { return new PluginDataObject[0]; } // handle the other case for free text message - else if (l3Radar.getMessageCode() == 75) { + else if (l3Radar.getMessageCode() == FREE_TEXT_MESSAGE) { // product already stored to the text database, so just send // to alertviz - EDEXUtil.sendMessageAlertViz( - Priority.SIGNIFICANT, - RadarConstants.PLUGIN_ID, - EDEX, - RADAR, + String formattedMsg = l3Radar.getTabularBlock().toString() + .replace("Page 1\n\t", ""); + EDEXUtil.sendMessageAlertViz(Priority.SIGNIFICANT, + RadarConstants.PLUGIN_ID, EDEX, RADAR, record.getIcao() + ": Free Text Message Received", - l3Radar.getTabularBlock().toString() - .replace("Page 1\n\t", ""), null); + formattedMsg, null); return new PluginDataObject[0]; } // the alert adaptations parameters product - else if (l3Radar.getMessageCode() == 6) { + else if (l3Radar.getMessageCode() == l3Radar.ALERT_ADAPTATION_PARAMETERS) { record.setAapMessage(l3Radar.getAapMessage()); record.setPrimaryElevationAngle(0.0); record.setTrueElevationAngle(0.0f); @@ -261,7 +276,7 @@ public class RadarDecoder extends AbstractDecoder { l3Radar.getAapMessage().toString(), null); } // the alert message product - else if (l3Radar.getMessageCode() == 9) { + else if (l3Radar.getMessageCode() == l3Radar.ALERT_MESSAGE) { record.setPrimaryElevationAngle(0.0); record.setTrueElevationAngle(0.0f); AlertMessage msg = l3Radar.getAlertMessage(); @@ -291,6 +306,8 @@ public class RadarDecoder extends AbstractDecoder { record.setOperationalMode(l3Radar.getOperationalMode()); record.setElevationNumber(l3Radar.getElevationNumber()); + // some products don't have real elevation angles, 0 is a + // default value if (record.getElevationNumber() == 0) { record.setTrueElevationAngle(0f); } else { @@ -320,13 +337,13 @@ public class RadarDecoder extends AbstractDecoder { } // code specific for clutter filter control - if (record.getProductCode() == 34) { + if (record.getProductCode() == CLUTTER_FILTER_CONTROL) { int segment = ((int) (Math.log(l3Radar .getProductDependentValue(0)) / Math.log(2))); record.setLayer((double) segment); } // code specific for user select accum - else if (record.getProductCode() == 173) { + else if (record.getProductCode() == USER_SELECT_ACCUM) { int layer = 0; // Default to zero int timeSpan = l3Radar.getProductDependentValue(1); @@ -491,7 +508,8 @@ public class RadarDecoder extends AbstractDecoder { String[] splits = temp.split(" "); AFOSProductId afos = new AFOSProductId( - RadarTextProductUtil.createAfosId(75, splits[1].substring(1))); + RadarTextProductUtil.createAfosId(FREE_TEXT_MESSAGE, + splits[1].substring(1))); // store the product to the text database Calendar cal = (TimeTools.allowArchive() ? header.getHeaderDate() @@ -510,7 +528,9 @@ public class RadarDecoder extends AbstractDecoder { record.setPluginName("radar"); record.constructDataURI(); record.setInsertTime(TimeTools.getSystemCalendar()); - if (record.getProductCode() == 2) { + // for GSM, we want all the messages as they have the possibility of + // being different + if (record.getProductCode() == Level3BaseRadar.GSM_MESSAGE) { record.setOverwriteAllowed(true); } else { record.setOverwriteAllowed(false); @@ -669,7 +689,8 @@ public class RadarDecoder extends AbstractDecoder { } } catch (Exception e) { - e.printStackTrace(); + theHandler.handle(Priority.ERROR, + "Unable to query for the radar station", e); } return station; diff --git a/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/level3/Level3BaseRadar.java b/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/level3/Level3BaseRadar.java index 74311c15fa..96234440ff 100644 --- a/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/level3/Level3BaseRadar.java +++ b/edexOsgi/com.raytheon.edex.plugin.radar/src/com/raytheon/edex/plugin/radar/level3/Level3BaseRadar.java @@ -28,6 +28,7 @@ import java.io.IOException; import java.io.InputStream; import java.text.DecimalFormat; import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; @@ -178,6 +179,21 @@ public class Level3BaseRadar { private RadarInfoDict dict = null; + private final List SPECIAL_PRODS = new ArrayList( + Arrays.asList(73, 62, 75, 77, 82)); + + public static final int GSM_MESSAGE = 2; + + public final int PRODUCT_REQUEST_RESPONSE_MESSAGE = 3; + + public final int ALERT_ADAPTATION_PARAMETERS = 6; + + public final int PRODUCT_LIST = 8; + + public final int RADAR_CODED_MESSAGE = 74; + + public final int ALERT_MESSAGE = 9; + /** * This baseradar constructor accepts a radar file contained within a * java.io.File object. @@ -251,16 +267,16 @@ public class Level3BaseRadar { this.parseRadarHeader(); // Handle the message contents - if (this.theMessageCode == 6) { + if (this.theMessageCode == ALERT_ADAPTATION_PARAMETERS) { // Alert Adaptation Params this.parseAAP(); - } else if (this.theMessageCode == 3) { + } else if (this.theMessageCode == PRODUCT_REQUEST_RESPONSE_MESSAGE) { this.parseRequestResponse(); - } else if (this.theMessageCode == 8) { + } else if (this.theMessageCode == PRODUCT_LIST) { this.parseProductList(headers); - } else if (this.theMessageCode == 2) { + } else if (this.theMessageCode == GSM_MESSAGE) { this.parseGeneralStatusMessage(); - } else if (this.theMessageCode == 9) { + } else if (this.theMessageCode == ALERT_MESSAGE) { this.parseAlertMessage(headers); } else { this.parseRadarMessage(headers); @@ -593,8 +609,13 @@ public class Level3BaseRadar { byte[] buf = new byte[lineLen]; theRadarData.readFully(buf); String temp = new String(buf); + // PSM is found in all products that have useful Site Adaptation + // Parameters. For this reason, we are dropping every other set of + // Site Adaptation Parameters. if (temp.contains("PSM")) { temp = temp.substring(temp.indexOf("PSM")); + } else { + temp = ""; } return temp; } else { @@ -795,15 +816,13 @@ public class Level3BaseRadar { } } - if (this.theProductCode == 73 || this.theProductCode == 62 - || this.theProductCode == 75 || this.theProductCode == 77 - || this.theProductCode == 82) { + if (SPECIAL_PRODS.contains(this.theProductCode)) { // The first offset will be to the tabular block tabularBlock = readStandaloneTabular(symbologyBlockOffset); // The second offset will be to a symbology block with no header symbologyBlock = readPseudoSymbologyBlock(graphicBlockOffset); // tabularBlock.getPages().toString(); - } else if (this.theProductCode == 74) { + } else if (this.theProductCode == RADAR_CODED_MESSAGE) { tabularBlock = readRadarCodedMessage(symbologyBlockOffset); } else { symbologyBlock = readSymbologyBlock(symbologyBlockOffset); From 46f252319e832c7a8e0af126a823df9adf806039 Mon Sep 17 00:00:00 2001 From: Ben Steffensmeier Date: Tue, 15 Jan 2013 18:08:19 -0600 Subject: [PATCH 02/10] Issue #1493 fix grib2 decoder to handle ensembles Former-commit-id: 02e0433afc4c5690b5c538f552bb738aba99fb6c [formerly 7d155653bc07e72a7240215f79c65d65a7aed74d] [formerly 02e0433afc4c5690b5c538f552bb738aba99fb6c [formerly 7d155653bc07e72a7240215f79c65d65a7aed74d] [formerly 4595797f5f635673aad386d55fdee8a84bac6c17 [formerly c694df943bb70f2903fe495400061444a67d3357]]] Former-commit-id: 4595797f5f635673aad386d55fdee8a84bac6c17 Former-commit-id: e7969ff457a1f0d71aecaeb209f84fe24d6b4d4e [formerly fb237583e2d6451e0bb4c3a866b99c279b1f6991] Former-commit-id: e8255e320db80266884382f2bc6c1e9c4772f089 --- .../com.raytheon.edex.plugin.grib/GribDecoder.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.grib/GribDecoder.py b/edexOsgi/com.raytheon.edex.plugin.grib/GribDecoder.py index 47d00f2970..9da78b1cab 100644 --- a/edexOsgi/com.raytheon.edex.plugin.grib/GribDecoder.py +++ b/edexOsgi/com.raytheon.edex.plugin.grib/GribDecoder.py @@ -593,19 +593,19 @@ class GribDecoder(): # Special case handling for specific PDS Templates if pdsTemplateNumber == 1 or pdsTemplateNumber == 11: - typeEnsemble = Integer(pdsTemplate[15]) - perturbationNumber = Integer(pdsTemplate[16]) + typeEnsemble = Integer(pdsTemplate[15]).intValue() + perturbationNumber = Integer(pdsTemplate[16]).intValue() pdsFields['numForecasts'] = Integer(pdsTemplate[17]) if(typeEnsemble == 0): - pdsFields['ensembleId'] = "ctlh" + perturbationNumber; + pdsFields['ensembleId'] = "ctlh" + str(perturbationNumber); elif(typeEnsemble == 1): - pdsFields['ensembleId'] = "ctll" + perturbationNumber; + pdsFields['ensembleId'] = "ctll" + str(perturbationNumber); elif(typeEnsemble == 2): - pdsFields['ensembleId'] = "n" + perturbationNumber; + pdsFields['ensembleId'] = "n" + str(perturbationNumber); elif(typeEnsemble == 3): - pdsFields['ensembleId'] = "p" + perturbationNumber; + pdsFields['ensembleId'] = "p" + str(perturbationNumber); else: - pdsFields['ensembleId'] = typeEnsemble + "." + perturbationNumber; + pdsFields['ensembleId'] = str(typeEnsemble) + "." + str(perturbationNumber); if pdsTemplateNumber == 11: endTime = GregorianCalendar(pdsTemplate[18], pdsTemplate[19] - 1, pdsTemplate[20], pdsTemplate[21], pdsTemplate[22], pdsTemplate[23]) From 4ab214c5d7ea2b543475859e450fe38033498580 Mon Sep 17 00:00:00 2001 From: Dustin Johnson Date: Tue, 15 Jan 2013 14:45:12 -0600 Subject: [PATCH 03/10] Issue #1487 Use XML to store stats grouping information in the database Amend: Increase length of grouping column to 1024. Add deltaScript to convert the grouping column to xml. Change regex to replace any pluginName fields with dashes, not just satellite-mcidas. Change-Id: I0d5081645c5f11909e5778c8e555d5da3cf77e1a Former-commit-id: c12b46027f678ec753d2e39f52fe2643d7be7eba [formerly b627dfc054ca845e7641fc2bb86c63b1f77d4843] [formerly c12b46027f678ec753d2e39f52fe2643d7be7eba [formerly b627dfc054ca845e7641fc2bb86c63b1f77d4843] [formerly 19d3a14d4f5292f4187ca2030521ae1f4deda537 [formerly 38ecb1f36dce4717d0ba9066c8cd22116770d34b]]] Former-commit-id: 19d3a14d4f5292f4187ca2030521ae1f4deda537 Former-commit-id: ecb1d5564afcef5c84eac80b44f85db2cd03b38c [formerly c750e2738946c044e62eeef4f22368359d799928] Former-commit-id: 19558ae3fa6c2fb7cb4aa9a7a2aa873747639a37 --- .../13.2.1/aggregateRecordGroupingLength.sh | 23 +++ .../convertAggregateRecordGroupToXml.sh | 23 +++ .../convertAggregateRecordGroupToXml.sql | 38 ++++ .../increaseAggregateRecordGroupingLength.sql | 22 +++ .../uf/common/stats/AggregateRecord.java | 12 +- .../uf/common/stats/StatsGrouping.java | 101 +++++++++++ .../uf/common/stats/StatsGroupingColumn.java | 87 +++++++++ .../uf/edex/stats/AggregateManager.java | 73 +++++--- .../edex/stats/data/StatsDataAccumulator.java | 115 ++++++++---- .../uf/edex/stats/util/ConfigLoader.java | 5 +- ...datadelivery.retrieval.util.LevelXmlWriter | 1 - ...delivery.retrieval.util.ParameterXmlWriter | 1 - .../retrieval/util/NullXmlWriter.java | 60 ------- .../common/localization/TestPathManager.java | 34 +++- .../uf/edex/stats/AggregateManagerTest.java | 116 ++++++++++++ .../com/raytheon/uf/edex/stats/MockEvent.java | 169 ++++++++++++++++++ .../stats/data/StatsDataAccumulatorTest.java | 163 +++++++++++------ .../edex_static/base/stats/mockStats.xml | 12 ++ 18 files changed, 863 insertions(+), 192 deletions(-) create mode 100644 deltaScripts/13.2.1/aggregateRecordGroupingLength.sh create mode 100644 deltaScripts/13.2.1/convertAggregateRecordGroupToXml.sh create mode 100644 deltaScripts/13.2.1/convertAggregateRecordGroupToXml.sql create mode 100644 deltaScripts/13.2.1/increaseAggregateRecordGroupingLength.sql create mode 100644 edexOsgi/com.raytheon.uf.common.stats/src/com/raytheon/uf/common/stats/StatsGrouping.java create mode 100644 edexOsgi/com.raytheon.uf.common.stats/src/com/raytheon/uf/common/stats/StatsGroupingColumn.java delete mode 100644 tests/resources/META-INF/services/com.raytheon.uf.common.datadelivery.retrieval.util.LevelXmlWriter delete mode 100644 tests/resources/META-INF/services/com.raytheon.uf.common.datadelivery.retrieval.util.ParameterXmlWriter delete mode 100644 tests/unit/com/raytheon/uf/common/datadelivery/retrieval/util/NullXmlWriter.java create mode 100644 tests/unit/com/raytheon/uf/edex/stats/AggregateManagerTest.java create mode 100644 tests/unit/com/raytheon/uf/edex/stats/MockEvent.java create mode 100644 tests/utility/edex_static/base/stats/mockStats.xml diff --git a/deltaScripts/13.2.1/aggregateRecordGroupingLength.sh b/deltaScripts/13.2.1/aggregateRecordGroupingLength.sh new file mode 100644 index 0000000000..8be0366f68 --- /dev/null +++ b/deltaScripts/13.2.1/aggregateRecordGroupingLength.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +SQL_SCRIPT="increaseAggregateRecordGroupingLength.sql" + +# ensure that the sql script is present +if [ ! -f ${SQL_SCRIPT} ]; then + echo "ERROR: the required sql script - ${SQL_SCRIPT} was not found." + echo "FATAL: the update has failed!" + exit 1 +fi + +echo "INFO: update started - increasing the size of the aggregate.grouping column" + +# run the update +/awips2/psql/bin/psql -U awips -d metadata -f ${SQL_SCRIPT} +if [ $? -ne 0 ]; then + echo "FATAL: the update has failed!" + exit 1 +fi + +echo "INFO: the update has completed successfully!" + +exit 0 diff --git a/deltaScripts/13.2.1/convertAggregateRecordGroupToXml.sh b/deltaScripts/13.2.1/convertAggregateRecordGroupToXml.sh new file mode 100644 index 0000000000..556254619a --- /dev/null +++ b/deltaScripts/13.2.1/convertAggregateRecordGroupToXml.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +SQL_SCRIPT="convertAggregateRecordGroupToXml.sql" + +# ensure that the sql script is present +if [ ! -f ${SQL_SCRIPT} ]; then + echo "ERROR: the required sql script - ${SQL_SCRIPT} was not found." + echo "FATAL: the update has failed!" + exit 1 +fi + +echo "INFO: update started - converting the aggregate.grouping column to xml" + +# run the update +/awips2/psql/bin/psql -U awips -d metadata -f ${SQL_SCRIPT} +if [ $? -ne 0 ]; then + echo "FATAL: the update has failed!" + exit 1 +fi + +echo "INFO: the update has completed successfully!" + +exit 0 diff --git a/deltaScripts/13.2.1/convertAggregateRecordGroupToXml.sql b/deltaScripts/13.2.1/convertAggregateRecordGroupToXml.sql new file mode 100644 index 0000000000..424de941cf --- /dev/null +++ b/deltaScripts/13.2.1/convertAggregateRecordGroupToXml.sql @@ -0,0 +1,38 @@ +/** + * 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. + **/ +\set ON_ERROR_STOP 1 +\connect metadata; + +-- Start a transaction +BEGIN; + +-- Temporarily replace dashes in pluginName rows with @@@ +update events.aggregate set grouping = regexp_replace(grouping, 'pluginName:(.*?)-(.*)', E'pluginName:\\1@@@\\2', 'g'); + +-- Convert to XML format +update events.aggregate set grouping = regexp_replace(grouping, ':', '" value="', 'g'); +update events.aggregate set grouping = regexp_replace(grouping, '-', '"/>'; + +-- Restore dashes from @@@ +update events.aggregate set grouping = regexp_replace(grouping, ' - * + * * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Aug 21, 2012 jsanchez Initial creation * Nov 12, 2012 dhladky Updates some things for stats - * + * Jan 15, 2013 1487 djohnson Increase length of grouping to 1024. + * * - * + * * @author jsanchez * @version 1.0 */ @@ -56,7 +57,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize -public class AggregateRecord extends PersistableDataObject { +public class AggregateRecord extends PersistableDataObject { private static final long serialVersionUID = -4553588456131256014L; @GeneratedValue(strategy = GenerationType.AUTO) @@ -77,6 +78,7 @@ public class AggregateRecord extends PersistableDataObject { private String eventType; @DynamicSerializeElement + @Column(length = 1024) private String grouping; @Column(nullable = false) diff --git a/edexOsgi/com.raytheon.uf.common.stats/src/com/raytheon/uf/common/stats/StatsGrouping.java b/edexOsgi/com.raytheon.uf.common.stats/src/com/raytheon/uf/common/stats/StatsGrouping.java new file mode 100644 index 0000000000..3995883cbc --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.stats/src/com/raytheon/uf/common/stats/StatsGrouping.java @@ -0,0 +1,101 @@ +/** + * 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.stats; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + +/** + * Contains a grouping for statistics. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 15, 2013 1487       djohnson     Initial creation
+ * 
+ * 
+ * + * @author djohnson + * @version 1.0 + */ +@XmlRootElement +@XmlAccessorType(XmlAccessType.NONE) +public class StatsGrouping { + + @XmlAttribute(required = true) + private String name; + + @XmlAttribute(required = true) + private String value; + + /** + * Constructor. + */ + public StatsGrouping() { + this(null, null); + } + + /** + * Constructor. + * + * @param name + * @param value + */ + public StatsGrouping(String name, String value) { + this.name = name; + this.value = value; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name + * the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the value + */ + public String getValue() { + return value; + } + + /** + * @param value + * the value to set + */ + public void setValue(String value) { + this.value = value; + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.stats/src/com/raytheon/uf/common/stats/StatsGroupingColumn.java b/edexOsgi/com.raytheon.uf.common.stats/src/com/raytheon/uf/common/stats/StatsGroupingColumn.java new file mode 100644 index 0000000000..b63902407a --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.stats/src/com/raytheon/uf/common/stats/StatsGroupingColumn.java @@ -0,0 +1,87 @@ +/** + * 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.stats; + +import java.util.List; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +import com.google.common.collect.Lists; + +/** + * Contains a list of groupings for statistics. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 15, 2013 1487       djohnson     Initial creation
+ * 
+ * 
+ * + * @author djohnson + * @version 1.0 + */ +@XmlRootElement(name = "stat") +@XmlAccessorType(XmlAccessType.NONE) +public class StatsGroupingColumn { + + @XmlElement + private List group = Lists.newArrayList(); + + /** + * @return the group + */ + public List getGroup() { + return group; + } + + /** + * @param group + * the group to set + */ + public void setGroup(List group) { + this.group = group; + } + + /** + * Create a {@link StatsGroupingColumn} to hold the specified + * {@link StatsGrouping} instances. + * + * @param statsGroupings + * the groupings + * @return the column + */ + public static StatsGroupingColumn withGroupings( + StatsGrouping... statsGroupings) { + StatsGroupingColumn column = new StatsGroupingColumn(); + + for (StatsGrouping grouping : statsGroupings) { + column.group.add(grouping); + } + + return column; + } +} diff --git a/edexOsgi/com.raytheon.uf.edex.stats/src/com/raytheon/uf/edex/stats/AggregateManager.java b/edexOsgi/com.raytheon.uf.edex.stats/src/com/raytheon/uf/edex/stats/AggregateManager.java index 44c27f32d7..40af314884 100644 --- a/edexOsgi/com.raytheon.uf.edex.stats/src/com/raytheon/uf/edex/stats/AggregateManager.java +++ b/edexOsgi/com.raytheon.uf.edex.stats/src/com/raytheon/uf/edex/stats/AggregateManager.java @@ -19,7 +19,9 @@ **/ package com.raytheon.uf.edex.stats; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.HashMap; @@ -28,11 +30,17 @@ import java.util.List; import java.util.Map; import java.util.TimeZone; +import javax.xml.bind.JAXBException; + +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ArrayListMultimap; import com.google.common.collect.Multimap; import com.raytheon.uf.common.event.Event; +import com.raytheon.uf.common.serialization.JAXBManager; import com.raytheon.uf.common.serialization.SerializationUtil; import com.raytheon.uf.common.stats.AggregateRecord; +import com.raytheon.uf.common.stats.StatsGrouping; +import com.raytheon.uf.common.stats.StatsGroupingColumn; import com.raytheon.uf.common.stats.StatsRecord; import com.raytheon.uf.common.stats.xml.StatisticsAggregate; import com.raytheon.uf.common.stats.xml.StatisticsEvent; @@ -61,6 +69,7 @@ import com.raytheon.uf.edex.stats.util.ConfigLoader; * Nov 07, 2012 1317 mpduff Updated Configuration Files. * Nov 28, 2012 1350 rjpeter Simplied aggregation and added aggregation with current db aggregate records. * Jan 07, 2013 1451 djohnson Use newGmtCalendar(). + * Jan 15, 2013 1487 djohnson Use xml for the grouping information on an {@link AggregateRecord}. * * * @author jsanchez @@ -70,6 +79,17 @@ public class AggregateManager { private static final IUFStatusHandler statusHandler = UFStatus .getHandler(AggregateManager.class); + private static final Object[] EMPTY_OBJ_ARR = new Object[0]; + + private static final JAXBManager JAXB_MANAGER; + static { + try { + JAXB_MANAGER = new JAXBManager(StatsGroupingColumn.class); + } catch (JAXBException e) { + throw new ExceptionInInitializerError(e); + } + } + /** In minutes */ private int bucketInterval; @@ -255,8 +275,6 @@ public class AggregateManager { Map> rval = new HashMap>(); TimeRange timeRange = null; Multimap eventsByGroup = null; - final Object[] EMPTY_OBJ_ARR = new Object[0]; - StringBuilder group = new StringBuilder(); for (StatsRecord record : records) { if ((timeRange == null) @@ -275,30 +293,11 @@ public class AggregateManager { Event event = SerializationUtil.transformFromThrift( Event.class, record.getEvent()); - // determine group - boolean addDelim = false; - Iterator gMethodIter = statEvent.getGroupByMethods() - .iterator(); - Iterator gFieldNameIter = statEvent - .getGroupList().iterator(); - group.setLength(0); - - while (gMethodIter.hasNext() && gFieldNameIter.hasNext()) { - Method m = gMethodIter.next(); - String field = gFieldNameIter.next().getName(); - String gVal = String - .valueOf(m.invoke(event, EMPTY_OBJ_ARR)); - - if (addDelim) { - group.append('-'); - } else { - addDelim = true; - } - - group.append(field).append(':').append(gVal); + String groupAsString = determineGroupRepresentationForEvent( + statEvent, event); + if (groupAsString != null) { + eventsByGroup.put(groupAsString, event); } - - eventsByGroup.put(group.toString(), event); } catch (Exception e) { statusHandler .error("Error processing event. Aggregation may be inaccurate. ", @@ -309,6 +308,30 @@ public class AggregateManager { return rval; } + @VisibleForTesting + static String determineGroupRepresentationForEvent( + StatisticsEvent statEvent, Event event) + throws IllegalAccessException, InvocationTargetException, + JAXBException { + Iterator gMethodIter = statEvent.getGroupByMethods().iterator(); + Iterator gFieldNameIter = statEvent.getGroupList() + .iterator(); + List groupings = new ArrayList(); + + while (gMethodIter.hasNext() && gFieldNameIter.hasNext()) { + Method m = gMethodIter.next(); + String field = gFieldNameIter.next().getName(); + String gVal = String.valueOf(m.invoke(event, EMPTY_OBJ_ARR)); + + groupings.add(new StatsGrouping(field, gVal)); + } + + StatsGroupingColumn column = new StatsGroupingColumn(); + column.setGroup(groupings); + + return JAXB_MANAGER.marshalToXml(column); + } + /** * Tests if the bucket interval is a valid value. If value is invalid then * value will be set to default value. diff --git a/edexOsgi/com.raytheon.uf.edex.stats/src/com/raytheon/uf/edex/stats/data/StatsDataAccumulator.java b/edexOsgi/com.raytheon.uf.edex.stats/src/com/raytheon/uf/edex/stats/data/StatsDataAccumulator.java index c21c31ff5e..233a1bd749 100644 --- a/edexOsgi/com.raytheon.uf.edex.stats/src/com/raytheon/uf/edex/stats/data/StatsDataAccumulator.java +++ b/edexOsgi/com.raytheon.uf.edex.stats/src/com/raytheon/uf/edex/stats/data/StatsDataAccumulator.java @@ -27,13 +27,18 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; -import java.util.TreeSet; -import java.util.regex.Pattern; + +import javax.xml.bind.JAXBException; import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import com.raytheon.uf.common.serialization.JAXBManager; import com.raytheon.uf.common.serialization.SerializationException; import com.raytheon.uf.common.serialization.SerializationUtil; import com.raytheon.uf.common.stats.AggregateRecord; +import com.raytheon.uf.common.stats.StatsGrouping; +import com.raytheon.uf.common.stats.StatsGroupingColumn; import com.raytheon.uf.common.stats.data.GraphData; import com.raytheon.uf.common.stats.data.StatsBin; import com.raytheon.uf.common.stats.data.StatsData; @@ -44,34 +49,42 @@ import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.time.TimeRange; import com.raytheon.uf.common.time.util.TimeUtil; +import com.raytheon.uf.common.util.CollectionUtil; /** * Accumulates the statistics data. - * + * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Nov 15, 2012    728     mpduff      Initial creation
- *
+ * Jan 15, 2013 1487       djohnson    Use xml for the grouping information on an {@link AggregateRecord}.
+ * 
  * 
- * + * * @author mpduff * @version 1.0 */ public class StatsDataAccumulator { - private static final Pattern COLON_PATTERN = Pattern.compile(":"); - - private static final Pattern DASH_PATTERN = Pattern.compile("-"); - - private static final String COLON = ":"; private static final IUFStatusHandler statusHandler = UFStatus .getHandler(StatsDataAccumulator.class); + private static final String COLON = ":"; + + private static final JAXBManager JAXB_MANAGER; + static { + try { + JAXB_MANAGER = new JAXBManager(StatsGroupingColumn.class); + } catch (JAXBException e) { + throw new ExceptionInInitializerError(e); + } + } + /** List of records */ private AggregateRecord[] records; @@ -108,7 +121,7 @@ public class StatsDataAccumulator { /** * Set the AggregateRecord[] - * + * * @param records * array of AggregateRecord objects */ @@ -122,28 +135,27 @@ public class StatsDataAccumulator { @VisibleForTesting public void setupGroupings() { for (AggregateRecord aggRec : records) { - String grouping = aggRec.getGrouping(); - String[] groupString = DASH_PATTERN.split(grouping); - String group; - String member; - for (String grp : groupString) { - String[] parts = COLON_PATTERN.split(grp); - group = parts[0]; - member = parts[1]; - if (!groupMemberMap.containsKey(group)) { - groupMemberMap.put(group, new TreeSet()); - } + StatsGroupingColumn columnValue = unmarshalGroupingColumnFromRecord(aggRec); - groupMemberMap.get(group).add(member); + final List groups = columnValue.getGroup(); + if (CollectionUtil.isNullOrEmpty(groups)) { + continue; + } + for (StatsGrouping group : groups) { + final String groupName = group.getName(); + if (!groupMemberMap.containsKey(groupName)) { + groupMemberMap.put(groupName, Sets. newTreeSet()); + } + groupMemberMap.get(groupName).add(group.getValue()); } } - groups = new ArrayList(groupMemberMap.keySet()); + groups = Lists.newArrayList(groupMemberMap.keySet()); } /** * Get the GraphData object - * + * * @param groups * List of groups * @return The GraphData object @@ -184,7 +196,7 @@ public class StatsDataAccumulator { /** * Create the StatsDataMap keys - * + * * @param unitUtils * UnitUtils object * @param groups @@ -202,21 +214,25 @@ public class StatsDataAccumulator { if (record.getEventType().equals(eventType) && record.getField().equals(dataType)) { + StatsGroupingColumn columnValue = unmarshalGroupingColumnFromRecord(record); + + final List columnValueGroups = columnValue + .getGroup(); + if (CollectionUtil.isNullOrEmpty(columnValueGroups)) { + continue; + } + // Have a matching record for (String key : keySequenceMap.keySet()) { keySequenceMap.put(key, ""); } - String[] groupings = DASH_PATTERN.split(record.getGrouping()); - for (String grouping : groupings) { - String[] parts = COLON_PATTERN.split(grouping); - String group = parts[0]; - String groupMember = parts[1]; + for (StatsGrouping group : columnValueGroups) { for (String key : keySequenceMap.keySet()) { - if (group.equals(key)) { + if (group.getName().equals(key)) { keySequenceMap.put(key, keySequenceMap.get(key) - .concat(groupMember + COLON)); + .concat(group.getValue() + COLON)); break; } } @@ -242,9 +258,32 @@ public class StatsDataAccumulator { } } + /** + * Unmarshals the {@link StatsGroupingColumn} from the + * {@link AggregateRecord}. + * + * @param record + * the aggregate record + * @return the unmarshalled column, or an empty column if unable to + * unmarshal + */ + private static StatsGroupingColumn unmarshalGroupingColumnFromRecord( + AggregateRecord record) { + String groupingXmlAsString = record.getGrouping(); + try { + return (StatsGroupingColumn) JAXB_MANAGER + .unmarshalFromXml(groupingXmlAsString); + } catch (JAXBException e) { + statusHandler.handle(Priority.PROBLEM, + "Unable to unmarshal stats grouping column, returning empty record, xml:\n" + + groupingXmlAsString, e); + return new StatsGroupingColumn(); + } + } + /** * Gather the data together in each bin. - * + * * @param unitUtils * UnitUtils object * @param groups @@ -323,7 +362,7 @@ public class StatsDataAccumulator { /** * Set the display units. - * + * * @param displayUnit * the displayUnit to set */ @@ -333,7 +372,7 @@ public class StatsDataAccumulator { /** * TimeStep in minutes - * + * * @param timeStep */ public void setTimeStep(int timeStep) { diff --git a/edexOsgi/com.raytheon.uf.edex.stats/src/com/raytheon/uf/edex/stats/util/ConfigLoader.java b/edexOsgi/com.raytheon.uf.edex.stats/src/com/raytheon/uf/edex/stats/util/ConfigLoader.java index e4e6e01d29..239ebfc79d 100644 --- a/edexOsgi/com.raytheon.uf.edex.stats/src/com/raytheon/uf/edex/stats/util/ConfigLoader.java +++ b/edexOsgi/com.raytheon.uf.edex.stats/src/com/raytheon/uf/edex/stats/util/ConfigLoader.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import com.google.common.annotations.VisibleForTesting; import com.raytheon.uf.common.event.Event; import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.LocalizationContext; @@ -57,6 +58,7 @@ import com.raytheon.uf.common.util.ReflectionUtil; * Aug 21, 2012 jsanchez Updated error handling and validated config files. * Nov 07, 2012 1317 mpduff Update config files. * Nov 29, 2012 1350 rjpeter Updated to static, fixed localization, increased validation. + * Jan 15, 2013 1487 djohnson Make validate() static and public, so it can be run independently. * * * @author jsanchez @@ -158,7 +160,8 @@ public class ConfigLoader { * * @param config */ - private void validate(Map eventMap, + @VisibleForTesting + public static void validate(Map eventMap, StatisticsConfig config) { for (Iterator iter = config.getEvents().iterator(); iter .hasNext();) { diff --git a/tests/resources/META-INF/services/com.raytheon.uf.common.datadelivery.retrieval.util.LevelXmlWriter b/tests/resources/META-INF/services/com.raytheon.uf.common.datadelivery.retrieval.util.LevelXmlWriter deleted file mode 100644 index eec9b4aec4..0000000000 --- a/tests/resources/META-INF/services/com.raytheon.uf.common.datadelivery.retrieval.util.LevelXmlWriter +++ /dev/null @@ -1 +0,0 @@ -com.raytheon.uf.common.datadelivery.retrieval.util.NullXmlWriter \ No newline at end of file diff --git a/tests/resources/META-INF/services/com.raytheon.uf.common.datadelivery.retrieval.util.ParameterXmlWriter b/tests/resources/META-INF/services/com.raytheon.uf.common.datadelivery.retrieval.util.ParameterXmlWriter deleted file mode 100644 index eec9b4aec4..0000000000 --- a/tests/resources/META-INF/services/com.raytheon.uf.common.datadelivery.retrieval.util.ParameterXmlWriter +++ /dev/null @@ -1 +0,0 @@ -com.raytheon.uf.common.datadelivery.retrieval.util.NullXmlWriter \ No newline at end of file diff --git a/tests/unit/com/raytheon/uf/common/datadelivery/retrieval/util/NullXmlWriter.java b/tests/unit/com/raytheon/uf/common/datadelivery/retrieval/util/NullXmlWriter.java deleted file mode 100644 index 38a044e069..0000000000 --- a/tests/unit/com/raytheon/uf/common/datadelivery/retrieval/util/NullXmlWriter.java +++ /dev/null @@ -1,60 +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.datadelivery.retrieval.util; - -import com.raytheon.uf.common.datadelivery.retrieval.xml.LevelLookup; -import com.raytheon.uf.common.datadelivery.retrieval.xml.ParameterLookup; - -/** - * Makes parser created XML not write out in test - * - *
- *
- * SOFTWARE HISTORY
- *
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jan 10, 2013            djohnson     Initial creation
- *
- * 
- * - * @author djohnson - * @version 1.0 - */ - -public class NullXmlWriter implements LevelXmlWriter, ParameterXmlWriter { - - /** - * {@inheritDoc} - */ - @Override - public void writeParameterXml(ParameterLookup pl, String modelName) - throws Exception { - } - - /** - * {@inheritDoc} - */ - @Override - public void writeLevelXml(LevelLookup ll, String modelName) - throws Exception { - } - -} diff --git a/tests/unit/com/raytheon/uf/common/localization/TestPathManager.java b/tests/unit/com/raytheon/uf/common/localization/TestPathManager.java index 6967828aac..0190fd04d0 100644 --- a/tests/unit/com/raytheon/uf/common/localization/TestPathManager.java +++ b/tests/unit/com/raytheon/uf/common/localization/TestPathManager.java @@ -40,6 +40,7 @@ import com.raytheon.uf.common.util.FileUtil; * ------------ ---------- ----------- -------------------------- * Jul 18, 2012 740 djohnson Initial creation * Oct 23, 2012 1286 djohnson Change to find more localization files. + * Jan 16, 2013 1487 djohnson Avoid adding new localization files to baseline utility directories. * * * @@ -131,21 +132,44 @@ public class TestPathManager extends PathManager { } if (foundFile == null - || !foundFile.exists() || foundFile.getAbsolutePath().startsWith( savedLocalizationFileDir.getAbsolutePath())) { return foundFile; } - // Make a copy in the savedFile folder, this way if any - // modifications are performed we don't mess with the file in - // the baseline + + File savedFile = createTestIsolatedVersionOfLocalizationFile( + context, fileName, foundFile); + return savedFile; + } + + /** + * Creates a test isolated version of the localization file. Allows the + * file to be written to, and changes to be read back, without affecting + * the baselined version of the file. + * + * @param context + * the context + * @param fileName + * the file path + * @param baselinedVersion + * the file reference + * @return + */ + private File createTestIsolatedVersionOfLocalizationFile( + LocalizationContext context, String fileName, File baselinedVersion) { File savedFileBaseDir = new File(savedLocalizationFileDir, context.toPath()); File savedFile = new File(savedFileBaseDir, fileName); savedFile.getParentFile().mkdirs(); try { - FileUtil.copyFile(foundFile, savedFile); + if (baselinedVersion.exists()) { + if (baselinedVersion.isDirectory()) { + savedFile.mkdirs(); + } else { + FileUtil.copyFile(baselinedVersion, savedFile); + } + } } catch (IOException e) { throw new RuntimeException(e); } diff --git a/tests/unit/com/raytheon/uf/edex/stats/AggregateManagerTest.java b/tests/unit/com/raytheon/uf/edex/stats/AggregateManagerTest.java new file mode 100644 index 0000000000..5590fa147e --- /dev/null +++ b/tests/unit/com/raytheon/uf/edex/stats/AggregateManagerTest.java @@ -0,0 +1,116 @@ +/** + * 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.stats; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.JAXBException; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.Maps; +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.localization.PathManagerFactoryTest; +import com.raytheon.uf.common.serialization.JAXBManager; +import com.raytheon.uf.common.stats.StatsGrouping; +import com.raytheon.uf.common.stats.StatsGroupingColumn; +import com.raytheon.uf.common.stats.xml.StatisticsConfig; +import com.raytheon.uf.common.stats.xml.StatisticsEvent; +import com.raytheon.uf.common.util.FileUtil; +import com.raytheon.uf.edex.stats.util.ConfigLoader; + +/** + * Test {@link AggregateManager}. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 15, 2013 1487       djohnson     Initial creation
+ * 
+ * 
+ * + * @author djohnson + * @version 1.0 + */ + +public class AggregateManagerTest { + private static JAXBManager jaxbManager; + + @BeforeClass + public static void classSetUp() throws JAXBException { + jaxbManager = new JAXBManager(StatisticsConfig.class, + StatsGroupingColumn.class); + } + + @Before + public void setUp() { + PathManagerFactoryTest.initLocalization(); + } + + @Test + public void testDeterminingGroupForEvent() throws Exception { + IPathManager pm = PathManagerFactory.getPathManager(); + final LocalizationFile lf = pm.getLocalizationFile( + new LocalizationContext(LocalizationType.EDEX_STATIC, + LocalizationLevel.BASE), FileUtil.join("stats", + "mockStats.xml")); + + final StatisticsConfig statisticsConfig = lf.jaxbUnmarshal( + StatisticsConfig.class, jaxbManager); + + ConfigLoader.validate(Maps. newHashMap(), + statisticsConfig); + + MockEvent mockEvent = new MockEvent(); + mockEvent.setPluginName("somePlugin"); + mockEvent.setFileName("someFileName"); + mockEvent.setProcessingTime(1000L); + mockEvent.setProcessingLatency(500L); + + List groupList = new ArrayList(); + groupList.add(new StatsGrouping("pluginName", "somePlugin")); + groupList.add(new StatsGrouping("fileName", "someFileName")); + StatsGroupingColumn column = new StatsGroupingColumn(); + column.setGroup(groupList); + + final String expectedGroupRepresentation = jaxbManager + .marshalToXml(column); + final String actualGroupRepresentation = AggregateManager.determineGroupRepresentationForEvent( + statisticsConfig.getEvents().iterator().next(), mockEvent); + assertThat(actualGroupRepresentation, + is(equalTo(expectedGroupRepresentation))); + } + +} diff --git a/tests/unit/com/raytheon/uf/edex/stats/MockEvent.java b/tests/unit/com/raytheon/uf/edex/stats/MockEvent.java new file mode 100644 index 0000000000..419ed5be0f --- /dev/null +++ b/tests/unit/com/raytheon/uf/edex/stats/MockEvent.java @@ -0,0 +1,169 @@ +/** + * 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.stats; + +import java.util.Collections; +import java.util.HashMap; +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.stats.ProcessEvent; +import com.raytheon.uf.common.stats.StatisticsEvent; + +/** + * Mock event based from {@link ProcessEvent}. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 15, 2013 1487       djohnson     Initial creation
+ * 
+ * 
+ * + * @author djohnson + * @version 1.0 + */ +@DynamicSerialize +public class MockEvent extends StatisticsEvent { + + private static final long serialVersionUID = 1L; + + private static final Map FIELD_UNIT_MAP; + static { + Map m = new HashMap(); + m.put("processingLatency", "ms"); + m.put("processingTime", "ms"); + FIELD_UNIT_MAP = Collections.unmodifiableMap(m); + } + + @DynamicSerializeElement + private String message; + + @DynamicSerializeElement + private String pluginName; + + @DynamicSerializeElement + private String fileName; + + /* + * Processing time in milliseconds + */ + @DynamicSerializeElement + private long processingTime; + + /* + * Processing latency in milliseconds + */ + @DynamicSerializeElement + private long processingLatency; + + public MockEvent() { + } + + @Override + protected Map getFieldUnitMap() { + return FIELD_UNIT_MAP; + } + + /** + * @return the fileName + */ + public String getFileName() { + return fileName; + } + + /** + * @return the message + */ + public String getMessage() { + return message; + } + + /** + * @return the pluginName + */ + public String getPluginName() { + return pluginName; + } + + /** + * @return the processingLatency in milliseconds + */ + public long getProcessingLatency() { + return processingLatency; + } + + /** + * @return the processingTime in milliseconds + */ + public long getProcessingTime() { + return processingTime; + } + + /** + * @param fileName + * the fileName to set + */ + public void setFileName(String fileName) { + this.fileName = fileName; + } + + /** + * @param message + * the message to set + */ + public void setMessage(String message) { + this.message = message; + } + + /** + * @param pluginName + * the pluginName to set + */ + public void setPluginName(String pluginName) { + this.pluginName = pluginName; + } + + /** + * @param processingLatency + * the processingLatency in milliseconds to set + */ + public void setProcessingLatency(long processingLatency) { + this.processingLatency = processingLatency; + } + + /** + * @param processingTime + * the processingTime in milliseconds to set + */ + public void setProcessingTime(long processingTime) { + this.processingTime = processingTime; + } + + @Override + public String toString() { + return super.toString() + " : " + getMessage(); + } + +} \ No newline at end of file diff --git a/tests/unit/com/raytheon/uf/edex/stats/data/StatsDataAccumulatorTest.java b/tests/unit/com/raytheon/uf/edex/stats/data/StatsDataAccumulatorTest.java index 4e6288206e..7b9e9664f0 100644 --- a/tests/unit/com/raytheon/uf/edex/stats/data/StatsDataAccumulatorTest.java +++ b/tests/unit/com/raytheon/uf/edex/stats/data/StatsDataAccumulatorTest.java @@ -1,47 +1,92 @@ +/** + * 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.stats.data; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.util.ArrayList; -import java.util.Calendar; +import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Set; -import java.util.TimeZone; + +import javax.xml.bind.JAXBException; import org.junit.Test; +import com.google.common.collect.Maps; +import com.raytheon.uf.common.datadelivery.event.retrieval.DataRetrievalEvent; +import com.raytheon.uf.common.datadelivery.event.retrieval.SubscriptionRetrievalEvent; +import com.raytheon.uf.common.serialization.JAXBManager; import com.raytheon.uf.common.stats.AggregateRecord; +import com.raytheon.uf.common.stats.StatsGrouping; +import com.raytheon.uf.common.stats.StatsGroupingColumn; +import com.raytheon.uf.common.stats.data.StatsData; import com.raytheon.uf.common.stats.util.UnitUtils; import com.raytheon.uf.common.time.TimeRange; +import com.raytheon.uf.common.time.util.TimeUtil; +/** + * + * Test {@link StatsDataAccumulator}. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 15, 2013 1487       djohnson     Use XML for grouping column.
+ * 
+ * 
+ * + * @author djohnson + * @version 1.0 + */ public class StatsDataAccumulatorTest { + private static final JAXBManager JAXB_MANAGER; + static { + try { + JAXB_MANAGER = new JAXBManager(StatsGroupingColumn.class); + } catch (JAXBException e) { + throw new ExceptionInInitializerError(e); + } + } + @Test public void testCalculateBinsCalculatesCorrectly() { - Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - c.set(Calendar.MILLISECOND, 0); - c.set(Calendar.SECOND, 0); - c.set(Calendar.MINUTE, 0); - c.set(Calendar.HOUR_OF_DAY, 0); - c.set(Calendar.DAY_OF_MONTH, 1); - c.set(Calendar.MONTH, 0); - long start = c.getTimeInMillis(); - - c.add(Calendar.DAY_OF_MONTH, 1); - long end = c.getTimeInMillis(); - - TimeRange tr = new TimeRange(start, end); + TimeRange tr = new TimeRange(0L, TimeUtil.MILLIS_PER_DAY); StatsDataAccumulator acc = new StatsDataAccumulator(); acc.setTimeRange(tr); acc.setTimeStep(5); acc.calculateBins(); - int expectedBinCount = 288; // 5 minute bins 12 per hour, * 24 + int expectedBinCount = 288; // 5 minute bins 12 per hour, * 24 int actualBinCount = acc.bins.keySet().size(); - assertEquals("Bin Counts do not match", expectedBinCount, actualBinCount); + assertEquals("Bin Counts do not match", expectedBinCount, + actualBinCount); int count = 0; for (long bin : acc.bins.keySet()) { @@ -51,7 +96,7 @@ public class StatsDataAccumulatorTest { } @Test - public void testSetupGroupings() { + public void testSetupGroupings() throws JAXBException { List recordList = getTestRecords(); StatsDataAccumulator acc = new StatsDataAccumulator(); acc.setRecords(recordList.toArray(new AggregateRecord[recordList.size()])); @@ -62,33 +107,39 @@ public class StatsDataAccumulatorTest { expectedGroups.add("provider"); expectedGroups.add("plugin"); - List expectedGroupMembers = new ArrayList(); - expectedGroupMembers.add("nomads"); - expectedGroupMembers.add("madis"); - expectedGroupMembers.add("owner0"); - expectedGroupMembers.add("owner1"); - expectedGroupMembers.add("owner2"); - expectedGroupMembers.add("owner3"); - expectedGroupMembers.add("owner4"); - expectedGroupMembers.add("grid"); + List expectedPlugins = Arrays.asList("grid"); + List expectedProviders = Arrays.asList("nomads", "madis"); + List expectedOwners = Arrays.asList("owner0", "owner1", + "owner2", "owner3", "owner4"); + Map> expectedGroupsToValues = Maps.newHashMap(); + expectedGroupsToValues.put("provider", expectedProviders); + expectedGroupsToValues.put("plugin", expectedPlugins); + expectedGroupsToValues.put("owner", expectedOwners); // Check the groups - for (String group : acc.groups) { - assertTrue(expectedGroups.contains(group)); + for (String expected : expectedGroups) { + assertTrue("Did not find group [" + expected + + "] in the group collection!", + acc.groups.contains(expected)); } // Check the group members - for (String key: acc.groupMemberMap.keySet()) { - for (String member: acc.groupMemberMap.get(key)) { - assertTrue(expectedGroupMembers.contains(member)); + final Map> groupMemberMap = acc.groupMemberMap; + for (Entry> entry : expectedGroupsToValues + .entrySet()) { + final String groupName = entry.getKey(); + final Set setToCheck = groupMemberMap.get(groupName); + for (String member : entry.getValue()) { + assertTrue("Did not find entry [" + member + "] for group [" + + groupName + "]!", setToCheck.contains(member)); } } } @Test - public void testCreateStatsDataMapCreation() { - String eventType = "com.raytheon.uf.common.datadelivery.event.retrieval.DataRetrievalEvent"; + public void testCreateStatsDataMapCreation() throws JAXBException { + String eventType = DataRetrievalEvent.class.getName(); String dataType = "bytes"; String displayUnit = "MB"; @@ -116,54 +167,54 @@ public class StatsDataAccumulatorTest { expectedSet.add("owner3:madis"); expectedSet.add("owner4:madis"); - for (String key : acc.statsDataMap.keySet()) { - assertTrue(expectedSet.contains(key)); + final Map statsDataMap = acc.statsDataMap; + for (String expected : expectedSet) { + assertTrue("Did not find expected value (" + expected + + "] as key in the statsDataMap!", + statsDataMap.containsKey(expected)); } } // Build the Aggregate records - private List getTestRecords() { + private List getTestRecords() throws JAXBException { String plugin = "plugin"; String provider = "provider"; String nomads = "nomads"; String madis = "madis"; String owner = "owner"; String grid = "grid"; - String dash = "-"; - String colon = ":"; - List groupings = new ArrayList(); - for (int i = 0; i < 5; i++) { - groupings.add(plugin + colon + grid + dash + owner + colon + owner + i); + List groupingColumns = new ArrayList(); + for (int i = 0; i < 15; i++) { + groupingColumns.add(StatsGroupingColumn.withGroupings( + new StatsGrouping(plugin, grid), new StatsGrouping(owner, + owner + i))); } for (int i = 0; i < 5; i++) { - groupings.add(plugin + colon + grid + dash + owner + colon + owner + i); + groupingColumns.add(StatsGroupingColumn.withGroupings( + new StatsGrouping(provider, nomads), new StatsGrouping( + owner, owner + i))); } for (int i = 0; i < 5; i++) { - groupings.add(plugin + colon + grid + dash + owner + colon + owner + i); - } - - for (int i = 0; i < 5; i++) { - groupings.add(provider + colon + nomads + dash + owner + colon + owner + i); - } - for (int i = 0; i < 5; i++) { - groupings.add(provider + colon + madis + dash + owner + colon + owner + i); + groupingColumns.add(StatsGroupingColumn.withGroupings( + new StatsGrouping(provider, madis), new StatsGrouping( + owner, owner + i))); } List records = new ArrayList(); - for (String group : groupings) { + for (StatsGroupingColumn group : groupingColumns) { AggregateRecord r = new AggregateRecord(); - if (group.contains("provider")) { - r.setEventType("com.raytheon.uf.common.datadelivery.event.retrieval.DataRetrievalEvent"); + if ("provider".equals(group.getGroup().iterator().next().getName())) { + r.setEventType(DataRetrievalEvent.class.getName()); r.setField("bytes"); } else { - r.setEventType("com.raytheon.uf.common.datadelivery.event.retrieval.SubscriptionRetrievalEvent"); + r.setEventType(SubscriptionRetrievalEvent.class.getName()); r.setField("numRecords"); } - r.setGrouping(group); + r.setGrouping(JAXB_MANAGER.marshalToXml(group)); records.add(r); } diff --git a/tests/utility/edex_static/base/stats/mockStats.xml b/tests/utility/edex_static/base/stats/mockStats.xml new file mode 100644 index 0000000000..3c9c5aef7a --- /dev/null +++ b/tests/utility/edex_static/base/stats/mockStats.xml @@ -0,0 +1,12 @@ + + + + + + + + + From fc87600adb32d4be74f8675317bd40164061c5d2 Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Wed, 16 Jan 2013 12:24:37 -0600 Subject: [PATCH 04/10] Issue #1420 - More Rules changes. Peer review comments Change-Id: I3ed89b332764bba2d995a248e361d20c1eec6edf Former-commit-id: 1df1b5a94dc1c61481ae7824c5a7064de1e8b904 [formerly 2a31447d6dd26b087c67871f4fd977e494911481] [formerly 1df1b5a94dc1c61481ae7824c5a7064de1e8b904 [formerly 2a31447d6dd26b087c67871f4fd977e494911481] [formerly 8d0a79703fb53faac547249f84be6638ad971ecc [formerly 84f2d0ed39e11059359558676c988a0bf1e989b9]]] Former-commit-id: 8d0a79703fb53faac547249f84be6638ad971ecc Former-commit-id: 72a70a6eaf5fbe07120aad7b3e12ce7b6dcf9dc7 [formerly c6924b6920e536ef970d887e6b7028385a788137] Former-commit-id: 7a750e72e398f4d87e3017934ac14cf12c70e098 --- .../subscription/xml/RuleXML.java | 7 - .../system/CreateEditRuleDlg.java | 72 ++++-- .../system/IRulesUpdateListener.java | 44 ++++ .../datadelivery/system/SystemLatencyTab.java | 5 +- .../system/SystemManagementDlg.java | 43 +++- .../system/SystemPriorityTab.java | 5 +- .../system/SystemRuleManager.java | 241 +++++++++++++----- .../systemManagement/rules/latencyRules.xml | 8 +- .../systemManagement/rules/priorityRules.xml | 4 + .../common_static/base/roles/userRoles.xml | 3 + 10 files changed, 319 insertions(+), 113 deletions(-) create mode 100644 cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/IRulesUpdateListener.java create mode 100644 edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/utility/common_static/base/datadelivery/systemManagement/rules/priorityRules.xml diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/xml/RuleXML.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/xml/RuleXML.java index 698c4ac80f..7a9904d210 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/xml/RuleXML.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/xml/RuleXML.java @@ -27,8 +27,6 @@ import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import com.raytheon.uf.common.datadelivery.registry.Subscription; -import com.raytheon.uf.common.status.IUFStatusHandler; -import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.viz.datadelivery.system.CreateEditRuleDlg.FreqUnitOptions; import com.raytheon.uf.viz.datadelivery.system.Operator; import com.raytheon.uf.viz.datadelivery.system.OpsNetFieldNames; @@ -54,11 +52,6 @@ import com.raytheon.uf.viz.datadelivery.utils.DataSizeUnit; @SuppressWarnings({ "unchecked", "rawtypes" }) @XmlAccessorType(XmlAccessType.NONE) public abstract class RuleXML { - - /** Status Handler */ - private final IUFStatusHandler statusHandler = UFStatus - .getHandler(RuleXML.class); - /** Rule name */ @XmlElement protected String ruleName; diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/CreateEditRuleDlg.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/CreateEditRuleDlg.java index 3b3c721501..b5cb686005 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/CreateEditRuleDlg.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/CreateEditRuleDlg.java @@ -19,6 +19,7 @@ **/ package com.raytheon.uf.viz.datadelivery.system; +import java.util.List; import java.util.regex.Pattern; import org.eclipse.swt.SWT; @@ -227,6 +228,9 @@ public class CreateEditRuleDlg extends CaveSWTDialog { this(parent, create, null, ruleType); } + /** + * Create the rule header. + */ private void createRuleHeader() { if (create) { if (PRIORITY_TYPE.equals(ruleType)) { @@ -269,9 +273,9 @@ public class CreateEditRuleDlg extends CaveSWTDialog { protected void initializeComponents(Shell shell) { if (!create) { if (PRIORITY_TYPE.equals(ruleType)) { - ruleXml = srm.loadPriorityRule(ruleName); + ruleXml = srm.getPriorityRule(ruleName); } else { - ruleXml = srm.loadLatencyRule(ruleName); + ruleXml = srm.getLatencyRule(ruleName); } if (DATASET_SIZE.equals(ruleXml.getRuleField())) { @@ -411,7 +415,6 @@ public class CreateEditRuleDlg extends CaveSWTDialog { String item = fieldCombo.getItem(index); updateSelectionFields(item); } - }); OpsNetFieldNames[] fieldItems = OpsNetFieldNames.values(); @@ -450,7 +453,6 @@ public class CreateEditRuleDlg extends CaveSWTDialog { createFreqUnitItems(); } unitsCombo.select(0); - } if (PRIORITY_TYPE.equals(ruleType)) { @@ -481,7 +483,6 @@ public class CreateEditRuleDlg extends CaveSWTDialog { } priorityCombo.select(0); - } else { gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); gl = new GridLayout(3, false); @@ -507,19 +508,16 @@ public class CreateEditRuleDlg extends CaveSWTDialog { Label minutesLbl = new Label(latencySelectionComp, SWT.NONE); minutesLbl.setLayoutData(gd); minutesLbl.setText("Minutes"); - } populateFields(); ruleDefinitionGroup.pack(); - } /** * Upon edit, populate the fields. */ private void populateFields() { - if (!create) { String field = ruleXml.getRuleField(); if (!field.isEmpty()) { @@ -602,7 +600,6 @@ public class CreateEditRuleDlg extends CaveSWTDialog { close(); } }); - } /** @@ -651,6 +648,13 @@ public class CreateEditRuleDlg extends CaveSWTDialog { Operator operator = OperatorAdapter.fromString(operationCombo .getItem(operationCombo.getSelectionIndex())); + List ruleNames = null; + if (PRIORITY_TYPE.equals(ruleType)) { + ruleNames = srm.getPriorityRuleNames(); + } else { + ruleNames = srm.getLatencyRuleNames(); + } + if (create) { valid = DataDeliveryGUIUtils.hasText(ruleNameText); @@ -663,13 +667,29 @@ public class CreateEditRuleDlg extends CaveSWTDialog { } ruleName = ruleNameText.getText(); + + if (INVALID_PATTERN.matcher(ruleName.trim()).find()) { + DataDeliveryUtils.showMessage(getShell(), SWT.ERROR, + INVALID_CHARS_TITLE, INVALID_CHARS_MESSAGE); + return false; + } + + // Check for duplicate rule name + if (ruleNames.contains(ruleName)) { + DataDeliveryUtils + .showMessage( + shell, + SWT.ERROR, + "Duplicate Rule", + "A rule titled " + + ruleName + + " already exists.\n\nPlease select a different name."); + ruleNameText.selectAll(); + + return false; + } } - if (INVALID_PATTERN.matcher(ruleName.trim()).find()) { - DataDeliveryUtils.showMessage(getShell(), SWT.ERROR, - INVALID_CHARS_TITLE, INVALID_CHARS_MESSAGE); - return false; - } String value = null; if (DataDeliveryGUIUtils.hasText(ruleValue)) { value = ruleValue.getText(); @@ -770,21 +790,12 @@ public class CreateEditRuleDlg extends CaveSWTDialog { } setReturnValue(saved); - - if (!saved) { - DataDeliveryUtils - .showMessage( - getShell(), - SWT.OK, - "Duplicate Name", - "A rule named " - + ruleName - + " already exists\n\nPlease select a different name."); - ruleNameText.selectAll(); - } return saved; } + /** + * Populate the units combo. + */ private void createSizeUnitItems() { unitsCombo.removeAll(); DataSizeUnit[] sizeUnits = DataSizeUnit.values(); @@ -793,6 +804,9 @@ public class CreateEditRuleDlg extends CaveSWTDialog { } } + /** + * Populate the operation combo. + */ private void createSizeOpItems() { operationCombo.removeAll(); OperatorTypes[] sizeOps = OperatorTypes.values(); @@ -801,6 +815,9 @@ public class CreateEditRuleDlg extends CaveSWTDialog { } } + /** + * Populate the frequency units combo. + */ private void createFreqUnitItems() { FreqUnitOptions[] freqUnits = FreqUnitOptions.values(); for (FreqUnitOptions fuo : freqUnits) { @@ -808,6 +825,9 @@ public class CreateEditRuleDlg extends CaveSWTDialog { } } + /** + * populate the operation combo. + */ private void createNameOpItems() { operationCombo.removeAll(); NameOperationItems[] nameOperation = NameOperationItems.values(); diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/IRulesUpdateListener.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/IRulesUpdateListener.java new file mode 100644 index 0000000000..f393c815b7 --- /dev/null +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/IRulesUpdateListener.java @@ -0,0 +1,44 @@ +/** + * 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.viz.datadelivery.system; + +/** + * Rules file update notifier interface. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 16, 2013   1420     mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ + +public interface IRulesUpdateListener { + /** + * Update rules. + */ + void update(); +} diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemLatencyTab.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemLatencyTab.java index ad70cc3fe4..1e2a94f8b6 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemLatencyTab.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemLatencyTab.java @@ -263,10 +263,7 @@ public class SystemLatencyTab { ruleDlg = new CreateEditRuleDlg(parentComp.getShell(), create, ruleName, LATENCY_TYPE); } - boolean reloadFlag = (Boolean) ruleDlg.open(); - if (reloadFlag) { - loadList(); - } + ruleDlg.open(); } else { ruleDlg.bringToTop(); } diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemManagementDlg.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemManagementDlg.java index 441f9eb9fa..61e2bab7e6 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemManagementDlg.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemManagementDlg.java @@ -45,6 +45,7 @@ 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.StringUtil; +import com.raytheon.uf.viz.core.VizApp; import com.raytheon.uf.viz.datadelivery.subscription.SubscriptionService.ForceApplyPromptResponse; import com.raytheon.uf.viz.datadelivery.subscription.SubscriptionService.IForceApplyPromptDisplayText; import com.raytheon.uf.viz.datadelivery.utils.DataDeliveryUtils; @@ -71,7 +72,7 @@ import com.raytheon.viz.ui.presenter.IDisplay; * @version 1.0 */ public class SystemManagementDlg extends CaveSWTDialog implements IDisplay, - IForceApplyPromptDisplayText { + IForceApplyPromptDisplayText, IRulesUpdateListener { /** Status Handler */ private final IUFStatusHandler statusHandler = UFStatus @@ -128,10 +129,18 @@ public class SystemManagementDlg extends CaveSWTDialog implements IDisplay, /** OK button */ private Button okBtn; + /** Available bandwidth modified flag */ private boolean availableBandwidthModified; + /** Available bandwidth spinner widget */ private Spinner availBandwidthSpinner; + /** The system latency tab */ + private SystemLatencyTab lTab; + + /** The system priority tab */ + private SystemPriorityTab pTab; + /** * Constructor. * @@ -141,6 +150,7 @@ public class SystemManagementDlg extends CaveSWTDialog implements IDisplay, public SystemManagementDlg(Shell parent) { super(parent, SWT.DIALOG_TRIM, CAVE.NONE); setText("Data Delivery System Management"); + SystemRuleManager.getInstance().registerAsListener(this); } @@ -181,6 +191,17 @@ public class SystemManagementDlg extends CaveSWTDialog implements IDisplay, } + /* + * (non-Javadoc) + * + * @see com.raytheon.viz.ui.dialogs.CaveSWTDialogBase#disposed() + */ + @Override + protected void disposed() { + super.disposed(); + SystemRuleManager.getInstance().deregisterAsListener(this); + } + /** * Create top bar route information. */ @@ -283,7 +304,7 @@ public class SystemManagementDlg extends CaveSWTDialog implements IDisplay, priorityComp.setLayout(gl); priorityComp.setLayoutData(gd); priorityTab.setControl(priorityComp); - SystemPriorityTab pTab = new SystemPriorityTab(priorityComp); + pTab = new SystemPriorityTab(priorityComp); gd = new GridData(SWT.FILL, SWT.DEFAULT, true, false); gl = new GridLayout(1, false); @@ -296,7 +317,7 @@ public class SystemManagementDlg extends CaveSWTDialog implements IDisplay, latencyComp.setLayout(gl); latencyComp.setLayoutData(gd); latencyTab.setControl(latencyComp); - SystemLatencyTab lTab = new SystemLatencyTab(latencyComp); + lTab = new SystemLatencyTab(latencyComp); gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false); gl = new GridLayout(1, false); @@ -309,6 +330,9 @@ public class SystemManagementDlg extends CaveSWTDialog implements IDisplay, routingComp.setLayoutData(gd); routingTab.setControl(routingComp); SystemRoutingTab rTab = new SystemRoutingTab(routingComp); + + lTab.loadList(); + pTab.loadList(); } /** @@ -466,4 +490,17 @@ public class SystemManagementDlg extends CaveSWTDialog implements IDisplay, "Don't know how to handle option [" + option + "]"); } } + + @Override + public void update() { + VizApp.runAsync(new Runnable() { + @Override + public void run() { + if (!shell.isDisposed()) { + lTab.loadList(); + pTab.loadList(); + } + } + }); + } } diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemPriorityTab.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemPriorityTab.java index f39ce7daae..1d4635fd11 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemPriorityTab.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemPriorityTab.java @@ -268,10 +268,7 @@ public class SystemPriorityTab { create, ruleName, PRIORITY_TYPE); } - boolean reloadFlag = (Boolean) ruleDlg.open(); - if (reloadFlag) { - loadList(); - } + ruleDlg.open(); } else { ruleDlg.bringToTop(); } diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemRuleManager.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemRuleManager.java index 5f1dc81a0b..434a3f1c94 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemRuleManager.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemRuleManager.java @@ -32,6 +32,8 @@ import javax.xml.bind.Unmarshaller; import com.raytheon.uf.common.datadelivery.bandwidth.IBandwidthService; import com.raytheon.uf.common.datadelivery.registry.Network; import com.raytheon.uf.common.datadelivery.registry.Subscription; +import com.raytheon.uf.common.localization.FileUpdatedMessage; +import com.raytheon.uf.common.localization.ILocalizationFileObserver; import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.LocalizationContext; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; @@ -89,6 +91,12 @@ public class SystemRuleManager { private final IUFStatusHandler statusHandler = UFStatus .getHandler(SystemRuleManager.class); + /** Latency Rules Localization File */ + private LocalizationFile latencyRulesLocFile; + + /** Priority Rules Localization File */ + private LocalizationFile priorityRulesLocFile; + /** JAXB context */ private JAXBContext jax; @@ -101,11 +109,21 @@ public class SystemRuleManager { /** Bandwidth service */ private IBandwidthService bandwidthService; + /** Latency Rules XML object */ + private LatencyRulesXML latencyRules; + + /** Priority Rules XML object */ + private PriorityRulesXML priorityRules; + + private final List listeners = new ArrayList(); + /** * Constructor. */ private SystemRuleManager() { createContext(); + loadLatencyRules(); + loadPriorityRules(); } /** @@ -144,7 +162,7 @@ public class SystemRuleManager { * @throws JAXBException */ public List getPriorityRuleNames() { - return getPriorityRules().getRuleNames(); + return getPriorityRules(false).getRuleNames(); } /** @@ -154,8 +172,8 @@ public class SystemRuleManager { * the name of the rule * @return the PriorityRuleXML object */ - public PriorityRuleXML loadPriorityRule(String name) { - PriorityRulesXML priorityRules = getPriorityRules(); + public PriorityRuleXML getPriorityRule(String name) { + PriorityRulesXML priorityRules = getPriorityRules(false); for (PriorityRuleXML rule : priorityRules.getRules()) { if (rule.getRuleName().equals(name)) { return rule; @@ -172,8 +190,8 @@ public class SystemRuleManager { * the name of the rule * @return the LatencyRuleXML object */ - public LatencyRuleXML loadLatencyRule(String name) { - LatencyRulesXML latencyRules = getLatencyRules(); + public LatencyRuleXML getLatencyRule(String name) { + LatencyRulesXML latencyRules = getLatencyRules(false); for (LatencyRuleXML rule : latencyRules.getRules()) { if (rule.getRuleName().equals(name)) { return rule; @@ -190,7 +208,7 @@ public class SystemRuleManager { * @throws JAXBException */ public List getLatencyRuleNames() { - return getLatencyRules().getRuleNames(); + return getLatencyRules(false).getRuleNames(); } /** @@ -203,15 +221,22 @@ public class SystemRuleManager { public boolean savePriorityRules(PriorityRulesXML xmlObj) { IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationContext context = pm.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - LocalizationFile priorityRulesLocFile = pm.getLocalizationFile(context, - this.PRIORITY_RULE_FILE); - try { - marshaller.marshal(xmlObj, priorityRulesLocFile.getFile()); - priorityRulesLocFile.save(); - return true; + // If site, then write out, otherwise save it as site. + if (priorityRulesLocFile.getContext().getLocalizationLevel() + .equals(LocalizationLevel.SITE)) { + marshaller.marshal(xmlObj, priorityRulesLocFile.getFile()); + return priorityRulesLocFile.save(); + } else { + LocalizationContext context = pm.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + + priorityRulesLocFile = pm.getLocalizationFile(context, + this.PRIORITY_RULE_FILE); + addPriorityRulesFileObserver(); + marshaller.marshal(xmlObj, priorityRulesLocFile.getFile()); + return priorityRulesLocFile.save(); + } } catch (JAXBException e) { statusHandler.handle(Priority.ERROR, e.getLocalizedMessage(), e); } catch (LocalizationOpFailedException e) { @@ -231,15 +256,22 @@ public class SystemRuleManager { public boolean saveLatencyRules(LatencyRulesXML xmlObj) { IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationContext context = pm.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); - LocalizationFile latencyRulesLocFile = pm.getLocalizationFile(context, - this.LATENCY_RULE_FILE); - try { - marshaller.marshal(xmlObj, latencyRulesLocFile.getFile()); - latencyRulesLocFile.save(); - return true; + // If site, then write out, otherwise save it as site. + if (latencyRulesLocFile.getContext().getLocalizationLevel() + .equals(LocalizationLevel.SITE)) { + marshaller.marshal(xmlObj, latencyRulesLocFile.getFile()); + return latencyRulesLocFile.save(); + } else { + LocalizationContext context = pm.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + + latencyRulesLocFile = pm.getLocalizationFile(context, + this.LATENCY_RULE_FILE); + addLatencyRulesFileObserver(); + marshaller.marshal(xmlObj, latencyRulesLocFile.getFile()); + return latencyRulesLocFile.save(); + } } catch (JAXBException e) { statusHandler.handle(Priority.ERROR, e.getLocalizedMessage(), e); } catch (LocalizationOpFailedException e) { @@ -256,7 +288,7 @@ public class SystemRuleManager { * the rule name to delete */ public void deleteLatencyRule(String ruleName) { - LatencyRulesXML latencyRules = getLatencyRules(); + LatencyRulesXML latencyRules = getLatencyRules(false); for (LatencyRuleXML rule : latencyRules.getRules()) { if (rule.getRuleName().equals(ruleName)) { @@ -274,7 +306,7 @@ public class SystemRuleManager { * the rule name to delete */ public void deletePriorityRule(String ruleName) { - PriorityRulesXML priorityRules = getPriorityRules(); + PriorityRulesXML priorityRules = getPriorityRules(false); for (PriorityRuleXML rule : priorityRules.getRules()) { if (rule.getRuleName().equals(ruleName)) { @@ -293,7 +325,7 @@ public class SystemRuleManager { * @return true if updated */ public boolean updateRule(LatencyRuleXML rule) { - LatencyRulesXML rulesXml = getLatencyRules(); + LatencyRulesXML rulesXml = getLatencyRules(false); boolean saved = rulesXml.updateRule(rule); if (saved) { return saveLatencyRules(rulesXml); @@ -310,7 +342,7 @@ public class SystemRuleManager { * @return true if updated */ public boolean updateRule(PriorityRuleXML rule) { - PriorityRulesXML rulesXml = getPriorityRules(); + PriorityRulesXML rulesXml = getPriorityRules(false); boolean saved = rulesXml.updateRule(rule); if (saved) { saved = savePriorityRules(rulesXml); @@ -331,7 +363,7 @@ public class SystemRuleManager { * @return true if updated */ public boolean saveRule(PriorityRuleXML rule) { - PriorityRulesXML rulesXml = getPriorityRules(); + PriorityRulesXML rulesXml = getPriorityRules(false); boolean saved = rulesXml.addRule(rule); if (saved) { saved = savePriorityRules(rulesXml); @@ -352,7 +384,7 @@ public class SystemRuleManager { * @return true if updated */ public boolean saveRule(LatencyRuleXML rule) { - LatencyRulesXML rulesXml = getLatencyRules(); + LatencyRulesXML rulesXml = getLatencyRules(false); boolean saved = rulesXml.addRule(rule); if (saved) { saved = saveLatencyRules(rulesXml); @@ -368,19 +400,23 @@ public class SystemRuleManager { /** * Get the latency rules. * + * @param reread + * true to reread the file from disk + * * @return The latency rules xml object */ - private LatencyRulesXML getLatencyRules() { - LocalizationFile lfile = getRules(this.LATENCY_RULE_FILE); - - LatencyRulesXML latencyRules = new LatencyRulesXML(); - if (lfile != null && lfile.exists()) { - try { - latencyRules = (LatencyRulesXML) unmarshaller.unmarshal(lfile - .getFile()); - } catch (JAXBException e) { - statusHandler - .handle(Priority.ERROR, e.getLocalizedMessage(), e); + private LatencyRulesXML getLatencyRules(boolean reread) { + if (latencyRules == null || reread) { + if (this.latencyRulesLocFile != null + && latencyRulesLocFile.exists()) { + try { + latencyRules = (LatencyRulesXML) unmarshaller + .unmarshal(latencyRulesLocFile.getFile()); + } catch (JAXBException e) { + statusHandler.handle(Priority.ERROR, + e.getLocalizedMessage(), e); + latencyRules = new LatencyRulesXML(); + } } } @@ -390,34 +426,26 @@ public class SystemRuleManager { /** * Get the priority rules * + * @param reread + * true to reread the file from disk + * * @return The priority rules xml object */ - private PriorityRulesXML getPriorityRules() { - LocalizationFile lfile = getRules(this.PRIORITY_RULE_FILE); - - PriorityRulesXML priorityRules = new PriorityRulesXML(); - if (lfile != null && lfile.exists()) { - try { - priorityRules = (PriorityRulesXML) unmarshaller.unmarshal(lfile - .getFile()); - } catch (JAXBException e) { - statusHandler - .handle(Priority.ERROR, e.getLocalizedMessage(), e); + private PriorityRulesXML getPriorityRules(boolean reread) { + if (priorityRules == null || reread) + if (this.priorityRulesLocFile != null + && priorityRulesLocFile.exists()) { + try { + priorityRules = (PriorityRulesXML) unmarshaller + .unmarshal(priorityRulesLocFile.getFile()); + } catch (JAXBException e) { + statusHandler.handle(Priority.ERROR, + e.getLocalizedMessage(), e); + priorityRules = new PriorityRulesXML(); + } } - } - return priorityRules; - } - /** - * Get the rules files - * - * @param name - * Rules file name to get - * @return The localization file - */ - private LocalizationFile getRules(String name) { - IPathManager pm = PathManagerFactory.getPathManager(); - return pm.getStaticLocalizationFile(name); + return priorityRules; } /** @@ -442,7 +470,7 @@ public class SystemRuleManager { * @return */ public int getLatency(Subscription sub, Set cycleTimes) { - LatencyRulesXML rulesXml = this.getLatencyRules(); + LatencyRulesXML rulesXml = this.getLatencyRules(false); int latency = 999; boolean found = false; for (LatencyRuleXML rule : rulesXml.getRules()) { @@ -471,7 +499,7 @@ public class SystemRuleManager { * @return */ public int getPriority(Subscription sub, Set cycleTimes) { - PriorityRulesXML rulesXml = this.getPriorityRules(); + PriorityRulesXML rulesXml = this.getPriorityRules(false); int priority = 3; boolean found = false; for (PriorityRuleXML rule : rulesXml.getRules()) { @@ -546,4 +574,87 @@ public class SystemRuleManager { return getInstance().bandwidthService .setBandwidthForNetworkInKilobytes(network, bandwidth); } + + /** + * Read the latency rules file. + */ + private void loadLatencyRules() { + IPathManager pm = PathManagerFactory.getPathManager(); + this.latencyRulesLocFile = pm + .getStaticLocalizationFile(this.LATENCY_RULE_FILE); + addLatencyRulesFileObserver(); + getLatencyRules(true); + } + + /** + * Load the priority rules file. + */ + private void loadPriorityRules() { + IPathManager pm = PathManagerFactory.getPathManager(); + this.priorityRulesLocFile = pm + .getStaticLocalizationFile(this.PRIORITY_RULE_FILE); + addPriorityRulesFileObserver(); + getPriorityRules(true); + } + + /** + * Add a file observer to the latency rules file to get notified when the + * file changes. + */ + private void addLatencyRulesFileObserver() { + latencyRulesLocFile + .addFileUpdatedObserver(new ILocalizationFileObserver() { + @Override + public void fileUpdated(FileUpdatedMessage message) { + loadLatencyRules(); + fireUpdates(); + } + }); + } + + /** + * Add a file observer to the priority rules file to get notified when the + * file changes. + */ + private void addPriorityRulesFileObserver() { + priorityRulesLocFile + .addFileUpdatedObserver(new ILocalizationFileObserver() { + @Override + public void fileUpdated(FileUpdatedMessage message) { + loadPriorityRules(); + fireUpdates(); + } + }); + } + + /** + * Notify the listeners the files changed. + */ + private void fireUpdates() { + for (IRulesUpdateListener listener : listeners) { + listener.update(); + } + } + + /** + * Register as a listener for rules file changes. + * + * @param listener + */ + public void registerAsListener(IRulesUpdateListener listener) { + if (!listeners.contains(listener)) { + listeners.add(listener); + } + } + + /** + * Unregister as a listener for rules files changed. + * + * @param listener + */ + public void deregisterAsListener(IRulesUpdateListener listener) { + if (listeners.contains(listener)) { + listeners.remove(listener); + } + } } diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/utility/common_static/base/datadelivery/systemManagement/rules/latencyRules.xml b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/utility/common_static/base/datadelivery/systemManagement/rules/latencyRules.xml index ab09f88dfb..f686a0eda8 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/utility/common_static/base/datadelivery/systemManagement/rules/latencyRules.xml +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/utility/common_static/base/datadelivery/systemManagement/rules/latencyRules.xml @@ -1,19 +1,19 @@ - + Dataset Frequency Hourly-Products <= Hrs 1 40 - - + + Dataset Frequency MultiHour-Products > Hrs 1 115 - + diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/utility/common_static/base/datadelivery/systemManagement/rules/priorityRules.xml b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/utility/common_static/base/datadelivery/systemManagement/rules/priorityRules.xml new file mode 100644 index 0000000000..36fe07252c --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/utility/common_static/base/datadelivery/systemManagement/rules/priorityRules.xml @@ -0,0 +1,4 @@ + + + + diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/utility/common_static/base/roles/userRoles.xml b/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/utility/common_static/base/roles/userRoles.xml index 67ab28709d..61c231cbea 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/utility/common_static/base/roles/userRoles.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/utility/common_static/base/roles/userRoles.xml @@ -89,6 +89,8 @@ + + com.raytheon.localization.site/common_static/purge com.raytheon.localization.site/cave_static/colormaps @@ -119,6 +121,7 @@ com.raytheon.localization.site/common_static/radar/rmr/rmrAvailableRequests.xml com.raytheon.localization.site/common_static/shef com.raytheon.localization.site/common_static/roles + com.raytheon.localization.site/common_static/datadelivery From 379b354ffc9010fc3c5bc98da739a094ca31a96f Mon Sep 17 00:00:00 2001 From: Brad Gonzales Date: Mon, 14 Jan 2013 09:20:38 -0600 Subject: [PATCH 05/10] Issue #1448 Added app context checks to ArealQpeGenSrv MpeLightningSrv. Uncommented run_report_alarm call in run_alarm_whfs. Moved internal methods to private in MpeRUCFreezingLevel. Amend: removed log statments from run_alarm_whfs based on review comments. removed tab. Change-Id: I05cd853814376bfb0ac61e3340210be928a35c57 Former-commit-id: 1a3e2792266b83cb4dc4f58ebed8c3ab2b5e175a [formerly 31c48be1c51ff1cef5af25138162fbee2c5737f6] [formerly 1a3e2792266b83cb4dc4f58ebed8c3ab2b5e175a [formerly 31c48be1c51ff1cef5af25138162fbee2c5737f6] [formerly 69eccc1d80e810857c0dffc2eaa2f40381bb0867 [formerly 86c094b2d301dbf6ead2d74bc64b3596cf2ef6d8]]] Former-commit-id: 69eccc1d80e810857c0dffc2eaa2f40381bb0867 Former-commit-id: a90db41abdb62050de8f302e90e2fa9b546269e0 [formerly e1e5001736bb3b3b93df1aea4eb633cc36c66059] Former-commit-id: 62770974507a8f945d2f903acc5d3204af75cd82 --- .../uf/edex/ohd/pproc/ArealQpeGenSrv.java | 4 ++ .../uf/edex/ohd/pproc/MpeLightningSrv.java | 5 +++ .../edex/ohd/pproc/MpeRUCFreezingLevel.java | 38 +++++++++---------- .../awips/hydroapps/whfs/bin/run_alarm_whfs | 16 ++------ 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.ohd/src/com/raytheon/uf/edex/ohd/pproc/ArealQpeGenSrv.java b/edexOsgi/com.raytheon.uf.edex.ohd/src/com/raytheon/uf/edex/ohd/pproc/ArealQpeGenSrv.java index a6411a4ec1..29e73a95a8 100644 --- a/edexOsgi/com.raytheon.uf.edex.ohd/src/com/raytheon/uf/edex/ohd/pproc/ArealQpeGenSrv.java +++ b/edexOsgi/com.raytheon.uf.edex.ohd/src/com/raytheon/uf/edex/ohd/pproc/ArealQpeGenSrv.java @@ -70,6 +70,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jan 26, 2011 snaples Initial creation + * Jan 10, 2013 1448 bgonzale Added app context check in processArealQpe(). * * * @@ -209,6 +210,9 @@ public class ArealQpeGenSrv { private SimpleDateFormat fdf = new SimpleDateFormat("yyyyMMddHH"); public Object processArealQpe() { + if (!AppsDefaults.getInstance().setAppContext(this)) { + return null; + } // Check to see if we need to run String gen = appsDefaults.getToken("mpe_generate_areal_qpe"); diff --git a/edexOsgi/com.raytheon.uf.edex.ohd/src/com/raytheon/uf/edex/ohd/pproc/MpeLightningSrv.java b/edexOsgi/com.raytheon.uf.edex.ohd/src/com/raytheon/uf/edex/ohd/pproc/MpeLightningSrv.java index 98653ac91e..f1e80fe538 100644 --- a/edexOsgi/com.raytheon.uf.edex.ohd/src/com/raytheon/uf/edex/ohd/pproc/MpeLightningSrv.java +++ b/edexOsgi/com.raytheon.uf.edex.ohd/src/com/raytheon/uf/edex/ohd/pproc/MpeLightningSrv.java @@ -37,6 +37,7 @@ import com.raytheon.uf.common.datastorage.DataStoreFactory; import com.raytheon.uf.common.datastorage.IDataStore; import com.raytheon.uf.common.datastorage.StorageException; import com.raytheon.uf.common.hydro.spatial.HRAP; +import com.raytheon.uf.common.ohd.AppsDefaults; import com.raytheon.uf.edex.core.EdexException; import com.raytheon.uf.edex.core.props.EnvProperties; import com.raytheon.uf.edex.core.props.PropertiesFactory; @@ -54,6 +55,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jan 06, 2011 5951 jnjanga Initial creation + * Jan 10, 2013 1448 bgonzale Added app context check in runOnSchedule(). * * * @@ -218,6 +220,9 @@ public class MpeLightningSrv { * @throws EdexException */ public void runOnSchedule() throws EdexException { + if (!AppsDefaults.getInstance().setAppContext(this)) { + return; + } QueryResultRow[] rows = getMostRecentStrikes(); ifhsInsertMostRecentStrikes(rows); } diff --git a/edexOsgi/com.raytheon.uf.edex.ohd/src/com/raytheon/uf/edex/ohd/pproc/MpeRUCFreezingLevel.java b/edexOsgi/com.raytheon.uf.edex.ohd/src/com/raytheon/uf/edex/ohd/pproc/MpeRUCFreezingLevel.java index 954bae7509..9e525fef4e 100644 --- a/edexOsgi/com.raytheon.uf.edex.ohd/src/com/raytheon/uf/edex/ohd/pproc/MpeRUCFreezingLevel.java +++ b/edexOsgi/com.raytheon.uf.edex.ohd/src/com/raytheon/uf/edex/ohd/pproc/MpeRUCFreezingLevel.java @@ -55,24 +55,24 @@ import com.raytheon.uf.edex.core.props.PropertiesFactory; import com.raytheon.uf.edex.dat.utils.FreezingLevel; import com.vividsolutions.jts.geom.Coordinate; +/** + * MPE RUC calculator + * + *
+ * SOFTWARE HISTORY
+ * Date         Ticket#  Engineer    Description
+ * ------------ -------- --------- --------------------------
+ * Nov 19, 2011          dhladky    Initial Creation.
+ * Oct 09, 2012 15168    wkwock     Fix incorrect values.
+ * Jan 10, 2013 1448     bgonzale   Made methods that are used internally private.
+ * 
+ * 
+ * + * @author dhladky + * @version 1.0 + */ public class MpeRUCFreezingLevel { - /** - * MPE RUC calculator - * - *
-     * SOFTWARE HISTORY
-     * Date         Ticket#  Engineer    Description
-     * ------------ -------- --------- --------------------------
-     * Nov 19, 2011          dhladky    Initial Creation.
-     * Oct 09, 2012 15168    wkwock     Fix incorrect values.
-     * 
-     * 
- * - * @author dhladky - * @version 1.0 - */ - private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(MpeRUCFreezingLevel.class); @@ -441,7 +441,7 @@ public class MpeRUCFreezingLevel { * * @return */ - public String getAbsoluteTempFileName(int forecastHour, String modelName) { + private String getAbsoluteTempFileName(int forecastHour, String modelName) { return modelOutputFilePath + File.separatorChar + modelName + forecastHour + "zFreezingLevel" + ".bin"; } @@ -451,7 +451,7 @@ public class MpeRUCFreezingLevel { * * @return */ - public String getAbsoluteOutFileName(Date date, String site) { + private String getAbsoluteOutFileName(Date date, String site) { return modelOutputFilePath + File.separatorChar + "freezing_1_" + site + "_point_" + getFormattedDate(date); } @@ -461,7 +461,7 @@ public class MpeRUCFreezingLevel { * * @param FreezingLevelXML */ - public void writeFreezingLevelTemp(FreezingLevelXML freezingLevel, + private void writeFreezingLevelTemp(FreezingLevelXML freezingLevel, String modelName) { try { diff --git a/nativeLib/rary.ohd.filesystem/awips/hydroapps/whfs/bin/run_alarm_whfs b/nativeLib/rary.ohd.filesystem/awips/hydroapps/whfs/bin/run_alarm_whfs index 9ee99f28f9..2533da9c7f 100755 --- a/nativeLib/rary.ohd.filesystem/awips/hydroapps/whfs/bin/run_alarm_whfs +++ b/nativeLib/rary.ohd.filesystem/awips/hydroapps/whfs/bin/run_alarm_whfs @@ -32,7 +32,7 @@ if [ -e "${LOGFILE}" ] then tail -1200 $LOGFILE > $TEMPNAME mv $TEMPNAME $LOGFILE -fi +fi # echo "------------------------------ " >> $LOGFILE @@ -42,18 +42,10 @@ echo "------------------------------ " >> $LOGFILE Dte=`date -u ` echo Starting alarm_whfs at $Dte >> $LOGFILE -Dte=`date -u` -echo Invoking roc_checker at $Dte >> $LOGFILE - $WHFS_LOCAL_BIN_DIR/run_roc_checker -# TODO re-enabled report_alarm if needed +$WHFS_LOCAL_BIN_DIR/run_report_alarm -#Dte=`date -u` -#echo Invoking report_alarm at $Dte >> $LOGFILE - -#$WHFS_LOCAL_BIN_DIR/run_report_alarm - -#Dte=`date -u ` -#echo Completed alarm_whfs at $Dte >> $LOGFILE +Dte=`date -u ` +echo Completed alarm_whfs at $Dte >> $LOGFILE From e3cf0246c785e7791af53868de9f171965f34321 Mon Sep 17 00:00:00 2001 From: Dustin Johnson Date: Thu, 17 Jan 2013 12:46:27 -0600 Subject: [PATCH 06/10] Issue #1412 Check file last modified times each time role data is requested Change-Id: Ieae84ad3106e3aa0cf4d253a10c27e8c9c60ecaa Former-commit-id: b1ce19e41d4c788f44c5c7355cbfd488a4f09d2e [formerly 74d5a70c30bcb01b068773d482d6bcc172db69ff] [formerly b1ce19e41d4c788f44c5c7355cbfd488a4f09d2e [formerly 74d5a70c30bcb01b068773d482d6bcc172db69ff] [formerly 037dabb683f3bcfc76db76137aea9c8b74020731 [formerly b7e577237df9e157fdb218af48c41f6209ff2bfb]]] Former-commit-id: 037dabb683f3bcfc76db76137aea9c8b74020731 Former-commit-id: fce3f8bec946c58ffa0cccfde4c3cfcabed83e69 [formerly 6468029207a2dd745fce0cd2e2fd81ee37271337] Former-commit-id: 799cf85f82dd2f2e45dd25d9939cbafde5fa0009 --- .../common/localization/LocalizationFile.java | 22 +++ .../META-INF/MANIFEST.MF | 3 +- .../plugin/nwsauth/xml/NwsRoleData.java | 17 ++ .../plugin/nwsauth/xml/PermissionXML.java | 12 ++ .../uf/common/plugin/nwsauth/xml/RoleXML.java | 15 ++ .../uf/common/plugin/nwsauth/xml/UserXML.java | 51 ++++-- .../META-INF/MANIFEST.MF | 3 +- .../uf/edex/plugin/nwsauth/FileManager.java | 82 ++++++--- tests/.classpath | 1 + .../common/localization/TestPathManager.java | 2 +- .../edex/plugin/nwsauth/FileManagerTest.java | 156 ++++++++++++++++++ .../site/OAX/roles/testUserAdminRoles.xml | 14 ++ 12 files changed, 343 insertions(+), 35 deletions(-) create mode 100644 tests/unit/com/raytheon/uf/edex/plugin/nwsauth/FileManagerTest.java create mode 100644 tests/utility/common_static/site/OAX/roles/testUserAdminRoles.xml diff --git a/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/LocalizationFile.java b/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/LocalizationFile.java index 811ccdc6f1..08b78508a8 100644 --- a/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/LocalizationFile.java +++ b/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/LocalizationFile.java @@ -29,6 +29,8 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import javax.xml.bind.JAXBException; + import com.raytheon.uf.common.localization.FileLocker.Type; import com.raytheon.uf.common.localization.ILocalizationAdapter.ListResponse; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; @@ -80,6 +82,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * This was added as part of an effort to improve * localization performance but caused updated * files on the server not to be retrieved. + * Jan 17, 2013 1412 djohnson Add jaxbMarshal. * * * @author njensen @@ -635,6 +638,25 @@ public final class LocalizationFile implements Comparable { return null; } + /** + * Marshal the specified object into this file. + * + * @param obj + * the object to marshal + * + * @param jaxbManager + * the jaxbManager + */ + public void jaxbMarshal(Object obj, JAXBManager jaxbManager) throws LocalizationException{ + try { + String xml = jaxbManager.marshalToXml(obj); + write(xml.getBytes()); + } catch (JAXBException e) { + throw new LocalizationException( + "Unable to marshal the object to the file.", e); + } + } + @Override public String toString() { return context + IPathManager.SEPARATOR + path; diff --git a/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/META-INF/MANIFEST.MF index 76e9413bb9..57095e23d0 100644 --- a/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/META-INF/MANIFEST.MF @@ -10,7 +10,8 @@ Require-Bundle: com.raytheon.uf.common.serialization;bundle-version="1.12.2", com.raytheon.uf.common.auth;bundle-version="1.12.1174", com.raytheon.uf.common.status;bundle-version="1.12.1174", com.raytheon.uf.common.localization;bundle-version="1.12.1174", - com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174" + com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174", + org.apache.commons.lang;bundle-version="2.3.0" Export-Package: com.raytheon.uf.common.plugin.nwsauth, com.raytheon.uf.common.plugin.nwsauth.exception, com.raytheon.uf.common.plugin.nwsauth.user, diff --git a/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/NwsRoleData.java b/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/NwsRoleData.java index 6dd1df05b6..8194b50017 100644 --- a/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/NwsRoleData.java +++ b/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/NwsRoleData.java @@ -302,4 +302,21 @@ public class NwsRoleData implements ISerializableObject { return false; } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("Application:").append(this.getApplication()).append("\n\n"); + sb.append("Users:\n").append(this.getUserList()).append("\n\n"); + sb.append("Permissions:\n").append(this.getPermissionList()) + .append("\n\n"); + sb.append("Roles:\n").append(this.getRoleList()).append("\n\n"); + + return sb.toString(); + } } diff --git a/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/PermissionXML.java b/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/PermissionXML.java index 824f9af8de..1966f492ea 100644 --- a/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/PermissionXML.java +++ b/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/PermissionXML.java @@ -94,4 +94,16 @@ public class PermissionXML implements ISerializableObject { public void setDescription(String description) { this.description = (description == null) ? null : description.trim(); } + + /** + * {@inheritDoc} + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("id:").append(this.getId()); + sb.append("\ndescription:").append(this.getDescription()); + + return sb.toString(); + } } diff --git a/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/RoleXML.java b/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/RoleXML.java index d17db43ea3..5802aa8118 100644 --- a/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/RoleXML.java +++ b/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/RoleXML.java @@ -117,4 +117,19 @@ public class RoleXML implements ISerializableObject { public void addPermission(String permission) { this.permissionList.add(permission); } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("roleId:").append(this.getRoleId()); + sb.append("\nroleDescription:").append(this.getRoleDescription()); + sb.append("\npermissionList:").append(this.getPermissionList()); + + return sb.toString(); + } } diff --git a/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/UserXML.java b/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/UserXML.java index aa8089901e..61f9a5d19e 100644 --- a/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/UserXML.java +++ b/edexOsgi/com.raytheon.uf.common.plugin.nwsauth/src/com/raytheon/uf/common/plugin/nwsauth/xml/UserXML.java @@ -28,6 +28,9 @@ import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElements; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + import com.raytheon.uf.common.auth.user.IAuthenticationData; import com.raytheon.uf.common.auth.user.IUser; import com.raytheon.uf.common.auth.user.IUserId; @@ -66,6 +69,17 @@ public class UserXML implements IUser, ISerializableObject { @XmlElements({ @XmlElement(name = "userRole", type = String.class) }) private List roleList = new ArrayList(); + public UserXML() { + + } + + /** + * @param userId + */ + public UserXML(String userId) { + setUserId(userId); + } + /** * @return the userId */ @@ -129,6 +143,30 @@ public class UserXML implements IUser, ISerializableObject { } } + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof UserXML) { + UserXML that = (UserXML) obj; + + EqualsBuilder builder = new EqualsBuilder(); + builder.append(this.getUserId(), that.getUserId()); + return builder.isEquals(); + + } + return super.equals(obj); + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + return new HashCodeBuilder().append(this.getUserId()).toHashCode(); + } + /* * (non-Javadoc) * @@ -136,17 +174,10 @@ public class UserXML implements IUser, ISerializableObject { */ @Override public String toString() { - final String nl = "\n"; StringBuilder sb = new StringBuilder(); - sb.append(this.getUserId()).append(nl); - - for (String role : this.roleList) { - sb.append(" ").append(role).append(nl); - } - - for (String perm : permissionList) { - sb.append(" ").append(perm).append(nl); - } + sb.append("userId:").append(this.getUserId()); + sb.append("\nroles:").append(this.getRoleList()); + sb.append("\npermissions:").append(this.getPermissionList()); return sb.toString(); } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/META-INF/MANIFEST.MF index 32525a99e7..4b8090eb4f 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/META-INF/MANIFEST.MF @@ -11,7 +11,8 @@ Require-Bundle: com.raytheon.uf.edex.auth;bundle-version="1.12.2", com.raytheon.uf.common.status;bundle-version="1.12.1174", com.raytheon.uf.common.localization, com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174", - com.raytheon.uf.common.useradmin;bundle-version="1.0.0" + com.raytheon.uf.common.useradmin;bundle-version="1.0.0", + com.raytheon.uf.common.time;bundle-version="1.12.1174" Import-Package: com.raytheon.uf.common.localization, com.raytheon.uf.common.serialization, com.raytheon.uf.common.status, diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/src/com/raytheon/uf/edex/plugin/nwsauth/FileManager.java b/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/src/com/raytheon/uf/edex/plugin/nwsauth/FileManager.java index c308db748d..13d71d3320 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/src/com/raytheon/uf/edex/plugin/nwsauth/FileManager.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.nwsauth/src/com/raytheon/uf/edex/plugin/nwsauth/FileManager.java @@ -19,9 +19,11 @@ **/ package com.raytheon.uf.edex.plugin.nwsauth; -import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicLong; import javax.xml.bind.JAXBException; @@ -40,6 +42,7 @@ import com.raytheon.uf.common.serialization.JAXBManager; 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.util.TimeUtil; /** * Uses localization data to determine role/permissions. Intentionally @@ -51,7 +54,9 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 09, 2013 1412 djohnson Moved file writing from viz plugin to server-side. + * Jan 09, 2013 1412 djohnson Moved file writing from viz plugin to server-side. + * Jan 17, 2013 1412 djohnson Check files for having been modified each time data is requested, + * in case they were written by another member of the cluster. * * * @@ -69,14 +74,22 @@ class FileManager { private final String ROLE_DIR = "roles"; - private final Map roleDataMap = new HashMap(); + private final AtomicLong lastReadTime = new AtomicLong(-1L); + + /** + * Application name -> Role Data. + */ + private final ConcurrentMap roleDataMap = new ConcurrentHashMap(); /** * Application name -> LocalizationFile map. */ - private final Map roleFileMap = new HashMap(); + private final ConcurrentMap roleFileMap = new ConcurrentHashMap(); - private FileManager() { + /** + * Package-level visibility so tests can create new instances. + */ + FileManager() { readXML(); } @@ -117,31 +130,54 @@ class FileManager { private void readXML() { try { - getJaxbManager(); - - IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationContext[] contexts = new LocalizationContext[2]; - contexts[0] = pm.getContext(LocalizationType.COMMON_STATIC, - LocalizationLevel.BASE); - contexts[1] = pm.getContext(LocalizationType.COMMON_STATIC, - LocalizationLevel.SITE); - LocalizationFile[] roleFiles = pm.listFiles(contexts, ROLE_DIR, - new String[] { ".xml" }, false, true); - + LocalizationFile[] roleFiles = getUserRoleLocalizationFiles(); + boolean needToReadFiles = false; for (LocalizationFile lf : roleFiles) { - NwsRoleData roleData = lf.jaxbUnmarshal(NwsRoleData.class, - getJaxbManager()); + final long fileLastModified = lf.getFile().lastModified(); + final long lastTimeFilesWereRead = lastReadTime.get(); - if (roleData != null) { - this.roleDataMap.put(roleData.getApplication(), roleData); - this.roleFileMap.put(roleData.getApplication(), lf); + if (fileLastModified > lastTimeFilesWereRead) { + needToReadFiles = true; + break; } } + + if (needToReadFiles) { + for (LocalizationFile lf : roleFiles) { + final long fileLastModified = lf.getFile().lastModified(); + final long lastTimeFilesWereRead = lastReadTime.get(); + + if (fileLastModified < lastTimeFilesWereRead) { + continue; + } + NwsRoleData roleData = lf.jaxbUnmarshal(NwsRoleData.class, + getJaxbManager()); + + if (roleData != null) { + final String application = roleData.getApplication(); + this.roleDataMap.put(application, roleData); + this.roleFileMap.put(application, lf); + } + } + } + lastReadTime.set(TimeUtil.currentTimeMillis()); } catch (Exception e) { statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); } } + private LocalizationFile[] getUserRoleLocalizationFiles() { + IPathManager pm = PathManagerFactory.getPathManager(); + LocalizationContext[] contexts = new LocalizationContext[2]; + contexts[0] = pm.getContext(LocalizationType.COMMON_STATIC, + LocalizationLevel.BASE); + contexts[1] = pm.getContext(LocalizationType.COMMON_STATIC, + LocalizationLevel.SITE); + LocalizationFile[] roleFiles = pm.listFiles(contexts, ROLE_DIR, + new String[] { ".xml" }, false, true); + return roleFiles; + } + private JAXBManager getJaxbManager() throws JAXBException { if (jaxbManager == null) { jaxbManager = new JAXBManager(NwsRoleData.class, @@ -154,13 +190,15 @@ class FileManager { * @return */ public Map getRoleDataMap() { + readXML(); return roleDataMap; } /** * @param roleDataWithChanges */ - public void writeApplicationRoleData(Map roleDataWithChanges) { + public void writeApplicationRoleData( + Map roleDataWithChanges) { for (Entry entry : roleDataWithChanges.entrySet()) { final String application = entry.getKey(); roleDataMap.put(application, entry.getValue()); diff --git a/tests/.classpath b/tests/.classpath index 65be975a6f..c7d4e8274f 100644 --- a/tests/.classpath +++ b/tests/.classpath @@ -67,5 +67,6 @@ + diff --git a/tests/unit/com/raytheon/uf/common/localization/TestPathManager.java b/tests/unit/com/raytheon/uf/common/localization/TestPathManager.java index 0190fd04d0..dbd105ca8e 100644 --- a/tests/unit/com/raytheon/uf/common/localization/TestPathManager.java +++ b/tests/unit/com/raytheon/uf/common/localization/TestPathManager.java @@ -165,7 +165,7 @@ public class TestPathManager extends PathManager { try { if (baselinedVersion.exists()) { if (baselinedVersion.isDirectory()) { - savedFile.mkdirs(); + FileUtil.copyDirectory(baselinedVersion, savedFile); } else { FileUtil.copyFile(baselinedVersion, savedFile); } diff --git a/tests/unit/com/raytheon/uf/edex/plugin/nwsauth/FileManagerTest.java b/tests/unit/com/raytheon/uf/edex/plugin/nwsauth/FileManagerTest.java new file mode 100644 index 0000000000..820336d9f7 --- /dev/null +++ b/tests/unit/com/raytheon/uf/edex/plugin/nwsauth/FileManagerTest.java @@ -0,0 +1,156 @@ +/** + * 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.plugin.nwsauth; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Map; + +import javax.xml.bind.JAXBException; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +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.localization.PathManagerFactoryTest; +import com.raytheon.uf.common.localization.exception.LocalizationException; +import com.raytheon.uf.common.plugin.nwsauth.xml.NwsRoleData; +import com.raytheon.uf.common.plugin.nwsauth.xml.UserXML; +import com.raytheon.uf.common.serialization.JAXBManager; +import com.raytheon.uf.common.time.util.TimeUtil; +import com.raytheon.uf.common.time.util.TimeUtilTest; + +/** + * Test {@link FileManager}. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 17, 2013 1412       djohnson     Initial creation
+ * 
+ * 
+ * + * @author djohnson + * @version 1.0 + */ + +public class FileManagerTest { + private static JAXBManager jaxbManager; + + private final UserXML someUser = new UserXML("someUser"); + + private FileManager manager; + + @BeforeClass + public static void classSetup() throws JAXBException { + jaxbManager = new JAXBManager(NwsRoleData.class); + } + + @Before + public void setUp() { + TimeUtilTest.freezeTime(); + PathManagerFactoryTest.initLocalization(); + manager = new FileManager(); + } + + @After + public void tearDown() { + TimeUtilTest.resumeTime(); + } + + @Test + public void fileNewerOnDiskIsReadBeforeResponse() + throws LocalizationException { + + addUserToUserAdminFile(); + + verifyUserIsFoundWhenRoleDataRetrieved(); + } + + @Test + public void fileOlderOnDiskIsNotReadBeforeResponse() + throws LocalizationException { + + addUserToUserAdminFile(); + setUserAdminFileModifiedTimeToOneSecondAgo(); + + verifyUserIsNotFoundWhenRoleDataRetrieved(); + } + + private void verifyUserIsFoundWhenRoleDataRetrieved() { + final Map roleDataMap = manager.getRoleDataMap(); + assertTrue( + "Did not find the user added to the role data map!", + roleDataMap.get("TestUserRoles").getUserList() + .contains(someUser)); + } + + /** + * @param someUser + */ + private void verifyUserIsNotFoundWhenRoleDataRetrieved() { + final Map roleDataMap = manager.getRoleDataMap(); + assertFalse( + "Should not have found the user added to the role data map!", + roleDataMap.get("TestUserRoles").getUserList() + .contains(someUser)); + + } + + private void addUserToUserAdminFile() throws LocalizationException { + final LocalizationFile file = getTestUserAdminRolesLocalizationFile(); + NwsRoleData roleData = file.jaxbUnmarshal(NwsRoleData.class, + jaxbManager); + + roleData.getUserList().add(someUser); + file.jaxbMarshal(roleData, jaxbManager); + file.save(); + // The file was written out 1 second after we last read it + file.getFile().setLastModified( + TimeUtil.currentTimeMillis() + TimeUtil.MILLIS_PER_SECOND); + } + + private void setUserAdminFileModifiedTimeToOneSecondAgo() { + // The file was written out 1 second before we last read it + getTestUserAdminRolesLocalizationFile().getFile().setLastModified( + TimeUtil.currentTimeMillis() - TimeUtil.MILLIS_PER_SECOND); + } + + private LocalizationFile getTestUserAdminRolesLocalizationFile() { + IPathManager pathManager = PathManagerFactory.getPathManager(); + final LocalizationFile file = pathManager.getLocalizationFile( + new LocalizationContext(LocalizationType.COMMON_STATIC, + LocalizationLevel.SITE, "OAX"), + "roles/testUserAdminRoles.xml"); + return file; + } + +} diff --git a/tests/utility/common_static/site/OAX/roles/testUserAdminRoles.xml b/tests/utility/common_static/site/OAX/roles/testUserAdminRoles.xml new file mode 100644 index 0000000000..5e02c0ca3d --- /dev/null +++ b/tests/utility/common_static/site/OAX/roles/testUserAdminRoles.xml @@ -0,0 +1,14 @@ + + + + TestUserRoles + + + This permission allows the user to access and edit AWIPS 2 User Administration + + + + + awips.user.admin + + \ No newline at end of file From 1e4df6722c83a314f134bee3726b47aa82e42190 Mon Sep 17 00:00:00 2001 From: Dustin Johnson Date: Thu, 17 Jan 2013 14:15:44 -0600 Subject: [PATCH 07/10] Issue #1501 Use registry version of subscription when sending notification responses Change-Id: I96622e8f1d2236ade47d4c5a11ad41b750bc7962 Former-commit-id: 9f775d2dd752d5b25053e6c912c2fc1fe0139f21 [formerly d9064bdc98904ce4ab3fd2f54cd76d931f7affe8] [formerly 9f775d2dd752d5b25053e6c912c2fc1fe0139f21 [formerly d9064bdc98904ce4ab3fd2f54cd76d931f7affe8] [formerly 38036a0e8b0d615744309d0d0937549fb5cc85bc [formerly da8f6de9ae2b897163b465c045114fbd9ebec6e8]]] Former-commit-id: 38036a0e8b0d615744309d0d0937549fb5cc85bc Former-commit-id: 9681f57fac07950955894060cddde285586e90a9 [formerly 13a75fabad9012ea6b4fe384dc17369f02eeb613] Former-commit-id: 6266e3e44c202041fcd1ce522987bfc08ba0af6e --- ...ServerSubscriptionNotificationService.java | 18 +++++----- .../system/SystemManagementDlg.java | 15 ++++++--- .../META-INF/MANIFEST.MF | 3 +- .../BaseSubscriptionNotificationResponse.java | 19 ++++++++--- ...ndingSubscriptionNotificationResponse.java | 21 +++++++++--- .../SubscriptionNotificationResponse.java | 19 ++++++++--- .../META-INF/MANIFEST.MF | 3 +- ...ery-request.xml => event-datadelivery.xml} | 0 .../SubscriptionNotificationHandler.java | 33 ++++++++++++++----- 9 files changed, 93 insertions(+), 38 deletions(-) rename edexOsgi/com.raytheon.uf.edex.datadelivery.event/res/spring/{event-datadelivery-request.xml => event-datadelivery.xml} (100%) diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SendToServerSubscriptionNotificationService.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SendToServerSubscriptionNotificationService.java index 8206745bcf..934ae37b54 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SendToServerSubscriptionNotificationService.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SendToServerSubscriptionNotificationService.java @@ -26,11 +26,11 @@ import com.raytheon.uf.common.datadelivery.event.notification.PendingSubscriptio import com.raytheon.uf.common.datadelivery.event.notification.SubscriptionNotificationRequest; import com.raytheon.uf.common.datadelivery.registry.InitialPendingSubscription; import com.raytheon.uf.common.datadelivery.registry.Subscription; +import com.raytheon.uf.common.datadelivery.request.DataDeliveryConstants; +import com.raytheon.uf.common.serialization.comm.RequestRouter; 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.viz.core.exception.VizException; -import com.raytheon.uf.viz.core.requests.ThriftClient; /** * Implementation of {@link ISubscriptionNotificationService} that sends the @@ -42,7 +42,8 @@ import com.raytheon.uf.viz.core.requests.ThriftClient; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jan 4, 2013 1441 djohnson Initial creation + * Jan 04, 2013 1441 djohnson Initial creation + * Jan 17, 2013 1501 djohnson Route to datadelivery. * * * @@ -207,8 +208,7 @@ public class SendToServerSubscriptionNotificationService implements */ @Override public void sendSubscriptionActivatedNotification( - Subscription subscription, - String username) { + Subscription subscription, String username) { SubscriptionNotificationRequest req = new SubscriptionNotificationRequest(); req.setUserId(username); req.setCategory("Subscription"); @@ -223,8 +223,7 @@ public class SendToServerSubscriptionNotificationService implements */ @Override public void sendSubscriptionDeactivatedNotification( - Subscription subscription, - String username) { + Subscription subscription, String username) { SubscriptionNotificationRequest req = new SubscriptionNotificationRequest(); req.setUserId(username); req.setCategory("Subscription"); @@ -241,8 +240,9 @@ public class SendToServerSubscriptionNotificationService implements */ private void sendRequest(BaseSubscriptionNotificationRequest req) { try { - ThriftClient.sendRequest(req); - } catch (VizException e) { + RequestRouter + .route(req, DataDeliveryConstants.DATA_DELIVERY_SERVER); + } catch (Exception e) { statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); } } diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemManagementDlg.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemManagementDlg.java index 61e2bab7e6..bd45484a53 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemManagementDlg.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/system/SystemManagementDlg.java @@ -65,6 +65,8 @@ import com.raytheon.viz.ui.presenter.IDisplay; * Oct 23, 2012 1286 djohnson Hook into bandwidth management. * Nov 20, 2012 1286 djohnson Implement IDisplay. * Jan 04, 2013 1420 mpduff Remove applying of rules. + * Jan 17, 2013 1501 djohnson Close the dialog when force apply occurs, + * and check whether changes have already been applied when OK is pressed. * * * @@ -437,21 +439,26 @@ public class SystemManagementDlg extends CaveSWTDialog implements IDisplay, sb.append("Would you like to change the bandwidth anyways?."); int response = DataDeliveryUtils.showMessage(getShell(), SWT.YES | SWT.NO, "Bandwidth Amount", sb.toString()); + boolean forceApplied = false; if (response == SWT.YES) { - boolean forceApplied = SystemRuleManager + forceApplied = SystemRuleManager .forceSetAvailableBandwidth(Network.OPSNET, bandwidth); - if (!forceApplied) { + if (forceApplied) { + availableBandwidthModified = false; + } else { statusHandler .handle(Priority.ERROR, "Bandwidth Change", "Unable to change the bandwidth for network " + Network.OPSNET + ". Please check the server for details."); - return false; + } } - return false; + return forceApplied; + } else { + availableBandwidthModified = false; } } diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.event/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.datadelivery.event/META-INF/MANIFEST.MF index 772a6e8dbc..2ffd2f8400 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.event/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.event/META-INF/MANIFEST.MF @@ -17,4 +17,5 @@ Require-Bundle: javax.persistence;bundle-version="1.0.0", com.raytheon.uf.common.event;bundle-version="1.0.0", com.raytheon.uf.common.serialization.comm;bundle-version="1.12.1174", com.raytheon.uf.common.time;bundle-version="1.12.1174", - com.raytheon.uf.common.stats;bundle-version="1.0.0" + com.raytheon.uf.common.stats;bundle-version="1.0.0", + com.raytheon.uf.common.registry.ebxml;bundle-version="1.0.0" diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/notification/BaseSubscriptionNotificationResponse.java b/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/notification/BaseSubscriptionNotificationResponse.java index bdc515c04a..567f1da440 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/notification/BaseSubscriptionNotificationResponse.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/notification/BaseSubscriptionNotificationResponse.java @@ -20,6 +20,7 @@ package com.raytheon.uf.common.datadelivery.event.notification; import com.raytheon.uf.common.datadelivery.registry.Subscription; +import com.raytheon.uf.common.datadelivery.registry.handlers.IBaseSubscriptionHandler; import com.raytheon.uf.common.serialization.ISerializableObject; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @@ -27,17 +28,18 @@ import com.raytheon.uf.common.serialization.comm.IServerRequest; /** * Base abstract class for the subscription notification response. - * + * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Sep 20, 2012    1157    mpduff      Initial creation
- *
+ * Jan 17, 2013 1501       djohnson     Allow a response to specify the subscription handler.
+ * 
  * 
- * + * * @author mpduff * @version 1.0 */ @@ -85,4 +87,11 @@ public abstract class BaseSubscriptionNotificationResponse getSubscriptionHandler(); } diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/notification/PendingSubscriptionNotificationResponse.java b/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/notification/PendingSubscriptionNotificationResponse.java index 46b9f011b7..ef857f96a0 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/notification/PendingSubscriptionNotificationResponse.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/notification/PendingSubscriptionNotificationResponse.java @@ -20,21 +20,24 @@ package com.raytheon.uf.common.datadelivery.event.notification; import com.raytheon.uf.common.datadelivery.registry.InitialPendingSubscription; +import com.raytheon.uf.common.datadelivery.registry.handlers.DataDeliveryHandlers; +import com.raytheon.uf.common.datadelivery.registry.handlers.IBaseSubscriptionHandler; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; /** * PendingSubscriptionNotificationResponse object. - * + * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Sep 20, 2012            mpduff     Initial creation
- *
+ * Jan 17, 2013 1501       djohnson     Allow a response to specify the subscription handler.
+ * 
  * 
- * + * * @author mpduff * @version 1.0 */ @@ -42,4 +45,12 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; public class PendingSubscriptionNotificationResponse extends BaseSubscriptionNotificationResponse { + /** + * {@inheritDoc} + */ + @Override + public IBaseSubscriptionHandler getSubscriptionHandler() { + return DataDeliveryHandlers.getPendingSubscriptionHandler(); + } + } diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/notification/SubscriptionNotificationResponse.java b/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/notification/SubscriptionNotificationResponse.java index 61239fe9e9..f9c81eed46 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/notification/SubscriptionNotificationResponse.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/notification/SubscriptionNotificationResponse.java @@ -20,25 +20,36 @@ package com.raytheon.uf.common.datadelivery.event.notification; import com.raytheon.uf.common.datadelivery.registry.Subscription; +import com.raytheon.uf.common.datadelivery.registry.handlers.DataDeliveryHandlers; +import com.raytheon.uf.common.datadelivery.registry.handlers.IBaseSubscriptionHandler; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; /** * SubscriptionNotificationResponse object. - * + * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Jun 25, 2012            mpduff     Initial creation.
  * Aug 21, 2012     712    mpduff     Add a Subscription Object.
+ * Jan 17, 2013 1501       djohnson     Allow a response to specify the subscription handler.
  * 
- * + * * @author mpduff * @version 1.0 */ @DynamicSerialize public class SubscriptionNotificationResponse extends BaseSubscriptionNotificationResponse{ + + /** + * {@inheritDoc} + */ + @Override + public IBaseSubscriptionHandler getSubscriptionHandler() { + return DataDeliveryHandlers.getSubscriptionHandler(); + } } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.event/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.edex.datadelivery.event/META-INF/MANIFEST.MF index 370aea781a..df1cbbaed8 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.event/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.event/META-INF/MANIFEST.MF @@ -18,4 +18,5 @@ Require-Bundle: com.google.guava;bundle-version="1.0.0", org.springframework;bundle-version="2.5.6", com.raytheon.uf.common.event;bundle-version="1.0.0", com.raytheon.uf.common.datadelivery.registry;bundle-version="1.0.0", - com.raytheon.uf.common.registry.event;bundle-version="1.0.0" + com.raytheon.uf.common.registry.event;bundle-version="1.0.0", + com.raytheon.uf.common.registry.ebxml;bundle-version="1.0.0" diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.event/res/spring/event-datadelivery-request.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.event/res/spring/event-datadelivery.xml similarity index 100% rename from edexOsgi/com.raytheon.uf.edex.datadelivery.event/res/spring/event-datadelivery-request.xml rename to edexOsgi/com.raytheon.uf.edex.datadelivery.event/res/spring/event-datadelivery.xml diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.event/src/com/raytheon/uf/edex/datadelivery/event/handler/SubscriptionNotificationHandler.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.event/src/com/raytheon/uf/edex/datadelivery/event/handler/SubscriptionNotificationHandler.java index e0a17c731e..814cbe65f7 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.event/src/com/raytheon/uf/edex/datadelivery/event/handler/SubscriptionNotificationHandler.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.event/src/com/raytheon/uf/edex/datadelivery/event/handler/SubscriptionNotificationHandler.java @@ -25,17 +25,18 @@ import com.raytheon.uf.common.datadelivery.event.notification.BaseSubscriptionNo import com.raytheon.uf.common.datadelivery.event.notification.BaseSubscriptionNotificationResponse; import com.raytheon.uf.common.datadelivery.event.notification.NotificationRecord; import com.raytheon.uf.common.datadelivery.registry.Subscription; +import com.raytheon.uf.common.datadelivery.registry.handlers.IBaseSubscriptionHandler; import com.raytheon.uf.common.serialization.comm.IRequestHandler; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; /** * Subscription Notification Handler. - * + * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Jun 25, 2012            mpduff     Initial creation.
@@ -44,13 +45,15 @@ import com.raytheon.uf.common.status.UFStatus;
  * Aug 31, 2012    1128    mpduff     Set priority and category from request.
  * Sep 06, 2012     687    mpduff     Send a SubscriptionNotificationResponse object.
  * Sep 24, 2012    1157    mpduff     Changed to use BaseSubscriptionNotificationRequest.
+ * Jan 17, 2013 1501       djohnson     If a subscription is still in the registry, use it for the notification response.
  * 
- * + * * @author mpduff * @version 1.0 */ -public class SubscriptionNotificationHandler extends AbstractHandler implements +public class SubscriptionNotificationHandler extends + AbstractHandler implements IRequestHandler> { private static final IUFStatusHandler statusHandler = UFStatus @@ -60,7 +63,7 @@ public class SubscriptionNotificationHandler extends Abs /** * Constructor - * + * * @param uri * the jms uri to send the response */ @@ -70,7 +73,7 @@ public class SubscriptionNotificationHandler extends Abs /* * (non-Javadoc) - * + * * @see * com.raytheon.uf.common.serialization.comm.IRequestHandler#handleRequest * (com.raytheon.uf.common.serialization.comm.IServerRequest) @@ -87,9 +90,21 @@ public class SubscriptionNotificationHandler extends Abs storeAndSend(record, uri); - BaseSubscriptionNotificationResponse response = request.getResponse(); + BaseSubscriptionNotificationResponse response = request + .getResponse(); response.setMessage(request.getMessage()); - response.setSubscription(request.getSubscription()); + + final IBaseSubscriptionHandler subscriptionHandler = response + .getSubscriptionHandler(); + final T requestSubscription = request.getSubscription(); + final T registryVersion = subscriptionHandler + .getByName(requestSubscription.getName()); + + // If the subscription is still in the registry, use that version which + // will reflect any updates that have occurred since the notification + // was sent, otherwise pass along the one provided with the request + response.setSubscription((registryVersion != null) ? registryVersion + : requestSubscription); send(response, uri); From 41f4599ba87cfecbb2d1e351a5ba90dbfa48576d Mon Sep 17 00:00:00 2001 From: Nate Jensen Date: Thu, 17 Jan 2013 08:58:35 -0600 Subject: [PATCH 08/10] Issue #1497 ported python fillEditArea to Java to boost speed Change-Id: Idbc2a027914e1a584d36551781df21ed9bf63c36 Former-commit-id: 449b3735f06e9f4068d7908a5fe3238cf5f8138f [formerly 278ea6d24e84972a4a97f6dba668938d9b0287ad] [formerly 449b3735f06e9f4068d7908a5fe3238cf5f8138f [formerly 278ea6d24e84972a4a97f6dba668938d9b0287ad] [formerly 15e1731ef317ed733b2be35a42f79acaeaf9d131 [formerly 32cf1236638c64a3e047398ca829d79d3b7cb5ef]]] Former-commit-id: 15e1731ef317ed733b2be35a42f79acaeaf9d131 Former-commit-id: 492634b6f5edf3f5b6f22958af48c9995465f2b3 [formerly f70f8d1f4fb41d5267ba9e9a4abb43a4a89e2510] Former-commit-id: ec5806fb58942e234507ecdf3056c793427ec33e --- .../base/python/gfe/JSmartUtils.py | 80 +++++++++++++ .../dataplugin/gfe/util/SmartUtils.java | 110 ++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 edexOsgi/build.edex/esb/data/utility/common_static/base/python/gfe/JSmartUtils.py create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/util/SmartUtils.java diff --git a/edexOsgi/build.edex/esb/data/utility/common_static/base/python/gfe/JSmartUtils.py b/edexOsgi/build.edex/esb/data/utility/common_static/base/python/gfe/JSmartUtils.py new file mode 100644 index 0000000000..0272c6b0fe --- /dev/null +++ b/edexOsgi/build.edex/esb/data/utility/common_static/base/python/gfe/JSmartUtils.py @@ -0,0 +1,80 @@ +## +# 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. +## + +# +# Provides Java implementations of common smart utility functions +# to boost performance. +# +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 01/14/13 njensen Initial Creation. +# +# +# + +import jep +from com.raytheon.uf.common.dataplugin.gfe.util import SmartUtils as JavaSmartUtils +import numpy + + +def __getMaskIndiciesForJava(mask): + flatMask = mask.flat #flatten the array + flatIndicies = numpy.nonzero(flatMask) # get the indicies of the set cells + ysize = mask.shape[1] + indexes = [] + # convert the flat incicies to the x, y indicies + for i in flatIndicies: + indexes.append((i / ysize, i % ysize)) + + # Make two new jarrays to hold the final coordinate tuples + size = len(indexes[0][0]) + xcoords = jep.jarray(size, jep.JINT_ID) + ycoords = jep.jarray(size, jep.JINT_ID) + + #=================================================================== + # Convert the coordinates from a tuple of numpy arrays to a list of + # coordinate tuples + + for index in xrange(size): + try: + x = indexes[0][0][index] + y = indexes[0][1][index] + xcoords[index] = int(x) + ycoords[index] = int(y) + except Exception, e: + print e + + return xcoords, ycoords + + +def fillEditArea(grid, fillMask, borderMask): + editPointsX, editPointsY = __getMaskIndiciesForJava(fillMask) + borderPointsX, borderPointsY = __getMaskIndiciesForJava(borderMask) + + gridObj = JavaSmartUtils.fillEditArea(grid, grid.shape[1], grid.shape[0], \ + editPointsY, editPointsX, borderPointsY, borderPointsX) + + retObj = gridObj.__numpy__[0] + return retObj + + diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/util/SmartUtils.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/util/SmartUtils.java new file mode 100644 index 0000000000..c39af168c3 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/util/SmartUtils.java @@ -0,0 +1,110 @@ +/** + * 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.dataplugin.gfe.util; + +import jep.INumpyable; + +import com.raytheon.uf.common.python.PythonNumpyFloatArray; + +/** + * Java port of python utility functions. Ported to Java to boost performance to + * surpass python's poor looping performance. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Jan 11, 2013            njensen     Initial creation
+ * 
+ * 
+ * + * @author njensen + * @version 1.0 + */ + +public class SmartUtils { + + /** + * Define a method to fill the specified edit area. Ported from python. + * + * @param grid + * @param gridNx + * @param gridNy + * @param editPointsX + * @param editPointsY + * @param borderPointsX + * @param borderPointsY + * @return + */ + public static INumpyable fillEditArea(float[] grid, int gridNx, int gridNy, + int[] editPointsX, int[] editPointsY, int[] borderPointsX, + int[] borderPointsY) { + // edit points and border points are a list of (x,y) indices + int[] e = new int[2]; + int[] b = new int[2]; + + for (int i = 0; i < editPointsX.length; i++) { + e[0] = editPointsX[i]; + e[1] = editPointsY[i]; + double numSum = 0.0; + double denomSum = 0.0; + + for (int k = 0; k < borderPointsX.length; k++) { + b[0] = borderPointsX[k]; + b[1] = borderPointsY[k]; + + // points in the same row, column or diagonal + int xdiff = e[0] - b[0]; + int ydiff = e[1] - b[1]; + int absXdiff = (xdiff < 0) ? -xdiff : xdiff; + int absYdiff = (ydiff < 0) ? -ydiff : ydiff; + if (e[0] == b[0] || e[1] == b[1] || absXdiff == absYdiff) { + + double xdist = xdiff; + double ydist = ydiff; + + // calculate the distance to the border point + double dist = Math.sqrt(xdist * xdist + ydist * ydist); + + // value = grid[b[0], b[1]] + float value = grid[b[0] + (gridNx * b[1])]; + + // Accumulate the distance-weighted average + numSum = numSum + value / dist; + denomSum = denomSum + 1 / dist; + } + } + + int eIndex = e[0] + (gridNx * e[1]); + if (denomSum > 0.0f) { + // grid[e[0], e[1]] = numSum / denomSum; + grid[eIndex] = (float) (numSum / denomSum); + } else { + // grid[e[0], e[1]] = 0.0; + grid[eIndex] = 0.0f; + } + } + + // Return completed grid + return new PythonNumpyFloatArray(grid, gridNx, gridNy); + } +} From c71320d9220f1850c32386d36bc641dabc86c7d2 Mon Sep 17 00:00:00 2001 From: Nate Jensen Date: Thu, 17 Jan 2013 18:37:32 -0600 Subject: [PATCH 09/10] Issue #1497 fix build Former-commit-id: 13b561929788dd719354afaebdc9db9d8a3db760 [formerly 6e0f0d330e71230a30bc7616c47b82067b17b9e1] [formerly 13b561929788dd719354afaebdc9db9d8a3db760 [formerly 6e0f0d330e71230a30bc7616c47b82067b17b9e1] [formerly b52aa8221319ec96d0b7fad94a24df2db7d8be0b [formerly 3b30fcffe24d19c6c694d9519d1a515843248d32]]] Former-commit-id: b52aa8221319ec96d0b7fad94a24df2db7d8be0b Former-commit-id: cc0725f0b7c8826815bf0ae1642a837763686794 [formerly 98ec6fcc1ca59e0682091e0041f4e02174608003] Former-commit-id: d269e1953b03a3bf7af5aba4dc70d9720ee30d2b --- .../raytheon/uf/viz/derivparam/python/function/DistFilter.java | 2 +- .../com/raytheon/uf/common}/python/PythonNumpyFloatArray.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename {cave/com.raytheon.uf.viz.derivparam.python/src/com/raytheon/uf/viz/derivparam => edexOsgi/com.raytheon.uf.common.python/src/com/raytheon/uf/common}/python/PythonNumpyFloatArray.java (97%) diff --git a/cave/com.raytheon.uf.viz.derivparam.python/src/com/raytheon/uf/viz/derivparam/python/function/DistFilter.java b/cave/com.raytheon.uf.viz.derivparam.python/src/com/raytheon/uf/viz/derivparam/python/function/DistFilter.java index fc5faf86f7..6a2c53bee9 100644 --- a/cave/com.raytheon.uf.viz.derivparam.python/src/com/raytheon/uf/viz/derivparam/python/function/DistFilter.java +++ b/cave/com.raytheon.uf.viz.derivparam.python/src/com/raytheon/uf/viz/derivparam/python/function/DistFilter.java @@ -23,7 +23,7 @@ import java.util.Arrays; import jep.INumpyable; -import com.raytheon.uf.viz.derivparam.python.PythonNumpyFloatArray; +import com.raytheon.uf.common.python.PythonNumpyFloatArray; /** * TODO Add Description diff --git a/cave/com.raytheon.uf.viz.derivparam.python/src/com/raytheon/uf/viz/derivparam/python/PythonNumpyFloatArray.java b/edexOsgi/com.raytheon.uf.common.python/src/com/raytheon/uf/common/python/PythonNumpyFloatArray.java similarity index 97% rename from cave/com.raytheon.uf.viz.derivparam.python/src/com/raytheon/uf/viz/derivparam/python/PythonNumpyFloatArray.java rename to edexOsgi/com.raytheon.uf.common.python/src/com/raytheon/uf/common/python/PythonNumpyFloatArray.java index 1f20590bcc..ec3357c58a 100644 --- a/cave/com.raytheon.uf.viz.derivparam.python/src/com/raytheon/uf/viz/derivparam/python/PythonNumpyFloatArray.java +++ b/edexOsgi/com.raytheon.uf.common.python/src/com/raytheon/uf/common/python/PythonNumpyFloatArray.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.uf.viz.derivparam.python; +package com.raytheon.uf.common.python; import jep.INumpyable; From 4119d2bb88c2e9b3831973df28a103f84d37046e Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Fri, 18 Jan 2013 09:28:43 -0600 Subject: [PATCH 10/10] Issue #1386 - Change menu text to read Save Graph Image. Former-commit-id: 754fbf637ed332025445461bac32b8e62932db33 [formerly 5b6ec484c0f49f4d2a71b0660bfc79c1c1bb603c] [formerly 754fbf637ed332025445461bac32b8e62932db33 [formerly 5b6ec484c0f49f4d2a71b0660bfc79c1c1bb603c] [formerly 592b2d9088592bcf83e38d872b96467dc0ef223a [formerly c8e849b1636d9429215a36ba85febf805cdd4fc6]]] Former-commit-id: 592b2d9088592bcf83e38d872b96467dc0ef223a Former-commit-id: b3c1a39a24011fa28553f6068f949cc3a7563e04 [formerly d0d05f975d80721c62d209a185cc6e3c40b83edd] Former-commit-id: 2f8c734d8ef77ab9c1a042478d50e9aa222a91d8 --- .../uf/viz/stats/ui/StatsGraphDlg.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/cave/com.raytheon.uf.viz.stats/src/com/raytheon/uf/viz/stats/ui/StatsGraphDlg.java b/cave/com.raytheon.uf.viz.stats/src/com/raytheon/uf/viz/stats/ui/StatsGraphDlg.java index 1a9e209d87..bec4cb0584 100644 --- a/cave/com.raytheon.uf.viz.stats/src/com/raytheon/uf/viz/stats/ui/StatsGraphDlg.java +++ b/cave/com.raytheon.uf.viz.stats/src/com/raytheon/uf/viz/stats/ui/StatsGraphDlg.java @@ -61,17 +61,18 @@ import com.raytheon.viz.ui.widgets.duallist.ButtonImages.ButtonImage; /** * The Graph Data Structure. - * + * *
- *
+ * 
  * SOFTWARE HISTORY
- *
+ * 
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
- * Oct 3, 2012     728     mpduff      Initial creation
- *
+ * Oct 03, 2012     728    mpduff      Initial creation.
+ * Jan 18, 2013    1386    mpduff      Change menu text.
+ * 
  * 
- * + * * @author mpduff * @version 1.0 */ @@ -145,7 +146,7 @@ public class StatsGraphDlg extends CaveSWTDialog implements IStatsDisplay, /** * Constructor. - * + * * @param parent * Parent Shell * @param callback @@ -315,7 +316,7 @@ public class StatsGraphDlg extends CaveSWTDialog implements IStatsDisplay, fileMenuItem.setMenu(fileMenu); saveMI = new MenuItem(fileMenu, SWT.NONE); - saveMI.setText("&Save\tCtrl+S"); + saveMI.setText("&Save Graph Image\tCtrl+S"); saveMI.setAccelerator(SWT.CTRL + 'S'); saveMI.addSelectionListener(new SelectionAdapter() { @Override @@ -375,7 +376,7 @@ public class StatsGraphDlg extends CaveSWTDialog implements IStatsDisplay, /** * Create the canvas. - * + * * @param comp * Composite holding the canvas */ @@ -395,7 +396,7 @@ public class StatsGraphDlg extends CaveSWTDialog implements IStatsDisplay, /** * Set the GraphData object. - * + * * @param graphData */ public void setGraphData(GraphData graphData) { @@ -412,7 +413,7 @@ public class StatsGraphDlg extends CaveSWTDialog implements IStatsDisplay, /** * Set the title. - * + * * @param title */ public void setTitle(String title) { @@ -421,7 +422,7 @@ public class StatsGraphDlg extends CaveSWTDialog implements IStatsDisplay, /** * Set the graph title. - * + * * @param graphTitle */ public void setGraphTitle(String graphTitle) { @@ -443,7 +444,7 @@ public class StatsGraphDlg extends CaveSWTDialog implements IStatsDisplay, /** * Captures the canvas and saves the result into a file in a format * determined by the filename extension . - * + * * @param control * The control to save * @param fileName @@ -480,7 +481,7 @@ public class StatsGraphDlg extends CaveSWTDialog implements IStatsDisplay, /** * Request the graph be redrawn with a new time range. - * + * * @param parameter * The amount of time to move */ @@ -596,7 +597,7 @@ public class StatsGraphDlg extends CaveSWTDialog implements IStatsDisplay, /** * Set the groups. - * + * * @param groupList * List of groups */ @@ -606,7 +607,7 @@ public class StatsGraphDlg extends CaveSWTDialog implements IStatsDisplay, /** * Set the category. - * + * * @param category */ public void setCategory(String category) { @@ -615,7 +616,7 @@ public class StatsGraphDlg extends CaveSWTDialog implements IStatsDisplay, /** * Set the event type. - * + * * @param typeID */ public void setEventType(String typeID) { @@ -624,7 +625,7 @@ public class StatsGraphDlg extends CaveSWTDialog implements IStatsDisplay, /** * Set the data type id. - * + * * @param dataTypeID */ public void setDataType(String dataTypeID) {