From 1dc5fcd8520681b41d77d5fc21b6d1a698a2b2b9 Mon Sep 17 00:00:00 2001 From: Ben Steffensmeier Date: Wed, 18 Dec 2013 11:26:02 -0600 Subject: [PATCH 01/62] Issue #2579 Make DecisionTree thread safe. Change-Id: I351135189c58ba5a6107de206f8f5dc2d72fc8c0 Former-commit-id: fea2532ea7573883862c6877bf2bb60e8ba8f81f [formerly b92f9efb53636029673dc4aba4d7cc5d79ee8dcf] [formerly b096554d97d5d39147d3f2ecd20779b22468445d [formerly 345316581c514136c823692a09ff0d71ce5b7877]] Former-commit-id: b096554d97d5d39147d3f2ecd20779b22468445d Former-commit-id: 0d1898a070d9b126f94a04e3b5463f8e84ffd6b8 --- .../uf/common/dataquery/DecisionTree.java | 135 +++++++++--------- .../uf/common/dataquery/db/QueryResult.java | 13 +- .../common/dataquery/db/QueryResultRow.java | 11 +- .../dataquery/requests/DbQueryRequestSet.java | 12 +- .../dataquery/requests/QlServerRequest.java | 10 +- .../dataquery/requests/RequestConstraint.java | 35 ++--- .../requests/TimeQueryRequestSet.java | 13 +- .../dataquery/responses/DbQueryResponse.java | 10 +- .../responses/DbQueryResponseSet.java | 16 ++- 9 files changed, 136 insertions(+), 119 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/DecisionTree.java b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/DecisionTree.java index 1e5bf9ea1c..61335e0b9a 100644 --- a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/DecisionTree.java +++ b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/DecisionTree.java @@ -28,6 +28,8 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; import com.raytheon.uf.common.dataquery.requests.RequestConstraint; import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType; @@ -43,12 +45,15 @@ import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintTyp * *
  * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jul 3, 2007             chammack    Initial Creation.
- * Jan 14, 2013 1442       rferrel     Added method searchTreeUsingContraints.
- *                                     Addition checks on constraints.
- * May 28, 2013 1638       mschenke    Added proper support for {@link ConstraintType#ISNULL}
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- -----------------------------------------
+ * Jul 03, 2007           chammack    Initial Creation.
+ * Jan 14, 2013  1442     rferrel     Added method searchTreeUsingContraints.
+ *                                    Addition checks on constraints.
+ * May 28, 2013  1638     mschenke    Added proper support for
+ *                                    {@link ConstraintType#ISNULL}
+ * Dec 18, 2013  2579     bsteffen    Replace synchronization with a
+ *                                    read/write lock.
  * 
  * 
* @@ -94,9 +99,7 @@ public class DecisionTree { if (lvl == 0) { // heuristic: Always start with pluginName entropyPair = new EntropyPair[1]; - entropyPair[0] = new EntropyPair(); - entropyPair[0].attribute = "pluginName"; - entropyPair[0].entropy = 1.0f; + entropyPair[0] = new EntropyPair("pluginName", 1.0f); } else { for (String attrib : localAttribList) { // For an attribute, pull out the possible values @@ -133,9 +136,8 @@ public class DecisionTree { Iterator attributeListIter = localAttribList.iterator(); for (int i = 0; attributeListIter.hasNext(); i++) { - entropyPair[i] = new EntropyPair(); - entropyPair[i].attribute = attributeListIter.next(); - entropyPair[i].entropy = entropyValues.get(i); + entropyPair[i] = new EntropyPair(attributeListIter.next(), + entropyValues.get(i)); } Arrays.sort(entropyPair); @@ -225,22 +227,25 @@ public class DecisionTree { } protected class DataPair { - public Map metadata; + public final Map metadata; + + public final T data; + + public DataPair(Map metadata, T data) { + this.metadata = metadata; + this.data = data; + } - public T data; } + private final ReadWriteLock lock = new ReentrantReadWriteLock(); + private final List dataPairs; - private final Set attributes; - private Node head; - private int size = 0; - public DecisionTree() { dataPairs = new ArrayList(); - attributes = new HashSet(); } public void insertCriteria(Map searchCriteria, @@ -249,25 +254,22 @@ public class DecisionTree { throw new IllegalArgumentException( "Search criteria must not be null"); - // Check for the case that the item is already listed - DataPair e = new DataPair(); - e.data = item; - e.metadata = searchCriteria; - this.dataPairs.add(e); - size++; + DataPair e = new DataPair(searchCriteria, item); - Set keys = searchCriteria.keySet(); - - this.attributes.addAll(keys); - - if (rebuild) { - // Now, trigger a tree rebuild - rebuildTree(); + lock.writeLock().lock(); + try { + this.dataPairs.add(e); + if (rebuild) { + rebuildTree(); + } + } finally { + lock.writeLock().unlock(); } } public void rebuildTree() { - synchronized (this) { + lock.writeLock().lock(); + try { if (this.dataPairs.size() == 0) { this.head = null; return; @@ -275,6 +277,8 @@ public class DecisionTree { this.head = new Node(); this.head.rebuildTree(dataPairs, new ArrayList(), 0); + } finally { + lock.writeLock().unlock(); } } @@ -318,7 +322,8 @@ public class DecisionTree { */ private List searchTree(Map searchCriteria, boolean evaluateConstraints) { - synchronized (this) { + lock.readLock().lock(); + try { List lst = new ArrayList(); if (head == null) { return lst; @@ -328,6 +333,8 @@ public class DecisionTree { searchTree(curNode, searchCriteria, lst, 0, evaluateConstraints); return lst; + } finally { + lock.readLock().unlock(); } } @@ -391,8 +398,10 @@ public class DecisionTree { * @param item */ public void remove(T item) { - boolean itemRemoved = false; - synchronized (this) { + lock.writeLock().lock(); + try { + boolean itemRemoved = false; + // This could be optimized but removes are a very uncommon operation Iterator exampleIterator = dataPairs.iterator(); while (exampleIterator.hasNext()) { @@ -404,39 +413,26 @@ public class DecisionTree { itemRemoved = true; } } - } - if (itemRemoved) { - rebuildTree(); - } - } - - public void traverse() { - System.out.println("Head:"); - traverse(head); - - } - - public void traverse(Node n) { - if (n == null) - return; - System.out.println(n.type); - if (n.type == NodeType.LEAF) { - System.out.println(n.values); - } else if (n.type == NodeType.DECISION) { - System.out.println(n.decision); - } - System.out.println(n.decisionAttribute); - System.out.println("-------"); - - for (int i = 0; i < n.nodeChildren.size(); i++) { - System.out.println("Child of: " + n.decisionAttribute + " " + i); - Node n2 = n.nodeChildren.get(i); - traverse(n2); + if (itemRemoved) { + rebuildTree(); + } + } finally { + lock.writeLock().unlock(); } } protected List getDataPairs() { - return new ArrayList.DataPair>(dataPairs); + /* + * Copy dataPairs to avoid external iterators getting concurrent + * modification. Must get read lock because copying iterates over + * dataPairs. + */ + lock.readLock().lock(); + try { + return new ArrayList(dataPairs); + } finally { + lock.readLock().unlock(); + } } private static double calcEntropy(int numExamples, Integer[] values) { @@ -451,9 +447,14 @@ public class DecisionTree { } private static class EntropyPair implements Comparable { - public String attribute; + public final String attribute; - public double entropy; + public final double entropy; + + public EntropyPair(String attribute, double entropy) { + this.attribute = attribute; + this.entropy = entropy; + } /* * (non-Javadoc) diff --git a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/db/QueryResult.java b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/db/QueryResult.java index f3316f174d..b491bc7709 100644 --- a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/db/QueryResult.java +++ b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/db/QueryResult.java @@ -25,7 +25,6 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import com.raytheon.uf.common.serialization.ISerializableObject; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @@ -35,16 +34,18 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * *
  * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * 11/07/08     #1673      bphillip    Initial Creation
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Nov 07, 2008  1673     bphillip    Initial Creation
+ * Dec 18, 2013  2579     bsteffen    Remove ISerializableObject
+ * 
  * 
* * @author bphillip * @version 1.0 */ @DynamicSerialize -public class QueryResult implements ISerializableObject { +public class QueryResult { /** A mapping of the column names to their index in the result */ @DynamicSerializeElement @@ -167,12 +168,10 @@ public class QueryResult implements ISerializableObject { */ public String[] getColumnNameArray() { String[] names = new String[columnNames.size()]; - int i = 0; for (Iterator it = columnNames.keySet().iterator(); it .hasNext();) { String key = it.next(); names[columnNames.get(key)] = key; - i++; } return names; } diff --git a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/db/QueryResultRow.java b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/db/QueryResultRow.java index df3b23c650..dadb348d90 100644 --- a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/db/QueryResultRow.java +++ b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/db/QueryResultRow.java @@ -22,7 +22,6 @@ package com.raytheon.uf.common.dataquery.db; import java.util.Arrays; -import com.raytheon.uf.common.serialization.ISerializableObject; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @@ -31,16 +30,18 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * *
  * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * 11/07/08     #1673      bphillip    Initial Creation
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Nov 07, 2008  1673     bphillip    Initial Creation
+ * Dec 18, 2013  2579     bsteffen    Remove ISerializableObject
+ * 
  * 
* * @author bphillip * @version 1.0 */ @DynamicSerialize -public class QueryResultRow implements ISerializableObject { +public class QueryResultRow { /** * The values of the returned columns diff --git a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/DbQueryRequestSet.java b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/DbQueryRequestSet.java index 517d84dda3..d9c50dde79 100644 --- a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/DbQueryRequestSet.java +++ b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/DbQueryRequestSet.java @@ -24,20 +24,24 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.comm.IServerRequest; /** - * TODO Add Description + * Send multiple {@link DbQueryRequestSet}s at once. This can be more efficient + * than sending multiple requests individually because it reduces the network + * overhead. * *
  * 
  * SOFTWARE HISTORY
  * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jun 30, 2011            rjpeter     Initial creation
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Jun 30, 2011           rjpeter     Initial creation
+ * Dec 18, 2013  2579     bsteffen    Class javadoc
  * 
  * 
* * @author rjpeter * @version 1.0 + * @see DbQueryRequest */ @DynamicSerialize public class DbQueryRequestSet implements IServerRequest { diff --git a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/QlServerRequest.java b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/QlServerRequest.java index 701dc92882..464044a9c9 100644 --- a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/QlServerRequest.java +++ b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/QlServerRequest.java @@ -21,7 +21,6 @@ package com.raytheon.uf.common.dataquery.requests; import java.util.Map; -import com.raytheon.uf.common.serialization.ISerializableObject; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.comm.IServerRequest; @@ -32,9 +31,10 @@ import com.raytheon.uf.common.serialization.comm.IServerRequest; *
  * 
  * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Feb 16, 2011 #8070      ekladstrup  Initial creation
+ * Date          Ticket#    Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Feb 16, 2011  8070     ekladstrup  Initial creation
+ * Dec 18, 2013  2579     bsteffen    Remove ISerializableObject
  * 
  * 
* @@ -42,7 +42,7 @@ import com.raytheon.uf.common.serialization.comm.IServerRequest; * @version 1.0 */ @DynamicSerialize -public class QlServerRequest implements IServerRequest, ISerializableObject { +public class QlServerRequest implements IServerRequest { @DynamicSerializeElement private Map rcMap; diff --git a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/RequestConstraint.java b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/RequestConstraint.java index 76fd4605bd..c1fd146734 100644 --- a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/RequestConstraint.java +++ b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/RequestConstraint.java @@ -40,29 +40,31 @@ import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; -import com.raytheon.uf.common.serialization.ISerializableObject; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.time.util.TimeUtil; /** - * RequestConstraint - Constraints on a uEngine request - * - * Allows non-equals style constraints + * Used in requests to limit the type of data returned. Similar to an sql WHERE + * clause, it consists of a type(operator) and a value. When a request is made + * fields will be compared to the constraint value with the specified type to + * determine what data to return. * *
  * 
- *    SOFTWARE HISTORY
+ * SOFTWARE HISTORY
  *   
- *    Date         Ticket#     Engineer    Description
- *    ------------ ----------  ----------- --------------------------
- *    Aug 21, 2007             chammack    Initial Creation.
- *    May 27, 2009 2408        jsanchez    Cast value to String.
- *    Sep 28, 2009 3099        bsteffen    Fixed constraintCompare to convert
- *                                         all non-numeric objects to String
- *    Nov 05, 2009 3553        rjpeter     Added isNull capability.
- *    Jul 09, 2013 1869        bsteffen    Format Calendar when making
- *                                         Constraint Mapping.
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- -----------------------------------------
+ * Aug 21, 2007           chammack    Initial Creation.
+ * May 27, 2009  2408     jsanchez    Cast value to String.
+ * Sep 28, 2009  3099     bsteffen    Fixed constraintCompare to convert all
+ *                                    non-numeric objects to String
+ * Nov 05, 2009  3553     rjpeter     Added isNull capability.
+ * Jul 09, 2013  1869     bsteffen    Format Calendar when making Constraint
+ *                                    Mapping.
+ * Dec 18, 2013  2579     bsteffen    Remove ISerializableObject
+ * 
  * 
  * 
* @@ -73,7 +75,7 @@ import com.raytheon.uf.common.time.util.TimeUtil; @XmlRootElement(name = "requestConstraint") @XmlType(name = "requestConstraint") @DynamicSerialize -public class RequestConstraint implements ISerializableObject, Cloneable { +public class RequestConstraint implements Cloneable { public static final RequestConstraint WILDCARD; static { @@ -114,7 +116,8 @@ public class RequestConstraint implements ISerializableObject, Cloneable { @DynamicSerializeElement protected String constraintValue; - protected transient Map, Object> asMap = new HashMap, Object>(); + protected transient Map, Object> asMap = new HashMap, Object>( + 2); /** * Constructor diff --git a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/TimeQueryRequestSet.java b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/TimeQueryRequestSet.java index f1f3f097b5..49aba3a8be 100644 --- a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/TimeQueryRequestSet.java +++ b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/requests/TimeQueryRequestSet.java @@ -24,20 +24,25 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; import com.raytheon.uf.common.serialization.comm.IServerRequest; /** - * TODO Add Description + * Send multiple {@link TimeQueryRequest}s at once. This can be more efficient + * than sending multiple requests individually because it reduces the network + * overhead. The response will be a List> where the list contains + * one entry for each request, in the same order as the requests. * *
  * 
  * SOFTWARE HISTORY
  * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jul 1, 2011            rjpeter     Initial creation
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Jul0 1, 2011           rjpeter     Initial creation
+ * Dec 18, 2013  2579     bsteffen    Class javadoc
  * 
  * 
* * @author rjpeter * @version 1.0 + * @see TimeQueryRequest */ @DynamicSerialize public class TimeQueryRequestSet implements IServerRequest { diff --git a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/responses/DbQueryResponse.java b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/responses/DbQueryResponse.java index 8ccf58cdd5..14762e63c2 100644 --- a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/responses/DbQueryResponse.java +++ b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/responses/DbQueryResponse.java @@ -24,7 +24,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import com.raytheon.uf.common.serialization.ISerializableObject; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @@ -37,9 +36,10 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; *
  * 
  * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jan 21, 2010            mschenke     Initial creation
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Jan 21, 2010           mschenke    Initial creation
+ * Dec 18, 2013  2579     bsteffen    Remove ISerializableObject
  * 
  * 
* @@ -47,7 +47,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * @version 1.0 */ @DynamicSerialize -public class DbQueryResponse implements ISerializableObject { +public class DbQueryResponse { public static final String ENTITY_RESULT_KEY = null; diff --git a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/responses/DbQueryResponseSet.java b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/responses/DbQueryResponseSet.java index 82c1c7bbeb..1e7b421475 100644 --- a/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/responses/DbQueryResponseSet.java +++ b/edexOsgi/com.raytheon.uf.common.dataquery/src/com/raytheon/uf/common/dataquery/responses/DbQueryResponseSet.java @@ -19,28 +19,32 @@ **/ package com.raytheon.uf.common.dataquery.responses; -import com.raytheon.uf.common.serialization.ISerializableObject; +import com.raytheon.uf.common.dataquery.requests.DbQueryRequestSet; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; /** - * TODO Add Description + * Response to a {@link DbQueryResponseSet}, contains a response to every + * request in the same order. * *
  * 
  * SOFTWARE HISTORY
  * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jul 1, 2011            rjpeter     Initial creation
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Jul 01, 2011           rjpeter     Initial creation
+ * Dec 18, 2013  2579     bsteffen    Remove ISerializableObject
  * 
  * 
* * @author rjpeter * @version 1.0 + * @see DbQueryResponse + * @see DbQueryRequestSet */ @DynamicSerialize -public class DbQueryResponseSet implements ISerializableObject { +public class DbQueryResponseSet { @DynamicSerializeElement private DbQueryResponse[] results; From 01a48c9f178db679639d2a97d7e5e48a3f8a36c7 Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Wed, 18 Dec 2013 14:52:11 -0600 Subject: [PATCH 02/62] Issue #2636 - Calculate a data set availability delay for each dataset. Former-commit-id: a4036f49a933b055a2478f818723ae352697246e [formerly f04e249e23a5156a006074772fbbf820f8749f9d] [formerly fb960848649a8090c7aa00b218e486f693a4cd61 [formerly 6c5fd79bd2a74422053b064d968de3ca440ecec1]] Former-commit-id: fb960848649a8090c7aa00b218e486f693a4cd61 Former-commit-id: a72fa709924d30b60dffa430b6b5ea873098eb87 --- .../common/datadelivery/registry/DataSet.java | 23 ++++++++++++++++++- .../opendap/OpenDAPMetaDataParser.java | 19 +++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/DataSet.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/DataSet.java index fe662b7516..4a4c67fc53 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/DataSet.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/DataSet.java @@ -40,6 +40,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Aug 22, 2012 0743 djohnson Store data type as an enum. * Sep 07, 2012 1102 djohnson Remove invalid {@code @XmlRootElement}. * Nov 19, 2012 1166 djohnson Clean up JAXB representation of registry objects. + * Dec 18, 2013 2636 mpduff Add a data availability delay for the dataset. * * * @@ -49,7 +50,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @RegistryObject({ "providerName", "collectionName", "dataSetName" }) -public abstract class DataSet{ +public abstract class DataSet { @RegistryObjectOwner @XmlAttribute @@ -94,6 +95,11 @@ public abstract class DataSet{ @SlotAttributeConverter(TimeSlotConverter.class) protected T time; + @XmlElement + @DynamicSerializeElement + @SlotAttribute + protected int availabilityDelay; + public Map getParameters() { return parameters; } @@ -157,6 +163,21 @@ public abstract class DataSet{ */ public abstract ServiceType getServiceType(); + /** + * @return the availabilityDelay + */ + public int getAvailabilityDelay() { + return availabilityDelay; + } + + /** + * @param availabilityDelay + * the availabilityDelay to set + */ + public void setAvailabilityDelay(int availabilityDelay) { + this.availabilityDelay = availabilityDelay; + } + @Override public boolean equals(Object obj) { if (obj instanceof DataSet) { diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java index b811595691..47a6938c7f 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java @@ -56,6 +56,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.time.util.ImmutableDate; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.common.util.CollectionUtil; import com.raytheon.uf.common.util.GridUtil; import com.raytheon.uf.edex.datadelivery.retrieval.Link; @@ -93,6 +94,7 @@ import dods.dap.DAS; * Jan 24, 2013 1527 dhladky Changed 0DEG to FRZ * Sept 25, 2013 1797 dhladky separated time from gridded time * Oct 10, 2013 1797 bgonzale Refactored registry Time objects. + * Dec 18, 2013 2636 mpduff Calculate a data availability delay for the dataset. * * * @@ -259,6 +261,23 @@ class OpenDAPMetaDataParser extends MetaDataParser { time.setStepUnit(Time.findStepUnit(step.get(1)) .getDurationUnit()); gdsmd.setTime(time); + + // Calculate dataset availability delay + long startMillis = time.getStart().getTime(); + long now = TimeUtil.newGmtCalendar().getTimeInMillis(); + long delay = (now - startMillis) / TimeUtil.MILLIS_PER_MINUTE; + + // There were some models where the availability delay was + // negative + dataSet.setAvailabilityDelay(Math.max(0, (int) delay)); + + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler.debug("Dataset Name: " + + dataSet.getDataSetName()); + statusHandler.debug("StartTime: " + time.getStart()); + statusHandler.debug("Delay: " + + dataSet.getAvailabilityDelay()); + } } catch (Exception le) { logParsingException(timecon, "Time", collectionName, url); } From 9f84482bb519c3f9861b8183fab24be5cb33cec1 Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Wed, 18 Dec 2013 15:34:00 -0600 Subject: [PATCH 03/62] Issue #2636 - Changed delay to offset Former-commit-id: 7fe007d48283bad5b0d1950238374fa0106555c0 [formerly fa314e5eb6be8aaef7fa645cf555e8a3dd8cd989] [formerly 14d9978528cf480f991f988bc06666bc7d6f5189 [formerly b5fefc92c0b80613b90acb29f70b96c459167843]] Former-commit-id: 14d9978528cf480f991f988bc06666bc7d6f5189 Former-commit-id: b9b03657c5e8fc2ce91f7f20d1a68311f83a595b --- .../uf/common/datadelivery/registry/DataSet.java | 16 ++++++++-------- .../retrieval/opendap/OpenDAPMetaDataParser.java | 11 ++++------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/DataSet.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/DataSet.java index 4a4c67fc53..da64088909 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/DataSet.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/DataSet.java @@ -98,7 +98,7 @@ public abstract class DataSet { @XmlElement @DynamicSerializeElement @SlotAttribute - protected int availabilityDelay; + protected int availabilityOffset; public Map getParameters() { return parameters; @@ -164,18 +164,18 @@ public abstract class DataSet { public abstract ServiceType getServiceType(); /** - * @return the availabilityDelay + * @return the availabilityOffset */ - public int getAvailabilityDelay() { - return availabilityDelay; + public int getAvailabilityOffset() { + return availabilityOffset; } /** - * @param availabilityDelay - * the availabilityDelay to set + * @param availabilityOffset + * the availabilityOffset to set */ - public void setAvailabilityDelay(int availabilityDelay) { - this.availabilityDelay = availabilityDelay; + public void setAvailabilityOffset(int availabilityOffset) { + this.availabilityOffset = availabilityOffset; } @Override diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java index 47a6938c7f..a0e7d74242 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java @@ -265,18 +265,15 @@ class OpenDAPMetaDataParser extends MetaDataParser { // Calculate dataset availability delay long startMillis = time.getStart().getTime(); long now = TimeUtil.newGmtCalendar().getTimeInMillis(); - long delay = (now - startMillis) / TimeUtil.MILLIS_PER_MINUTE; - - // There were some models where the availability delay was - // negative - dataSet.setAvailabilityDelay(Math.max(0, (int) delay)); + long offset = (now - startMillis) / TimeUtil.MILLIS_PER_MINUTE; + dataSet.setAvailabilityOffset((int) offset); if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { statusHandler.debug("Dataset Name: " + dataSet.getDataSetName()); statusHandler.debug("StartTime: " + time.getStart()); - statusHandler.debug("Delay: " - + dataSet.getAvailabilityDelay()); + statusHandler.debug("Offset: " + + dataSet.getAvailabilityOffset()); } } catch (Exception le) { logParsingException(timecon, "Time", collectionName, url); From 6e642b81fe7585ff5a9298ba5f5a535236165645 Mon Sep 17 00:00:00 2001 From: David Gillingham Date: Wed, 18 Dec 2013 16:18:34 -0600 Subject: [PATCH 04/62] Issue #2641: Fix ETN assignment issues introduced by baseline merge. Former-commit-id: c48c0523ff1fc53a9a9dae1cd3ec58b1041e2b8b [formerly 136265183df0cae4d1d16e5a8f2111152c21e52f] [formerly 09bfdc49e3ac6e066182b9c4a783e5f543aa6cb1 [formerly 7ae8efacb3c886ec18af64dca7784f4aa1512bf4]] Former-commit-id: 09bfdc49e3ac6e066182b9c4a783e5f543aa6cb1 Former-commit-id: 8f3802eecf4c6bff6716d530592863ce8500b933 --- .../dialogs/formatterlauncher/StoreTransmitDlg.java | 5 +++-- .../src/com/raytheon/viz/gfe/vtec/GFEVtecUtil.java | 12 +++++++----- .../uf/edex/activetable/GetNextEtnUtil.java | 13 +++++++++++-- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/StoreTransmitDlg.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/StoreTransmitDlg.java index 33ec5ea936..faceaf7403 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/StoreTransmitDlg.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/formatterlauncher/StoreTransmitDlg.java @@ -21,8 +21,8 @@ package com.raytheon.viz.gfe.dialogs.formatterlauncher; import java.text.SimpleDateFormat; import java.util.HashMap; +import java.util.List; import java.util.Map; -import java.util.Set; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; @@ -79,6 +79,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * 23 Oct 2013 1843 dgilling Ensure that dialog is always closed, * even on failure, changes for error handling * of intersite ETN assignment. + * 18 Dec 2013 2641 dgilling Support changes to GFEVtecUtil.getVtecLinesThatNeedEtn(). * * * @author lvenable @@ -345,7 +346,7 @@ public class StoreTransmitDlg extends CaveSWTDialog implements if (!countdownThread.threadCancelled()) { boolean retrieveEtnFailed = false; - Set vtecsToAssignEtn = GFEVtecUtil + List vtecsToAssignEtn = GFEVtecUtil .getVtecLinesThatNeedEtn(productText); // With GFE VTEC products, it's possible to have multiple segments // with diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/vtec/GFEVtecUtil.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/vtec/GFEVtecUtil.java index c9175beb37..b1ee8cdd46 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/vtec/GFEVtecUtil.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/vtec/GFEVtecUtil.java @@ -19,11 +19,11 @@ **/ package com.raytheon.viz.gfe.vtec; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; +import java.util.List; import java.util.Map; -import java.util.Set; import java.util.regex.Matcher; import com.google.common.collect.ImmutableSet; @@ -58,6 +58,8 @@ import com.raytheon.viz.texteditor.util.VtecUtil; * Nov 22, 2013 #2578 dgilling Fix ETN assignment for products with * multiple NEW VTEC lines for the same * phensig but disjoint TimeRanges. + * Dec 18, 2013 #2641 dgilling Force ordering of items returned by + * getVtecLinesThatNeedEtn(). * * * @@ -192,12 +194,12 @@ public class GFEVtecUtil { * @return A Set of VtecObjects that need to have * a new ETN assigned to them. */ - public static Set getVtecLinesThatNeedEtn(String product) { + public static List getVtecLinesThatNeedEtn(String product) { if (StringUtil.isEmptyString(product)) { - return Collections.emptySet(); + return Collections.emptyList(); } - Set phensigs = new HashSet(); + List phensigs = new ArrayList(); Matcher vtecMatcher = VtecUtil.VTEC_REGEX.matcher(product); while (vtecMatcher.find()) { diff --git a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/GetNextEtnUtil.java b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/GetNextEtnUtil.java index fbae5469ed..bfb842f3f7 100644 --- a/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/GetNextEtnUtil.java +++ b/edexOsgi/com.raytheon.uf.edex.activetable/src/com/raytheon/uf/edex/activetable/GetNextEtnUtil.java @@ -61,6 +61,7 @@ import com.raytheon.uf.edex.auth.RemoteServerRequestRouter; import com.raytheon.uf.edex.database.cluster.ClusterLockUtils; import com.raytheon.uf.edex.database.cluster.ClusterLockUtils.LockState; import com.raytheon.uf.edex.database.cluster.ClusterTask; +import com.raytheon.uf.edex.database.cluster.handler.CurrentTimeClusterLockHandler; /** * Library module of functions to support retrieval of next ETN in sequence for @@ -73,6 +74,7 @@ import com.raytheon.uf.edex.database.cluster.ClusterTask; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Aug 29, 2013 #1843 dgilling Initial creation + * Dec 18, 2013 #2641 dgilling Fix ClusterTask locking. * * * @@ -276,7 +278,9 @@ public final class GetNextEtnUtil { * set to true if you want to actually move the * sequence forward. * @param etnOverride - * TODO + * Allows the user to influence the next ETN assigned by using + * this value unless it is less than or equal to the last ETN + * used by this site or one of its partners. * @return The next ETN to be used in sequence. */ public static int lockAndGetNextEtn(String siteId, ActiveTableMode mode, @@ -286,7 +290,9 @@ public final class GetNextEtnUtil { ClusterTask ct = null; if (isLock) { do { - ct = ClusterLockUtils.lock(lockName, phensig, 15000, true); + // ct = ClusterLockUtils.lock(lockName, phensig, 15000, true); + ct = ClusterLockUtils.lock(lockName, phensig, + new CurrentTimeClusterLockHandler(15000, false), true); } while (!ct.getLockState().equals(LockState.SUCCESSFUL)); statusHandler.info("Locking::[lockName = " + lockName + ", phensig = " + phensig + "]"); @@ -302,6 +308,9 @@ public final class GetNextEtnUtil { if (etnOverride == null) { String year = Integer.toString(currentTime.get(Calendar.YEAR)); String eInfo = ct.getExtraInfo(); + + statusHandler.info("ClusterTask Lock info: " + eInfo); + if ((!StringUtil.isEmptyString(eInfo)) && (eInfo.startsWith(year))) { // parse year info try { From 86b77001a7db48da956b21b6fa424849a4cbe90a Mon Sep 17 00:00:00 2001 From: Slav Korolev Date: Thu, 2 Jan 2014 15:20:43 -0500 Subject: [PATCH 05/62] Issue #2580. Fixed FSSObs error. Former-commit-id: 45d7b28f730dd7d9b1bb92f972c64fce1852714a [formerly cab076a9a9e0364b9949ae4c5d2bfb9a1854dfdf] [formerly 05a93ea955cbc6fdb4eccc0711542b8f5f7458af [formerly bb56933cea0f68c18e9cdc352dc6bd53473932ff]] Former-commit-id: 05a93ea955cbc6fdb4eccc0711542b8f5f7458af Former-commit-id: 16f66b2c074fe9b7d332317b0c34a3dad181ef32 --- .../uf/edex/plugin/fssobs/FSSObsUtils.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/FSSObsUtils.java b/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/FSSObsUtils.java index 93113bf8ed..7e0d807672 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/FSSObsUtils.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.fssobs/src/com/raytheon/uf/edex/plugin/fssobs/FSSObsUtils.java @@ -54,6 +54,7 @@ import com.raytheon.uf.edex.pointdata.PointDataQuery; * Nov 26, 2012 1297 skorolev Changed ArrayList to List.Clean code * May 15, 2013 1869 bsteffen Remove DataURI column from ldadmesonet. * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. + * Jan 02, 2014 2580 skorolev Fixed FSSObs error. * * * @@ -348,8 +349,9 @@ public class FSSObsUtils { * @return -- Snow data from METAR */ public static float[] getSnowData(FSSObsRecord tableRow) { - // Check parameters for wind chill in K/frostbite in minutes/snow - // increase and depth in inches + // Check parameters for wind chill in K + // frost bite in minutes + // snow increase and depth in inches // time calculation (upper limit for wind chill // is set at 40F and wind speed between 14 and 43 knts) : float[] retVal = new float[5]; @@ -363,23 +365,28 @@ public class FSSObsUtils { whatMatched = sc.findWithinHorizon("SNINCR", 0); if (whatMatched != null) { sc.useDelimiter("/"); - // last hour snow in inches - retVal[0] = sc.nextInt(); + if (sc.hasNextInt()) { + // last hour snow in inches + retVal[0] = sc.nextInt(); + } sc.reset(); - // total snow in inches - retVal[1] = sc.nextInt(); + if (sc.hasNextInt()) { + // total snow in inches + retVal[1] = sc.nextInt(); + } } whatMatched = sc.findWithinHorizon("4/", 0); if (whatMatched != null) { // snow depth on ground in inches if (retVal.length >= 5) { - retVal[5] = sc.nextInt(); + retVal[2] = sc.nextInt(); } } } + sc.close(); if ((tableRow.getTemperature() != MISSING) && (tableRow.getTemperature() < 4.4f) - // 277.6 K = 40 F = 4.44444 Celsium + // 277.6 K = 40 F = 4.44444 C && (tableRow.getWindSpeed() != MISSING) && (tableRow.getWindSpeed() <= 43.0f && tableRow.getWindSpeed() >= 14.0f)) { float speedKPH = tableRow.getWindSpeed() * 1.6f; From 8dfcffb4a21e4adec601c601050005a8691095b6 Mon Sep 17 00:00:00 2001 From: Nate Jensen Date: Fri, 3 Jan 2014 09:21:49 -0600 Subject: [PATCH 06/62] Issue #2581 fix LocalStormReports with coastal floods Change-Id: Ifa8bd71e068f5ba1e1b534f00fbcbc59a2e9bf1e Former-commit-id: fda6dea53bafcff07d5573563e81a1f92b387e1a [formerly b5a80b2f1a4022e5aaf048d244502c4f6ae84bfa] [formerly 9729b11a07f239a4b661333a9df3c5ab6146c21b [formerly 852767e0dbf3e6c34de876b550f7f39baf181a2c]] Former-commit-id: 9729b11a07f239a4b661333a9df3c5ab6146c21b Former-commit-id: 0dbaae9855b9b163ceca296c76762eb65643f685 --- .../com/raytheon/uf/common/dataplugin/lsr/LSREventType.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java b/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java index ba01baf8fc..fd2fe785cd 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java @@ -34,6 +34,7 @@ import java.util.Map; * ------------ ---------- ----------- -------------------------- * Oct 14, 2009 jkorman Initial creation * Dec 09, 2013 2581 njensen Added freezing drizzle + * Jan 03, 2014 2581 njensen Added coastal flood * * * @@ -83,7 +84,8 @@ public enum LSREventType { TSTMWNDGST("TSTM WND GST",37,LSRUnits.MPH), WATERSPOUT("WATER SPOUT",38,LSRUnits.NOUNITS), WILDFIRE("WILDFIRE",39,LSRUnits.NOUNITS), - FREEZINGDRIZZLE("FREEZING DRIZZLE", 40, LSRUnits.NOUNITS); + FREEZINGDRIZZLE("FREEZING DRIZZLE", 40, LSRUnits.NOUNITS), + COASTALFLOOD("COASTAL FLOOD", 41, LSRUnits.NOUNITS); private final String eventName; From 0989c177103a15ecae1e39cb072503b7963d207b Mon Sep 17 00:00:00 2001 From: Steve Harris Date: Mon, 6 Jan 2014 14:02:30 -0500 Subject: [PATCH 07/62] 14.1.1-14 baseline Former-commit-id: 6df7c67f95f305f605d34911b1fafb6465e02c33 [formerly f2ad9da4eb6388bf3734fa204377fb17236b72ae] [formerly 9ef1c841b931ef87c9417a846c3d3139e0ce8d40 [formerly 46bdb43889bdc681fec2aba45004a1583caaa6ae]] Former-commit-id: 9ef1c841b931ef87c9417a846c3d3139e0ce8d40 Former-commit-id: 43cc501e0d731ddbc60510005843a2b9abdbd6e7 --- cave/.dm/.dirs.dmdb | Bin 16640 -> 0 bytes cave/build/static/linux/cave/caveUtil.sh | 2 +- .../raytheon/uf/viz/archive/data/SizeJob.java | 51 +- .../uf/viz/archive/ui/AbstractArchiveDlg.java | 23 +- .../.dm/.dirs.dmdb | Bin 16640 -> 0 bytes .../src/.dm/.dirs.dmdb | Bin 16640 -> 0 bytes .../src/com/.dm/.dirs.dmdb | Bin 16640 -> 0 bytes .../src/com/raytheon/.dm/.dirs.dmdb | Bin 16640 -> 0 bytes .../src/com/raytheon/uf/.dm/.dirs.dmdb | Bin 16640 -> 0 bytes .../src/com/raytheon/uf/viz/.dm/.dirs.dmdb | Bin 16640 -> 0 bytes .../raytheon/uf/viz/monitor/.dm/.dirs.dmdb | Bin 16640 -> 0 bytes .../uf/viz/monitor/scan/.dm/.dirs.dmdb | Bin 16640 -> 0 bytes .../scan/commondialogs/.dm/.items.dmdb | Bin 16640 -> 0 bytes .../viz/monitor/scan/resource/.dm/.items.dmdb | Bin 16640 -> 0 bytes .../viz/monitor/scan/tables/.dm/.items.dmdb | Bin 16640 -> 0 bytes .../rsc/CrossSectionImageResource.java | 11 +- .../rsc/CrossSectionVectorResource.java | 3 +- .../rsc/TimeHeightImageResource.java | 10 +- .../META-INF/MANIFEST.MF | 3 +- .../xy/timeseries/rsc/TimeSeriesResource.java | 6 +- .../util/TimeSeriesZoomHandler.java | 36 +- .../META-INF/MANIFEST.MF | 3 +- .../xy/varheight/rsc/VarHeightResource.java | 11 +- .../varheight/util/VarHeightZoomHandler.java | 24 +- .../src/com/raytheon/viz/gfe/Activator.java | 6 +- .../com/raytheon/viz/gfe/GridManagerView.java | 21 +- .../viz/gfe/actions/RunProcedureAction.java | 13 +- .../raytheon/viz/gfe/core/DataManager.java | 38 + .../viz/gfe/dialogs/KillJobsOnExitDialog.java | 18 +- .../perspective/GFEPerspectiveManager.java | 13 +- .../viz/gfe/procedures/ProcedureJob.java | 449 ----------- .../viz/gfe/procedures/ProcedureJobPool.java | 432 ++++++++++ .../gfe/procedures/ProcedureSelectionDlg.java | 6 +- .../viz/gfe/procedures/ProcedureUtil.java | 7 +- .../com/raytheon/viz/gfe/rsc/GFEResource.java | 7 +- .../raytheon/viz/gfe/smarttool/SmartUtil.java | 18 +- .../gfe/smarttool/script/SmartToolJob.java | 378 --------- .../smarttool/script/SmartToolJobPool.java | 377 +++++++++ .../script/SmartToolSelectionDlg.java | 17 +- .../viz/grid/rsc/general/GeneralGridData.java | 38 +- .../viz/radar/ui/xy/RadarXsectXYResource.java | 7 +- edexOsgi/build.edex/esb/conf/modes.xml | 8 + .../bufrua/decoder/BUFRUAManLevelAdapter.java | 128 ++- .../plugin/gfe/server/GridParmManager.java | 4 +- .../gfe/server/database/IFPGridDatabase.java | 10 + .../obs/metar/MetarPointDataTransform.java | 3 +- .../res/spring/text-common.xml | 7 +- .../res/spring/text-ingest.xml | 9 +- .../com.raytheon.edex.text.properties | 5 + .../edex/plugin/text/dao/TextDao.java | 30 +- .../TextArchiveFileNameFormatter.java | 82 +- .../archive/config/ArchiveConfigManager.java | 415 +++++++--- .../archive/config/CategoryDataSet.java | 59 +- .../config/CategoryFileDateHelper.java | 94 ++- .../common/archive/config/DataSetStatus.java | 128 +++ .../common/archive/config/FileDateFilter.java | 127 --- .../archive/config/IFileDateHelper.java | 6 +- .../common/archive/config/SelectConfig.java | 13 +- .../archive/config/select/CategorySelect.java | 21 +- .../res/spring/archive-spring.xml | 4 +- ...m.raytheon.uf.edex.archive.cron.properties | 9 +- .../uf/edex/archive/DataArchiver.java | 11 +- .../archive/DatabaseArchiveProcessor.java | 739 ++++++++++++++++++ .../uf/edex/archive/DatabaseArchiver.java | 348 ++------- ...DefaultPluginArchiveFileNameFormatter.java | 121 +-- .../IPluginArchiveFileNameFormatter.java | 37 +- .../uf/edex/archive/purge/ArchivePurger.java | 2 + .../base/archiver/purger/PROCESSED_DATA.xml | 54 +- .../base/archiver/purger/RAW_DATA.xml | 12 +- .../META-INF/MANIFEST.MF | 1 + .../database/cluster/ClusterLockUtils.java | 123 ++- .../uf/edex/database/dao/CoreDao.java | 136 +++- .../uf/edex/database/plugin/PluginDao.java | 102 +-- .../processor/IDatabaseProcessor.java | 69 ++ .../base/dissemination/handleOUP.py | 2 +- .../res/spring/DPADecoder-spring.xml | 5 - .../res/spring/hpeDHRDecoder-spring.xml | 5 - .../res/spring/ohd-common.xml | 17 +- .../res/spring/aww-common.xml | 5 + .../res/spring/nctext-common.xml | 6 +- .../res/spring/nctext-ingest.xml | 5 - 81 files changed, 3014 insertions(+), 1976 deletions(-) delete mode 100644 cave/.dm/.dirs.dmdb delete mode 100644 cave/com.raytheon.uf.viz.monitor.scan/.dm/.dirs.dmdb delete mode 100644 cave/com.raytheon.uf.viz.monitor.scan/src/.dm/.dirs.dmdb delete mode 100644 cave/com.raytheon.uf.viz.monitor.scan/src/com/.dm/.dirs.dmdb delete mode 100644 cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/.dm/.dirs.dmdb delete mode 100644 cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/.dm/.dirs.dmdb delete mode 100644 cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/.dm/.dirs.dmdb delete mode 100644 cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/.dm/.dirs.dmdb delete mode 100644 cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/.dm/.dirs.dmdb delete mode 100644 cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/commondialogs/.dm/.items.dmdb delete mode 100644 cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/resource/.dm/.items.dmdb delete mode 100644 cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/tables/.dm/.items.dmdb delete mode 100644 cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureJob.java create mode 100644 cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureJobPool.java delete mode 100644 cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolJob.java create mode 100644 cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolJobPool.java create mode 100644 edexOsgi/com.raytheon.edex.plugin.text/resources/com.raytheon.edex.text.properties create mode 100644 edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/DataSetStatus.java delete mode 100644 edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/FileDateFilter.java create mode 100644 edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiveProcessor.java create mode 100644 edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/processor/IDatabaseProcessor.java diff --git a/cave/.dm/.dirs.dmdb b/cave/.dm/.dirs.dmdb deleted file mode 100644 index 730698d65cf7fdd3ff38baba67d61b7734685385..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16640 zcmeI&&rZTH90%~?p9>d#g!uqgwstWbmM|FzhcSX^qPJzvFe4iogG67!ix1(WdGIm( zb&Ldd;UXc*w@LeJ$6EUPkPu4dxNd7`J6DXc2Gt5Ae8oz<}_1Rwwb2<%!web0aG zdJ}m6{Sqk7|HWBhe2jZ z-Mo}_vt|lm2zzy8II=Abp$loWgq~MN3h6ATp3kC3OE+~{7gAPpciLBfxwj%xjulCL zjp`X|dM+Q>_rp%h>+#z*zw175*XwnM-hkgU?Oy5Aqd97>Dq7xBvnjLE5*R`N0uX=z T1Rwwb2tWV=5P$##wj%HYuk|4T diff --git a/cave/build/static/linux/cave/caveUtil.sh b/cave/build/static/linux/cave/caveUtil.sh index 0e3d27f9da..a0bcf5ec78 100644 --- a/cave/build/static/linux/cave/caveUtil.sh +++ b/cave/build/static/linux/cave/caveUtil.sh @@ -120,7 +120,7 @@ function copyVizShutdownUtilIfNecessary() function getPidsOfMyRunningCaves() { local user=`whoami` - local caveProcs=`ps -ef | grep "/awips2/cave/cave " | grep -v "grep" | grep $user` + local caveProcs=`ps -ef | grep -E "(/awips2/cave|/usr/local/viz)/cave " | grep -v "grep" | grep $user` # preserve IFS and set it to line feed only local PREV_IFS=$IFS diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/SizeJob.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/SizeJob.java index c4c6bfdb87..f796cf72a6 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/SizeJob.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/data/SizeJob.java @@ -4,6 +4,7 @@ import java.io.File; import java.util.ArrayList; import java.util.Calendar; import java.util.Comparator; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -48,6 +49,8 @@ import com.raytheon.uf.common.time.util.TimeUtil; * Jul 24, 2013 #2220 rferrel Change to get all data sizes only one time. * Aug 02, 2013 #2224 rferrel Changes for new configuration files. * Aug 06, 2013 #2222 rferrel Changes to display all selected data. + * Dec 11, 2013 #2603 rferrel Selected list changed to a Set. + * Dec 11, 2013 #2624 rferrel Clear display variables when recomputing sizes. * * * @@ -231,6 +234,8 @@ public class SizeJob extends Job { */ public void recomputeSize() { clearQueue(); + displayArchive = null; + displayCategory = null; for (ArchiveInfo archiveInfo : archiveInfoMap.values()) { for (String categoryName : archiveInfo.getCategoryNames()) { CategoryInfo categoryInfo = archiveInfo.get(categoryName); @@ -300,19 +305,19 @@ public class SizeJob extends Job { for (String archiveName : getArchiveNames()) { ArchiveInfo archiveInfo = get(archiveName); for (String categoryName : archiveInfo.getCategoryNames()) { - List selectionsList = selections.getSelectedList( + Set selectionsSet = selections.getSelectedSet( archiveName, categoryName); MissingData missingData = removeMissingData(archiveName, categoryName); if (missingData != null) { - missingData.setSelectedList(selectionsList); + missingData.setSelectedSet(selectionsSet); addMissingData(missingData); } else { CategoryInfo categoryInfo = archiveInfo.get(categoryName); for (DisplayData displayData : categoryInfo .getDisplayDataList()) { String displayLabel = displayData.getDisplayLabel(); - boolean selected = selectionsList + boolean selected = selectionsSet .contains(displayLabel); if (selected != displayData.isSelected()) { setSelect(displayData, selected); @@ -506,10 +511,10 @@ public class SizeJob extends Job { visibleList = manager.getDisplayData(displayArchive, displayCategory, false); - List selectedList = selections.getSelectedList(displayArchive, + Set selectedSet = selections.getSelectedSet(displayArchive, displayCategory); for (DisplayData displayData : visibleList) { - displayData.setSelected(selectedList.contains(displayData + displayData.setSelected(selectedSet.contains(displayData .getDisplayLabel())); } @@ -528,10 +533,10 @@ public class SizeJob extends Job { schedule(); } } else { - selectedList = selections.getSelectedList(archiveName, + selectedSet = selections.getSelectedSet(archiveName, categoryName); MissingData missingData = new MissingData(archiveName, - categoryName, selectedList); + categoryName, selectedSet); missingDataQueue.add(missingData); } } @@ -658,14 +663,11 @@ public class SizeJob extends Job { break mainLoop; } - // System.out.println("+++SizeJob: " + currentDisplayData); - List files = manager.getDisplayFiles(currentDisplayData, startCal, endCal); // Size no longer needed. if (currentDisplayData != sizeQueue.peek()) { - // System.out.println("---SizeJob: " + currentDisplayData); continue mainLoop; } @@ -682,7 +684,6 @@ public class SizeJob extends Job { // Skip when size no longer needed. if (stopComputeSize) { - // System.out.println("---SizeJob: " + currentDisplayData); continue mainLoop; } } @@ -692,7 +693,6 @@ public class SizeJob extends Job { displayQueue.add(currentDisplayData); } - // System.out.println("xxxSizeJob: OK_STATUS"); shutdownDisplayTimer.set(true); return Status.OK_STATUS; } @@ -748,15 +748,10 @@ public class SizeJob extends Job { displayQueue.size()); displayQueue.drainTo(list); - // for (DisplayData displayData : list) { - // System.out.println("== " + displayData); - // } - // for (IUpdateListener listener : listeners) { listener.update(list); } } else if (shutdownDisplayTimer.get()) { - // System.out.println("xxx updateDisplayTimer canceled"); displayTimer.cancel(); displayTimer = null; } @@ -773,7 +768,6 @@ public class SizeJob extends Job { */ @Override protected void canceling() { - // System.err.println("canceling SizeJob"); clearQueue(); missingDataQueue.clear(); missingDataJob.cancel(); @@ -789,28 +783,28 @@ public class SizeJob extends Job { protected final String category; - protected final List selectedList; + protected final Set selectedSet; protected boolean visiable = false; public MissingData(String archive, String category, - List selectedList) { + Set selectedSet) { this.archive = archive; this.category = category; - this.selectedList = new ArrayList(selectedList); + this.selectedSet = new HashSet(selectedSet); } public boolean isSelected() { - return !selectedList.isEmpty(); + return !selectedSet.isEmpty(); } public void setVisiable(boolean state) { this.visiable = state; } - public void setSelectedList(List selectedList) { - this.selectedList.clear(); - this.selectedList.addAll(selectedList); + public void setSelectedSet(Set selectedSet) { + this.selectedSet.clear(); + this.selectedSet.addAll(selectedSet); } @Override @@ -861,8 +855,7 @@ public class SizeJob extends Job { String archiveName = currentMissingData.archive; String categoryName = currentMissingData.category; - // System.out.println("== missingData: " + currentMissingData); - List selectedList = currentMissingData.selectedList; + Set selectedSet = currentMissingData.selectedSet; List displayDatas = manager.getDisplayData( archiveName, categoryName, false); if (shutdown.get()) { @@ -870,7 +863,7 @@ public class SizeJob extends Job { } for (DisplayData displayData : displayDatas) { - displayData.setSelected(selectedList.contains(displayData + displayData.setSelected(selectedSet.contains(displayData .getDisplayLabel())); sizeQueue.add(displayData); } @@ -883,13 +876,11 @@ public class SizeJob extends Job { } } - // System.out.println("xxx missingData"); return Status.OK_STATUS; } @Override protected void canceling() { - // System.err.println("canceling MissingDataJob"); shutdown.set(true); } } diff --git a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/AbstractArchiveDlg.java b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/AbstractArchiveDlg.java index 3bc0e0706d..1840f6293e 100644 --- a/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/AbstractArchiveDlg.java +++ b/cave/com.raytheon.uf.viz.archive/src/com/raytheon/uf/viz/archive/ui/AbstractArchiveDlg.java @@ -76,6 +76,7 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * Aug 01, 2013 2221 rferrel Changes for select configuration. * Aug 06, 2013 2222 rferrel Changes to display all selected data. * Nov 14, 2013 2549 rferrel Get category data moved off the UI thread. + * Dec 11, 2013 2624 rferrel No longer clear table prior to populating. * * * @author bgonzale @@ -131,6 +132,10 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements /** Which table is being displayed. */ private boolean showingSelected = true; + private String previousSelectedArchive = null; + + private String previousSelectedCategory = null; + /** * @param parentShell */ @@ -386,7 +391,11 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements * Method invoked when archive combo selection is changed. */ protected void archiveComboSelection() { - populateCategoryCbo(); + String selectedArchvieName = getSelectedArchiveName(); + if (!selectedArchvieName.equals(previousSelectedArchive)) { + previousSelectedArchive = selectedArchvieName; + populateCategoryCbo(); + } } /** @@ -412,7 +421,14 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements * Method invoked when the category combo selection is changed. */ protected void categoryComboSelection() { - populateTableComp(); + String archiveName = getSelectedArchiveName(); + String categoryName = getSelectedCategoryName(); + if (!archiveName.equals(previousSelectedArchive) + || !categoryName.equals(previousSelectedCategory)) { + previousSelectedArchive = archiveName; + previousSelectedCategory = categoryName; + populateTableComp(); + } } /** @@ -463,9 +479,6 @@ public abstract class AbstractArchiveDlg extends CaveSWTDialog implements setCursorBusy(true); setShowingSelected(false); - tableComp.populateTable(archiveName, categoryName, - new ArrayList(0)); - tableComp.refresh(); Job job = new Job("populate category table") { diff --git a/cave/com.raytheon.uf.viz.monitor.scan/.dm/.dirs.dmdb b/cave/com.raytheon.uf.viz.monitor.scan/.dm/.dirs.dmdb deleted file mode 100644 index 72bab39d1ab0f15ad4a51a64e0b476842144fe82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16640 zcmeI&K~BOz6oBDDaKlE9z`}(a3++r}STqqW>W0Lq7iek?HPVt&Nc0kV2#@3;JccvS zCWRPQBue;S@|fwgoy_|}7t_=q4hIi?|3V0HuCpdYOE;!%nASwu(PQGUa%|4+eE7rL zYh8q?O~=vqvR(WhRQjf?9cm|QV;mx|ErIem+tz%{v!4RyfAqDVrBgKm2q1s}0tg_0 z00Nr@iv54F*I(KHZ@!VU2q1s}0tg_000IagfB*srAh0t6#s0ruEcj;I3vUw$Ab{=fM4dgc56?%KNmbB!7M&{>~m;mX?e*r!et@5@Grd6Z4# zH1X`NZ#|vGkDl$?swb6dw)MJxsi|h_YUyl< q`@73(QF`oHr-}0Yh*+ntAevNZS_!Vf1vmspV&E9q zZ6c*9BN9aVTXJo`+LGU|(~D9+2rlo({<#q1O!tlu`+6{A&y1#36CD$~wYB-K_013N zu5}V7H{JHW*5m4Pr#3fJ?a(=G#8@JL00IagfB*srAbcc`~AblvjDTl#NKu9M%i@Z?mG6NyJ>IhL5O9X&yy_m z?4jlK^Z0od785TDm+?TKw({_$n8aCXEgr39@@h@9G%2#&nnz(enCFq%)Sun|Qb_bHEK&%>8u7-y+zK-E6f(DAlNLd@cP zl4PlGw=AcT$Is)i82V8-iNIM1Hq zsPLujoyxY?@?6((JJl;EkeAYNZC5&7*Pf3+x-u}go=lSm-}Y?TcBO3SeXD)`(qrvV z)%Bl1_QYN1e$eaQT$fF%+OZls>Wd_V*`RSCBY*$`2q1s}0tg_000Iagu#N)Xa=sL{ diff --git a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/.dm/.dirs.dmdb b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/.dm/.dirs.dmdb deleted file mode 100644 index 99cdff69427e455f787dfc5160599e2dc34acc07..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16640 zcmeI(u};E37{KuZbYaoK2ViiurR_D!&_qm87ZL}3fTosEBP}T{iN1_JgpcIlV|WLx zp~Qi~#FG5K?#{{Gf)0eX$jy{pzPCiT))?n5;lZ|hEoWt1)A zH1VvyVRy6Wc^>3bFASEE8KyHM3tsYRlqNlX4G^RN diff --git a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/.dm/.dirs.dmdb b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/.dm/.dirs.dmdb deleted file mode 100644 index 41940fd55c91111c0078ce30a37f92c586229c51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16640 zcmeI&O-{l<6u|L8aKlE9;KHpf?M!1>G!aw379=i=3wNZJP$MlVg+#C81w4d@@cn^am>9G6p?h-?zpd?EuYKxn+WTq{Vi9Gt zI8A(~Yq{+#dYKOMu^$c>ksYQJD;vJ%<0wt6`N-1$W=+y0&eP1Ag~P<2WuXbO%OHC` zvUN~9I**@x$8%IqD%Gy% z@Jr5(6P-^-_m+6LeXKs9*UUZB%JUOZcd5oRM*sl?5I_I{1Q0*~0R#|0U|Rw|5iS!A diff --git a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/.dm/.dirs.dmdb b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/.dm/.dirs.dmdb deleted file mode 100644 index a517d9dc7690c106e6d15735865a2b60fb520e98..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16640 zcmeI&O-{l<6bJCZk6^lyBe-yDOFPpT7EQzyKNb~ZxIj}&sF9YGLZVl4;~_i@2k-#C zSEdGtJ4{H!f0E%%r?1Vt-)^S(LC_m?{c9n_74?P?EeafuIC857G$)Q%uK8Z=n;$&h zQW0DmwbR8imcIupV;+)2<8EUPmk@ve1Rwwb2tWV=5P$##AOHaf)IdP*|MgyfZU0|` z)nkbe*joWUm;Bz_>QVT%0@b$VZr@1fc+&-2; zhw(3Zw zjIs_|_a8Mk&S}0y{X_))hxL#1Jb7$WdHyG diff --git a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/.dm/.dirs.dmdb b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/.dm/.dirs.dmdb deleted file mode 100644 index b1215f56d1c36a2ab5f2a3ac90ceb66f2c14250e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16640 zcmeI&O-{l<6u|MKuwf%daN*XLw$m6EO+@R*24kWZAhm=VX-O$0dMXd$VLX5ba9*7z zg}5{j;{PSXd_CyQZ&L;ujYe0G!|1}YtaDvjmetdh)NQFH>V_V(I*q=}?R`X}`y0Ip z*_)1|&!4(_J!rJ0sU2Fk8)I}4KmY**5ZJareP7=8b-5k_2q1s}0tozH0r~#%weQKWAD1O7x6f2E?$p)=prHWRjiU?k>*+G_HD0Q zBro%EISu3SDskd`W*6hva+>6sy`0#q^v#~-Sz6|WEuZWxidd4II>}j19G&EtBuA3E z^CEvv;xbfjaHa-9Kk$9eA2xelq^_0cyT0Nv7^>mp&g>K-gfv;3oFZ!1~ xw@&nUPnVAMa5=ndY+8@WoP^j^vFXxCr-=Xp2q1s}0tg_000IagfWXcKz5yz27VH23 diff --git a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/.dm/.dirs.dmdb b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/.dm/.dirs.dmdb deleted file mode 100644 index 3629c1037196383b68af23b78e36f0f0d036fd72..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16640 zcmeI(!A{#S7zc2-WsFr~;}JOQO41~*CJvQWNMJ~WPQauccF95*nMzY7X(f094m=D8 zB(w|aL+k-|*kO;s=fq}B)lDF!La2XBt{wM_`$zLXBt_ zL@SEw&=`9$b}hbp_QiHTZc`E>H!5%br#1jK%$IyZ%KtzOMdwn!8L5P(4W0^&LPrTl4&Gs^RSH6JaU z|BHdRf&c^{009U<00IzrsK7j({U2(AI0!%h0uXp&0eSwf$z^;fdpWBp5P$##AOHaf zKmY;|fB*y_009U*xqv+X%Xid;-}g5r-UWylF*c&Q>_?}kQST`9y3x0UvY@e_R7JVX z8^(q~oP<%YWi&Li9tYjNm!7nIZy4xww-$S6=}8dvw861949_*1E=;3XOMI`VC$TSr zbQPozj&%ysWssf)71mJi$InpbJ9CSYIZ#oiz#+2** z|4-B!$DF3k`HSuyQC&>EuiZdwR9R?Dx!zDeE3R$updjDUaNhcMH76K4}00bZa0SG_<0uXrq0(S=xW0n8_ diff --git a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/commondialogs/.dm/.items.dmdb b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/commondialogs/.dm/.items.dmdb deleted file mode 100644 index 9637c565e7b0215edab7edde88ff851f155a9d5f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16640 zcmeI&O^(_y7zW@#+f6p@V!CJ1Es0}00Tz+SOkk?2psK%X6U>k)At-TZJ16ORdV(IJ ziyosk1Sx~6N@zx^s=k(t?c}rJdz_6U;>l$6Hj2+J%Npw1vaBb%G3`UsnsVsqYu2O2 z*xdW)OFVgXsgp3d>GJsJzTJJc8-3H&4(+c;*D!$`5x z-dse}ck550Sj&05x^k|?Ry32*aX0qrujPbh(qmE$*fzY^U(7>K465} zi*zNshZt%nOPPEut1Jw9ge8Q{W`g;gkbb|%1Jd^cDF~%OLhOZ9$+BCfH!`GTzj%v54f_54mz5itgxvFceBcwGG0GxFxW_!kbtSrbbi_Rx`^=}DvGZUYP;=KG zGtX4Ym{%{QgsRGrQ{U$Ue!;n&mR1MJ;8%cB+N5O>dkmU#BWBoH7w>w=5D9=c!obSEc*A z4Y4;xek~Jqly%d9#(d0oS<;coU)Pv39v`MQwn%5$+~H0~@9Xfew{@$Zk@j5oJGwr# zcE4%*A$mO>#qrBa=SB2BYAm5+xUQz0?Hg-9-GJfB*y_009U<00Izz00ba# Gg1|2xV^25$ diff --git a/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/resource/.dm/.items.dmdb b/cave/com.raytheon.uf.viz.monitor.scan/src/com/raytheon/uf/viz/monitor/scan/resource/.dm/.items.dmdb deleted file mode 100644 index 2b4d5e85ce4909d0cd7d44908e617b51bfb1ba90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 16640 zcmeI&!EV|x7zgmsZI@iO!@4ssKoZAx2!}|d4Q!gkHUZn+1S8TFf)WR9eS$sJw1?P3 z>@j9TqEggbD@}BNOXhQuFCpL0T%3@MMuTabTv(RX*S%#~uXHf+xrwGV1HI3Baj}Q|00Izz00bZa0SG_<0uX?}2?*5d z|9Y)|XZ?QycaK|y00bcLAc5xj?t?CZlb@V`dEWi{$yJ4dAOHafKmY;|`0oYk_5ZUP z;@x9|w9y~{0SG_<0uX=z1Rwwb2tWV=5cuZ;_4>bl2X^QG{r#h70VYT9YyHyke3FXw zSeAKJq%sjoI9FmT4yw_4zjdB&t)Kg7SzB3@S-y^l=lFJ}C;^N4W5dejT-MRqMa zO-^X1OPPKxt5rljHt+Ho6Mi6t6r6{GcRf$Y1(^l2u4gZ#N|&87yO9wg0SWDu%2s+z z!+`Q`FAVozR&Hb(F~Ym7$30G|Ph)*)LJ4Kmqdgi>-ybmIC!BJhQF;*!1K%9wLrP5d zDJAu#lu%U}F`skRW0#ECS=o`_R3TC&=aFYNmr~4i!PTr(5wQz-y%A~|rD7}HG+#M| z_^y^RUpv*p*=9G+Dqm+RFPu`tx@D1?B)3U&tA(qR+&anKB^5Qld+%J>nWyp6vt`TMi9b4yRfs?B3n!I$&UpA$)=p5u-c#&vMxmqE2WZUh?LOg1UW($ zJwO+|LA&U(2k4@U9-xaJqHicsq7)Hs9J{7~H^6X)nu&>YUeDOOkU%({v+@O5=_q@%vW}&aUpu^Em8^>_BT!EaM zatl0z3ZMd2R{);l!)#Hgx})eHDu4Du4>00;s^FE3o+fhu^GpS^Ix~Gdr}}Xd5`T_Zze)tzME&f-vm{ zy`l1l-_~CTv!E~=u=@k-pzQrRZw+InCdpuY?NL%^<{(w0)9E1csHDQ>l$h~gs7`Ym z%MAM}{4SY}JXT1g9HoPi@+fyK zE^XIw=7S|SD)a=Ews0kpoHO3y1a3&VfXcYVZPpf)`I1W}I6t#4ET+%O3r=-qoYTdv z(jc8Co?uc6SDXuB4w6&#eWr+tJfe5|Du`ghQxM9d=0pu|g0%02!Av#6@u)rten|Uj zd|jW$_1WM}eKfuvq~l3F34`lKG6}U&BR6VH;|3Tt7DkQCDAm#@jjfR|Zzki{Doi)# zTbw=f#f8Y`$J#JAU46lYpI=%C4$M!77UI~>e z_Ag)5zi7Q`t)Kv#{CCk4=x1fC_p3{4VARYER~tR%?>UE8=dCZ#)o^%k9Ex=g?G=YS zq?RL{h`FvSLQ4u_D@xsfF;~Slv5OoE;ELRlLz`Q>$l=yV>@)*y(@ERd@Wzh*m diff --git a/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/CrossSectionImageResource.java b/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/CrossSectionImageResource.java index 30a951a78a..d9e8135014 100644 --- a/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/CrossSectionImageResource.java +++ b/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/CrossSectionImageResource.java @@ -71,6 +71,7 @@ import com.vividsolutions.jts.geom.Coordinate; * ------------ ---------- ----------- -------------------------- * Nov 29, 2007 njensen Initial creation * 02/17/09 njensen Refactored to new rsc architecture + * Dec 11, 2013 DR 16795 D. Friedman Transform pixel coordinate in inspect * * * @@ -288,13 +289,15 @@ public class CrossSectionImageResource extends AbstractCrossSectionResource IExtent extent = descriptor.getGraph(this).getExtent(); + double val = Double.NaN; - if (extent.contains(new double[] { coord.getObject().x, - coord.getObject().y })) { + double[] worldCoord = descriptor.pixelToWorld(new double[] { + coord.getObject().x, coord.getObject().y }); + if (extent.contains(worldCoord)) { try { - DirectPosition2D dp = new DirectPosition2D(coord.getObject().x, - coord.getObject().y); + DirectPosition2D dp = new DirectPosition2D(worldCoord[0], + worldCoord[1]); descriptor.getGridGeometry().getGridToCRS().transform(dp, dp); val = reproj.reprojectedGridCell(sampler, (int) dp.x, (int) dp.y); diff --git a/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/CrossSectionVectorResource.java b/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/CrossSectionVectorResource.java index 16eceac2c6..6f2873a47c 100644 --- a/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/CrossSectionVectorResource.java +++ b/cave/com.raytheon.uf.viz.xy.crosssection/src/com/raytheon/uf/viz/xy/crosssection/rsc/CrossSectionVectorResource.java @@ -59,6 +59,7 @@ import com.vividsolutions.jts.geom.Coordinate; * ------------ ---------- ----------- -------------------------- * Jun 15, 2010 bsteffen Initial creation * Feb 14, 2011 8244 bkowal enabled magnification capability. + * Dec 11, 2013 DR 16795 D. Friedman Transform pixel coordinate in inspect * * * @@ -178,7 +179,7 @@ public class CrossSectionVectorResource extends AbstractCrossSectionResource { String s = null; Coordinate c = coord.getObject(); DataTime time = descriptor.getTimeForResource(this); - double[] values = descriptor.getGraph(this).getGridLocation(c.x, c.y); + double[] values = descriptor.pixelToWorld(new double[] { c.x, c.y }); // if geometry has not been created yet dont sample if (geometry == null) { diff --git a/cave/com.raytheon.uf.viz.xy.timeheight/src/com/raytheon/uf/viz/xy/timeheight/rsc/TimeHeightImageResource.java b/cave/com.raytheon.uf.viz.xy.timeheight/src/com/raytheon/uf/viz/xy/timeheight/rsc/TimeHeightImageResource.java index 0dee9ff574..b3bf5de7d2 100644 --- a/cave/com.raytheon.uf.viz.xy.timeheight/src/com/raytheon/uf/viz/xy/timeheight/rsc/TimeHeightImageResource.java +++ b/cave/com.raytheon.uf.viz.xy.timeheight/src/com/raytheon/uf/viz/xy/timeheight/rsc/TimeHeightImageResource.java @@ -62,6 +62,7 @@ import com.vividsolutions.jts.geom.Coordinate; * ------------ ---------- ----------- -------------------------- * Dec 4, 2007 njensen Initial creation * Feb 20, 2009 njensen Refactored to new rsc architecture + * Dec 11, 2013 DR 16795 D. Friedman Transform pixel coordinate in inspect * * * @@ -273,12 +274,13 @@ public class TimeHeightImageResource extends AbstractTimeHeightResource IExtent extent = descriptor.getGraph(this).getExtent(); double val = Double.NaN; - if (extent.contains(new double[] { coord.getObject().x, - coord.getObject().y })) { + double[] worldCoord = descriptor.pixelToWorld(new double[] { + coord.getObject().x, coord.getObject().y }); + if (extent.contains(worldCoord)) { try { - DirectPosition2D dp = new DirectPosition2D(coord.getObject().x, - coord.getObject().y); + DirectPosition2D dp = new DirectPosition2D(worldCoord[0], + worldCoord[1]); descriptor.getGridGeometry().getGridToCRS().transform(dp, dp); val = reproj.reprojectedGridCell(sampler, (int) dp.x, (int) dp.y); diff --git a/cave/com.raytheon.uf.viz.xy.timeseries/META-INF/MANIFEST.MF b/cave/com.raytheon.uf.viz.xy.timeseries/META-INF/MANIFEST.MF index 908de32e7f..3390b08b0b 100644 --- a/cave/com.raytheon.uf.viz.xy.timeseries/META-INF/MANIFEST.MF +++ b/cave/com.raytheon.uf.viz.xy.timeseries/META-INF/MANIFEST.MF @@ -8,7 +8,8 @@ Bundle-Vendor: RAYTHEON Eclipse-RegisterBuddy: com.raytheon.viz.core, com.raytheon.uf.viz.core Eclipse-BuddyPolicy: ext, global Require-Bundle: org.eclipse.ui, - org.eclipse.core.runtime + org.eclipse.core.runtime, + org.geotools Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-ActivationPolicy: lazy Export-Package: com.raytheon.uf.viz.xy.timeseries, diff --git a/cave/com.raytheon.uf.viz.xy.timeseries/src/com/raytheon/uf/viz/xy/timeseries/rsc/TimeSeriesResource.java b/cave/com.raytheon.uf.viz.xy.timeseries/src/com/raytheon/uf/viz/xy/timeseries/rsc/TimeSeriesResource.java index 9e8e7b17d0..5388e4bae2 100644 --- a/cave/com.raytheon.uf.viz.xy.timeseries/src/com/raytheon/uf/viz/xy/timeseries/rsc/TimeSeriesResource.java +++ b/cave/com.raytheon.uf.viz.xy.timeseries/src/com/raytheon/uf/viz/xy/timeseries/rsc/TimeSeriesResource.java @@ -96,6 +96,7 @@ import com.vividsolutions.jts.geom.Geometry; * Feb 10, 2011 8244 bkowal enabled the magnification * capability. * Feb 14, 2011 8244 bkowal enabled magnification for wind barbs. + * Dec 19, 2013 DR 16795 D. Friedman Transform pixel coordinate in inspect * * * @@ -580,7 +581,10 @@ public class TimeSeriesResource extends @Override public String inspect(ReferencedCoordinate coord) throws VizException { String inspect = null; - Coordinate c = descriptor.getGraphCoordiante(this, coord.getObject()); + double[] worldCoord = descriptor.pixelToWorld( + new double[] { coord.getObject().x, coord.getObject().y }); + Coordinate c = descriptor.getGraphCoordiante(this, + new Coordinate(worldCoord[0], worldCoord[1])); if (c != null && data != null) { double[] vals = data.inspectXY(c); NumberFormat nf = NumberFormat.getInstance(); diff --git a/cave/com.raytheon.uf.viz.xy.timeseries/src/com/raytheon/uf/viz/xy/timeseries/util/TimeSeriesZoomHandler.java b/cave/com.raytheon.uf.viz.xy.timeseries/src/com/raytheon/uf/viz/xy/timeseries/util/TimeSeriesZoomHandler.java index e96132d4cd..02dba0e768 100644 --- a/cave/com.raytheon.uf.viz.xy.timeseries/src/com/raytheon/uf/viz/xy/timeseries/util/TimeSeriesZoomHandler.java +++ b/cave/com.raytheon.uf.viz.xy.timeseries/src/com/raytheon/uf/viz/xy/timeseries/util/TimeSeriesZoomHandler.java @@ -22,7 +22,11 @@ package com.raytheon.uf.viz.xy.timeseries.util; import java.util.Stack; import org.eclipse.swt.widgets.Event; +import org.geotools.geometry.DirectPosition2D; +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.IDisplayPaneContainer; import com.raytheon.uf.viz.core.drawables.IRenderableDisplay; import com.raytheon.uf.viz.xy.AbstractGraphInputHandler; @@ -42,6 +46,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Oct 16, 2009 mschenke Initial creation + * Dec 11, 2013 DR 16795 D. Friedman Transform pixel coordinate for zoom * * * @@ -51,6 +56,9 @@ import com.vividsolutions.jts.geom.Coordinate; public class TimeSeriesZoomHandler extends AbstractGraphInputHandler { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(TimeSeriesZoomHandler.class); + private MousePreferenceManager prefManager = MousePreferenceManager .getInstance(); @@ -103,7 +111,7 @@ public class TimeSeriesZoomHandler extends AbstractGraphInputHandler { private boolean zoomIn(int x, int y) { IDisplayPaneContainer editor = display.getContainer(); - Coordinate grid = editor.translateClick(x, y); + Coordinate grid = translateClick(x, y); if (grid == null) { return false; } @@ -129,7 +137,7 @@ public class TimeSeriesZoomHandler extends AbstractGraphInputHandler { private boolean zoomOut(int x, int y) { IDisplayPaneContainer editor = display.getContainer(); - Coordinate grid = editor.translateClick(x, y); + Coordinate grid = translateClick(x, y); if (grid == null) { return false; } @@ -153,4 +161,28 @@ public class TimeSeriesZoomHandler extends AbstractGraphInputHandler { return true; } + private Coordinate translateClick(int x, int y) { + IDisplayPaneContainer editor = display.getContainer(); + XyGraphDescriptor desc = (XyGraphDescriptor) editor + .getActiveDisplayPane().getDescriptor(); + Coordinate grid = editor.translateClick(x, y); + if (grid == null) { + return null; + } + /* Convert from the overall display coordinate space to the coordinate + * space for our resource. + */ + DirectPosition2D dp = new DirectPosition2D(grid.x, grid.y); + try { + desc.getGridGeometry().getGridToCRS().transform(dp, dp); + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Error converting coordinate", e); + } + grid.x = dp.x; + grid.y = dp.y; + grid.z = 0; + return grid; + } + } diff --git a/cave/com.raytheon.uf.viz.xy.varheight/META-INF/MANIFEST.MF b/cave/com.raytheon.uf.viz.xy.varheight/META-INF/MANIFEST.MF index e05c73bf24..d0137e20e0 100644 --- a/cave/com.raytheon.uf.viz.xy.varheight/META-INF/MANIFEST.MF +++ b/cave/com.raytheon.uf.viz.xy.varheight/META-INF/MANIFEST.MF @@ -7,7 +7,8 @@ Bundle-Activator: com.raytheon.uf.viz.xy.varheight.Activator Bundle-Vendor: RAYTHEON Eclipse-RegisterBuddy: com.raytheon.viz.core, com.raytheon.uf.viz.core Require-Bundle: org.eclipse.core.runtime, - org.eclipse.ui;bundle-version="3.4.1" + org.eclipse.ui;bundle-version="3.4.1", + org.geotools Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-ActivationPolicy: lazy Import-Package: com.raytheon.uf.common.dataplugin, diff --git a/cave/com.raytheon.uf.viz.xy.varheight/src/com/raytheon/uf/viz/xy/varheight/rsc/VarHeightResource.java b/cave/com.raytheon.uf.viz.xy.varheight/src/com/raytheon/uf/viz/xy/varheight/rsc/VarHeightResource.java index 200341ed45..0626f01f39 100644 --- a/cave/com.raytheon.uf.viz.xy.varheight/src/com/raytheon/uf/viz/xy/varheight/rsc/VarHeightResource.java +++ b/cave/com.raytheon.uf.viz.xy.varheight/src/com/raytheon/uf/viz/xy/varheight/rsc/VarHeightResource.java @@ -78,6 +78,7 @@ import com.vividsolutions.jts.geom.Geometry; * ------------ ---------- ----------- -------------------------- * Nov 23, 2009 mschenke Initial creation * Feb 10, 2011 8344 bkowal enabled the magnification capability. + * Dec 19, 2013 DR 16795 D. Friedman Transform pixel coordinate in inspect * * * @@ -543,9 +544,13 @@ public class VarHeightResource extends @Override public String inspect(ReferencedCoordinate coord) throws VizException { Coordinate object = coord.getObject(); - object = descriptor.getGraphCoordiante(this, object); - if (object != null) { - return object.x + ", " + object.y; + double[] worldCoord = descriptor.pixelToWorld( + new double[] { object.x, object.y }); + Coordinate c = new Coordinate(worldCoord[0], worldCoord[1]); + + c = descriptor.getGraphCoordiante(this, c); + if (c != null) { + return c.x + ", " + c.y; } return null; } diff --git a/cave/com.raytheon.uf.viz.xy.varheight/src/com/raytheon/uf/viz/xy/varheight/util/VarHeightZoomHandler.java b/cave/com.raytheon.uf.viz.xy.varheight/src/com/raytheon/uf/viz/xy/varheight/util/VarHeightZoomHandler.java index d097c2d50b..03da2b34d2 100644 --- a/cave/com.raytheon.uf.viz.xy.varheight/src/com/raytheon/uf/viz/xy/varheight/util/VarHeightZoomHandler.java +++ b/cave/com.raytheon.uf.viz.xy.varheight/src/com/raytheon/uf/viz/xy/varheight/util/VarHeightZoomHandler.java @@ -20,7 +20,11 @@ package com.raytheon.uf.viz.xy.varheight.util; import org.eclipse.swt.widgets.Event; +import org.geotools.geometry.DirectPosition2D; +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.IDisplayPaneContainer; import com.raytheon.uf.viz.core.drawables.IRenderableDisplay; import com.raytheon.uf.viz.core.drawables.ResourcePair; @@ -44,6 +48,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jul 3, 2010 bsteffen Initial creation + * Dec 11, 2013 DR 16795 D. Friedman Transform pixel coordinate for zoom * * * @@ -52,6 +57,9 @@ import com.vividsolutions.jts.geom.Coordinate; */ public class VarHeightZoomHandler extends AbstractGraphInputHandler { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(VarHeightZoomHandler.class); + private MousePreferenceManager prefManager = MousePreferenceManager .getInstance(); @@ -113,12 +121,24 @@ public class VarHeightZoomHandler extends AbstractGraphInputHandler { && zoomIndex < ZoomMenuAction.ZOOM_LEVELS.length - 1) { zoomIndex += 1; } + + /* Convert from the overall display coordinate space to the coordinate + * space for our resource. + */ + DirectPosition2D dp = new DirectPosition2D(grid.x, grid.y); + try { + desc.getGridGeometry().getGridToCRS().transform(dp, dp); + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Error converting coordinate for zoom", e); + } + for (ResourcePair rsc : desc.getResourceList()) { if (rsc.getResource() instanceof IGraphableResource) { IGraph graph = desc.getGraph((IGraphableResource) rsc .getResource()); - if (graph.getExtent().contains(new double[] { grid.x, grid.y })) { - graph.zoom((int) Math.pow(2, zoomIndex), grid); + if (graph.getExtent().contains(new double[] { dp.x, dp.y })) { + graph.zoom((int) Math.pow(2, zoomIndex), new Coordinate(dp.x, dp.y)); } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/Activator.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/Activator.java index 3416f2bdc0..d2c70bbc84 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/Activator.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/Activator.java @@ -29,8 +29,6 @@ import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.viz.gfe.dialogs.GFEConfigDialog; -import com.raytheon.viz.gfe.procedures.ProcedureJob; -import com.raytheon.viz.gfe.smarttool.script.SmartToolJob; /** * The activator class controls the plug-in life cycle @@ -43,6 +41,8 @@ import com.raytheon.viz.gfe.smarttool.script.SmartToolJob; * ------------ ---------- ----------- -------------------------- * Initial creation * Oct 30, 2012 1298 rferrel Must be a blocking dialog. + * Dec 09, 2013 #2367 dgilling Remove shutdown of ProcedureJob and + * SmartToolJob. * * * @@ -92,8 +92,6 @@ public class Activator extends AbstractUIPlugin implements BundleActivator { @Override public void stop(BundleContext context) throws Exception { plugin = null; - ProcedureJob.shutdown(); - SmartToolJob.shutdown(); super.stop(context); } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/GridManagerView.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/GridManagerView.java index 1b08f40d78..746cedf8c6 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/GridManagerView.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/GridManagerView.java @@ -38,8 +38,6 @@ import com.raytheon.viz.gfe.core.parm.Parm; import com.raytheon.viz.gfe.dialogs.KillJobsOnExitDialog; import com.raytheon.viz.gfe.dialogs.SaveParameterDialog; import com.raytheon.viz.gfe.gridmanager.GridManager; -import com.raytheon.viz.gfe.procedures.ProcedureJob; -import com.raytheon.viz.gfe.smarttool.script.SmartToolJob; import com.raytheon.viz.ui.DetachedViewListener; import com.raytheon.viz.ui.color.BackgroundColor; import com.raytheon.viz.ui.color.IBackgroundColorChangedListener.BGColorMode; @@ -56,6 +54,7 @@ import com.raytheon.viz.ui.color.IBackgroundColorChangedListener.BGColorMode; * adding cancel capability and if error on * save then the close is cancelled. * 10/30/2012 #1298 rferrel Must keep blocking dialogs to work with eclipse plugins. + * 12/10/2013 #2367 dgilling Use new ProcedureJobePool and SmartToolJobPool. * * * @author dfitch @@ -138,11 +137,12 @@ public class GridManagerView extends ViewPart implements ISaveablePart2 { @Override public int promptToSaveOnClose() { // Check for any running/queued jobs. - if (ProcedureJob.haveJobs() || SmartToolJob.haveJobs()) { + if (dataManager.getProcedureJobPool().isActive() + || dataManager.getSmartToolJobPool().isActive()) { Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow() .getShell(); - - KillJobsOnExitDialog dialog = new KillJobsOnExitDialog(shell); + KillJobsOnExitDialog dialog = new KillJobsOnExitDialog(shell, + dataManager); // Must keep modal and blocking in order to work with eclipse // plugins. dialog.setBlockOnOpen(true); @@ -187,13 +187,10 @@ public class GridManagerView extends ViewPart implements ISaveablePart2 { @Override public boolean isDirty() { - if ((dataManager != null && dataManager.getParmManager() - .getModifiedParms().length > 0) - || SmartToolJob.haveJobs() - || ProcedureJob.haveJobs()) { - return true; - } - return false; + return ((dataManager != null) && (dataManager.getParmManager() + .getModifiedParms().length > 0)) + || dataManager.getProcedureJobPool().isActive() + || dataManager.getSmartToolJobPool().isActive(); } @Override diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/RunProcedureAction.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/RunProcedureAction.java index 1f0bd1b4e7..7839a08908 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/RunProcedureAction.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/RunProcedureAction.java @@ -32,7 +32,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.viz.gfe.core.DataManager; -import com.raytheon.viz.gfe.procedures.ProcedureJob; +import com.raytheon.viz.gfe.core.DataManagerUIFactory; import com.raytheon.viz.gfe.procedures.ProcedureRequest; import com.raytheon.viz.gfe.procedures.ProcedureSelectionDlg; import com.raytheon.viz.gfe.procedures.ProcedureUtil; @@ -47,8 +47,9 @@ import com.raytheon.viz.gfe.ui.runtimeui.SelectionDlg; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Nov 4, 2008 njensen Initial creation - * Nov 15, 2012 1298 rferrel Changes for non-blocking ProcedureSelectionDlg. + * Nov 04, 2008 njensen Initial creation + * Nov 15, 2012 #1298 rferrel Changes for non-blocking ProcedureSelectionDlg. + * Dec 09, 2013 #2367 dgilling Use new ProcedureJobPool. * * * @author njensen @@ -69,11 +70,11 @@ public class RunProcedureAction extends AbstractHandler { @Override public Object execute(ExecutionEvent event) throws ExecutionException { String procedureName = event.getParameter("name"); - DataManager dm = DataManager.getCurrentInstance(); + DataManager dm = DataManagerUIFactory.getCurrentInstance(); try { List varList = dm.getProcedureInterface() .getVarDictWidgets(procedureName); - if (varList == null || varList.size() == 0) { + if (varList == null || varList.isEmpty()) { // no VariableList found on procedure, just run it PreviewInfo pi = ProcedureUtil.checkAndBuildPreview(dm, procedureName); @@ -81,7 +82,7 @@ public class RunProcedureAction extends AbstractHandler { ProcedureRequest req = ProcedureUtil.buildProcedureRequest( procedureName, dm); if (req != null) { - ProcedureJob.enqueue(dm, req); + dm.getProcedureJobPool().schedule(req); } } } else { diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java index 721d9188a1..1aa76a05b8 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java @@ -69,10 +69,12 @@ import com.raytheon.viz.gfe.itool.IToolController; import com.raytheon.viz.gfe.itool.IToolFactory; import com.raytheon.viz.gfe.jobs.AutoSaveJob; import com.raytheon.viz.gfe.procedures.ProcedureFactory; +import com.raytheon.viz.gfe.procedures.ProcedureJobPool; import com.raytheon.viz.gfe.procedures.ProcedureUIController; import com.raytheon.viz.gfe.smarttool.EditActionProcessor; import com.raytheon.viz.gfe.smarttool.GridCycler; import com.raytheon.viz.gfe.smarttool.script.SmartToolFactory; +import com.raytheon.viz.gfe.smarttool.script.SmartToolJobPool; import com.raytheon.viz.gfe.smarttool.script.SmartToolUIController; import com.raytheon.viz.gfe.textformatter.TextProductManager; @@ -97,6 +99,7 @@ import com.raytheon.viz.gfe.textformatter.TextProductManager; * 04/24/2013 1936 dgilling Move initialization of TextProductMgr * to GFE startup. * 08/27/2013 2302 randerso Code cleanup for AutoSaveJob + * 12/09/2013 2367 dgilling Instantiate ProcedureJobPool here. * * * @@ -195,6 +198,10 @@ public class DataManager { private List allSites; + private final ProcedureJobPool procJobPool; + + private final SmartToolJobPool toolJobPool; + public IISCDataAccess getIscDataAccess() { return iscDataAccess; } @@ -228,6 +235,8 @@ public class DataManager { strInitJob.schedule(); initializeScriptControllers(); + procJobPool = new ProcedureJobPool(4, 4, this); + toolJobPool = new SmartToolJobPool(3, 3, this); this.weGroupManager = new WEGroupManager(this); this.editActionProcessor = new EditActionProcessor(this); @@ -297,6 +306,28 @@ public class DataManager { procedureInterface.dispose(); } + // by moving the the pools' cancel calls to another thread, we prevent + // GFE shutdown from freezing the UI thread until all jobs have + // completed. The unfortunate side effect is that we get that annoying + // "Job found still running after platform shutdown" warning from + // Eclipse. + Runnable killJobPools = new Runnable() { + + @Override + public void run() { + if (toolJobPool != null) { + toolJobPool.cancel(); + } + + if (procJobPool != null) { + procJobPool.cancel(); + } + } + }; + Thread killPoolsThread = new Thread(killJobPools, "shutdown-gfe-pools"); + killPoolsThread.setDaemon(false); + killPoolsThread.start(); + NotificationManagerJob.removeObserver("edex.alerts.gfe", router); } @@ -689,4 +720,11 @@ public class DataManager { return textProductMgr; } + public ProcedureJobPool getProcedureJobPool() { + return procJobPool; + } + + public SmartToolJobPool getSmartToolJobPool() { + return toolJobPool; + } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/KillJobsOnExitDialog.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/KillJobsOnExitDialog.java index c1808c867c..5a809bb65e 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/KillJobsOnExitDialog.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/dialogs/KillJobsOnExitDialog.java @@ -30,8 +30,7 @@ import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; -import com.raytheon.viz.gfe.procedures.ProcedureJob; -import com.raytheon.viz.gfe.smarttool.script.SmartToolJob; +import com.raytheon.viz.gfe.core.DataManager; import com.raytheon.viz.ui.dialogs.CaveJFACEDialog; /** @@ -44,6 +43,8 @@ import com.raytheon.viz.ui.dialogs.CaveJFACEDialog; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 13, 2011 rferrel Initial creation + * Dec 10, 2013 #2367 dgilling Rewrite to use new ProcedureJobPool and + * SmartToolJobPool. * * * @@ -54,13 +55,16 @@ public class KillJobsOnExitDialog extends CaveJFACEDialog { private Composite top; + private final DataManager dataMgr; + /** * Use defaults of -240, minimum and 240 max. */ - public KillJobsOnExitDialog(Shell parent) { + public KillJobsOnExitDialog(Shell parent, DataManager dataMgr) { super(parent); int style = this.getShellStyle() | SWT.MODELESS | SWT.TITLE | SWT.CLOSE; this.setShellStyle(style); + this.dataMgr = dataMgr; } @Override @@ -77,9 +81,9 @@ public class KillJobsOnExitDialog extends CaveJFACEDialog { private void initializeComponents() { - int cnt[] = ProcedureJob.getJobCount(); + int cnt[] = dataMgr.getProcedureJobPool().getWorkRemaining(); GridData data = null; - if (cnt[0] > 0 || cnt[1] > 0) { + if ((cnt[0] > 0) || (cnt[1] > 0)) { Label lab = new Label(top, SWT.NONE); lab.setText(String .format("Have %d procedure(s) running and %d procedures(s) pending", @@ -88,8 +92,8 @@ public class KillJobsOnExitDialog extends CaveJFACEDialog { lab.setLayoutData(data); } - cnt = SmartToolJob.getJobCount(); - if (cnt[0] > 0 || cnt[1] > 0) { + cnt = dataMgr.getSmartToolJobPool().getWorkRemaining(); + if ((cnt[0] > 0) || (cnt[1] > 0)) { Label lab = new Label(top, SWT.NONE); lab.setText(String .format("Have %d Smart tool(s) running and %d Smart tool(s) pending", diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/perspective/GFEPerspectiveManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/perspective/GFEPerspectiveManager.java index 9902f4f472..1fd339dd28 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/perspective/GFEPerspectiveManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/perspective/GFEPerspectiveManager.java @@ -60,9 +60,7 @@ import com.raytheon.viz.gfe.core.DataManagerUIFactory; import com.raytheon.viz.gfe.core.GFEMapRenderableDisplay; import com.raytheon.viz.gfe.core.ISpatialDisplayManager; import com.raytheon.viz.gfe.core.internal.GFESpatialDisplayManager; -import com.raytheon.viz.gfe.procedures.ProcedureJob; import com.raytheon.viz.gfe.rsc.GFELegendResourceData; -import com.raytheon.viz.gfe.smarttool.script.SmartToolJob; import com.raytheon.viz.gfe.statusline.ISCSendEnable; import com.raytheon.viz.ui.EditorUtil; import com.raytheon.viz.ui.cmenu.ZoomMenuAction; @@ -88,6 +86,8 @@ import com.raytheon.viz.ui.perspectives.VizPerspectiveListener; * Jul 7, 2011 #9897 ryu close formatters on perspective close/reset * Aug 20,2012 #1077 randerso Added support for bgColor setting * Oct 23, 2012 #1287 rferrel Changes for non-blocking FormattrLauncherDialog. + * Dec 09, 2013 #2367 dgilling Remove shutdown of ProcedureJob and + * SmartToolJob. * * * @author randerso @@ -235,15 +235,6 @@ public class GFEPerspectiveManager extends AbstractCAVEPerspectiveManager { DataManagerUIFactory.dispose(perspectiveWindow); - // Put on own thread so close is not slowed down. - new Thread(new Runnable() { - - @Override - public void run() { - ProcedureJob.shutdown(); - SmartToolJob.shutdown(); - } - }).start(); FormatterlauncherAction.closeDialog(); } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureJob.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureJob.java deleted file mode 100644 index 21c8f4523e..0000000000 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureJob.java +++ /dev/null @@ -1,449 +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.viz.gfe.procedures; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import jep.JepException; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; - -import com.raytheon.uf.common.dataplugin.gfe.StatusConstants; -import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData; -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.TimeRange; -import com.raytheon.uf.viz.core.jobs.AbstractQueueJob; -import com.raytheon.viz.gfe.Activator; -import com.raytheon.viz.gfe.GFEException; -import com.raytheon.viz.gfe.core.DataManager; -import com.raytheon.viz.gfe.jobs.AsyncProgressJob; - -/** - * Job for running GFE procedures. Since JEP/JNI requires that the thread that - * initialized the python interpreter is the same one that runs it, this job - * initializes an interpreter for procedures and then sleeps until a request is - * enqueued. - * - *
- * 
- * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Oct 8, 2009             njensen     Initial creation
- * Jan 8, 2013  1486       dgilling    Support changes to BaseGfePyController.
- * Jan 18, 2013 1509       njensen     Garbage collect after running procedure
- * Apr 03, 2013    1855  njensen   Never dispose interpreters until shutdown and
- *                                                      reuse interpreter if called from procedure
- * 
- * 
- * - * @author njensen - * @version 1.0 - */ - -public class ProcedureJob extends AbstractQueueJob { - /** - * Maximum number of jobs to keep for a given Data Manager. - */ - private final static int maxJobs = 4; - - /** - * Index of job with the queue. Will break code if not zero. - */ - private final static int QUEUE_JOB_INDEX = 0; - - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(ProcedureJob.class); - - private static Map> instanceMap = null; - - private ProcedureController python; - - private DataManager dataMgr; - - private ProcedureRequest request; - - protected ProcedureJob(DataManager dataMgr) { - super("GFE Procedures Job"); - this.dataMgr = dataMgr; - } - - private void getRequest() throws InterruptedException { - if (instanceMap == null) { - request = null; - return; - } - - List jobList = instanceMap.get(dataMgr); - if (jobList == null || jobList.size() == 0 - || jobList.get(QUEUE_JOB_INDEX).queue == null) { - request = null; - } else { - request = jobList.get(QUEUE_JOB_INDEX).queue.poll(1000L, - TimeUnit.MILLISECONDS); - } - } - - /* - * (non-Javadoc) - * - * @seeorg.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime. - * IProgressMonitor) - */ - @Override - protected IStatus run(IProgressMonitor monitor) { - try { - python = ProcedureFactory.buildController(dataMgr); - } catch (JepException e) { - ProcedureJob.removeJob(dataMgr, this); - return new Status(IStatus.ERROR, StatusConstants.PLUGIN_ID, - "Error initializing procedure python", e); - } - - try { - while (monitor.isCanceled() == false) { - // ProcedureRequest request; - try { - getRequest(); - } catch (InterruptedException e) { - continue; - } - // May have been canceled while waiting. - if (monitor.isCanceled()) { - break; - } - synchronized (this) { - try { - if (request != null) { - python.processFileUpdates(); - processRequest(request); - if (request != null) { - request.requestComplete(null); - } - } - } catch (Throwable t) { - statusHandler.handle(Priority.PROBLEM, - "Error running procedure ", t); - if (request != null) { - request.requestComplete(t); - } - } finally { - request = null; - } - } - } - } finally { - if (python != null) { - python.dispose(); - python = null; - } - } - - return Status.OK_STATUS; - } - - /** - * Remove a job from the Data Manger's job list. - * - * @param dataMgr - * - The job's data manager - * @param job - * - The job to remove - */ - private static synchronized void removeJob(DataManager dataMgr, - ProcedureJob job) { - if (instanceMap == null) { - return; - } - - List jobList = instanceMap.get(dataMgr); - - if (jobList != null) { - jobList.remove(job); - - // Removing job with queue remove job list so next request will set - // up new queue. - if (job.queue != null) { - jobList.clear(); - instanceMap.remove(dataMgr); - } - } - } - - public void processRequest(ProcedureRequest request) { - this.execute(python, request.getProcedureName(), request.getRefSet(), - request.getTimeRange(), request.getVarDict()); - this.dataMgr.getEditActionProcessor().wrapUpExecute( - request.getPreview(), false); - } - - /** - * This manages the scheduling of jobs to service a Data Manger's requests. - * - * @param dataMgr - * - Data Manger for the request - * @param request - * - The request to service - * @return state - true when job available to process request otherwise - * false and request is queued to wait for next available job - */ - public static synchronized boolean enqueue(DataManager dataMgr, - ProcedureRequest request) { - if (instanceMap == null) { - instanceMap = new HashMap>(); - } - - Thread currentThread = Thread.currentThread(); - List jobList = instanceMap.get(dataMgr); - if (jobList == null) { - jobList = new ArrayList(); - // Add the first job which contains the queue used by all jobs in - // the list. - ProcedureJob job = new ProcedureJob(dataMgr); - jobList.add(job); - instanceMap.put(dataMgr, jobList); - job.setSystem(true); - job.schedule(); - } - boolean jobAvailable = false; - ProcedureJob alreadyOnThread = null; - for (ProcedureJob job : jobList) { - Thread jobThread = job.getThread(); - if (currentThread == jobThread) { - // this occurs when a running procedure uses - // SmartScript.callProcedure() - // for efficiency we want to just stay on this thread - alreadyOnThread = job; - jobAvailable = true; - break; - } else if (job.request == null) { - jobAvailable = true; - break; - } - } - - // All jobs for data manager are busy, add another if we haven't - // reached the limit. - if (alreadyOnThread == null && !jobAvailable - && jobList.size() < maxJobs) { - ProcedureJob job = new ProcedureJob(dataMgr); - job.setSystem(true); - jobList.add(job); - // Never used additional job's queue - job.queue = null; - job.schedule(); - jobAvailable = true; - } - - if (alreadyOnThread != null) { - try { - alreadyOnThread.processRequest(request); - request.requestComplete(null); - } catch (Throwable t) { - statusHandler.handle(Priority.PROBLEM, - "Error running procedure ", t); - request.requestComplete(t); - } - } else { - jobList.get(QUEUE_JOB_INDEX).enqueue(request); - } - return jobAvailable; - } - - /** - * This returns an array of two integers the first is the number of - * Procedure Tool Jobs being processed and the second is the number in the - * queue waiting to be processed. - * - * @return cnts - */ - public static int[] getJobCount() { - int[] cnt = new int[] { 0, 0 }; - if (instanceMap != null) { - for (List jobList : instanceMap.values()) { - cnt[1] += jobList.get(QUEUE_JOB_INDEX).queue.size(); - for (ProcedureJob job : jobList) { - if (job.request != null) { - ++cnt[0]; - } - } - } - } - return cnt; - } - - /** - * Determine if there are any Procedure Tool Jobs queued and/or being - * processed. - * - * @return true when there are job(s)s queued or being processed otherwise - * false - */ - public static boolean haveJobs() { - boolean result = false; - - if (instanceMap != null) { - for (List jobList : instanceMap.values()) { - // Any pending requests. - if (jobList.get(QUEUE_JOB_INDEX).queue.size() > 0) { - result = true; - break; - } - - // Any requests being processed. - for (ProcedureJob job : jobList) { - if (job.request != null) { - result = true; - break; - } - } - } - } - return result; - } - - /** - * This terminates all the Data Managers' jobs. - */ - public static synchronized void shutdown() { - // TODO This currently joins with a job waiting for it to finish which - // can take a long time and may even be waiting for user to input. Must - // find a wait to kill any GUI associated with a request and if python - // running a way to terminate it so no waiting is involved. - if (instanceMap != null) { - for (List jobList : instanceMap.values()) { - jobList.get(QUEUE_JOB_INDEX).queue.clear(); - - // Do in reverse order so last job cancel is the one with the - // queue. - for (int index = jobList.size() - 1; index >= 0; --index) { - jobList.get(index).cancel(); - } - } - - for (List jobList : instanceMap.values()) { - for (ProcedureJob job : jobList) { - synchronized (job) { - try { - if (job.getState() != Job.NONE) { - job.join(); - } - } catch (InterruptedException ex) { - System.err.println("here SmartToolJob"); - } - } - } - } - - for (List jobList : instanceMap.values()) { - jobList.clear(); - } - - instanceMap.clear(); - instanceMap = null; - } - } - - /** - * Executes a procedure - * - * @param procedureName - * the name of the procedure - * @param refSet - * the edit area to run the procedure against - * @param timeRange - * the time range to run the procedure against - * @param varDict - * the cached varDict for the procedure, or null if there is none - * (should be null unless called from within another procedure) - */ - private void execute(ProcedureController controller, String procedureName, - ReferenceData refSet, TimeRange timeRange, String varDict) { - - Job progressJob = new AsyncProgressJob(procedureName, this); - IStatus pjStatus = Status.CANCEL_STATUS; - try { - List argNames = controller.getMethodArguments( - procedureName, "execute"); - Map argMap = getArgValues(argNames, refSet, - timeRange); - controller.setVarDict(varDict); - progressJob.schedule(); - controller.executeProcedure(procedureName, argMap); - pjStatus = Status.OK_STATUS; - } catch (Exception e) { - pjStatus = new Status(IStatus.WARNING, Activator.PLUGIN_ID, - "Error in procedure " + procedureName, e); - statusHandler.handle(Priority.PROBLEM, "Error executing procedure " - + procedureName, e); - } catch (JepException e) { - pjStatus = new Status(IStatus.WARNING, Activator.PLUGIN_ID, - "Error in procedure " + procedureName, e); - statusHandler.handle(Priority.PROBLEM, "Error executing procedure " - + procedureName, e); - } finally { - controller.garbageCollect(); - progressJob.done(pjStatus); - } - } - - /** - * Maps a procedure's execute's argument name to an object - * - * @param args - * the name of the objects - * @param refSet - * the edit area to run the procedure on - * @param timeRange - * the time range to run the procedure on - * @return a map of argument names to objects - * @throws GFEException - */ - private Map getArgValues(List args, - ReferenceData refSet, TimeRange timeRange) throws GFEException { - Map argValueMap = new HashMap(); - // For each argument in args, append a value to the argValueList - for (String arg : args) { - if (arg.equals("varDict")) { - argValueMap.put("varDict", null); - } else if (arg.equals("editArea")) { - argValueMap.put("editArea", refSet); - } else if (arg.equals("timeRange")) { - argValueMap.put("timeRange", timeRange); - } else if (arg.equals("self")) { - // skip - } else { - throw new GFEException("Unknown argument " + arg); - } - - } - return argValueMap; - } - -} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureJobPool.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureJobPool.java new file mode 100644 index 0000000000..0f6016dc80 --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureJobPool.java @@ -0,0 +1,432 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.procedures; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +import jep.JepException; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; + +import com.raytheon.uf.common.dataplugin.gfe.StatusConstants; +import com.raytheon.uf.common.dataplugin.gfe.reference.ReferenceData; +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.TimeRange; +import com.raytheon.uf.common.time.util.TimeUtil; +import com.raytheon.viz.gfe.Activator; +import com.raytheon.viz.gfe.GFEException; +import com.raytheon.viz.gfe.core.DataManager; +import com.raytheon.viz.gfe.jobs.AsyncProgressJob; + +/** + * Job pool for running GFE procedures. Since JEP/JNI requires that the thread + * that initialized the python interpreter is the same one that runs it, this + * pool initializes an interpreter for procedures and then sleeps until a + * request is enqueued. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Dec 09, 2013  #2367    dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class ProcedureJobPool { + + protected LinkedBlockingQueue workQueue = new LinkedBlockingQueue(); + + protected LinkedBlockingQueue jobQueue = new LinkedBlockingQueue(); + + protected List jobList; + + protected boolean cancel = false; + + protected Object cancelLock = new Object(); + + protected Object joinLock = new Object(); + + private final DataManager dataMgr; + + private final int poolMaxSize; + + /** + * Creates a new ProcedureJobPool with the specified size parameters. + * + * @param corePoolSize + * The minimum size of the job pool--will always have at least + * this many Jobs ready to execute. + * @param poolMaxSize + * The maximum size of the job pool. + * @param dataMgr + * DataManager instance. + */ + public ProcedureJobPool(int corePoolSize, int poolMaxSize, + DataManager dataMgr) { + this.dataMgr = dataMgr; + this.poolMaxSize = poolMaxSize; + for (int i = 0; i < corePoolSize; i++) { + Job job = new ProcedureJob(this.dataMgr); + jobQueue.add(job); + } + this.jobList = new CopyOnWriteArrayList(); + } + + /** + * Enqueue the specified request into the job pool's request queue. Will be + * worked by first available job. If calling from an existing thread in the + * job pool, that thread will be reused to execute the request. + * + * @param request + * ProcedureRequest containing information on procedure to + * execute. + */ + public void schedule(ProcedureRequest request) { + ProcedureJob reuseJob = null; + + // do not schedule while canceling(cancel should be fast). + synchronized (cancelLock) { + if (cancel) { + return; + } + // do not schedule while joining, join might be slow but the javaDoc + // warns others. + synchronized (joinLock) { + boolean jobAvailable = false; + Thread currentThread = Thread.currentThread(); + for (Job job : jobList) { + Thread jobThread = job.getThread(); + ProcedureJob procJob = (ProcedureJob) job; + if (currentThread == jobThread) { + // this occurs when a running procedure uses + // SmartScript.callProcedure() + // for efficiency we want to just stay on this thread + reuseJob = procJob; + jobAvailable = true; + break; + } else if (!procJob.isRunning()) { + jobAvailable = true; + } + } + + if (reuseJob == null) { + if (!jobAvailable) { + Job job = jobQueue.poll(); + if ((job == null) && (jobList.size() < poolMaxSize)) { + job = new ProcedureJob(dataMgr); + } + if (job != null) { + job.schedule(); + jobList.add(job); + } + } + workQueue.offer(request); + } + } + } + + if (reuseJob != null) { + reuseJob.processRequest(request); + } + } + + /** + * Join on the Jobs in the pool. Attempting to schedule other Jobs will + * block until join has returned so be careful when calling + */ + public void join() { + synchronized (joinLock) { + for (Job j : jobList) { + try { + j.join(); + } catch (InterruptedException e) { + // Ignore interupt + } + } + } + } + + /** + * Cancel the job pool, will clear out the workQueue then join on all jobs + * running. Once canceled all future calls to schedule will be ignored. + */ + public void cancel() { + cancel(true); + } + + /** + * Cancel the job pool, will clear out the workQueue and optionally join + * running jobs. Once canceled all future calls to schedule will be ignored. + * + * @param join + * true if you want to join before returning. + */ + public void cancel(boolean join) { + synchronized (cancelLock) { + cancel = true; + workQueue.clear(); + for (Job j : jobList) { + j.cancel(); + } + } + if (join) { + join(); + } + } + + /** + * Cancels the specified request. Returns true if the provided request was + * waiting to be run but now is not. Returns false if the provided request + * is already running or if it was not enqueued to begin with. + * + * @param request + * The request to cancel. + * @return True, if the request was in the queue. False, if it was already + * being worked by the pool or if it was not in the queue. + */ + public boolean cancel(ProcedureRequest request) { + return workQueue.remove(request); + } + + /** + * A job pool is considered active if any of the jobs it contains are + * servicing a request or there is still requests to be worked off in the + * queue. + * + * @return If any jobs are working off a request or there are requests still + * in the work queue. + */ + public boolean isActive() { + if (!workQueue.isEmpty()) { + return true; + } + for (Job job : jobList) { + ProcedureJob procJob = (ProcedureJob) job; + if (procJob.isRunning()) { + return true; + } + } + return false; + } + + /** + * Get the number requests remaining in the queue and the number of jobs in + * the pool currently working off a request. + * + * @return The number requests remaining in the queue and the number of jobs + * in the pool currently working off a request. + */ + public int[] getWorkRemaining() { + int jobsRunning = 0; + for (Job job : jobList) { + ProcedureJob procJob = (ProcedureJob) job; + if (procJob.isRunning()) { + jobsRunning++; + } + } + + return new int[] { jobsRunning, workQueue.size() }; + } + + protected class ProcedureJob extends Job { + + private final IUFStatusHandler statusHandler = UFStatus + .getHandler(ProcedureJob.class); + + private ProcedureController python; + + private final DataManager dataMgr; + + private volatile boolean running; + + public ProcedureJob(DataManager dataMgr) { + super("GFE Procedures Job"); + this.dataMgr = dataMgr; + this.running = false; + setSystem(true); + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + python = ProcedureFactory.buildController(dataMgr); + } catch (JepException e) { + jobList.remove(this); + statusHandler.error("Error initializing procedure python", e); + return new Status(IStatus.ERROR, StatusConstants.PLUGIN_ID, + "Error initializing procedure python", e); + } + + IStatus statusCode = Status.OK_STATUS; + try { + while (!monitor.isCanceled()) { + try { + ProcedureRequest request = null; + try { + request = workQueue.poll( + TimeUtil.MILLIS_PER_SECOND, + TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + statusCode = Status.CANCEL_STATUS; + break; + } + + if (monitor.isCanceled()) { + statusCode = Status.CANCEL_STATUS; + break; + } + + if (request != null) { + running = true; + + python.processFileUpdates(); + if (monitor.isCanceled()) { + statusCode = Status.CANCEL_STATUS; + break; + } + + processRequest(request); + running = false; + } + } catch (Throwable t) { + statusHandler.error( + "Unhandled exception in ProcedureJob.", t); + } + } + } finally { + if (python != null) { + python.dispose(); + python = null; + } + } + + return statusCode; + } + + protected void processRequest(ProcedureRequest request) { + Object retVal = null; + try { + execute(python, request); + retVal = null; + } catch (Throwable t) { + statusHandler + .handle(Priority.PROBLEM, "Error running procedure " + + request.getProcedureName(), t); + retVal = t; + } finally { + dataMgr.getEditActionProcessor().wrapUpExecute( + request.getPreview(), false); + request.requestComplete(retVal); + } + } + + /** + * Executes a procedure + * + * @param procedureName + * the name of the procedure + * @param request + * the request containing data on the procedure to run. + * @throws Exception + * @throws JepException + */ + private void execute(ProcedureController controller, + ProcedureRequest request) throws Exception, JepException { + String procedureName = request.getProcedureName(); + Job progressJob = new AsyncProgressJob(procedureName, this); + IStatus pjStatus = Status.CANCEL_STATUS; + progressJob.schedule(); + + try { + List argNames = controller.getMethodArguments( + procedureName, "execute"); + Map argMap = getArgValues(argNames, + request.getRefSet(), request.getTimeRange()); + controller.setVarDict(request.getVarDict()); + controller.executeProcedure(procedureName, argMap); + pjStatus = Status.OK_STATUS; + } catch (Exception e) { + pjStatus = new Status(IStatus.WARNING, Activator.PLUGIN_ID, + "Error in procedure " + procedureName, e); + throw e; + } catch (JepException e) { + pjStatus = new Status(IStatus.WARNING, Activator.PLUGIN_ID, + "Error in procedure " + procedureName, e); + throw e; + } finally { + controller.garbageCollect(); + progressJob.done(pjStatus); + } + } + + /** + * Maps a procedure's execute's argument name to an object + * + * @param args + * the name of the objects + * @param refSet + * the edit area to run the procedure on + * @param timeRange + * the time range to run the procedure on + * @return a map of argument names to objects + * @throws GFEException + */ + private Map getArgValues(List args, + ReferenceData refSet, TimeRange timeRange) throws GFEException { + Map argValueMap = new HashMap(); + // For each argument in args, append a value to the argValueList + for (String arg : args) { + if (arg.equals("varDict")) { + argValueMap.put("varDict", null); + } else if (arg.equals("editArea")) { + argValueMap.put("editArea", refSet); + } else if (arg.equals("timeRange")) { + argValueMap.put("timeRange", timeRange); + } else if (arg.equals("self")) { + // skip + } else { + throw new GFEException("Unknown argument " + arg); + } + + } + return argValueMap; + } + + public boolean isRunning() { + return running; + } + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureSelectionDlg.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureSelectionDlg.java index b5656882db..415b56bd35 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureSelectionDlg.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureSelectionDlg.java @@ -36,7 +36,8 @@ import com.raytheon.viz.gfe.ui.runtimeui.SelectionDlg; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Feb 9, 2010 njensen Initial creation + * Feb 09, 2010 njensen Initial creation + * Dec 09, 2013 #2367 dgilling Use new ProcedureJobPool. * * * @@ -67,8 +68,7 @@ public class ProcedureSelectionDlg extends SelectionDlg { .transformVarDict(getValues()); req.setVarDict(varDict); req.setPreview(pi); - // ProcedureJob.getInstance(dataMgr).enqueue(req); - ProcedureJob.enqueue(dataMgr, req); + dataMgr.getProcedureJobPool().schedule(req); } } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureUtil.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureUtil.java index 0cbf79a5ae..8ace2dd5cd 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureUtil.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/procedures/ProcedureUtil.java @@ -44,8 +44,9 @@ import com.raytheon.viz.gfe.smarttool.PreviewInfo; * SOFTWARE HISTORY * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Feb 9, 2010 njensen Initial creation - * 4/26/2012 14748 ryu Use edit area and time range from preview info + * Feb 09, 2010 njensen Initial creation + * Apr 26, 2012 14748 ryu Use edit area and time range from preview info + * Dec 09, 2013 #2367 dgilling Use new ProcedureJobPool. * * * @@ -123,7 +124,7 @@ public class ProcedureUtil { }); } - ProcedureJob.enqueue(dm, req); + dm.getProcedureJobPool().schedule(req); return req.getResult(); } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEResource.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEResource.java index 028ced353e..6a204d55fc 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEResource.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/rsc/GFEResource.java @@ -162,6 +162,7 @@ import com.vividsolutions.jts.geom.Envelope; * Nov 08, 2012 1298 rferrel Changes for non-blocking FuzzValueDialog. * Mar 04, 2013 1637 randerso Fix time matching for ISC grids * Aug 27, 2013 2287 randerso Fixed scaling and direction of wind arrows + * Dec 11, 2013 2621 randerso Removed conditional from getParm so it never returns null * * * @@ -341,11 +342,7 @@ public class GFEResource extends * @return Returns the parm associated with the GFE Resource */ public Parm getParm() { - Parm retVal = null; - if (this.getStatus() != ResourceStatus.DISPOSED) { - retVal = this.parm; - } - return retVal; + return this.parm; } /* diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/SmartUtil.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/SmartUtil.java index 3f83503148..16fcc25c37 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/SmartUtil.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/SmartUtil.java @@ -36,14 +36,13 @@ import com.raytheon.viz.gfe.core.DataManager; import com.raytheon.viz.gfe.core.parm.Parm; import com.raytheon.viz.gfe.smartscript.FieldDefinition; import com.raytheon.viz.gfe.smarttool.script.SmartToolBlockingSelectionDlg; -import com.raytheon.viz.gfe.smarttool.script.SmartToolJob; import com.raytheon.viz.gfe.smarttool.script.SmartToolRequest; import com.raytheon.viz.gfe.smarttool.script.SmartToolSelectionDlg; import com.raytheon.viz.gfe.ui.runtimeui.SelectionDlg; /** * Utilities for smart tools - * + * *
  * SOFTWARE HISTORY
  * Date         Ticket#    Engineer    Description
@@ -52,9 +51,10 @@ import com.raytheon.viz.gfe.ui.runtimeui.SelectionDlg;
  * Dec 1,  2009  1426      ryu         Add time range warning
  * Nov 15, 2012 1298       rferrel     Changes for non-blocking prcedures.
  * Jun 25, 2013  16065     ryu         Passing outerLevel to smart tool job.
- *
+ * Dec 10, 2013  #2367     dgilling    Use new SmartToolJobPool.
+ * 
  * 
- * + * * @author njensen * @version 1.0 */ @@ -67,7 +67,7 @@ public class SmartUtil { * Checks if LD_PRELOAD is set in the environment. If not, jep may have * issues importing modules. (Note that this presumes LD_PRELOAD was set * correctly to point at the python .so file). - * + * * @return if LD_PRELOAD is set */ public static boolean isLdPreloadSet() { @@ -118,7 +118,7 @@ public class SmartUtil { if (pi != null) { SmartToolRequest req = buildSmartToolRequest(dm, pi, true); if (req != null) { - SmartToolJob.enqueue(dm, req); + dm.getSmartToolJobPool().schedule(req); } } } @@ -145,8 +145,8 @@ public class SmartUtil { timeRange, editArea, emptyEditAreaFlag, MissingDataMode.valueFrom(missingDataMode)); PreviewInfo pi = new PreviewInfo(editAction, passErrors, parm); - final SmartToolRequest req = SmartUtil. - buildSmartToolRequest(dm, pi, false); + final SmartToolRequest req = SmartUtil.buildSmartToolRequest(dm, pi, + false); if (varDict != null) { req.setVarDict(varDict); @@ -195,7 +195,7 @@ public class SmartUtil { }); } - SmartToolJob.enqueue(dm, req); + dm.getSmartToolJobPool().schedule(req); return req.getResult(); } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolJob.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolJob.java deleted file mode 100644 index 0b58e7d93e..0000000000 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolJob.java +++ /dev/null @@ -1,378 +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.viz.gfe.smarttool.script; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import jep.JepException; - -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; - -import com.raytheon.uf.common.dataplugin.gfe.StatusConstants; -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.jobs.AbstractQueueJob; -import com.raytheon.viz.gfe.Activator; -import com.raytheon.viz.gfe.core.DataManager; -import com.raytheon.viz.gfe.jobs.AsyncProgressJob; -import com.raytheon.viz.gfe.smarttool.EditAction; -import com.raytheon.viz.gfe.smarttool.SmartToolException; -import com.raytheon.viz.gfe.smarttool.Tool; - -/** - * Job for running smart tools off the UI thread - * - *
- *
- * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jan 19, 2010            njensen     Initial creation
- * Jan 18, 2013    1509  njensen  Garbage collect after running tool
- * Apr 03, 2013    1855  njensen   Never dispose interpreters until shutdown
- * Jun 25, 2013   16065    ryu     Clear undo parms list before tool execution
- *
- * 
- * - * @author njensen - * @version 1.0 - */ - -public class SmartToolJob extends AbstractQueueJob { - - /** - * Maximum number of jobs to keep for a given Data Manager. - */ - private final static int maxJobs = 3; - - /** - * Index of job with the queue. Will break code if not zero. - */ - private final static int QUEUE_JOB_INDEX = 0; - - private static final transient IUFStatusHandler statusHandler = UFStatus - .getHandler(SmartToolJob.class); - - private static Map> instanceMap = null; - - private DataManager dataMgr; - - /** - * The request being processed. - */ - private SmartToolRequest request = null; - - protected SmartToolJob(DataManager dataMgr) { - super("GFE Smart Tool Job"); - this.dataMgr = dataMgr; - } - - private void getRequest() throws InterruptedException { - if (instanceMap == null) { - request = null; - return; - } - - List jobList = instanceMap.get(dataMgr); - if (jobList == null || jobList.size() == 0 - || jobList.get(QUEUE_JOB_INDEX).queue == null) { - request = null; - } else { - request = jobList.get(QUEUE_JOB_INDEX).queue.poll(1000L, - TimeUnit.MILLISECONDS); - } - } - - @Override - protected IStatus run(IProgressMonitor monitor) { - SmartToolController python = null; - try { - python = SmartToolFactory.buildController(dataMgr); - } catch (JepException e) { - SmartToolJob.removeJob(dataMgr, this); - return new Status(IStatus.ERROR, StatusConstants.PLUGIN_ID, - "Error initializing smart tool python", e); - } - - try { - // Used req to wrap up request after leaving the synchronized - // region. - SmartToolRequest req = null; - while (monitor.isCanceled() == false) { - try { - getRequest(); - - // May have been canceled while waiting. - if (monitor.isCanceled()) { - break; - } - - synchronized (this) { - if (request != null) { - python.processFileUpdates(); - EditAction ea = request.getPreview() - .getEditAction(); - Job progressJob = new AsyncProgressJob( - ea.getItemName(), this); - progressJob.schedule(); - IStatus pjResult = Status.CANCEL_STATUS; - try { - if (request.getOuterLevel()) { - dataMgr.getParmOp().clearUndoParmList(); - } - Tool tool = new Tool(dataMgr.getParmManager(), - request.getPreview().getParm(), - ea.getItemName(), python); - tool.execute(ea.getItemName(), request - .getPreview().getParm(), - ea.getRefSet(), ea.getTimeRange(), - request.getVarDict(), ea - .getMissingDataMode(), monitor); - request.requestComplete(null); - pjResult = Status.OK_STATUS; - - } catch (SmartToolException e) { - pjResult = new Status(IStatus.WARNING, - Activator.PLUGIN_ID, - "Error in smart tool", e); - throw e; - } finally { - python.garbageCollect(); - progressJob.done(pjResult); - req = request; - request = null; - } - } - } - } catch (InterruptedException e) { - statusHandler.handle(Priority.PROBLEM, - "Smart tool thread interrupted", e); - break; - } catch (SmartToolException e) { - statusHandler.handle(Priority.PROBLEM, - "Error running tool ", e); - if (req != null) { - req.requestComplete(e); - } - } catch (Throwable t) { - statusHandler.handle(Priority.PROBLEM, - "Error running tool ", t); - if (req != null) { - req.requestComplete(t); - } - } finally { - if (req != null && req.getPreview() != null) { - this.dataMgr.getEditActionProcessor().wrapUpExecute( - req.getPreview(), true); - } - req = null; - } - } - } finally { - System.err.println("Shutdown instance of SmartToolJob"); - if (python != null) { - python.dispose(); - python = null; - } - } - - return Status.OK_STATUS; - } - - /** - * Remove a job from the Data Manger's job list. - * - * @param dataMgr - * - The job's data manager - * @param job - * - The job to remove - */ - private static synchronized void removeJob(DataManager dataMgr, - SmartToolJob job) { - if (instanceMap == null) { - return; - } - - List jobList = instanceMap.get(dataMgr); - - if (jobList != null) { - jobList.remove(job); - - // Removing job with queue remove job list so next request will set - // up new queue. - if (job.queue != null) { - jobList.clear(); - instanceMap.remove(dataMgr); - } - } - } - - /** - * This manages the scheduling of jobs to service a Data Manger's requests. - * - * @param dataMgr - * - Data Manger for the request - * @param request - * - The request to service - * @return state - true when job available to process request otherwise - * false and request is queued to wait for next available job - */ - public static synchronized boolean enqueue(DataManager dataMgr, - SmartToolRequest request) { - if (instanceMap == null) { - instanceMap = new HashMap>(); - } - - List jobList = instanceMap.get(dataMgr); - if (jobList == null) { - jobList = new ArrayList(); - // Add the first job which contains the queue used by all jobs in - // the list. - SmartToolJob job = new SmartToolJob(dataMgr); - jobList.add(job); - instanceMap.put(dataMgr, jobList); - job.setSystem(true); - job.schedule(); - } - boolean jobAvailable = false; - for (SmartToolJob job : jobList) { - if (job.request == null) { - jobAvailable = true; - break; - } - } - - // All jobs for data manager are busy, add another if we haven't reached - // the limit - if (!jobAvailable && jobList.size() < maxJobs) { - SmartToolJob job = new SmartToolJob(dataMgr); - job.setSystem(true); - jobList.add(job); - // Never used additional job's queue - job.queue = null; - job.schedule(); - jobAvailable = true; - } - - jobList.get(QUEUE_JOB_INDEX).enqueue(request); - return jobAvailable; - } - - /** - * This returns an array of two integers the first is the number of Smart - * Tool Jobs being processed and the second is the number in the queue - * waiting to be processed. - * - * @return cnts - */ - public static int[] getJobCount() { - int[] cnt = new int[] { 0, 0 }; - if (instanceMap != null) { - for (List jobList : instanceMap.values()) { - cnt[1] += jobList.get(QUEUE_JOB_INDEX).queue.size(); - for (SmartToolJob job : jobList) { - if (job.request != null) { - ++cnt[0]; - } - } - } - } - return cnt; - } - - /** - * Determine if there are any Smart Tool Jobs queued and/or being processed. - * - * @return true when there are job(s)s queued or being processed otherwise - * false - */ - public static boolean haveJobs() { - boolean result = false; - - if (instanceMap != null) { - for (List jobList : instanceMap.values()) { - // Any pending requests. - if (jobList.get(QUEUE_JOB_INDEX).queue.size() > 0) { - result = true; - break; - } - - // Any requests being processed. - for (SmartToolJob job : jobList) { - if (job.request != null) { - result = true; - break; - } - } - } - } - return result; - } - - /** - * This terminates all the Data Managers' jobs. - */ - public static synchronized void shutdown() { - // TODO This currently joins with a job waiting for it to finish which - // can take a long time and may even be waiting for user input. Must - // find a wait to kill any GUI associated with a request and if python - // running a way to terminate it so no waiting is involved. - if (instanceMap != null) { - for (List jobList : instanceMap.values()) { - jobList.get(QUEUE_JOB_INDEX).queue.clear(); - - // Do in reverse order so last job cancel is the one with the - // queue. - for (int index = jobList.size() - 1; index >= 0; --index) { - jobList.get(index).cancel(); - } - } - - for (List jobList : instanceMap.values()) { - for (SmartToolJob job : jobList) { - synchronized (job) { - try { - if (job.getState() != Job.NONE) { - job.join(); - } - } catch (InterruptedException ex) { - // System.err.println("here SmartToolJob"); - } - } - } - } - - for (List jobList : instanceMap.values()) { - jobList.clear(); - } - - instanceMap.clear(); - instanceMap = null; - } - } -} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolJobPool.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolJobPool.java new file mode 100644 index 0000000000..4cbcd3d97c --- /dev/null +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolJobPool.java @@ -0,0 +1,377 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.gfe.smarttool.script; + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +import jep.JepException; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; + +import com.raytheon.uf.common.dataplugin.gfe.StatusConstants; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.time.util.TimeUtil; +import com.raytheon.viz.gfe.Activator; +import com.raytheon.viz.gfe.core.DataManager; +import com.raytheon.viz.gfe.jobs.AsyncProgressJob; +import com.raytheon.viz.gfe.smarttool.EditAction; +import com.raytheon.viz.gfe.smarttool.SmartToolException; +import com.raytheon.viz.gfe.smarttool.Tool; + +/** + * Job pool for running smart tools off the UI thread. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Dec 09, 2013  #2367    dgilling     Initial creation
+ * 
+ * 
+ * + * @author dgilling + * @version 1.0 + */ + +public class SmartToolJobPool { + + protected LinkedBlockingQueue workQueue = new LinkedBlockingQueue(); + + protected LinkedBlockingQueue jobQueue = new LinkedBlockingQueue(); + + protected List jobList; + + protected boolean cancel = false; + + protected Object cancelLock = new Object(); + + protected Object joinLock = new Object(); + + private final DataManager dataMgr; + + private final int poolMaxSize; + + /** + * Creates a new SmartToolJobPool with the specified size parameters. + * + * @param corePoolSize + * The minimum size of the job pool--will always have at least + * this many Jobs ready to execute. + * @param poolMaxSize + * The maximum size of the job pool. + * @param dataMgr + * DataManager instance. + */ + public SmartToolJobPool(int corePoolSize, int poolMaxSize, + DataManager dataMgr) { + this.dataMgr = dataMgr; + this.poolMaxSize = poolMaxSize; + for (int i = 0; i < corePoolSize; i++) { + Job job = new SmartToolJob(this.dataMgr); + jobQueue.add(job); + } + this.jobList = new CopyOnWriteArrayList(); + } + + /** + * Enqueue the specified request into the job pool's request queue. Will be + * worked by first available job. + * + * @param request + * SmartToolRequest containing information on procedure to + * execute. + */ + public void schedule(SmartToolRequest request) { + // do not schedule while canceling(cancel should be fast). + synchronized (cancelLock) { + if (cancel) { + return; + } + // do not schedule while joining, join might be slow but the javaDoc + // warns others. + synchronized (joinLock) { + if (!isJobAvailable()) { + Job job = jobQueue.poll(); + if ((job == null) && (jobList.size() < poolMaxSize)) { + job = new SmartToolJob(dataMgr); + } + if (job != null) { + job.schedule(); + jobList.add(job); + } + } + workQueue.offer(request); + } + } + } + + private boolean isJobAvailable() { + for (Job job : jobList) { + SmartToolJob toolJob = (SmartToolJob) job; + if (!toolJob.isRunning()) { + return true; + } + } + + return false; + } + + /** + * Join on the Jobs in the pool. Attempting to schedule other Jobs will + * block until join has returned so be careful when calling + */ + public void join() { + synchronized (joinLock) { + for (Job j : jobList) { + try { + j.join(); + } catch (InterruptedException e) { + // Ignore interupt + } + } + } + } + + /** + * Cancel the job pool, will clear out the workQueue then join on all jobs + * running. Once canceled all future calls to schedule will be ignored. + */ + public void cancel() { + cancel(true); + } + + /** + * Cancel the job pool, will clear out the workQueue and optionally join + * running jobs. Once canceled all future calls to schedule will be ignored. + * + * @param join + * true if you want to join before returning. + */ + public void cancel(boolean join) { + synchronized (cancelLock) { + cancel = true; + workQueue.clear(); + for (Job j : jobList) { + j.cancel(); + } + } + if (join) { + join(); + } + } + + /** + * Cancels the specified request. Returns true if the provided request was + * waiting to be run but now is not. Returns false if the provided request + * is already running or if it was not enqueued to begin with. + * + * @param request + * The request to cancel. + * @return True, if the request was in the queue. False, if it was already + * being worked by the pool or if it was not in the queue. + */ + public boolean cancel(SmartToolRequest request) { + return workQueue.remove(request); + } + + /** + * A job pool is considered active if any of the jobs it contains are + * servicing a request or there is still requests to be worked off in the + * queue. + * + * @return If any jobs are working off a request or there are requests still + * in the work queue. + */ + public boolean isActive() { + if (!workQueue.isEmpty()) { + return true; + } + for (Job job : jobList) { + SmartToolJob toolJob = (SmartToolJob) job; + if (toolJob.isRunning()) { + return true; + } + } + return false; + } + + /** + * Get the number requests remaining in the queue and the number of jobs in + * the pool currently working off a request. + * + * @return The number requests remaining in the queue and the number of jobs + * in the pool currently working off a request. + */ + public int[] getWorkRemaining() { + int jobsRunning = 0; + for (Job job : jobList) { + SmartToolJob toolJob = (SmartToolJob) job; + if (toolJob.isRunning()) { + jobsRunning++; + } + } + + return new int[] { jobsRunning, workQueue.size() }; + } + + protected class SmartToolJob extends Job { + + private final IUFStatusHandler statusHandler = UFStatus + .getHandler(SmartToolJob.class); + + private SmartToolController python; + + private final DataManager dataMgr; + + private volatile boolean running; + + public SmartToolJob(DataManager dataMgr) { + super("GFE Smart Tool Job"); + this.dataMgr = dataMgr; + this.running = false; + setSystem(true); + } + + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + python = SmartToolFactory.buildController(dataMgr); + } catch (JepException e) { + jobList.remove(this); + statusHandler.error("Error initializing procedure python", e); + return new Status(IStatus.ERROR, StatusConstants.PLUGIN_ID, + "Error initializing procedure python", e); + } + + IStatus statusCode = Status.OK_STATUS; + try { + while (!monitor.isCanceled()) { + try { + SmartToolRequest request = null; + try { + request = workQueue.poll( + TimeUtil.MILLIS_PER_SECOND, + TimeUnit.MILLISECONDS); + } catch (InterruptedException e) { + statusCode = Status.CANCEL_STATUS; + break; + } + + if (monitor.isCanceled()) { + statusCode = Status.CANCEL_STATUS; + break; + } + + if (request != null) { + running = true; + + python.processFileUpdates(); + if (monitor.isCanceled()) { + statusCode = Status.CANCEL_STATUS; + break; + } + + Object retVal = null; + try { + execute(python, request, monitor); + retVal = null; + } catch (Throwable t) { + String toolName = request.getPreview() + .getEditAction().getItemName(); + statusHandler.error("Error running smart tool " + + toolName, t); + retVal = t; + } finally { + if (request.getPreview() != null) { + dataMgr.getEditActionProcessor() + .wrapUpExecute( + request.getPreview(), true); + } + request.requestComplete(retVal); + running = false; + } + } + } catch (Throwable t) { + statusHandler.error( + "Unhandled exception in SmartToolJob.", t); + } + } + } finally { + if (python != null) { + python.dispose(); + python = null; + } + } + + return statusCode; + } + + /** + * Executes a smart tool. + * + * @param controller + * @param request + * @param monitor + * @throws SmartToolException + */ + private void execute(SmartToolController controller, + SmartToolRequest request, IProgressMonitor monitor) + throws SmartToolException { + EditAction ea = request.getPreview().getEditAction(); + String toolName = ea.getItemName(); + + Job progressJob = new AsyncProgressJob(toolName, this); + progressJob.schedule(); + IStatus pjStatus = Status.CANCEL_STATUS; + + try { + if (request.getOuterLevel()) { + dataMgr.getParmOp().clearUndoParmList(); + } + Tool tool = new Tool(dataMgr.getParmManager(), request + .getPreview().getParm(), ea.getItemName(), python); + tool.execute(ea.getItemName(), request.getPreview().getParm(), + ea.getRefSet(), ea.getTimeRange(), + request.getVarDict(), ea.getMissingDataMode(), monitor); + pjStatus = Status.OK_STATUS; + } catch (SmartToolException e) { + pjStatus = new Status(IStatus.WARNING, Activator.PLUGIN_ID, + "Error in smart tool " + toolName, e); + throw e; + } finally { + controller.garbageCollect(); + progressJob.done(pjStatus); + } + } + + public boolean isRunning() { + return running; + } + } +} diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolSelectionDlg.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolSelectionDlg.java index 2646891061..40f88306ec 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolSelectionDlg.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/smarttool/script/SmartToolSelectionDlg.java @@ -31,17 +31,18 @@ import com.raytheon.viz.gfe.ui.runtimeui.SelectionDlg; /** * Dynamic GUI for showing smart tools' Variable Lists and running the tools - * + * *
- *
+ * 
  * SOFTWARE HISTORY
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Feb 9, 2010            njensen     Initial creation
  * Jun 25, 2013  16065    ryu         Passing outerLevel to tool job
- *
+ * Dec 10, 2013  #2367    dgilling    Use new SmartToolJobPool.
+ * 
  * 
- * + * * @author njensen * @version 1.0 */ @@ -55,20 +56,20 @@ public class SmartToolSelectionDlg extends SelectionDlg { /* * (non-Javadoc) - * + * * @see com.raytheon.viz.gfe.ui.runtimeui.SelectionDlg#run() */ @Override public void run() { PreviewInfo pi = SmartUtil.checkAndBuildPreview(dataMgr, name); if (pi != null) { - SmartToolRequest req = SmartUtil. - buildSmartToolRequest(dataMgr, pi, true); + SmartToolRequest req = SmartUtil.buildSmartToolRequest(dataMgr, pi, + true); if (req != null) { String varDict = dataMgr.getSmartToolInterface() .transformVarDict(getValues()); req.setVarDict(varDict); - SmartToolJob.enqueue(dataMgr, req); + dataMgr.getSmartToolJobPool().schedule(req); } } } diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/GeneralGridData.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/GeneralGridData.java index 862861e277..86f3a21327 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/GeneralGridData.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/GeneralGridData.java @@ -54,11 +54,14 @@ import com.vividsolutions.jts.geom.Coordinate; * * SOFTWARE HISTORY * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Mar 9, 2011 bsteffen Initial creation - * Aug 27, 2013 #2287 randerso Removed 180 degree adjustment required by error - * in Maputil.rotation + * Date Ticket# Engineer Description + * ------------- -------- ----------- -------------------------- + * Mar 9, 2011 bsteffen Initial creation + * Aug 27, 2013 2287 randerso Removed 180 degree adjustment required by error + * in Maputil.rotation + * Dec 09, 2013 2617 bsteffen Added 180 degree rotation into reproject + * so wind direction is calculated as + * direction wind is coming from. * * * @@ -249,8 +252,29 @@ public class GeneralGridData { Coordinate ll = new Coordinate(dp.x, dp.y); double rot = MapUtil.rotation(ll, newGeom); double rot2 = MapUtil.rotation(ll, gridGeometry); - double cos = Math.cos(Math.toRadians(rot - rot2)); - double sin = Math.sin(Math.toRadians(rot - rot2)); + /* + * When code calls into this method, the observed state + * of things is that u and v represent the direction + * the vector is going while mag and dir represent + * the direction the vector is coming from. The extra + * 180 here makes everything consistently represent the + * direction the vector is coming from so that when the + * barbs or arrows are rendered the mag and dir are + * calculated as expected. Overall this is a completely + * rediculous way of doing things. During construction + * everything should be forced to represent the vector + * consistently and we should only be keeping either + * u/v or mag/dir to minimize memory consumption. + * Unfortunately that is a significant change which is + * made high risk by the fact no one documents which + * areas are expecting vectors oriented to vs from. So + * for now I(bsteffen) have chosen to simply add in 180 + * so that the behavior will be exactly as it was before + * 2287 because even though it is rediculous it is a well + * tested rediculous(theoretically). + */ + double cos = Math.cos(Math.toRadians(rot - rot2 + 180)); + double sin = Math.sin(Math.toRadians(rot - rot2 + 180)); double u = udata[index]; double v = vdata[index]; udata[index] = (float) (cos * u - sin * v); diff --git a/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/ui/xy/RadarXsectXYResource.java b/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/ui/xy/RadarXsectXYResource.java index b8f096de02..8384c081fc 100644 --- a/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/ui/xy/RadarXsectXYResource.java +++ b/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/ui/xy/RadarXsectXYResource.java @@ -58,6 +58,7 @@ import com.vividsolutions.jts.geom.LineString; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Aug 17, 2010 bsteffen Initial creation + * Dec 11, 2013 DR 16795 D. Friedman Transform pixel coordinate in inspect * * * @@ -213,11 +214,13 @@ public class RadarXsectXYResource extends RadarXYResource implements DrawableImage image = images.get(displayedDate); try { Coordinate c = latLon.asLatLon(); + double[] worldCoord = descriptor.pixelToWorld(new double[] { + c.x, c.y }); IExtent extent = image.getCoverage().getExtent(); // Convert the screen coordinate to a coordinate within the image. // 0,0 is the upper left and 1,1 is the lower right of the iamge. - double xRat = (c.x - extent.getMinX()) / extent.getWidth(); - double yRat = (c.y - extent.getMinY()) / extent.getHeight(); + double xRat = (worldCoord[0] - extent.getMinX()) / extent.getWidth(); + double yRat = (worldCoord[1] - extent.getMinY()) / extent.getHeight(); return super.inspect(new ReferencedCoordinate(new Coordinate(xRat, yRat))); } catch (Exception e) { diff --git a/edexOsgi/build.edex/esb/conf/modes.xml b/edexOsgi/build.edex/esb/conf/modes.xml index 86d13b4bcd..babb2749d6 100644 --- a/edexOsgi/build.edex/esb/conf/modes.xml +++ b/edexOsgi/build.edex/esb/conf/modes.xml @@ -118,6 +118,11 @@ manualIngest-common.xml manualIngest-spring.xml shef-ingest.xml + persist-ingest.xml + obs-common.xml + obs-ingest.xml + metartohmdb-plugin.xml + pointdata-common.xml shef-common.xml ohd-common.xml alarmWhfs-spring.xml @@ -139,6 +144,8 @@ q2FileProcessor-spring.xml satpre-spring.xml purge-logs.xml + fssobs-ingest.xml + fssobs-common.xml ohd-common.xml @@ -147,6 +154,7 @@ alertviz-request.xml auth-common.xml auth-request.xml + persist-request.xml menus-request.xml utility-request.xml management-common.xml diff --git a/edexOsgi/com.raytheon.edex.plugin.bufrua/src/com/raytheon/edex/plugin/bufrua/decoder/BUFRUAManLevelAdapter.java b/edexOsgi/com.raytheon.edex.plugin.bufrua/src/com/raytheon/edex/plugin/bufrua/decoder/BUFRUAManLevelAdapter.java index 395e8060eb..83cb6d0052 100644 --- a/edexOsgi/com.raytheon.edex.plugin.bufrua/src/com/raytheon/edex/plugin/bufrua/decoder/BUFRUAManLevelAdapter.java +++ b/edexOsgi/com.raytheon.edex.plugin.bufrua/src/com/raytheon/edex/plugin/bufrua/decoder/BUFRUAManLevelAdapter.java @@ -21,7 +21,12 @@ package com.raytheon.edex.plugin.bufrua.decoder; import static com.raytheon.uf.edex.decodertools.bufr.packets.DataPacketTypes.RepSubList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; import com.raytheon.uf.common.dataplugin.bufrua.LayerTools; import com.raytheon.uf.common.dataplugin.bufrua.UAObs; @@ -42,6 +47,7 @@ import com.raytheon.uf.edex.pointdata.PointDataPluginDao; * ------------- -------- ----------- -------------------------- * Mar 03, 2008 969 jkorman Initial implementation. * Dec 05, 2013 2612 bsteffen Fix max wind decoding. + * Dec 17, 2013 2639 bsteffen Validate mandatory level heights. * * * @@ -50,6 +56,20 @@ import com.raytheon.uf.edex.pointdata.PointDataPluginDao; */ public class BUFRUAManLevelAdapter extends AbstractBUFRUAAdapter { + /** Mandatory pressure levels */ + private static final float[] VALID_PR = { 100000, 92500, 85000, 70000, + 50000, 40000, 30000, 25000, 20000, 15000, 10000, 5000 }; + + /** Reasonable height levels corresponding to VALID_PR */ + private static final float[] VALID_HT = { 100, 750, 1450, 3000, 5550, 7150, + 9150, 10350, 11800, 13600, 16150, 20000 }; + + /** Map VALID_PR to VALID_HT values. */ + private static final Map VALID_HEIGHT_MAP = generateValidHeights(); + + /** Reasonable range for reasonable heights in VALID_HT */ + private static final float VALID_HEIGHT_RANGE = 1000; + /** * * @param pdd @@ -98,7 +118,7 @@ public class BUFRUAManLevelAdapter extends AbstractBUFRUAAdapter { int maxManLevels = -1; int maxTropLevels = -1; - float sfcPressure = -9999; + float sfcPressure = PDV_FILL_INT; Dimension[] dims = getPointDataDescription().dimensions; for (Dimension d : dims) { @@ -120,21 +140,21 @@ public class BUFRUAManLevelAdapter extends AbstractBUFRUAAdapter { List p = (List) packet .getValue(); int sig = getInt(p.get(1), IDecoderConstants.VAL_MISSING); - double pres = getDouble(p.get(0), -9999); + double pres = getDouble(p.get(0), PDV_FILL_DBL); switch (sig) { case LayerTools.TROP_LEVEL: { // Tropopause level if ((tropIdx < maxTropLevels) && (pres > 0) && (pres != 99900.0)) { setViewData("prTrop", view, p.get(0), tropIdx); - double t = getDouble(p.get(3), -9999); - if (t < -9999) { - t = -9999.0; + double t = getDouble(p.get(3), PDV_FILL_DBL); + if (t < PDV_FILL_DBL) { + t = PDV_FILL_DBL; } view.setFloat("tpTrop", (float) t, tropIdx); - t = getDouble(p.get(4), -9999); - if (t < -9999) { - t = -9999.0; + t = getDouble(p.get(4), PDV_FILL_DBL); + if (t < PDV_FILL_DBL) { + t = PDV_FILL_DBL; } view.setFloat("tdTrop", (float) t, tropIdx); setViewData("wdTrop", view, p.get(5), tropIdx); @@ -144,7 +164,7 @@ public class BUFRUAManLevelAdapter extends AbstractBUFRUAAdapter { break; } case LayerTools.SFC_LEVEL: { - sfcPressure = (float) getDouble(p.get(0), -9999); + sfcPressure = (float) getDouble(p.get(0), PDV_FILL_DBL); // fall through } case LayerTools.MANPRE_LEVEL: { @@ -152,14 +172,14 @@ public class BUFRUAManLevelAdapter extends AbstractBUFRUAAdapter { if ((manIdx < maxManLevels) && (pres > 0)) { setViewData("prMan", view, p.get(0), manIdx); setViewData("htMan", view, p.get(2), manIdx); - double t = getDouble(p.get(3), -9999); - if (t < -9999) { - t = -9999.0; + double t = getDouble(p.get(3), PDV_FILL_DBL); + if (t < PDV_FILL_DBL) { + t = PDV_FILL_DBL; } view.setFloat("tpMan", (float) t, manIdx); - t = getDouble(p.get(4), -9999); - if (t < -9999) { - t = -9999.0; + t = getDouble(p.get(4), PDV_FILL_DBL); + if (t < PDV_FILL_DBL) { + t = PDV_FILL_DBL; } view.setFloat("tdMan", (float) t, manIdx); setViewData("wdMan", view, p.get(5), manIdx); @@ -168,12 +188,13 @@ public class BUFRUAManLevelAdapter extends AbstractBUFRUAAdapter { } break; } - // No default! + // No default! } // switch } // for view.setInt("numMand", manIdx); view.setInt("numTrop", tropIdx); view.setFloat("sfcPressure", sfcPressure); + removeInvalidHeights(view); } return pointData; } @@ -209,7 +230,7 @@ public class BUFRUAManLevelAdapter extends AbstractBUFRUAAdapter { .getValue(); int sig = getInt(p.get(1), IDecoderConstants.VAL_MISSING); if (sig == LayerTools.MAXWND_LEVEL) { - double pres = getDouble(p.get(0), -9999); + double pres = getDouble(p.get(0), PDV_FILL_DBL); if (pres > 0) { setViewData("prMaxW", view, p.get(0), maxWindIdx); setViewData("wdMaxW", view, p.get(2), maxWindIdx); @@ -225,4 +246,77 @@ public class BUFRUAManLevelAdapter extends AbstractBUFRUAAdapter { } return pointData; } + + /** + * Check the heights for each reading, removing invalid readings. Check + * that heights are within the range specified from the mean value and that + * they are between the preceeding and following values. + * + * One reason this is needed is because there is a known error in the + * encoded data when the height for the 250MB level is less than 10000. For + * these cases the encoder is prepending a 1 so a height of 9990 becomes + * 19990. It appears this may be an artifact of the compression used to + * encode the heights. For this case it would be theoretically possible to + * remove the extra 1 and treat the data as valid, but invalidating the + * height is done because it is not clear if this would always be a safe + * fix or if there are other possible errors to detect. + * + * @param view + * {@link PointDataView} which will be modified to have invalid + * mandataory hight data removed. + */ + private void removeInvalidHeights(PointDataView view) { + int numMand = view.getInt("numMand"); + if (numMand < 3) { + return; + } + /* Convert pressure and height data into a map for easy access. */ + Number[] pr = view.getNumberAllLevels("prMan"); + Number[] ht = view.getNumberAllLevels("htMan"); + Map heights = new HashMap(numMand * 2); + for (int i = 0; i < numMand; i += 1) { + heights.put(pr[i].floatValue(), ht[i].floatValue()); + } + /* Check each predefined level. */ + Set invalidPrLevels = new HashSet(); + for (int i = 1; i < VALID_PR.length - 1; i += 1) { + float prLevel = VALID_PR[i]; + float validHt = VALID_HEIGHT_MAP.get(prLevel); + float minHt = validHt - VALID_HEIGHT_RANGE; + float maxHt = validHt + VALID_HEIGHT_RANGE; + Float testHt = heights.get(prLevel); + /* First detect values which don't look reasonable. */ + if (testHt != null && testHt > PDV_FILL_INT + && (minHt > testHt || maxHt < testHt)) { + float prevPr = VALID_PR[i - 1]; + float nextPr = VALID_PR[i + 1]; + Float prevHt = heights.get(prevPr); + Float nextHt = heights.get(nextPr); + /* Next check if its at least ascending. */ + if (prevHt != null && prevHt > PDV_FILL_INT && nextHt != null + && nextHt > PDV_FILL_INT + && (testHt < prevHt || testHt > nextHt)) { + invalidPrLevels.add(prLevel); + } + } + } + + if (invalidPrLevels.isEmpty()) { + return; + } + + for (int i = 0; i < numMand; i += 1) { + if (invalidPrLevels.contains(pr[i].floatValue())) { + view.setFloat("htMan", PDV_FILL_INT, i); + } + } + } + + private static Map generateValidHeights() { + Map validHeights = new HashMap(); + for (int i = 0; i < VALID_HT.length; i += 1) { + validHeights.put(VALID_PR[i], VALID_HT[i]); + } + return Collections.unmodifiableMap(validHeights); + } } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java index 3e9020f91a..feeb19d645 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java @@ -108,7 +108,6 @@ import com.raytheon.uf.edex.database.purge.PurgeLogger; * 10/02/13 #2444 randerso Fix error handling when creating IFPGridDatabases. * DO NOT ATTEMPT TO MERGE THIS CHANGE INTO 14.2 as the GFE * server code has been significantly refactored. - * 12/03/13 #2595 randerso Added check for null update time in commitGrid * * * @@ -595,8 +594,7 @@ public class GridParmManager { // if update time is less than publish time, grid has not // changed since last published, therefore only update // history, do not publish - if ((gdh.getUpdateTime() == null) - || (gdh.getPublishTime() == null) + if ((gdh.getPublishTime() == null) || (gdh.getUpdateTime().getTime() > gdh .getPublishTime().getTime()) // in service backup, times on srcHistory could diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java index a44ad62234..6f47e5e22d 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java @@ -86,6 +86,7 @@ import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.PerformanceStatus; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.time.SimulatedTime; import com.raytheon.uf.common.time.TimeRange; import com.raytheon.uf.common.time.util.ITimer; import com.raytheon.uf.common.time.util.TimeUtil; @@ -119,6 +120,7 @@ import com.vividsolutions.jts.geom.Coordinate; * 03/20/13 #1774 randerso Cleanup code to use proper constructors * 04/08/13 #1949 rjpeter Updated to work with normalized database. * 05/02/13 #1969 randerso Removed updateDbs from parent class + * 12/10/13 #2611 randerso Change saveGridData to set update time when saving grids * * * @author bphillip @@ -964,6 +966,14 @@ public class IFPGridDatabase extends GridDatabase { // track merge with existing records or add to new list for (GFERecord recToSave : recordsToSave) { + // modify update time for non ISC/Official db + if (!this.dbId.getModelName().equals("ISC") + && !this.dbId.getModelName().equals("Official")) { + Date nowTime = SimulatedTime.getSystemTime().getTime(); + for (GridDataHistory history : recToSave.getGridHistory()) { + history.setUpdateTime(nowTime); + } + } TimeRange tr = recToSave.getTimeRange(); GFERecord existing = existingMap.get(tr); if (existing != null) { diff --git a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/metar/MetarPointDataTransform.java b/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/metar/MetarPointDataTransform.java index 8ca48f7421..ee1e76c41e 100644 --- a/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/metar/MetarPointDataTransform.java +++ b/edexOsgi/com.raytheon.edex.plugin.obs/src/com/raytheon/edex/plugin/obs/metar/MetarPointDataTransform.java @@ -60,6 +60,7 @@ import com.raytheon.uf.edex.decodertools.time.TimeTools; * May 09, 2013 1869 bsteffen Modified D2D time series of point data to * work without dataURI. * Aug 30, 2013 2298 rjpeter Make getPluginName abstract + * Dec 16, 2013 DR 16920 D. Friemdan Fix type of tempFromTenths access. * * * @@ -398,7 +399,7 @@ public class MetarPointDataTransform { mr.setTemperature(pdv.getNumber(TEMPERATURE).intValue()); mr.setDewPoint(pdv.getNumber(DEWPOINT).intValue()); - mr.setTempFromTenths(pdv.getNumber(TEMP_FROM_TENTHS).intValue()); + mr.setTempFromTenths(pdv.getNumber(TEMP_FROM_TENTHS).floatValue()); mr.setDewPointFromTenths(pdv.getNumber(DP_FROM_TENTHS).floatValue()); mr.setMinTemp6Hour(pdv.getNumber(MIN_TEMP6_HOUR).floatValue()); diff --git a/edexOsgi/com.raytheon.edex.plugin.text/res/spring/text-common.xml b/edexOsgi/com.raytheon.edex.plugin.text/res/spring/text-common.xml index 0fdf5c4a1c..eb21ea0ed3 100644 --- a/edexOsgi/com.raytheon.edex.plugin.text/res/spring/text-common.xml +++ b/edexOsgi/com.raytheon.edex.plugin.text/res/spring/text-common.xml @@ -56,5 +56,10 @@ - + + + + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.edex.plugin.text/res/spring/text-ingest.xml b/edexOsgi/com.raytheon.edex.plugin.text/res/spring/text-ingest.xml index 945f5599a4..f2c2cdc1bc 100644 --- a/edexOsgi/com.raytheon.edex.plugin.text/res/spring/text-ingest.xml +++ b/edexOsgi/com.raytheon.edex.plugin.text/res/spring/text-ingest.xml @@ -14,11 +14,6 @@ - - - - @@ -52,6 +47,10 @@ + + + + * * @author * @version 1 */ public class TextDao extends DefaultPluginDao { + private static final int fullPurgeInterval; + + static { + String fullPurgeProperty = System.getProperty( + "text.fullVersionPurge.intervalhours", "3"); + Integer val = null; + try { + val = Integer.parseInt(fullPurgeProperty); + if ((val < 0) || (val > 23)) { + + } + } catch (Exception e) { + val = new Integer(3); + } + fullPurgeInterval = val.intValue(); + } public TextDao(String pluginName) throws PluginException { super(pluginName); @@ -71,7 +89,7 @@ public class TextDao extends DefaultPluginDao { // only do full purge every few hours since incremental purge runs every // minute - if (Calendar.getInstance().get(Calendar.HOUR_OF_DAY) % 3 == 0) { + if ((TimeUtil.newGmtCalendar().get(Calendar.HOUR_OF_DAY) % fullPurgeInterval) == 0) { TextDB.purgeStdTextProducts(); } @@ -79,10 +97,9 @@ public class TextDao extends DefaultPluginDao { "text"); } - @SuppressWarnings("unchecked") @Override - public List getRecordsToArchive( - Calendar insertStartTime, Calendar insertEndTime) + public int processArchiveRecords(Calendar insertStartTime, + Calendar insertEndTime, IDatabaseProcessor processor) throws DataAccessLayerException { StdTextProductDao dao = new StdTextProductDao(true); DatabaseQuery dbQuery = new DatabaseQuery(dao.getDaoClass()); @@ -91,8 +108,9 @@ public class TextDao extends DefaultPluginDao { dbQuery.addQueryParam("insertTime", insertEndTime, QueryOperand.LESSTHAN); dbQuery.addOrder("insertTime", true); + dbQuery.addOrder("refTime", true); - return (List) dao.queryByCriteria(dbQuery); + return this.processByCriteria(dbQuery, processor); } @Override diff --git a/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/maintenance/archiver/TextArchiveFileNameFormatter.java b/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/maintenance/archiver/TextArchiveFileNameFormatter.java index b795ffb25e..f9448db854 100644 --- a/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/maintenance/archiver/TextArchiveFileNameFormatter.java +++ b/edexOsgi/com.raytheon.edex.plugin.text/src/com/raytheon/edex/plugin/text/maintenance/archiver/TextArchiveFileNameFormatter.java @@ -19,15 +19,7 @@ **/ package com.raytheon.edex.plugin.text.maintenance.archiver; -import java.util.ArrayList; -import java.util.Calendar; import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; import com.raytheon.uf.common.dataplugin.persist.DefaultPathProvider; import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; @@ -35,7 +27,6 @@ import com.raytheon.uf.common.dataplugin.text.db.StdTextProduct; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.edex.archive.IPluginArchiveFileNameFormatter; -import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.plugin.PluginDao; /** @@ -47,8 +38,9 @@ import com.raytheon.uf.edex.database.plugin.PluginDao; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Apr 20, 2012 dgilling Initial creation - * Nov 05, 2013 2499 rjpeter Moved IPluginArchiveFileNameFormatter. + * Apr 20, 2012 dgilling Initial creation + * Nov 05, 2013 2499 rjpeter Moved IPluginArchiveFileNameFormatter. + * Dec 13, 2013 2555 rjpeter Refactored. * * * @author dgilling @@ -65,60 +57,26 @@ public class TextArchiveFileNameFormatter implements * (non-Javadoc) * * @see - * com.raytheon.uf.edex.maintenance.archive.IPluginArchiveFileNameFormatter - * #getPdosByFile(java.lang.String, - * com.raytheon.uf.edex.database.plugin.PluginDao, java.util.Map, - * java.util.Calendar, java.util.Calendar) + * com.raytheon.uf.edex.archive.IPluginArchiveFileNameFormatter#getFilename + * (java.lang.String, com.raytheon.uf.edex.database.plugin.PluginDao, + * com.raytheon.uf.common.dataplugin.persist.PersistableDataObject) */ - @SuppressWarnings("rawtypes") @Override - public Map> getPdosByFile( - String pluginName, PluginDao dao, - Map> pdoMap, - Calendar startTime, Calendar endTime) - throws DataAccessLayerException { - List pdos = dao.getRecordsToArchive(startTime, - endTime); + public String getFilename(String pluginName, PluginDao dao, + PersistableDataObject pdo) { + String path = null; + if (pdo instanceof StdTextProduct) { + StdTextProduct casted = (StdTextProduct) pdo; - Set newFileEntries = new HashSet(); - if ((pdos != null) && !pdos.isEmpty()) { - if (pdos.get(0) instanceof StdTextProduct) { - for (PersistableDataObject pdo : pdos) { - StdTextProduct casted = (StdTextProduct) pdo; - - // no refTime to use, so we use creation time - Date time = new Date(casted.getRefTime()); - String path = pluginName - + DefaultPathProvider.fileNameFormat.get().format( - time); - - newFileEntries.add(path); - List list = pdoMap.get(path); - if (list == null) { - list = new ArrayList(pdos.size()); - pdoMap.put(path, list); - } - list.add(pdo); - } - } else { - statusHandler.error("Invalid PersistableDataObject class " - + pdos.get(0).getClass() - + "sent to TextArchiveFileNameFormatter to archive"); - } + // no refTime to use, so we use creation time + Date time = new Date(casted.getRefTime()); + path = pluginName + + DefaultPathProvider.fileNameFormat.get().format(time); + } else { + statusHandler.error("Invalid PersistableDataObject class " + + pdo.getClass() + + "sent to TextArchiveFileNameFormatter to archive"); } - - Iterator iter = pdoMap.keySet().iterator(); - Map> pdosToSave = new HashMap>( - pdoMap.size() - newFileEntries.size()); - - while (iter.hasNext()) { - String key = iter.next(); - if (!newFileEntries.contains(key)) { - pdosToSave.put(key, pdoMap.get(key)); - iter.remove(); - } - } - - return pdosToSave; + return path; } } diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java index 3c82b24d5e..0943772df9 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/ArchiveConfigManager.java @@ -31,7 +31,6 @@ import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -88,6 +87,8 @@ import com.raytheon.uf.common.util.FileUtil; * Jul 24, 2013 2221 rferrel Changes for select configuration. * Aug 06, 2013 2224 rferrel Changes to use DataSet. * Aug 28, 2013 2299 rferrel purgeExpiredFromArchive now returns the number of files purged. + * Dec 04, 2013 2603 rferrel Changes to improve archive purging. + * Dec 17, 2013 2603 rjpeter Fix directory purging. * * * @author rferrel @@ -189,23 +190,31 @@ public class ArchiveConfigManager { String fileName = ArchiveConstants.selectFileName(Type.Retention, null); SelectConfig selections = loadSelection(fileName); if ((selections != null) && !selections.isEmpty()) { - try { - for (ArchiveSelect archiveSelect : selections.getArchiveList()) { - ArchiveConfig archiveConfig = archiveMap.get(archiveSelect - .getName()); - for (CategorySelect categorySelect : archiveSelect - .getCategorySelectList()) { - CategoryConfig categoryConfig = archiveConfig - .getCategory(categorySelect.getName()); - categoryConfig.setSelectedDisplayNames(categorySelect - .getSelectList()); - } + for (ArchiveSelect archiveSelect : selections.getArchiveList()) { + String archiveName = archiveSelect.getName(); + ArchiveConfig archiveConfig = archiveMap.get(archiveName); + if (archiveConfig == null) { + statusHandler.handle(Priority.WARN, + "Archive Configuration [" + archiveName + + "] not found. Skipping selections."); + continue; + } + + for (CategorySelect categorySelect : archiveSelect + .getCategorySelectList()) { + String categoryname = categorySelect.getName(); + CategoryConfig categoryConfig = archiveConfig + .getCategory(categoryname); + if (categoryConfig == null) { + statusHandler.handle(Priority.WARN, + "Archive Configuration [" + archiveName + + "] Category [" + categoryname + + "] not found. Skipping selections."); + continue; + } + categoryConfig.setSelectedDisplayNames(categorySelect + .getSelectSet()); } - } catch (NullPointerException ex) { - statusHandler - .handle(Priority.ERROR, - "Retention selection and Archive configuration no longer in sync: ", - ex); } } return archiveMap.values(); @@ -285,7 +294,8 @@ public class ArchiveConfigManager { /** * Purge the Files that fall outside of the time frame constraints for the - * Archive. + * archive. This will always leave the archive's top level directories even + * when they are empty. * * @param archive * @return purgeCount @@ -293,107 +303,244 @@ public class ArchiveConfigManager { public int purgeExpiredFromArchive(ArchiveConfig archive) { String archiveRootDirPath = archive.getRootDir(); File archiveRootDir = new File(archiveRootDirPath); - - String[] topLevelDirs = archiveRootDir.list(); - - List topLevelDirsNotPurged = new ArrayList(); int purgeCount = 0; - if (topLevelDirs != null) { - topLevelDirsNotPurged.addAll(Arrays.asList(topLevelDirs)); - topLevelDirs = null; + if (!archiveRootDir.isDirectory()) { + statusHandler.error(archiveRootDir.getAbsolutePath() + + " not a directory."); + return purgeCount; } + if (statusHandler.isPriorityEnabled(Priority.INFO)) { + statusHandler.info("Purging directory: \"" + + archiveRootDir.getAbsolutePath() + "\"."); + } + + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + String message = String.format( + "Start setup of category date helpers for archive: %s.", + archive.getName()); + statusHandler.debug(message); + } + + Map helperMap = new HashMap(); for (CategoryConfig category : archive.getCategoryList()) { - Calendar purgeTime = calculateExpiration(archive, category); - CategoryFileDateHelper helper = new CategoryFileDateHelper( - category, archive.getRootDir()); - IOFileFilter fileDateFilter = FileFilterUtils.and(FileFilterUtils - .fileFileFilter(), new FileDateFilter(null, purgeTime, - helper)); - - // Remove the directory associated with this category from the not - // purged list since it is being purged. - for (Iterator iter = topLevelDirsNotPurged.iterator(); iter - .hasNext();) { - String dirName = iter.next(); - if (helper.isCategoryDirectory(dirName)) { - iter.remove(); - break; - } - } - for (DisplayData display : getDisplayData(archive.getName(), - category.getName(), true)) { - List displayFiles = getDisplayFiles(display, null, - purgeTime); - for (File file : displayFiles) { - purgeCount += purgeFile(file, fileDateFilter); - } - } + CategoryFileDateHelper helper = new CategoryFileDateHelper(category); + helperMap.put(category, helper); } - // check for other expired in top level directories not covered - // by the categories in the archive. - Calendar defaultPurgeTime = calculateExpiration(archive, null); - IOFileFilter fileDateFilter = FileFilterUtils.and(FileFilterUtils - .fileFileFilter(), new FileDateFilter(null, defaultPurgeTime)); - for (String topDirName : topLevelDirsNotPurged) { - File topLevelDir = new File(archiveRootDir, topDirName); + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + String message = String.format( + "End setup of category date helpers for archive: %s.", + archive.getName()); + statusHandler.debug(message); + } - // Keep both top level hidden files and hidden directories. - if (!topLevelDir.isHidden()) { - purgeCount += purgeFile(topLevelDir, fileDateFilter); + final Calendar minPurgeTime = calculateExpiration(archive, null); + + IOFileFilter defaultTimeFilter = new IOFileFilter() { + + @Override + public boolean accept(File dir, String name) { + File file = new File(dir, name); + return accept(file); + } + + @Override + public boolean accept(File file) { + Calendar time = TimeUtil.newGmtCalendar(); + time.setTimeInMillis(file.lastModified()); + return time.compareTo(minPurgeTime) < 0; + } + }; + + File[] topLevelFiles = archiveRootDir.listFiles(); + for (File topFile : topLevelFiles) { + // In top level directory ignore all hidden files and directories. + if (!topFile.isHidden()) { + if (topFile.isDirectory()) { + boolean isInCategory = false; + for (CategoryConfig category : archive.getCategoryList()) { + CategoryFileDateHelper helper = helperMap.get(category); + + if (helper.isCategoryDirectory(topFile.getName())) { + isInCategory = true; + if (statusHandler.isPriorityEnabled(Priority.INFO)) { + String message = String + .format("Start purge of category %s - %s, directory \"%s\".", + archive.getName(), + category.getName(), + topFile.getAbsolutePath()); + statusHandler.info(message); + } + + final Calendar extPurgeTime = calculateExpiration( + archive, category); + int pc = purgeDir(topFile, defaultTimeFilter, + minPurgeTime, extPurgeTime, helper, + category); + purgeCount += pc; + if (statusHandler.isPriorityEnabled(Priority.INFO)) { + String message = String + .format("End purge of category %s - %s, directory \"%s\", deleted %d files and directories.", + archive.getName(), + category.getName(), + topFile.getAbsolutePath(), pc); + statusHandler.info(message); + } + break; + } + } + if (isInCategory == false) { + if (statusHandler.isPriorityEnabled(Priority.INFO)) { + String message = String.format( + "Start purge of directory: \"%s\".", + topFile.getAbsolutePath()); + statusHandler.info(message); + } + int pc = purgeDir(topFile, defaultTimeFilter); + purgeCount += pc; + if (statusHandler.isPriorityEnabled(Priority.INFO)) { + String message = String + .format("End purge of directory: \"%s\", deleted %d files and directories.", + topFile.getAbsolutePath(), pc); + statusHandler.info(message); + } + } + } else { + if (defaultTimeFilter.accept(topFile)) { + purgeCount += deleteFile(topFile); + } + } } } return purgeCount; } /** - * Recursive method for purging files. Never pass in a directory you do not - * want deleted when purging makes it an empty directory. + * Purge the contents of a directory of expired data leaving a possibly + * empty directory. * - * @param fileToPurge - * @param filter - * @return purgeCount number of files and directories purged + * @param dir + * @param defaultTimeFilter + * @param minPurgeTime + * @param extPurgeTime + * @param helper + * @return purgerCount */ - private int purgeFile(File fileToPurge, IOFileFilter filter) { + private int purgeDir(File dir, IOFileFilter defaultTimeFilter, + Calendar minPurgeTime, Calendar extPurgeTime, + CategoryFileDateHelper helper, CategoryConfig category) { int purgeCount = 0; - if (fileToPurge.isFile() && filter.accept(fileToPurge)) { - if (fileToPurge.delete()) { - ++purgeCount; - if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { - statusHandler.debug("Purged file: \"" - + fileToPurge.getAbsolutePath() + "\""); - } - } else { - statusHandler.warn("Failed to purge file: " - + fileToPurge.getAbsolutePath()); - } - } else if (fileToPurge.isDirectory() && !fileToPurge.isHidden()) { - // Purge only visible directories. - File[] expiredFilesInDir = fileToPurge.listFiles(); - - for (File dirFile : expiredFilesInDir) { - purgeCount += purgeFile(dirFile, filter); - } - - // Attempt to delete empty directory. - if ((purgeCount >= expiredFilesInDir.length) - && (fileToPurge.list().length == 0)) { - if (!fileToPurge.delete()) { - statusHandler.warn("Failed to purge directory: " - + fileToPurge.getAbsolutePath()); - } else { - ++purgeCount; - if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { - statusHandler.debug("Purged directory: \"" - + fileToPurge.getAbsolutePath() - + File.separator + "\""); + for (File file : dir.listFiles()) { + if (!file.isHidden()) { + DataSetStatus status = helper.getFileDate(file); + if (status.isInDataSet()) { + Collection labels = category + .getSelectedDisplayNames(); + boolean isSelected = false; + for (String label : status.getDisplayLabels()) { + if (labels.contains(label)) { + isSelected = true; + break; + } } + + Calendar checkTime = (isSelected ? extPurgeTime + : minPurgeTime); + Calendar fileTime = status.getTime(); + boolean purge = fileTime.compareTo(checkTime) < 0; + + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + String message = String + .format("%s [%s] category [%s] %s retention [%s] checkTime [%s] = %s.", + (file.isDirectory() ? "Directory" + : "File"), file + .getAbsoluteFile(), category + .getName(), (isSelected ? "ext" + : "min"), TimeUtil + .formatCalendar(checkTime), + TimeUtil.formatCalendar(fileTime), + (purge ? "purge" : "retain")); + statusHandler.debug(message); + } + + if (purge) { + if (file.isDirectory()) { + purgeCount += purgeDir(file, + FileFilterUtils.trueFileFilter()); + if (file.list().length == 0) { + purgeCount += purgeDir(file, + FileFilterUtils.trueFileFilter()); + } + } else { + purgeCount += deleteFile(file); + } + } + } else if (file.isDirectory()) { + purgeCount += purgeDir(file, defaultTimeFilter, + minPurgeTime, extPurgeTime, helper, category); + if (file.list().length == 0) { + purgeCount += deleteFile(file); + } + } else if (defaultTimeFilter.accept(file)) { + purgeCount += deleteFile(file); } } } + + return purgeCount; + } + + /** + * Recursively purge the contents of a directory based on the filter. The + * directory in the initial call is not deleted. This may result in an empty + * directory which is the desired result for top level directories. + * + * + * @param dir + * @param fileDataFilter + * @return purgeCount + */ + private int purgeDir(File dir, IOFileFilter fileDataFilter) { + int purgeCount = 0; + for (File file : dir.listFiles()) { + if (!file.isHidden()) { + if (file.isDirectory()) { + purgeCount += purgeDir(file, fileDataFilter); + if (file.list().length == 0) { + purgeCount += deleteFile(file); + } + } else if (fileDataFilter.accept(file)) { + purgeCount += deleteFile(file); + } + } + } + return purgeCount; + } + + /** + * Delete a file or directory. + * + * @param file + * @return purgeCount + */ + private int deleteFile(File file) { + int purgeCount = 0; + boolean isDir = file.isDirectory(); + if (file.delete()) { + ++purgeCount; + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler + .debug(String.format("Purged %s: \"%s\"", + (isDir ? "directory" : "file"), + file.getAbsolutePath())); + } + } else { + statusHandler.warn(String.format("Failed to purge %s: \"%s\"", + (isDir ? "directory" : "file"), file.getAbsolutePath())); + } return purgeCount; } @@ -644,39 +791,60 @@ public class ArchiveConfigManager { * @param categoryConfig * @return dirs */ - private List getDirs(File rootFile, CategoryDataSet dataSet) { - List resultDirs = new ArrayList(); + private Map> getDirs(File rootFile, + CategoryConfig categoryConfig) { + List resultDirs = null; List dirs = new ArrayList(); List tmpDirs = new ArrayList(); List swpDirs = null; + List dataSets = categoryConfig.getDataSetList(); + Map> rval = new HashMap>( + dataSets.size(), 1); - for (String dirPattern : dataSet.getDirPatterns()) { - String[] subExpr = dirPattern.split(File.separator); - dirs.clear(); - dirs.add(rootFile); - tmpDirs.clear(); + // keep an in memory map since some of the categories cause the same + // directories to be listed over and over + Map> polledDirs = new HashMap>(); - for (String regex : subExpr) { - Pattern subPattern = Pattern.compile("^" + regex + "$"); - IOFileFilter filter = FileFilterUtils - .makeDirectoryOnly(new RegexFileFilter(subPattern)); + for (CategoryDataSet dataSet : dataSets) { + resultDirs = new LinkedList(); - for (File dir : dirs) { - File[] list = dir.listFiles(); - if (list != null) { - List dirList = Arrays.asList(list); - tmpDirs.addAll(Arrays.asList(FileFilterUtils.filter( - filter, dirList))); - } - } - swpDirs = dirs; - dirs = tmpDirs; - tmpDirs = swpDirs; + for (String dirPattern : dataSet.getDirPatterns()) { + String[] subExpr = dirPattern.split(File.separator); + dirs.clear(); + dirs.add(rootFile); tmpDirs.clear(); + + for (String regex : subExpr) { + Pattern subPattern = Pattern.compile("^" + regex + "$"); + IOFileFilter filter = FileFilterUtils + .makeDirectoryOnly(new RegexFileFilter(subPattern)); + + for (File dir : dirs) { + List dirList = polledDirs.get(dir); + if (dirList == null) { + File[] list = dir.listFiles(); + dirList = Arrays.asList(list); + polledDirs.put(dir, dirList); + } + + if (dirList != null) { + tmpDirs.addAll(FileFilterUtils.filterList(filter, + dirList)); + } + } + + swpDirs = dirs; + dirs = tmpDirs; + tmpDirs = swpDirs; + tmpDirs.clear(); + } + + resultDirs.addAll(dirs); } - resultDirs.addAll(dirs); + rval.put(dataSet, resultDirs); } - return resultDirs; + + return rval; } /** @@ -701,10 +869,11 @@ public class ArchiveConfigManager { categoryName); File rootFile = new File(rootDirName); TreeMap displays = new TreeMap(); + Map> dirMap = getDirs(rootFile, + categoryConfig); for (CategoryDataSet dataSet : categoryConfig.getDataSetList()) { List dataSetDirPatterns = dataSet.getDirPatterns(); - - List dirs = getDirs(rootFile, dataSet); + List dirs = dirMap.get(dataSet); int beginIndex = rootFile.getAbsolutePath().length() + 1; List patterns = new ArrayList( diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryDataSet.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryDataSet.java index a68e9f887f..a36177d1f4 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryDataSet.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryDataSet.java @@ -43,7 +43,8 @@ import com.raytheon.uf.common.time.util.TimeUtil; * ------------ ---------- ----------- -------------------------- * Aug 6, 2013 #2224 rferrel Initial creation * Oct 02, 2013 #2147 rferrel Allow Date to ignore hour in time stamp. - * + * Dec 10, 2013 #2624 rferrel Added Julian date. + * Dec 17, 2013 2603 rjpeter Clear low order time fields on time generation. * * * @author rferrel @@ -52,22 +53,26 @@ import com.raytheon.uf.common.time.util.TimeUtil; @XmlAccessorType(XmlAccessType.NONE) @XmlRootElement(name = "dataSet") public class CategoryDataSet { - public static final int YEAR_INDEX = 0; + private static final int YEAR_INDEX = 0; - public static final int MONTH_INDEX = 1; + private static final int MONTH_INDEX = 1; - public static final int DAY_INDEX = 2; + private static final int DAY_OF_YEAR_INDEX = 1; - public static final int HOUR_INDEX = 3; + private static final int DAY_INDEX = 2; - public static final int TIMESTAMP_INDEX = 0; + private static final int JULIAN_HOUR_INDEX = 2; + + private static final int HOUR_INDEX = 3; + + private static final int TIMESTAMP_INDEX = 0; /** * Types of times and the number of indices for getting the time stamp from * patterns. */ public static enum TimeType { - Date(4), EpochSec(1), EpochMS(1), File(0); + Date(4), EpochSec(1), EpochMS(1), File(0), Julian(3); private final int numIndices; @@ -199,7 +204,8 @@ public class CategoryDataSet { * @return true when only the dirPatterns should be used. */ public boolean isDirOnly() { - return filePattern == null || filePattern.equals(".*"); + return (filePattern == null) || (filePattern.length() == 0) + || ".*".equals(filePattern); } /** @@ -249,6 +255,7 @@ public class CategoryDataSet { } fileCal.set(year, month, day, hour, 0, 0); + fileCal.set(Calendar.MILLISECOND, 0); fileTime = fileCal.getTimeInMillis(); break; case EpochMS: @@ -263,6 +270,42 @@ public class CategoryDataSet { case File: fileTime = null; break; + case Julian: + Calendar julainCal = TimeUtil.newGmtCalendar(); + int jYear = Integer.parseInt(matcher + .group(timeIndices[CategoryDataSet.YEAR_INDEX])); + int jDay = Integer.parseInt(matcher + .group(timeIndices[CategoryDataSet.DAY_OF_YEAR_INDEX])); + + // When two digit year determine century. + if (jYear < 100) { + int cYear = julainCal.get(Calendar.YEAR); + jYear += (cYear - (cYear % 100)); + julainCal.add(Calendar.YEAR, 1); + int nextYear = julainCal.get(Calendar.YEAR); + + // If date too far into the future back up a century. + if ((jYear > nextYear) || ((jYear == nextYear) && (jDay > 31))) { + jYear -= 100; + } + } + + julainCal.set(Calendar.YEAR, jYear); + julainCal.set(Calendar.DAY_OF_YEAR, jDay); + + // Default to last hour of the day. + int jHour = 23; + if (timeIndices[CategoryDataSet.JULIAN_HOUR_INDEX] >= 0) { + jHour = Integer.parseInt(matcher + .group(timeIndices[CategoryDataSet.JULIAN_HOUR_INDEX])); + } + julainCal.set(Calendar.HOUR_OF_DAY, jHour); + julainCal.set(Calendar.MINUTE, 0); + julainCal.set(Calendar.SECOND, 0); + julainCal.set(Calendar.MILLISECOND, 0); + fileTime = julainCal.getTimeInMillis(); + break; + default: fileTime = null; break; diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryFileDateHelper.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryFileDateHelper.java index 6f87b7e73d..441eb00c7d 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryFileDateHelper.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/CategoryFileDateHelper.java @@ -20,14 +20,14 @@ package com.raytheon.uf.common.archive.config; import java.io.File; +import java.text.FieldPosition; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.commons.io.FilenameUtils; - import com.raytheon.uf.common.time.util.TimeUtil; /** @@ -42,7 +42,8 @@ import com.raytheon.uf.common.time.util.TimeUtil; * Jun 21, 2013 1965 bgonzale Initial creation * Aug 03, 2013 2224 rferrel Changes for new configuration files. * Aug 28, 2013 2299 rferrel Changes in IFileDateHelper. - * + * Dec 04, 2013 2603 rferrel Changes to improve archive purging. + * Dec 17, 2013 2603 rjpeter Fix file data pattern matching. * * * @author bgonzale @@ -54,16 +55,27 @@ public class CategoryFileDateHelper implements IFileDateHelper { * Date information derived from each of a Category's dirPatterns. */ private static class CategoryDateInfo { + /** Always use the same field postion. */ + private static final FieldPosition pos0 = new FieldPosition(0); + + /** Pattern used to get the date. */ private final Pattern datePattern; + /** Pattern for getting top level directories. */ private final Pattern categoryTopLevelDirPattern; + /** The type of type stamp being used. */ private final CategoryDataSet.TimeType timeType; - private final boolean isDirOnly; - + /** Indices in the pattern group used to get the time stamp. */ private final int[] timeIndices; + /** The format used to get the display label. */ + private final String displayLabelFormat; + + /** Formatter used to get display label. */ + private final MessageFormat msgfmt; + /** * Initialization constructor. * @@ -73,24 +85,46 @@ public class CategoryFileDateHelper implements IFileDateHelper { * @param monthIndex * @param dayIndex * @param hourIndex + * @param displayLabelFormat */ public CategoryDateInfo(Pattern datePattern, Pattern categoryTopLevelDirPattern, - CategoryDataSet.TimeType timeType, boolean isDirOnly, - int[] timeIndices) { + CategoryDataSet.TimeType timeType, int[] timeIndices, + String displayLabelFormat) { this.datePattern = datePattern; this.categoryTopLevelDirPattern = categoryTopLevelDirPattern; this.timeType = timeType; - this.isDirOnly = isDirOnly; this.timeIndices = timeIndices; + this.displayLabelFormat = displayLabelFormat; + if (displayLabelFormat != null) { + this.msgfmt = new MessageFormat(this.displayLabelFormat); + } else { + this.msgfmt = null; + } } + /** + * Get the display label from the matcher. This assumes the matcher is a + * pattern match for the date pattern. + * + * @param matcher + * @return label + */ + public String getDisplayLabel(Matcher matcher) { + // Unable to use StringBuilder with MessageFormat. + StringBuffer sb = new StringBuffer(); + String[] args = new String[matcher.groupCount() + 1]; + args[0] = matcher.group(); + for (int i = 1; i < args.length; ++i) { + args[i] = matcher.group(i); + } + String label = msgfmt.format(args, sb, pos0).toString(); + return label; + } } private final List dateInfoList; - private final String rootDir; - /** * Initialization constructor. * @@ -98,8 +132,7 @@ public class CategoryFileDateHelper implements IFileDateHelper { * @param rootDirPattern * categoryTopLevelDirPattern */ - public CategoryFileDateHelper(CategoryConfig config, String rootDir) { - this.rootDir = rootDir; + public CategoryFileDateHelper(CategoryConfig config) { List categoryDataSetList = config.getDataSetList(); int size = 0; for (CategoryDataSet dataSet : categoryDataSetList) { @@ -109,26 +142,26 @@ public class CategoryFileDateHelper implements IFileDateHelper { this.dateInfoList = new ArrayList( size); - boolean isDirOnly; CategoryDataSet.TimeType timeType; for (CategoryDataSet dataSet : categoryDataSetList) { - isDirOnly = dataSet.isDirOnly(); timeType = dataSet.getTimeType(); for (String patternString : dataSet.getDirPatterns()) { Pattern datePattern = dataSet.getPattern(patternString); int dirSeparatorIndex = patternString .indexOf(File.separatorChar); - patternString = dirSeparatorIndex > patternString.length() - || dirSeparatorIndex < 0 ? patternString + patternString = (dirSeparatorIndex > patternString.length()) + || (dirSeparatorIndex < 0) ? patternString : patternString.substring(0, dirSeparatorIndex); Pattern categoryTopLevelDirPattern = Pattern .compile(patternString); int[] timeIndices = dataSet.getTimeIndices(); + String displayLabelFormat = dataSet.getDisplayLabel(); + dateInfoList.add(new CategoryDateInfo(datePattern, - categoryTopLevelDirPattern, timeType, isDirOnly, - timeIndices)); + categoryTopLevelDirPattern, timeType, timeIndices, + displayLabelFormat)); } } } @@ -141,26 +174,19 @@ public class CategoryFileDateHelper implements IFileDateHelper { * .io.File) */ @Override - public Calendar getFileDate(File file) { + public DataSetStatus getFileDate(File file) { String filenamePath = file.getAbsolutePath(); - String pathForFilePatternCheck = filenamePath.substring(rootDir - .length()); - String pathForDirPatternCheck = FilenameUtils - .getFullPathNoEndSeparator(pathForFilePatternCheck); - Calendar result = null; Long timestamp = null; + DataSetStatus result = new DataSetStatus(file); for (CategoryDateInfo dateInfo : dateInfoList) { - Matcher matcher = null; - if (dateInfo.isDirOnly) { - matcher = dateInfo.datePattern.matcher(pathForDirPatternCheck); - } else { - matcher = dateInfo.datePattern.matcher(pathForFilePatternCheck); - } + Matcher matcher = dateInfo.datePattern.matcher(filenamePath); if (matcher.matches()) { timestamp = CategoryDataSet.getMatchTimeInMilliseconds( dateInfo.timeType, dateInfo.timeIndices, matcher); + result.setInDataSet(true); + result.addDisplayLabel(dateInfo.getDisplayLabel(matcher)); break; } } @@ -170,11 +196,9 @@ public class CategoryFileDateHelper implements IFileDateHelper { timestamp = file.lastModified(); } - // TODO future speed improvement refactor IFileDateHelper to have a - // method that returns a long instead of Calendar. That will prevent - // converting Calendar to long then back to a Calendar. - result = TimeUtil.newGmtCalendar(); - result.setTimeInMillis(timestamp); + Calendar time = TimeUtil.newGmtCalendar(); + time.setTimeInMillis(timestamp); + result.setTime(time); return result; } diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/DataSetStatus.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/DataSetStatus.java new file mode 100644 index 0000000000..622e354ff6 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/DataSetStatus.java @@ -0,0 +1,128 @@ +/** + * 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.archive.config; + +import java.io.File; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +/** + * This class used by IFileDateHelper to contains additional information about a + * file. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Dec 4, 2013  2603      rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +public class DataSetStatus { + + /** The file the status is for. */ + private final File file; + + /** Set to true when file is contains in a data set. */ + private boolean inDataSet = false; + + private final List displayLabels = new ArrayList(1); + + /** The file's time based on IFileDataHelper. */ + private Calendar time = null; + + /** + * The constructor with default values set. + * + * @param file + * should not be null. + */ + DataSetStatus(File file) { + this.file = file; + } + + /** + * The file the information is for. + * + * @return file + */ + public File getFile() { + return file; + } + + /** + * + * @return true when file is in a data set. + */ + public boolean isInDataSet() { + return inDataSet; + } + + /** + * Set data set status. + * + * @param inDataSet + */ + public void setInDataSet(boolean inDataSet) { + this.inDataSet = inDataSet; + } + + /** + * + * @return non-null only when file is in a data set. + */ + public List getDisplayLabels() { + return displayLabels; + } + + /** + * Set the select status. Should only be true when in a data set. + * + * @param isSelected + */ + public void addDisplayLabel(String displayLabel) { + this.displayLabels.add(displayLabel); + } + + /** + * The file's time + * + * @return time + */ + public Calendar getTime() { + return time; + } + + /** + * Set the file's time. + * + * @param time + */ + public void setTime(Calendar time) { + this.time = time; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/FileDateFilter.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/FileDateFilter.java deleted file mode 100644 index d349faf652..0000000000 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/FileDateFilter.java +++ /dev/null @@ -1,127 +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.archive.config; - -import java.io.File; -import java.util.Calendar; - -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.io.filefilter.IOFileFilter; - -import com.raytheon.uf.common.time.util.TimeUtil; - -/** - * Filter files based on a file date parsed using the given file date helper. - * Accept returns true for files that fall between the Start and End times. If - * start is null, then all after start checks will return true. If end is null, - * then all before end checks will return true. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jun 18, 2013 1965       bgonzale    Initial creation
- * Aug 28, 2013 2299       rferrel     Reject hidden directories.
- * 
- * 
- * - * @author bgonzale - * @version 1.0 - */ - -public class FileDateFilter implements IOFileFilter { - - private IFileDateHelper helper; - - private final Calendar start; - - private final Calendar end; - - /** - * Initialization constructor. This filter uses file last modified time as - * the filter time. - * - * @param startDate - * @param endDate - */ - public FileDateFilter(Calendar start, Calendar end) { - this(start, end, DEFAULT_FILE_DATE_HELPER); - } - - /** - * Initialization constructor. - * - * @param startDate - * @param endDate - * @param helper - */ - public FileDateFilter(Calendar start, Calendar end, IFileDateHelper helper) { - this.helper = helper == null ? DEFAULT_FILE_DATE_HELPER : helper; - this.start = start; - this.end = end; - } - - /* - * (non-Javadoc) - * - * @see org.apache.commons.io.filefilter.IOFileFilter#accept(java.io.File) - */ - @Override - public boolean accept(File file) { - String filePath = file.getAbsolutePath(); - String dirName = FilenameUtils.getFullPath(filePath); - String fileName = FilenameUtils.getName(filePath); - return accept(new File(dirName), fileName); - } - - /* - * (non-Javadoc) - * - * @see org.apache.commons.io.filefilter.IOFileFilter#accept(java.io.File, - * java.lang.String) - */ - @Override - public boolean accept(File dir, String name) { - File file = new File(dir, name); - Calendar fileDate = helper.getFileDate(file); - boolean isAfterEqualsStart = start == null || fileDate.after(start) - || fileDate.equals(start); - boolean isBeforeEqualsEnd = end == null || fileDate.before(end) - || fileDate.equals(end); - return isAfterEqualsStart && isBeforeEqualsEnd; - } - - /** - * This File Date helper returns a file's last modified time. - */ - private static final IFileDateHelper DEFAULT_FILE_DATE_HELPER = new IFileDateHelper() { - @Override - public Calendar getFileDate(File file) { - // use file last modified date - long lastModifiedMillis = file.lastModified(); - Calendar result = TimeUtil.newGmtCalendar(); - result.setTimeInMillis(lastModifiedMillis); - return result; - } - }; - -} diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/IFileDateHelper.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/IFileDateHelper.java index 368e6fe6d4..553da5d085 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/IFileDateHelper.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/IFileDateHelper.java @@ -20,7 +20,6 @@ package com.raytheon.uf.common.archive.config; import java.io.File; -import java.util.Calendar; /** * Helper to get a file last modification date. @@ -33,7 +32,8 @@ import java.util.Calendar; * ------------ ---------- ----------- -------------------------- * Jun 21, 2013 bgonzale Initial creation * Aug 28, 2013 2299 rferrel Change getFileDate argument. - * + * Dec 04, 2013 2603 rferrel Changes to improve archive purging. + * Dec 17, 2013 2603 rjpeter Clean up imports. * * * @author bgonzale @@ -48,6 +48,6 @@ public interface IFileDateHelper { * @param file * @return calendar */ - public Calendar getFileDate(File file); + public DataSetStatus getFileDate(File file); } diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/SelectConfig.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/SelectConfig.java index babc5a51ae..0de3e8b925 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/SelectConfig.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/SelectConfig.java @@ -20,7 +20,9 @@ package com.raytheon.uf.common.archive.config; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @@ -40,6 +42,7 @@ import com.raytheon.uf.common.archive.config.select.CategorySelect; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jul 19, 2013 2221 rferrel Initial creation + * Dec 11, 2013 2603 rferrel Make selections a set. * * * @@ -113,24 +116,24 @@ public class SelectConfig { } /** - * Get a list of selected display names for the archive and its category. + * Get a set of selected display names for the archive and its category. * * @param archiveName * @param categoryName * @return displayLabelList may be an empty list. */ - public List getSelectedList(String archiveName, String categoryName) { + public Set getSelectedSet(String archiveName, String categoryName) { ArchiveSelect archiveSelect = getArchive(archiveName); if (archiveSelect == null || archiveSelect.isEmpty()) { - return new ArrayList(0); + return new HashSet(0); } CategorySelect categorySelect = getCategorySelect(categoryName, archiveSelect); if (categorySelect == null || categorySelect.isEmpty()) { - return new ArrayList(0); + return new HashSet(0); } - List selected = categorySelect.getSelectList(); + Set selected = categorySelect.getSelectSet(); return selected; } diff --git a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/select/CategorySelect.java b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/select/CategorySelect.java index 5d4d2c5ec0..3e0f7103d7 100644 --- a/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/select/CategorySelect.java +++ b/edexOsgi/com.raytheon.uf.common.archive/src/com/raytheon/uf/common/archive/config/select/CategorySelect.java @@ -20,7 +20,9 @@ package com.raytheon.uf.common.archive.config.select; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @@ -38,6 +40,7 @@ import javax.xml.bind.annotation.XmlRootElement; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jul 19, 2013 2221 rferrel Initial creation + * Dec 11, 2013 2603 rferrel Selected now a Set. * * * @@ -57,7 +60,7 @@ public class CategorySelect { * List of selected labels. */ @XmlElement(name = "selectedDisplayName") - private final List selectList = new ArrayList(); + private final Set selectSet = new HashSet(); public String getName() { return name; @@ -67,21 +70,21 @@ public class CategorySelect { this.name = name; } - public List getSelectList() { - return selectList; + public Set getSelectSet() { + return selectSet; } - public void setSelectList(List selectList) { - this.selectList.clear(); - this.selectList.addAll(selectList); + public void setSelectSet(Set selectList) { + this.selectSet.clear(); + this.selectSet.addAll(selectList); } public void add(String displayName) { - selectList.add(displayName); + selectSet.add(displayName); } public boolean isEmpty() { - return selectList.isEmpty(); + return selectSet.isEmpty(); } @Override @@ -89,7 +92,7 @@ public class CategorySelect { StringBuilder sb = new StringBuilder(); sb.append("CategorySelect [ name: ").append(getName()); sb.append("[ "); - for (String select : getSelectList()) { + for (String select : getSelectSet()) { sb.append("\"").append(select).append("\", "); } sb.append("]"); diff --git a/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archive-spring.xml b/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archive-spring.xml index aa18209389..473509382e 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archive-spring.xml +++ b/edexOsgi/com.raytheon.uf.edex.archive/res/spring/archive-spring.xml @@ -3,9 +3,7 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> - - - + diff --git a/edexOsgi/com.raytheon.uf.edex.archive/resources/com.raytheon.uf.edex.archive.cron.properties b/edexOsgi/com.raytheon.uf.edex.archive/resources/com.raytheon.uf.edex.archive.cron.properties index 3a69251ba6..a7a334bc48 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/resources/com.raytheon.uf.edex.archive.cron.properties +++ b/edexOsgi/com.raytheon.uf.edex.archive/resources/com.raytheon.uf.edex.archive.cron.properties @@ -2,12 +2,15 @@ archive.enable=true # runs database and hdf5 archive for archive server to pull data from archive.cron=0+40+*+*+*+? +# path to store processed archive data +archive.path=/archive + # enable archive purge archive.purge.enable=true -# purge archives -archive.purge.cron=0+5+0/3+*+*+? +# when to purge archives +archive.purge.cron=0+5+0/2+*+*+? # compress database records -archive.compression.enable=true +archive.compression.enable=false # to disable a specific archive, use property archive.disable=pluginName,pluginName... #archive.disable=grid,text,acars \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DataArchiver.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DataArchiver.java index 73449c929f..1d070faeaf 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DataArchiver.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DataArchiver.java @@ -45,6 +45,7 @@ import com.raytheon.uf.edex.core.dataplugin.PluginRegistry; * ------------ ---------- ----------- -------------------------- * Dec 16, 2011 rjpeter Initial creation * Nov 05, 2013 2499 rjpeter Repackaged, updated to use System properties. + * Dec 11, 2013 2555 rjpeter archivePath overridable via System properties. * * * @author rjpeter @@ -60,6 +61,8 @@ public class DataArchiver { // allows for disabling of specific plugins if desired private final static String DISABLE_PROPERTY = "archive.disable"; + private final static String PATH_PROPERTY = "archive.path"; + private final boolean ARCHIVING_ENABLED; private final Set DISABLED_PLUGINS; @@ -68,10 +71,9 @@ public class DataArchiver { private final List dataArchivers = new LinkedList(); - private String archivePath = null; + private final String archivePath; - public DataArchiver(String archivePath) { - this.archivePath = archivePath; + public DataArchiver() { ARCHIVING_ENABLED = Boolean.getBoolean(ENABLE_PROPERTY); String disabledPluginList = System.getProperty(DISABLE_PROPERTY); if (disabledPluginList != null) { @@ -83,6 +85,9 @@ public class DataArchiver { } else { DISABLED_PLUGINS = Collections.emptySet(); } + + // default to /archive + archivePath = System.getProperty(PATH_PROPERTY, "/archive"); } public void archivePlugins() { diff --git a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiveProcessor.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiveProcessor.java new file mode 100644 index 0000000000..4bbb77c4d1 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiveProcessor.java @@ -0,0 +1,739 @@ +/** + * 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.archive; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Writer; +import java.text.DecimalFormat; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; + +import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.dataplugin.PluginProperties; +import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; +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.datastorage.StorageProperties.Compression; +import com.raytheon.uf.common.serialization.SerializationException; +import com.raytheon.uf.common.serialization.SerializationUtil; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.util.FileUtil; +import com.raytheon.uf.edex.core.dataplugin.PluginRegistry; +import com.raytheon.uf.edex.database.plugin.PluginDao; +import com.raytheon.uf.edex.database.processor.IDatabaseProcessor; + +/** + * Receives records to be archived to disk. Records can be written over extended + * periods of time and so when writing, the previous records must be dup elim'd + * against the current set of data to handle database being updated. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Dec 10, 2013 2555       rjpeter     Initial creation
+ * 
+ * 
+ * + * @author rjpeter + * @version 1.0 + */ + +public class DatabaseArchiveProcessor implements IDatabaseProcessor { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(DatabaseArchiveProcessor.class); + + /** Chunk size for I/O Buffering and Compression */ + private static final int CHUNK_SIZE = 8192; + + private static final String BIN_FILE_EXT = ".bin"; + + private static final String GZIP_FILE_EXT = ".gz"; + + private static final Pattern FILE_COUNT_PATTERN = Pattern + .compile("^(.*\\.bin\\.)(\\d+)(?:\\.gz)?$"); + + protected final String archivePath; + + protected final String pluginName; + + protected final PluginDao dao; + + protected final IPluginArchiveFileNameFormatter nameFormatter; + + protected boolean debugArchiver = false; + + protected boolean compressDatabaseFiles = false; + + protected int fetchSize = 1000; + + protected Set datastoreFilesToArchive = new HashSet(); + + protected Set filesCreatedThisSession = new HashSet(); + + protected Set dirsToCheckNumbering = new HashSet(); + + protected int recordsSaved = 0; + + protected boolean failed = false; + + public DatabaseArchiveProcessor(String archivePath, String pluginName, + PluginDao dao, IPluginArchiveFileNameFormatter nameFormatter) { + this.archivePath = archivePath; + this.pluginName = pluginName; + this.dao = dao; + this.nameFormatter = nameFormatter; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.edex.database.processor.IDatabaseProcessor#process(java + * .util.List) + */ + @Override + public boolean process(List objects) { + if ((objects != null) && !objects.isEmpty()) { + Set datastoreFiles = new HashSet(); + statusHandler.info(pluginName + ": Processing rows " + recordsSaved + + " to " + (recordsSaved + objects.size())); + + @SuppressWarnings("unchecked") + List> pdos = (List>) objects; + Map>> pdosByFile = new HashMap>>(); + for (PersistableDataObject pdo : pdos) { + String path = nameFormatter.getFilename(pluginName, dao, pdo); + if (path.endsWith(".h5")) { + datastoreFiles.add(path); + path = path.substring(0, path.length() - 3); + } + + List> list = pdosByFile.get(path); + if (list == null) { + list = new LinkedList>(); + pdosByFile.put(path, list); + } + + list.add(pdo); + } + + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler.debug(pluginName + ": Processed " + + objects.size() + " rows into " + pdosByFile.size() + + " files"); + } + + try { + savePdoMap(pdosByFile); + datastoreFilesToArchive.addAll(datastoreFiles); + recordsSaved += pdos.size(); + } catch (Exception e) { + statusHandler.error(pluginName + + ": Error occurred saving data to archive", e); + failed = true; + return false; + } + } + + return true; + } + + /** + * Checks file numbering on any directory that have been flagged. Also + * archives any associated hdf5 files. + */ + @Override + public void finish() { + for (File dir : dirsToCheckNumbering) { + checkFileNumbering(dir); + } + + if (!datastoreFilesToArchive.isEmpty()) { + statusHandler.info(pluginName + ": archiving " + + datastoreFilesToArchive.size() + " hdf5 file(s)"); + Compression compRequired = Compression.LZF; + PluginProperties props = PluginRegistry.getInstance() + .getRegisteredObject(pluginName); + + if ((props != null) && (props.getCompression() != null)) { + if (compRequired.equals(Compression.valueOf(props + .getCompression()))) { + // if plugin is already compressed to the correct level, + // no additional compression required + compRequired = null; + } + } + + for (String dataStoreFile : datastoreFilesToArchive) { + IDataStore ds = DataStoreFactory.getDataStore(new File(FileUtil + .join(pluginName, dataStoreFile))); + // all dataStore files should end with .h5 + String destDir = (dataStoreFile.endsWith(".h5") ? dataStoreFile + .substring(0, dataStoreFile.length() - 3) + : dataStoreFile); + + String outputDir = FileUtil.join(archivePath, pluginName, + destDir) + File.separator; + + try { + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler.debug(pluginName + + ": Archiving data store file " + + dataStoreFile + " to " + outputDir); + } + + // copy the changed hdf5 file, does repack if + // compRequired, otherwise pure file copy + ds.copy(outputDir, compRequired, null, 0, 0); + } catch (StorageException e) { + statusHandler.handle(Priority.PROBLEM, + e.getLocalizedMessage()); + } + } + statusHandler.info(pluginName + ": hdf5 archiving complete"); + } + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.edex.database.processor.IDatabaseProcessor#getFetchSize() + */ + @Override + public int getBatchSize() { + return fetchSize; + } + + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.edex.database.processor.IDatabaseProcessor#setFetchSize + * (int) + */ + @Override + public void setBatchSize(int fetchSize) { + this.fetchSize = fetchSize; + } + + /** + * True if the processor had a failure during its execution. + * + * @return + */ + public boolean isFailed() { + return failed; + } + + /** + * Reset any state fields so processor can be reused. + */ + public void reset() { + datastoreFilesToArchive.clear(); + filesCreatedThisSession.clear(); + dirsToCheckNumbering.clear(); + recordsSaved = 0; + failed = false; + } + + /** + * @return the debugArchiver + */ + public boolean isDebugArchiver() { + return debugArchiver; + } + + /** + * @param debugArchiver + * the debugArchiver to set + */ + public void setDebugArchiver(boolean debugArchiver) { + this.debugArchiver = debugArchiver; + } + + /** + * @return the compressDatabaseFiles + */ + public boolean isCompressDatabaseFiles() { + return compressDatabaseFiles; + } + + /** + * @param compressDatabaseFiles + * the compressDatabaseFiles to set + */ + public void setCompressDatabaseFiles(boolean compressDatabaseFiles) { + this.compressDatabaseFiles = compressDatabaseFiles; + } + + /** + * @return the recordsSaved + */ + public int getRecordsSaved() { + return recordsSaved; + } + + /** + * Saves data in the pdo map to disk. The data in the pdoMap is dup elim'd + * against any previously written records. + * + * @param pdoMap + * @throws SerializationException + * @throws IOException + */ + protected void savePdoMap(Map>> pdoMap) + throws SerializationException, IOException { + StringBuilder baseDir = new StringBuilder(160); + Set identifierSet = null; + + for (Map.Entry>> entry : pdoMap + .entrySet()) { + baseDir.setLength(0); + baseDir.append(archivePath).append(File.separator) + .append(pluginName).append(File.separator) + .append(entry.getKey()).append(File.separator); + File dir = new File(baseDir.toString()); + + if (!dir.exists()) { + if (!dir.mkdirs() && !dir.exists()) { + throw new IOException("Cannot create directory " + + baseDir.toString()); + } + } + + List> pdos = entry.getValue(); + if (identifierSet == null) { + identifierSet = new HashSet(pdos.size(), 1); + } else { + identifierSet.clear(); + } + + for (PersistableDataObject pdo : pdos) { + identifierSet.add(pdo.getIdentifier()); + } + + SortedMap fileMap = getArchivedFiles(dir); + pdos = dupElimPreviousFiles(fileMap, pdos, identifierSet); + + // if any records left in pdos, write to disk + if (pdos.size() > 0) { + int fileCount = 1; + if (!fileMap.isEmpty()) { + fileCount += fileMap.lastKey(); + } + File newFile = new File(dir, dir.getName() + BIN_FILE_EXT + "." + + fileCount); + fileMap.put(fileCount, newFile); + writeDataToDisk(newFile, pdos); + filesCreatedThisSession.add(newFile.getAbsolutePath()); + + // check if we have added another digit and should add a 0 to + // previous numbers + String fileCountStr = Integer.toString(fileCount); + if (fileCountStr.startsWith("1") && fileCountStr.endsWith("0")) { + dirsToCheckNumbering.add(dir); + } + } + } + } + + /** + * Checks the pdos against the previously written pdos. If a previous pdo + * would be overwritten its entry is deleted from the previous file and the + * file rewritten. If the last file does not contain a full fetch set, then + * pdos are appended up to the fetch size. If any pdos are remaining to be + * written they are returned otherwise an empty list is returned. + * + * @param fileMap + * @param pdos + * @param identifierSet + * @return + * @throws IOException + * @throws SerializationException + */ + protected List> dupElimPreviousFiles( + SortedMap fileMap, + List> pdos, Set identifierSet) + throws IOException, SerializationException { + if (!fileMap.isEmpty()) { + Iterator fileIter = fileMap.values().iterator(); + while (fileIter.hasNext()) { + File dataFile = fileIter.next(); + + if (filesCreatedThisSession + .contains(dataFile.getAbsolutePath())) { + statusHandler + .debug(pluginName + + ": Skipping dup check on data file created this session: " + + dataFile.getName()); + continue; + } + + List> pdosFromDisk = readDataFromDisk(dataFile); + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler.debug(pluginName + ": Checking " + + pdosFromDisk.size() + " old records from file: " + + dataFile.getAbsolutePath()); + } + Iterator> pdoIter = pdosFromDisk + .iterator(); + boolean needsUpdate = false; + int dupsRemoved = 0; + while (pdoIter.hasNext()) { + PersistableDataObject pdo = pdoIter.next(); + if (identifierSet.contains(pdo.getIdentifier())) { + pdoIter.remove(); + needsUpdate = true; + dupsRemoved++; + } + } + + if (statusHandler.isPriorityEnabled(Priority.DEBUG) + && (dupsRemoved > 0)) { + statusHandler.debug(pluginName + ": Removed " + dupsRemoved + + " old records from file: " + + dataFile.getAbsolutePath()); + } + + if (!fileIter.hasNext() && (pdosFromDisk.size() < fetchSize)) { + // last file, add more data to it + needsUpdate = true; + int numToAdd = fetchSize - pdosFromDisk.size(); + numToAdd = Math.min(numToAdd, pdos.size()); + + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler.debug(pluginName + ": Adding " + numToAdd + + " records to file: " + + dataFile.getAbsolutePath()); + } + + pdosFromDisk.addAll(pdos.subList(0, numToAdd)); + if (numToAdd < pdos.size()) { + pdos = pdos.subList(numToAdd, pdos.size()); + } else { + pdos = Collections.emptyList(); + } + } + + if (needsUpdate) { + if (!pdosFromDisk.isEmpty()) { + writeDataToDisk(dataFile, pdosFromDisk); + } else { + dirsToCheckNumbering.add(dataFile.getParentFile()); + dataFile.delete(); + fileIter.remove(); + } + } + } + } + + return pdos; + } + + /** + * Reads the serialized data from file. If there is a problem reading the + * file it is renamed to .bad. + * + * @param file + * @return + * @throws IOException + * @throws SerializationException + */ + @SuppressWarnings("unchecked") + protected List> readDataFromDisk(File file) + throws IOException, SerializationException { + if (file.exists()) { + InputStream is = null; + boolean successful = false; + try { + if (file.getName().endsWith(GZIP_FILE_EXT)) { + is = new GZIPInputStream(new FileInputStream(file), + CHUNK_SIZE); + } else { + is = new BufferedInputStream(new FileInputStream(file), + CHUNK_SIZE); + } + + List> rval = SerializationUtil + .transformFromThrift(List.class, is); + successful = true; + return rval; + } finally { + if (!successful) { + // couldn't read in file, move it to bad + file.renameTo(new File(file.getAbsoluteFile() + ".bad")); + } + if (is != null) { + try { + is.close(); + } catch (IOException e) { + statusHandler.error(pluginName + + ": Error occurred closing input stream", e); + } + } + } + } + + return Collections.emptyList(); + } + + /** + * Dynamic serializes the pdos. The data will be written to file. If the + * file has .gz extension and the database compression flag is not set, the + * .gz file will be deleted in favor of the uncompressed file. Reverse also + * holds true. This allows a file written under a different compression + * scheme to automatically be converted if rewritten out. + * + * @param file + * @param pdos + * @throws IOException + * @throws SerializationException + */ + protected void writeDataToDisk(File file, + List> pdos) throws IOException, + SerializationException { + OutputStream os = null; + + File gzipFile = null; + File baseFile = null; + String fileAbsPath = file.getAbsolutePath(); + + if (fileAbsPath.endsWith(GZIP_FILE_EXT)) { + gzipFile = file; + baseFile = new File(fileAbsPath.substring(0, + fileAbsPath.length() - 3)); + } else { + baseFile = file; + gzipFile = new File(fileAbsPath + GZIP_FILE_EXT); + } + + try { + if (!file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + + if (compressDatabaseFiles) { + if (baseFile.exists()) { + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler + .debug(pluginName + + ": Database compression flag changed, deleting uncompressed file " + + baseFile.getAbsolutePath()); + } + baseFile.delete(); + } + + os = new GZIPOutputStream(new FileOutputStream(gzipFile), + CHUNK_SIZE); + } else { + if (gzipFile.exists()) { + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler + .debug(pluginName + + ": Database compression flag changed, deleting compressed file " + + gzipFile.getAbsolutePath()); + } + gzipFile.delete(); + } + + os = new BufferedOutputStream(new FileOutputStream(baseFile), + CHUNK_SIZE); + } + + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler.debug(pluginName + ": Serializing " + pdos.size() + + " records to file " + file.getAbsolutePath()); + } + + // Thrift serialize pdo list + SerializationUtil.transformToThriftUsingStream(pdos, os); + os.flush(); + } finally { + if (os != null) { + try { + os.close(); + } catch (IOException e) { + statusHandler.error(pluginName + + ": Error occurred closing output stream", e); + } + } + } + + if (debugArchiver) { + String debugPath = baseFile.getAbsolutePath() + ".debug"; + dumpPdos(debugPath.toString(), pdos); + } + } + + /** + * Dump the record information being archived to a file. + * + * @param basePath + * @param pdos + */ + private void dumpPdos(String basePath, List> pdos) { + Writer writer = null; + File dumpFile = null; + + try { + int index = 0; + do { + index++; + dumpFile = new File(basePath + "." + index); + } while (dumpFile.exists()); + + Iterator> pdoIter = pdos.iterator(); + writer = new BufferedWriter(new FileWriter(dumpFile)); + statusHandler.info(String.format("%s: Dumping records to: %s", + pluginName, dumpFile.getAbsolutePath())); + + while (pdoIter.hasNext()) { + PersistableDataObject pdo = pdoIter.next(); + if (pdo instanceof PluginDataObject) { + PluginDataObject pluginDataObject = (PluginDataObject) pdo; + if (pluginDataObject.getId() != 0) { + // otherwise was read from file and will be recorded in + // a previous entry + writer.write("" + pluginDataObject.getId() + ":"); + writer.write(pluginDataObject.getDataURI()); + writer.write("\n"); + } + } else { + writer.write(pdo.getIdentifier().toString()); + writer.write("\n"); + } + } + } catch (Exception e) { + statusHandler + .handle(Priority.PROBLEM, pluginName + + ": Unable to dump pdo data to debug file: " + + (dumpFile != null ? dumpFile.getAbsolutePath() + : null), e); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (Exception e) { + // Ignore + } + } + } + } + + /** + * Returns a map of the archived database files in the directory. Map + * ordered by file count in the file name. + * + * @param baseDir + * @return + */ + protected SortedMap getArchivedFiles(File baseDir) { + File[] dirListing = baseDir.listFiles(); + SortedMap fileMap = new TreeMap(); + + if ((dirListing != null) && (dirListing.length > 0)) { + for (File dataFile : dirListing) { + if (dataFile.isFile()) { + String name = dataFile.getName(); + Matcher matcher = FILE_COUNT_PATTERN.matcher(name); + if (matcher.matches()) { + String fileNumStr = matcher.group(2); + int fileNum = Integer.parseInt(fileNumStr); + fileMap.put(fileNum, dataFile); + } + } + } + } + + return fileMap; + } + + /** + * Checks database bin files in directory for consistency. If a file has + * been deleted or if the number of digits has increased, files are renamed + * to fill in holes as well as to have leading zeros as necessary. + * + * @param dir + */ + protected void checkFileNumbering(File dir) { + SortedMap fileMap = getArchivedFiles(dir); + int nextFileCount = 1; + int size = fileMap.size(); + StringBuilder formatString = new StringBuilder(4); + do { + formatString.append("0"); + size /= 10; + } while (size > 0); + + DecimalFormat format = new DecimalFormat(formatString.toString()); + + for (Map.Entry entry : fileMap.entrySet()) { + int fileNum = entry.getKey(); + File oldFile = entry.getValue(); + String name = oldFile.getName(); + Matcher m = FILE_COUNT_PATTERN.matcher(name); + if (m.matches()) { + String oldCountString = m.group(2); + + if ((fileNum > nextFileCount) + || (oldCountString.length() != formatString.length())) { + // rename file to file count + String newFileName = m.group(1) + format.format(fileNum); + if (name.endsWith(GZIP_FILE_EXT)) { + newFileName += GZIP_FILE_EXT; + } + + File newFile = new File(oldFile.getParent(), newFileName); + oldFile.renameTo(newFile); + } + + nextFileCount++; + } + } + } +} diff --git a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java index 74d256d8cd..f9a4e8af2c 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DatabaseArchiver.java @@ -19,47 +19,20 @@ **/ package com.raytheon.uf.edex.archive; -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Writer; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; -import java.util.HashSet; -import java.util.List; import java.util.Map; -import java.util.Set; import java.util.TimeZone; -import java.util.zip.GZIPInputStream; -import java.util.zip.GZIPOutputStream; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.PluginProperties; -import com.raytheon.uf.common.dataplugin.persist.IPersistable; -import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; -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.datastorage.StorageProperties.Compression; -import com.raytheon.uf.common.serialization.SerializationException; -import com.raytheon.uf.common.serialization.SerializationUtil; 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; -import com.raytheon.uf.common.util.FileUtil; import com.raytheon.uf.edex.core.dataplugin.PluginRegistry; import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.cluster.ClusterLockUtils; @@ -70,7 +43,7 @@ import com.raytheon.uf.edex.database.plugin.PluginDao; import com.raytheon.uf.edex.database.plugin.PluginFactory; /** - * This class handles moving processed data to the archiver directory. + * This class handles saving processed data to the archiver directory. * *
  * 
@@ -84,6 +57,7 @@ import com.raytheon.uf.edex.database.plugin.PluginFactory;
  *                                     Add debug information.
  * Nov 05, 2013 2499       rjpeter     Repackaged, removed config files, always compresses hdf5.
  * Nov 11, 2013 2478       rjpeter     Updated data store copy to always copy hdf5.
+ * Dec 13, 2013 2555       rjpeter     Refactored logic into DatabaseArchiveProcessor.
  * 
* * @author rjpeter @@ -100,29 +74,34 @@ public class DatabaseArchiver implements IPluginArchiver { protected SimpleDateFormat initialValue() { SimpleDateFormat df = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss.SSS"); - df.setTimeZone(TimeZone.getTimeZone("GMT")); + df.setTimeZone(TimeUtil.GMT_TIME_ZONE); return df; } }; /** Minimum time increment to archive, note based off of insertTime. */ - private static final int MIN_DURATION_MILLIS = 1000 * 60 * 30; + private static final long MIN_DURATION_MILLIS = 30 * TimeUtil.MILLIS_PER_MINUTE; /** Maximum time increment to archive, note based off of insertTime. */ - private static final int MAX_DURATION_MILLIS = 1000 * 60 * 60; + private static final long MAX_DURATION_MILLIS = 120 * TimeUtil.MILLIS_PER_MINUTE; + + /** Default batch size for database queries */ + private static final Integer defaultBatchSize = 10000; /** Job's name. */ private static final String TASK_NAME = "DB Archiver"; /** Cluster time out on lock. */ - private static final int CLUSTER_LOCK_TIMEOUT = 60000; - - /** Chunk size for I/O Buffering and Compression */ - private static final int CHUNK_SIZE = 8192; + private static final long CLUSTER_LOCK_TIMEOUT = 10 * TimeUtil.MILLIS_PER_MINUTE; /** Mapping for plug-in formatters. */ private final Map pluginArchiveFormatters; + /** Mapping for plug-in fetch size */ + private final Map pluginBatchSize; + + private final IPluginArchiveFileNameFormatter defaultFormatter = new DefaultPluginArchiveFileNameFormatter(); + /** When true dump the pdos. */ private final boolean debugArchiver; @@ -133,8 +112,7 @@ public class DatabaseArchiver implements IPluginArchiver { */ public DatabaseArchiver() { pluginArchiveFormatters = new HashMap(); - pluginArchiveFormatters.put("default", - new DefaultPluginArchiveFileNameFormatter()); + pluginBatchSize = new HashMap(); debugArchiver = Boolean.getBoolean("archive.debug.enable"); compressDatabaseFiles = Boolean .getBoolean("archive.compression.enable"); @@ -159,12 +137,10 @@ public class DatabaseArchiver implements IPluginArchiver { } } - @SuppressWarnings("rawtypes") public boolean archivePluginData(String pluginName, String archivePath) { SimpleDateFormat dateFormat = TL_DATE_FORMAT.get(); // set archive time - Calendar runTime = Calendar.getInstance(); - runTime.setTimeZone(TimeZone.getTimeZone("GMT")); + Calendar runTime = TimeUtil.newGmtCalendar(); runTime.add(Calendar.MINUTE, -30); // cluster lock, grabbing time of last successful archive @@ -195,99 +171,52 @@ public class DatabaseArchiver implements IPluginArchiver { return false; } - Set datastoreFilesToArchive = new HashSet(); - startTime = determineStartTime(pluginName, ct.getExtraInfo(), runTime, dao); Calendar endTime = determineEndTime(startTime, runTime); - Map> pdoMap = new HashMap>(); IPluginArchiveFileNameFormatter archiveFormatter = pluginArchiveFormatters .get(pluginName); if (archiveFormatter == null) { - archiveFormatter = pluginArchiveFormatters.get("default"); + archiveFormatter = defaultFormatter; } - while ((startTime != null) && (endTime != null)) { - Map> pdosToSave = archiveFormatter - .getPdosByFile(pluginName, dao, pdoMap, startTime, - endTime); + Integer batchSize = pluginBatchSize.get(pluginName); - if ((pdosToSave != null) && !pdosToSave.isEmpty()) { - recordCount += savePdoMap(pluginName, archivePath, - pdosToSave); - for (Map.Entry> entry : pdosToSave - .entrySet()) { - List pdoList = entry.getValue(); - if ((pdoList != null) && !pdoList.isEmpty() - && (pdoList.get(0) instanceof IPersistable)) { - datastoreFilesToArchive.add(entry.getKey()); - } - } - } - - startTime = endTime; - endTime = determineEndTime(startTime, runTime); + if (batchSize == null) { + batchSize = defaultBatchSize; } - if ((pdoMap != null) && !pdoMap.isEmpty()) { - recordCount += savePdoMap(pluginName, archivePath, pdoMap); - // don't forget to archive the HDF5 for the records that weren't - // saved off by the prior while block - for (Map.Entry> entry : pdoMap - .entrySet()) { - List pdoList = entry.getValue(); - if ((pdoList != null) && !pdoList.isEmpty() - && (pdoList.get(0) instanceof IPersistable)) { - datastoreFilesToArchive.add(entry.getKey()); - } + DatabaseArchiveProcessor processor = new DatabaseArchiveProcessor( + archivePath, pluginName, dao, archiveFormatter); + processor.setCompressDatabaseFiles(compressDatabaseFiles); + processor.setDebugArchiver(debugArchiver); + processor.setBatchSize(batchSize.intValue()); + + while ((startTime != null) && (endTime != null) + && !processor.isFailed()) { + statusHandler.info(pluginName + ": Checking for records from " + + TimeUtil.formatDate(startTime) + " to " + + TimeUtil.formatDate(endTime)); + + processor.reset(); + dao.processArchiveRecords(startTime, endTime, processor); + if (!processor.isFailed()) { + recordCount += processor.getRecordsSaved(); + startTime = endTime; + endTime = determineEndTime(startTime, runTime); + + // update the cluster lock with check point details + String extraInfo = dateFormat.format(startTime.getTime()); + lockHandler.setExtraInfo(extraInfo); + ClusterLockUtils.updateExtraInfoAndLockTime(TASK_NAME, + pluginName, extraInfo, System.currentTimeMillis()); } } - if (!datastoreFilesToArchive.isEmpty()) { - Compression compRequired = Compression.LZF; - - PluginProperties props = PluginRegistry.getInstance() - .getRegisteredObject(pluginName); - - if ((props != null) && (props.getCompression() != null)) { - if (compRequired.equals(Compression.valueOf(props - .getCompression()))) { - // if plugin is already compressed to the correct level, - // no additional compression required - compRequired = null; - } - } - - for (String dataStoreFile : datastoreFilesToArchive) { - IDataStore ds = DataStoreFactory.getDataStore(new File( - FileUtil.join(pluginName, dataStoreFile))); - int pathSep = dataStoreFile.lastIndexOf(File.separatorChar); - String outputDir = (pathSep > 0 ? FileUtil.join( - archivePath, pluginName, - dataStoreFile.substring(0, pathSep)) : FileUtil - .join(archivePath, pluginName, dataStoreFile)); - - try { - // copy the changed hdf5 file, does repack if - // compRequired, otherwise pure file copy - ds.copy(outputDir, compRequired, null, 0, 0); - } catch (StorageException e) { - statusHandler.handle(Priority.PROBLEM, - e.getLocalizedMessage()); - } - } - } - - // set last archive time to startTime - if (startTime != null) { - lockHandler - .setExtraInfo(dateFormat.format(startTime.getTime())); - } - if (recordCount > 0) { statusHandler.info(pluginName - + ": successfully archived " + + ": archived " + recordCount + " records in " + TimeUtil.prettyDuration(System.currentTimeMillis() @@ -315,180 +244,6 @@ public class DatabaseArchiver implements IPluginArchiver { return true; } - @SuppressWarnings("rawtypes") - protected int savePdoMap(String pluginName, String archivePath, - Map> pdoMap) - throws SerializationException, IOException { - int recordsSaved = 0; - - StringBuilder path = new StringBuilder(); - for (Map.Entry> entry : pdoMap - .entrySet()) { - path.setLength(0); - path.append(archivePath).append(File.separator).append(pluginName) - .append(File.separator).append(entry.getKey()); - // remove .h5 - if (path.lastIndexOf(".h5") == (path.length() - 3)) { - path.setLength(path.length() - 3); - } - int pathDebugLength = path.length(); - if (compressDatabaseFiles) { - path.append(".bin.gz"); - } else { - path.append(".bin"); - } - - File file = new File(path.toString()); - List pdosToSerialize = entry.getValue(); - recordsSaved += pdosToSerialize.size(); - - if (file.exists()) { - // read previous list in from disk (in gz format) - InputStream is = null; - - try { - - // created gzip'd stream - if (compressDatabaseFiles) { - is = new GZIPInputStream(new FileInputStream(file), - CHUNK_SIZE); - } else { - is = new BufferedInputStream(new FileInputStream(file), - CHUNK_SIZE); - } - - // transform back for list append - @SuppressWarnings("unchecked") - List> prev = SerializationUtil - .transformFromThrift(List.class, is); - - statusHandler.info(pluginName + ": Read in " + prev.size() - + " records from file " + file.getAbsolutePath()); - - List newList = new ArrayList( - prev.size() + pdosToSerialize.size()); - - // get set of new identifiers - Set identifierSet = new HashSet( - pdosToSerialize.size(), 1); - for (PersistableDataObject pdo : pdosToSerialize) { - identifierSet.add(pdo.getIdentifier()); - } - - // merge records by Identifier, to remove old duplicate - for (PersistableDataObject pdo : prev) { - if (!identifierSet.contains(pdo.getIdentifier())) { - newList.add(pdo); - } - } - - // release prev - prev = null; - - newList.addAll(pdosToSerialize); - pdosToSerialize = newList; - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - statusHandler.error(pluginName - + ": Error occurred closing input stream", - e); - } - } - } - } - - statusHandler.info(pluginName + ": Serializing " - + pdosToSerialize.size() + " records to file " - + file.getAbsolutePath()); - - OutputStream os = null; - - try { - if (!file.getParentFile().exists()) { - file.getParentFile().mkdirs(); - } - - if (debugArchiver) { - String debugRootName = path.substring(0, pathDebugLength); - dumpPdos(pluginName, pdosToSerialize, debugRootName); - } - - // created gzip'd stream - if (compressDatabaseFiles) { - os = new GZIPOutputStream(new FileOutputStream(file), CHUNK_SIZE); - } else { - os = new BufferedOutputStream(new FileOutputStream(file), - CHUNK_SIZE); - } - - // Thrift serialize pdo list - SerializationUtil.transformToThriftUsingStream(pdosToSerialize, - os); - } finally { - if (os != null) { - try { - os.close(); - } catch (IOException e) { - statusHandler.error(pluginName - + ": Error occurred closing output stream", e); - } - } - } - } - - return recordsSaved; - } - - /** - * Dump the record information being archived to a file. - */ - @SuppressWarnings("rawtypes") - private void dumpPdos(String pluginName, - List pdosToSerialize, String debugRootName) { - StringBuilder sb = new StringBuilder(debugRootName); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss"); - sdf.setTimeZone(TimeZone.getTimeZone("GMT")); - sb.append("_").append(sdf.format(Calendar.getInstance().getTime())) - .append(".txt"); - File file = new File(sb.toString()); - Writer writer = null; - try { - PersistableDataObject[] pdoArray = pdosToSerialize - .toArray(new PersistableDataObject[0]); - writer = new BufferedWriter(new FileWriter(file)); - statusHandler.info(String.format("Dumping %s records to: %s", - pdoArray.length, file.getAbsolutePath())); - for (int i = 0; i < pdosToSerialize.size(); ++i) { - if (pdoArray[i] instanceof PluginDataObject) { - PluginDataObject pdo = (PluginDataObject) pdoArray[i]; - if (pdo.getId() != 0) { - // otherwise was read from file - writer.write("" + pdo.getId() + ":"); - writer.write(pdo.getDataURI()); - writer.write("\n"); - } - } else { - writer.write(pdoArray[i].toString()); - writer.write("\n"); - } - } - } catch (Exception e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); - } finally { - if (writer != null) { - try { - writer.close(); - } catch (Exception e) { - // Ignore - } - writer = null; - } - } - } - /** * Get the plug-in's start time for a query. * @@ -591,4 +346,17 @@ public class DatabaseArchiver implements IPluginArchiver { return this; } + + /** + * Register batch size for a plug-in. + * + * @param pluginName + * @param batchSize + * Batch Size for the plugin. Default is 10000. + * @return databaseArchiver + */ + public Object registerPluginBatchSize(String pluginName, Integer batchSize) { + pluginBatchSize.put(pluginName, batchSize); + return this; + } } diff --git a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DefaultPluginArchiveFileNameFormatter.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DefaultPluginArchiveFileNameFormatter.java index 1246c23c10..a0ad88420b 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DefaultPluginArchiveFileNameFormatter.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/DefaultPluginArchiveFileNameFormatter.java @@ -20,22 +20,13 @@ package com.raytheon.uf.edex.archive; import java.io.File; -import java.util.Calendar; import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.persist.DefaultPathProvider; import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider; import com.raytheon.uf.common.dataplugin.persist.IPersistable; import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; -import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.plugin.PluginDao; /** @@ -47,11 +38,12 @@ import com.raytheon.uf.edex.database.plugin.PluginDao; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Apr 20, 2012 dgilling Initial creation - * Mar 12, 2013 1783 rferrel Replace ArrayList with LinkedList to - * remove excess capacity and reduce - * time to resize a growing list. - * Nov 05, 2013 2499 rjpeter Repackaged + * Apr 20, 2012 dgilling Initial creation + * Mar 12, 2013 1783 rferrel Replace ArrayList with LinkedList to + * remove excess capacity and reduce + * time to resize a growing list. + * Nov 05, 2013 2499 rjpeter Repackaged + * Dec 14, 2013 2555 rjpeter Refactored * * * @author dgilling @@ -60,89 +52,40 @@ import com.raytheon.uf.edex.database.plugin.PluginDao; public class DefaultPluginArchiveFileNameFormatter implements IPluginArchiveFileNameFormatter { - /* * (non-Javadoc) * * @see - * com.raytheon.uf.edex.maintenance.archive.IPluginArchiveFileNameFormatter - * #getPdosByFile(java.lang.String, - * com.raytheon.uf.edex.database.plugin.PluginDao, java.util.Map, - * java.util.Calendar, java.util.Calendar) + * com.raytheon.uf.edex.archive.IPluginArchiveFileNameFormatter#getFilename + * (java.lang.String, com.raytheon.uf.edex.database.plugin.PluginDao, + * com.raytheon.uf.common.dataplugin.persist.PersistableDataObject) */ - @SuppressWarnings("rawtypes") @Override - public Map> getPdosByFile( - String pluginName, PluginDao dao, - Map> pdoMap, - Calendar startTime, Calendar endTime) - throws DataAccessLayerException { - List pdos = dao.getRecordsToArchive(startTime, - endTime); - - Set newFileEntries = new HashSet(); - if ((pdos != null) && !pdos.isEmpty()) { - if (pdos.get(0) instanceof IPersistable) { - IHDFFilePathProvider pathProvider = dao.pathProvider; - - for (PersistableDataObject pdo : pdos) { - IPersistable persistable = (IPersistable) pdo; - String path = pathProvider.getHDFPath(pluginName, - persistable) - + File.separator - + pathProvider.getHDFFileName(pluginName, - persistable); - newFileEntries.add(path); - List list = pdoMap.get(path); - if (list == null) { - list = new LinkedList(); - pdoMap.put(path, list); - } - list.add(pdo); - } + public String getFilename(String pluginName, PluginDao dao, + PersistableDataObject pdo) { + String path = null; + if (pdo instanceof IPersistable) { + IPersistable persistable = (IPersistable) pdo; + IHDFFilePathProvider pathProvider = dao.pathProvider; + path = pathProvider.getHDFPath(pluginName, persistable) + + File.separator + + pathProvider.getHDFFileName(pluginName, persistable); + } else { + String timeString = null; + PluginDataObject pluginDataObj = (PluginDataObject) pdo; + if (pdo instanceof PluginDataObject) { + Date time = pluginDataObj.getDataTime().getRefTimeAsCalendar() + .getTime(); + timeString = DefaultPathProvider.fileNameFormat.get().format( + time); } else { - // order files by refTime hours - for (PersistableDataObject pdo : pdos) { - String timeString = null; - if (pdo instanceof PluginDataObject) { - PluginDataObject pluginDataObj = (PluginDataObject) pdo; - Date time = pluginDataObj.getDataTime() - .getRefTimeAsCalendar().getTime(); - timeString = DefaultPathProvider.fileNameFormat.get() - .format(time); - } else { - // no refTime to use bounded insert query bounds - Date time = startTime.getTime(); - timeString = DefaultPathProvider.fileNameFormat.get() - .format(time); - } - - String path = pluginName + timeString; - newFileEntries.add(path); - List list = pdoMap.get(path); - if (list == null) { - list = new LinkedList(); - pdoMap.put(path, list); - } - list.add(pdo); - } - + // no refTime, use current time as last resort + timeString = DefaultPathProvider.fileNameFormat.get().format( + new Date()); } + + path = pluginName + timeString; } - - Iterator iter = pdoMap.keySet().iterator(); - Map> pdosToSave = new HashMap>( - pdoMap.size() - newFileEntries.size()); - - while (iter.hasNext()) { - String key = iter.next(); - if (!newFileEntries.contains(key)) { - pdosToSave.put(key, pdoMap.get(key)); - iter.remove(); - } - } - - return pdosToSave; + return path; } - } diff --git a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IPluginArchiveFileNameFormatter.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IPluginArchiveFileNameFormatter.java index b0e106df98..5121fe3b0e 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IPluginArchiveFileNameFormatter.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/IPluginArchiveFileNameFormatter.java @@ -19,12 +19,7 @@ **/ package com.raytheon.uf.edex.archive; -import java.util.Calendar; -import java.util.List; -import java.util.Map; - import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; -import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.plugin.PluginDao; /** @@ -36,8 +31,9 @@ import com.raytheon.uf.edex.database.plugin.PluginDao; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Apr 20, 2012 dgilling Initial creation + * Apr 20, 2012 dgilling Initial creation * Nov 05, 2013 2499 rjpeter Repackaged + * Dec 13, 2013 2555 rjpeter Refactored * * * @author dgilling @@ -45,29 +41,18 @@ import com.raytheon.uf.edex.database.plugin.PluginDao; */ public interface IPluginArchiveFileNameFormatter { - /** + * Returns base file name for the pdo. In the case of IPersistable objects, + * it should match the h5 file. * * @param pluginName + * The plugin name. * @param dao - * @param pdoMap - * The current pdos by file. This map will be merged with pdos, - * if a key was not referenced by pdos it will be removed and - * returned in the returned map for storage. - * @param startTime - * @param endTime - * @return The pdos to save to disk. If sortPdosByFiles did not store any - * entries from pdos into a file listed in currentPdoMap then that - * entry will be returned in a new map and removed from - * currentPdoMap. - * @throws DataAccessLayerException - * If the DAO is unable to retrieve the records from the - * database. + * The dao for the object. + * @param pdo + * The object to look up. + * @return */ - @SuppressWarnings("rawtypes") - public abstract Map> getPdosByFile( - String pluginName, PluginDao dao, - Map> pdoMap, - Calendar startTime, Calendar endTime) - throws DataAccessLayerException; + public String getFilename(String pluginName, PluginDao dao, + PersistableDataObject pdo); } diff --git a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/purge/ArchivePurger.java b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/purge/ArchivePurger.java index 6af9a95018..fdfc1133ec 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/purge/ArchivePurger.java +++ b/edexOsgi/com.raytheon.uf.edex.archive/src/com/raytheon/uf/edex/archive/purge/ArchivePurger.java @@ -44,6 +44,7 @@ import com.raytheon.uf.common.time.util.TimeUtil; * number of files purged. * Sep 03, 2013 2224 rferrel Add check to enable/disable purger. * Nov 05, 2013 2499 rjpeter Repackaged + * Dec 17, 2013 2603 rjpeter Reload configuration every run of purge. * * * @author bgonzale @@ -67,6 +68,7 @@ public class ArchivePurger { timer.start(); statusHandler.info("Archive Purge started."); ArchiveConfigManager manager = ArchiveConfigManager.getInstance(); + manager.reset(); Collection archives = manager.getArchives(); for (ArchiveConfig archive : archives) { ITimer archiveTimer = TimeUtil.getTimer(); diff --git a/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/PROCESSED_DATA.xml b/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/PROCESSED_DATA.xml index 8cc6e745f7..bb2d928ab0 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/PROCESSED_DATA.xml +++ b/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/PROCESSED_DATA.xml @@ -28,6 +28,8 @@ * Oct 01, 2013 2147 rferrel Date time stamp no longer requires an hour field. * Nov 05, 2013 2497 rferrel Change root directory. * Nov 13, 2013 2549 rferrel Changes to GFE and modelsounding. + * Dec 12, 2013 2624 rferrel Document Julian time stamp. + * Dec 13, 2013 2555 rjpeter Updated all to use dirPatterns. * * @author rferrel * @version 1.0 @@ -66,14 +68,19 @@ single table entry. - Optional tag to determine what type of time stamp is being used to get files/directories for retention and case creation. The value dictates how many groupings in the s and/or are - used to get the time stamp for a file. The four values are: - Date - (default) the time stamp is made up of four groups in the patterns: year, month, day and hour. + used to get the time stamp for a file. The five values are: + Date - (default) the time stamp is made up of 3 or 4 groups in the patterns: year, month, day and optional hour. + Julian - The time stamp is made up of 2 or 3 groups in the patterns: year, day_of_year and optional hour. + if the year is less then 100 it is adjust to a year prior to or no more then a month into the future + of the current simulate year. EpochSec - The time stamp has one group in the patterns which is the epoch time in seconds. EpochMS - The time stamp has one group in the patterns which is the epoch time in milliseconds. File - No group is used to get the time stamp. Instead use the files date of last modification. - Required tag when has any value but File. Date - A comma separated list of 3 or 4 numbers which are in order the index for year, month, day and hour. When only 3 numbers the hour is value is 23. + Julian - A comma separated list of 2 or 3 numbers which are in order the index for year, day of year, and hour. + When only two numbers the hour value is 23. EpochSec - A number which is the index for the epoch in seconds. EpochMS - A number which is the index for the epoch in milliseconds. File - Not needed since no group is used to get the time stamp. @@ -116,7 +123,7 @@ {1} Date 2,3,4,5 - [^/]*-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..* + .*-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..* The first looks for files matching the in the directories acars, airep, airmet or taf. @@ -137,8 +144,7 @@ Decision Assistance 168 - (cwat|fog|ffmp|fssobs|preciprate|qpf|scan|vil) - .*(\d{4})-(\d{2})-(\d{2})-(\d{2}).* + (cwat|fog|ffmp|fssobs|preciprate|qpf|scan|vil)/.*(\d{4})-(\d{2})-(\d{2})-(\d{2}).* {1} 2,3,4,5 @@ -147,13 +153,12 @@ GFE 168 - gfe/(.*)/(.*)/(\d{4})_(\d{2})_(\d{2})_(\d{2})\d{2} + gfe/(.*)/(.*)/(\d{4})_(\d{2})_(\d{2})_(\d{2})\d{2}.* {1} - {2} 3,4,5,6 - gfe/(.*)/(.*) - .*_(\d{4})(\d{2})(\d{2})_.* + gfe/(.*)/(.*)/.*_(\d{4})(\d{2})(\d{2})_.* {1} - {2} 3,4,5 @@ -162,8 +167,7 @@ Local 168 - (ldadhydro|ldadmesonet|ldadprofiler|ldad_manual|mesowest|qc) - .*(\d{4})-(\d{2})-(\d{2})-(\d{2}).* + (ldadhydro|ldadmesonet|ldadprofiler|ldad_manual|mesowest|qc)/.*(\d{4})-(\d{2})-(\d{2})-(\d{2}).* {1} 2,3,4,5 @@ -172,54 +176,48 @@ Model 168 - (grid)/(.*)/(.*) + (grid)/(.*)/(.*)/.*-(\d{4})-(\d{2})-(\d{2})-(\d{2})-.* {2} 4,5,6,7 - .*-(\d{4})-(\d{2})-(\d{2})-(\d{2})-.* - (modelsounding)/(.*)/.* - (bufrmos)(.*) + (modelsounding)/(.*)/.*/.*(\d{4})-(\d{2})-(\d{2})-(\d{2}).* + (bufrmos)(.*)/.*(\d{4})-(\d{2})-(\d{2})-(\d{2}) {1} - {2} 3,4,5,6 - .*(\d{4})-(\d{2})-(\d{2})-(\d{2}).* Products 168 - (airmet|atcf|aww|bufrncwf|ccfp|convsigmet|cwa|ffg|intlsigmet|nonconvsigmet|stormtrack|taf|tcg|tcm|tcs|text|vaa|warning|wcp) - (bufrsigwx|redbook)/.* + (airmet|atcf|aww|bufrncwf|ccfp|convsigmet|cwa|ffg|intlsigmet|nonconvsigmet|stormtrack|taf|tcg|tcm|tcs|text|vaa|warning|wcp)/.*-(\d{4})-(\d{2})-(\d{2})-(\d{2}) + (bufrsigwx|redbook)/.*/.*-(\d{4})-(\d{2})-(\d{2})-(\d{2}) {1} 2,3,4,5 - [^/]*-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..* Observation 168 - (acars|airep|binlightning|bufrascat|bufrhdw|bufrmthdw|bufrssmi|idft|lsr|obs|pirep|recco|svrwx) - (sfcobs)/.* + (acars|airep|binlightning|bufrascat|bufrhdw|bufrmthdw|bufrssmi|idft|lsr|obs|pirep|recco|svrwx)/.*-(\d{4})-(\d{2})-(\d{2})-(\d{2}) + (sfcobs)/.*/.*-(\d{4})-(\d{2})-(\d{2})-(\d{2}) {1} 2,3,4,5 - .*-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..* Satellite 168 - satellite/(.*)/(.*) - .*-(\d{4})-(\d{2})-(\d{2})-(\d{2}).* + satellite/(.*)/(.*)/.*-(\d{4})-(\d{2})-(\d{2})-(\d{2}) 3,4,5,6 {1} - (mcidas|viirs)/.*/.*/.*/.* - .*-(\d{4})-(\d{2})-(\d{2})-(\d{2}).* + (mcidas|viirs)/.*/.*/.*/.*/.*-(\d{4})-(\d{2})-(\d{2})-(\d{2}) 2,3,4,5 {1} @@ -228,10 +226,9 @@ Profiles 168 - (acarssounding|bufrua|goessounding|poessounding|profiler) + (acarssounding|bufrua|goessounding|poessounding|profiler)/.*-(\d{4})-(\d{2})-(\d{2})-(\d{2}) {1} 2,3,4,5 - .*-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..* @@ -239,10 +236,9 @@ radar 168 - radar/(.*)/(.*) + radar/(.*)/(.*)/.*-(\d{4})-(\d{2})-(\d{2})-(\d{2}) {1} 3,4,5,6 - .*-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..* diff --git a/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml b/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml index c9aff14e97..c88591683c 100644 --- a/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml +++ b/edexOsgi/com.raytheon.uf.edex.archive/utility/common_static/base/archiver/purger/RAW_DATA.xml @@ -26,6 +26,7 @@ * Jun 20, 2013 1966 rferrel Initial creation * Aug 05, 2013 2224 rferrel Changes to add dataSet tags. * Oct 01, 2013 2147 rferrel Date time stamp no longer requires an hour field. + * Dec 12, 2013 2624 rferrel Document Julian time stamp. * * @author rferrel * @version 1.0 @@ -64,14 +65,19 @@ single table entry. - Optional tag to determine what type of time stamp is being used to get files/directories for retention and case creation. The value dictates how many groupings in the s and/or are - used to get the time stamp for a file. The four values are: - Date - (default) the time stamp is made up of four groups in the patterns: year, month, day and hour. + used to get the time stamp for a file. The five values are: + Date - (default) the time stamp is made up of 3 or 4 groups in the patterns: year, month, day and optional hour. + Julian - The time stamp is made up of 2 or 3 groups in the patterns: year, day_of_year and optional hour. + if the year is less then 100 it is adjust to a year prior to or no more then a month into the future + of the current simulate year. EpochSec - The time stamp has one group in the patterns which is the epoch time in seconds. EpochMS - The time stamp has one group in the patterns which is the epoch time in milliseconds. File - No group is used to get the time stamp. Instead use the files date of last modification. - Required tag when has any value but File. Date - A comma separated list of 3 or 4 numbers which are in order the index for year, month, day and hour. When only 3 numbers the hour is value is 23. + Julian - A comma separated list of 2 or 3 numbers which are in order the index for year, day of year, and hour. + When only two numbers the hour value is 23. EpochSec - A number which is the index for the epoch in seconds. EpochMS - A number which is the index for the epoch in milliseconds. File - Not needed since no group is used to get the time stamp. @@ -114,7 +120,7 @@ {1} Date 2,3,4,5 - [^/]*-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..* + .*-(\d{4})-(\d{2})-(\d{2})-(\d{2})\..* The first looks for files matching the in the directories acars, airep, airmet or taf. diff --git a/edexOsgi/com.raytheon.uf.edex.database/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.edex.database/META-INF/MANIFEST.MF index a68d121ade..a32b47bf5f 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.edex.database/META-INF/MANIFEST.MF @@ -28,6 +28,7 @@ Export-Package: com.raytheon.uf.edex.database, com.raytheon.uf.edex.database.handlers, com.raytheon.uf.edex.database.init, com.raytheon.uf.edex.database.plugin, + com.raytheon.uf.edex.database.processor, com.raytheon.uf.edex.database.purge, com.raytheon.uf.edex.database.query, com.raytheon.uf.edex.database.status, diff --git a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/cluster/ClusterLockUtils.java b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/cluster/ClusterLockUtils.java index 55b6439c83..375f1546c5 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/cluster/ClusterLockUtils.java +++ b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/cluster/ClusterLockUtils.java @@ -50,7 +50,7 @@ import com.raytheon.uf.edex.database.dao.DaoConfig; * Apr 28, 2010 #5050 rjpeter Initial creation from SmartInitTransaction. * Aug 26, 2013 #2272 bkowal Add a function to see if a cluster suffix has * been specified via the environment. - * + * Dec 13, 2013 2555 rjpeter Added updateExtraInfoAndLockTime and javadoc. * * * @author rjpeter @@ -116,6 +116,13 @@ public class ClusterLockUtils { } /** + * Attempts to lock based on the taskName/details and the specified + * validTime for checkTime. If waitForRunningToFinish it will sleep and then + * attempt to lock again until it achieves a lock other than already + * running. The waitForRunningToFinish is not part of the main lock logic + * due to checkTime being keyed off something other than System clock. If + * the validTime is older than the current validTime for the lock, an OLD + * LockState will be returned. * * @param taskName * @param details @@ -131,6 +138,11 @@ public class ClusterLockUtils { } /** + * Attempts to lock based on the taskName/details and the specified + * lockHandler. If waitForRunningToFinish it will sleep and then attempt to + * lock again until it achieves a lock other than already running. The + * waitForRunningToFinish is not part of the main lock logic due to + * checkTime being keyed off something other than System clock. * * @param taskName * @param details @@ -214,6 +226,9 @@ public class ClusterLockUtils { } /** + * Updates the lock time for the specified lock. IMPORTANT: No tracking is + * done to ensure caller has lock, so only use when you know you have a + * valid lock. * * @param taskName * @param details @@ -268,7 +283,9 @@ public class ClusterLockUtils { } /** - * Updates the extra info field for a cluster task + * Updates the extra info field for a cluster task. IMPORTANT: No tracking + * is done to ensure caller has lock, so only use when you know you have a + * valid lock. * * @param taskName * The name of the task @@ -327,6 +344,70 @@ public class ClusterLockUtils { } /** + * Updates the extra info and lock time fields for a cluster task. + * IMPORTANT: No tracking is done to ensure caller has lock, so only use + * when you know you have a valid lock. + * + * @param taskName + * The name of the task + * @param details + * The details associated with the task + * @param extraInfo + * The new extra info to set + * @oaran lockTime The lock time to set + * @return True if the update was successful, else false if the update + * failed + */ + public static boolean updateExtraInfoAndLockTime(String taskName, + String details, String extraInfo, long lockTime) { + CoreDao cd = new CoreDao(DaoConfig.DEFAULT); + Session s = null; + Transaction tx = null; + ClusterTask ct = null; + boolean rval = true; + + try { + s = cd.getHibernateTemplate().getSessionFactory().openSession(); + tx = s.beginTransaction(); + ClusterTaskPK pk = new ClusterTaskPK(); + pk.setName(taskName); + pk.setDetails(details); + + ct = getLock(s, pk, true); + ct.setExtraInfo(extraInfo); + ct.setLastExecution(lockTime); + s.update(ct); + tx.commit(); + } catch (Throwable t) { + handler.handle(Priority.ERROR, + "Error processing update lock time for cluster task [" + + taskName + "/" + details + "]", t); + rval = false; + + if (tx != null) { + try { + tx.rollback(); + } catch (HibernateException e) { + handler.handle(Priority.ERROR, + "Error rolling back cluster task lock transaction", + e); + } + } + } finally { + if (s != null) { + try { + s.close(); + } catch (HibernateException e) { + handler.handle(Priority.ERROR, + "Error closing cluster task lock session", e); + } + } + } + return rval; + } + + /** + * Looks up the specified cluster lock. * * @param taskName * @param details @@ -388,6 +469,9 @@ public class ClusterLockUtils { } /** + * Unlocks the given cluster lock. If clear time is set, time field will be + * reset to the epoch time. This can be useful when wanting the next check + * to always succeed. * * @param taskName * @param details @@ -500,6 +584,7 @@ public class ClusterLockUtils { } /** + * Deletes the specified cluster lock. * * @param taskName * @param details @@ -554,11 +639,22 @@ public class ClusterLockUtils { return rval; } + /** + * Looks up and returns the specified cluster lock. If the lock does not + * exist and create flag is set, the lock will be created. This is done + * using a Master lock to ensure isolation among all transactions. + * + * @param s + * @param pk + * @param create + * @return + * @throws HibernateException + */ private static ClusterTask getLock(Session s, ClusterTaskPK pk, boolean create) throws HibernateException { ClusterTask ct = (ClusterTask) s.get(ClusterTask.class, pk, LockOptions.UPGRADE); - if (ct == null && create) { + if ((ct == null) && create) { getMasterLock(s); // now have master lock, verify new row hasn't already been @@ -577,6 +673,13 @@ public class ClusterLockUtils { return ct; } + /** + * Returns the master lock. + * + * @param s + * @return + * @throws HibernateException + */ private static ClusterTask getMasterLock(Session s) throws HibernateException { ClusterTaskPK masterNewRowLockId = new ClusterTaskPK(); @@ -597,6 +700,12 @@ public class ClusterLockUtils { return masterLock; } + /** + * Returns all cluster locks that match the specified name. + * + * @param name + * @return + */ @SuppressWarnings("unchecked") public static List getLocks(String name) { StatelessSession sess = null; @@ -611,15 +720,15 @@ public class ClusterLockUtils { crit.add(nameCrit); tasks = crit.list(); } catch (Throwable e) { - // TODO - e.printStackTrace(); + handler.handle(Priority.ERROR, + "Error retrieving cluster locks for name: " + name, e); } finally { if (sess != null) { try { sess.close(); } catch (HibernateException e) { - // TODO - e.printStackTrace(); + handler.handle(Priority.ERROR, + "Error closing cluster task getLocks session", e); } } } diff --git a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/dao/CoreDao.java b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/dao/CoreDao.java index e7b6865c95..29cdbb6950 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/dao/CoreDao.java +++ b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/dao/CoreDao.java @@ -21,7 +21,6 @@ package com.raytheon.uf.edex.database.dao; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.Serializable; @@ -68,7 +67,9 @@ import com.raytheon.uf.common.dataquery.db.QueryResult; import com.raytheon.uf.common.dataquery.db.QueryResultRow; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.util.FileUtil; import com.raytheon.uf.edex.database.DataAccessLayerException; +import com.raytheon.uf.edex.database.processor.IDatabaseProcessor; import com.raytheon.uf.edex.database.query.DatabaseQuery; /** @@ -94,7 +95,7 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery; * 5/14/08 1076 brockwoo Fix for distinct with multiple properties * Oct 10, 2012 1261 djohnson Incorporate changes to DaoConfig, add generic to {@link IPersistableDataObject}. * Apr 15, 2013 1868 bsteffen Rewrite mergeAll in PluginDao. - * + * Dec 13, 2013 2555 rjpeter Added processByCriteria and fixed Generics warnings. * * * @author bphillip @@ -242,13 +243,13 @@ public class CoreDao extends HibernateDaoSupport { return loadAll(daoClass); } - @SuppressWarnings("unchecked") public List loadAll(final Class entity) { - return (List) txTemplate.execute(new TransactionCallback() { + return txTemplate.execute(new TransactionCallback>() { @Override - public Object doInTransaction(TransactionStatus status) { + @SuppressWarnings("unchecked") + public List doInTransaction(TransactionStatus status) { HibernateTemplate ht = getHibernateTemplate(); - return ht.loadAll(entity); + return (List) ht.loadAll(entity); } }); } @@ -278,10 +279,10 @@ public class CoreDao extends HibernateDaoSupport { * Null if not found */ public PersistableDataObject queryById(final Serializable id) { - @SuppressWarnings("unchecked") - PersistableDataObject retVal = (PersistableDataObject) txTemplate - .execute(new TransactionCallback() { + PersistableDataObject retVal = txTemplate + .execute(new TransactionCallback>() { @Override + @SuppressWarnings("unchecked") public PersistableDataObject doInTransaction( TransactionStatus status) { return (PersistableDataObject) getHibernateTemplate() @@ -299,10 +300,10 @@ public class CoreDao extends HibernateDaoSupport { * @return The object */ public PersistableDataObject queryById(final PluginDataObject id) { - @SuppressWarnings("unchecked") - PersistableDataObject retVal = (PersistableDataObject) txTemplate - .execute(new TransactionCallback() { + PersistableDataObject retVal = txTemplate + .execute(new TransactionCallback>() { @Override + @SuppressWarnings("unchecked") public PersistableDataObject doInTransaction( TransactionStatus status) { DetachedCriteria criteria = DetachedCriteria.forClass( @@ -333,12 +334,12 @@ public class CoreDao extends HibernateDaoSupport { * Maximum number of results to return * @return A list of similar objects */ - @SuppressWarnings("unchecked") public List> queryByExample( final PersistableDataObject obj, final int maxResults) { - List> retVal = (List>) txTemplate - .execute(new TransactionCallback() { + List> retVal = txTemplate + .execute(new TransactionCallback>>() { @Override + @SuppressWarnings("unchecked") public List> doInTransaction( TransactionStatus status) { return getHibernateTemplate().findByExample(obj, 0, @@ -377,8 +378,8 @@ public class CoreDao extends HibernateDaoSupport { int rowsDeleted = 0; try { // Get a session and create a new criteria instance - rowsDeleted = (Integer) txTemplate - .execute(new TransactionCallback() { + rowsDeleted = txTemplate + .execute(new TransactionCallback() { @Override public Integer doInTransaction(TransactionStatus status) { String queryString = query.createHQLDelete(); @@ -414,8 +415,8 @@ public class CoreDao extends HibernateDaoSupport { List queryResult = null; try { // Get a session and create a new criteria instance - queryResult = (List) txTemplate - .execute(new TransactionCallback() { + queryResult = txTemplate + .execute(new TransactionCallback>() { @Override public List doInTransaction(TransactionStatus status) { String queryString = query.createHQLQuery(); @@ -444,6 +445,68 @@ public class CoreDao extends HibernateDaoSupport { return queryResult; } + /** + * Queries the database in batches using a DatabaseQuery object and send + * each batch to processor. + * + * @param query + * The query object + * @param processor + * The processor object + * @return The number of results processed + * @throws DataAccessLayerException + * If the query fails + */ + public int processByCriteria(final DatabaseQuery query, + final IDatabaseProcessor processor) throws DataAccessLayerException { + int rowsProcessed = 0; + try { + // Get a session and create a new criteria instance + rowsProcessed = txTemplate + .execute(new TransactionCallback() { + @Override + public Integer doInTransaction(TransactionStatus status) { + String queryString = query.createHQLQuery(); + Query hibQuery = getSession(false).createQuery( + queryString); + try { + query.populateHQLQuery(hibQuery, + getSessionFactory()); + } catch (DataAccessLayerException e) { + throw new org.hibernate.TransactionException( + "Error populating query", e); + } + + if (processor.getBatchSize() > 0) { + hibQuery.setMaxResults(processor.getBatchSize()); + } else if (query.getMaxResults() != null) { + hibQuery.setMaxResults(query.getMaxResults()); + } + + List results = null; + boolean continueProcessing = false; + int count = 0; + + do { + hibQuery.setFirstResult(count); + results = hibQuery.list(); + continueProcessing = processor.process(results); + count += results.size(); + getSession().clear(); + } while (continueProcessing && (results != null) + && (results.size() > 0)); + processor.finish(); + return count; + } + }); + + } catch (TransactionException e) { + throw new DataAccessLayerException("Transaction failed", e); + } + + return rowsProcessed; + } + public void deleteAll(final List objs) { txTemplate.execute(new TransactionCallbackWithoutResult() { @Override @@ -643,8 +706,8 @@ public class CoreDao extends HibernateDaoSupport { */ public QueryResult executeHQLQuery(final String hqlQuery) { - QueryResult result = (QueryResult) txTemplate - .execute(new TransactionCallback() { + QueryResult result = txTemplate + .execute(new TransactionCallback() { @Override public QueryResult doInTransaction(TransactionStatus status) { Query hibQuery = getSession(false) @@ -697,8 +760,8 @@ public class CoreDao extends HibernateDaoSupport { */ public int executeHQLStatement(final String hqlStmt) { - int queryResult = (Integer) txTemplate - .execute(new TransactionCallback() { + int queryResult = txTemplate + .execute(new TransactionCallback() { @Override public Integer doInTransaction(TransactionStatus status) { Query hibQuery = getSession(false).createQuery(hqlStmt); @@ -722,8 +785,8 @@ public class CoreDao extends HibernateDaoSupport { public Object[] executeSQLQuery(final String sql) { long start = System.currentTimeMillis(); - List queryResult = (List) txTemplate - .execute(new TransactionCallback() { + List queryResult = txTemplate + .execute(new TransactionCallback>() { @Override public List doInTransaction(TransactionStatus status) { return getSession(false).createSQLQuery(sql).list(); @@ -737,8 +800,8 @@ public class CoreDao extends HibernateDaoSupport { public List executeCriteriaQuery(final List criterion) { long start = System.currentTimeMillis(); - List queryResult = (List) txTemplate - .execute(new TransactionCallback() { + List queryResult = txTemplate + .execute(new TransactionCallback>() { @Override public List doInTransaction(TransactionStatus status) { @@ -772,8 +835,8 @@ public class CoreDao extends HibernateDaoSupport { public int executeSQLUpdate(final String sql) { long start = System.currentTimeMillis(); - int updateResult = (Integer) txTemplate - .execute(new TransactionCallback() { + int updateResult = txTemplate + .execute(new TransactionCallback() { @Override public Integer doInTransaction(TransactionStatus status) { return getSession(false).createSQLQuery(sql) @@ -1006,27 +1069,16 @@ public class CoreDao extends HibernateDaoSupport { * If reading the file fails */ public void runScript(File script) throws DataAccessLayerException { - FileInputStream fileIn; + byte[] bytes = null; try { - fileIn = new FileInputStream(script); + bytes = FileUtil.file2bytes(script); } catch (FileNotFoundException e) { throw new DataAccessLayerException( "Unable to open input stream to sql script: " + script); - } - byte[] bytes = null; - try { - bytes = new byte[fileIn.available()]; - fileIn.read(bytes); } catch (IOException e) { throw new DataAccessLayerException( "Unable to read script contents for script: " + script); } - try { - fileIn.close(); - } catch (IOException e) { - throw new DataAccessLayerException( - "Error closing file input stream to: " + script); - } runScript(new StringBuffer().append(new String(bytes))); } diff --git a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginDao.java b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginDao.java index 6c7d2e2858..8b155100ea 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginDao.java +++ b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/plugin/PluginDao.java @@ -21,7 +21,6 @@ package com.raytheon.uf.edex.database.plugin; import java.io.File; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -52,7 +51,6 @@ import org.springframework.transaction.support.TransactionCallbackWithoutResult; import com.raytheon.uf.common.dataplugin.PluginDataObject; import com.raytheon.uf.common.dataplugin.PluginException; import com.raytheon.uf.common.dataplugin.annotations.DataURIUtil; -import com.raytheon.uf.common.dataplugin.persist.DefaultPathProvider; import com.raytheon.uf.common.dataplugin.persist.IHDFFilePathProvider; import com.raytheon.uf.common.dataplugin.persist.IPersistable; import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; @@ -74,11 +72,11 @@ import com.raytheon.uf.common.serialization.SerializationException; import com.raytheon.uf.common.serialization.SerializationUtil; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.time.util.TimeUtil; -import com.raytheon.uf.common.util.FileUtil; import com.raytheon.uf.edex.core.EdexException; import com.raytheon.uf.edex.database.DataAccessLayerException; import com.raytheon.uf.edex.database.dao.CoreDao; import com.raytheon.uf.edex.database.dao.DaoConfig; +import com.raytheon.uf.edex.database.processor.IDatabaseProcessor; import com.raytheon.uf.edex.database.purge.PurgeLogger; import com.raytheon.uf.edex.database.purge.PurgeRule; import com.raytheon.uf.edex.database.purge.PurgeRuleSet; @@ -114,6 +112,7 @@ import com.raytheon.uf.edex.database.query.DatabaseQuery; * May 16, 2013 1869 bsteffen Rewrite dataURI property mappings. * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * Oct 07, 2013 2392 rjpeter Updated to pass null productKeys as actual null instead of string null. + * Dec 13, 2013 2555 rjpeter Refactored archiving logic into processArchiveRecords. * * * @author bphillip @@ -457,7 +456,7 @@ public abstract class PluginDao extends CoreDao { for (IPersistable persistable : persistables) { try { - if (((PersistableDataObject) persistable) + if (((PersistableDataObject) persistable) .isOverwriteAllowed()) { if (replaceDataStore == null) { replaceDataStore = DataStoreFactory @@ -1695,105 +1694,18 @@ public abstract class PluginDao extends CoreDao { return null; } - public void archiveData(String archivePath, Calendar insertStartTime, - Calendar insertEndTime) throws DataAccessLayerException, - SerializationException, IOException { - List pdos = getRecordsToArchive(insertStartTime, - insertEndTime); - if ((pdos != null) && (pdos.size() > 0)) { - // map of file to list of pdo - Map> pdoMap = new HashMap>(); - if (pdos.get(0) instanceof IPersistable) { - IHDFFilePathProvider pathProvider = this.pathProvider; - - for (PersistableDataObject pdo : pdos) { - IPersistable persistable = (IPersistable) pdo; - String path = pathProvider.getHDFPath(pluginName, - persistable) - + File.separator - + pathProvider.getHDFFileName(pluginName, - persistable); - List list = pdoMap.get(path); - if (list == null) { - list = new ArrayList(pdos.size()); - pdoMap.put(path, list); - } - list.add(pdo); - } - } else { - // order files by refTime hours - for (PersistableDataObject pdo : pdos) { - String timeString = null; - if (pdo instanceof PluginDataObject) { - PluginDataObject pluginDataObj = (PluginDataObject) pdo; - Date time = pluginDataObj.getDataTime() - .getRefTimeAsCalendar().getTime(); - timeString = DefaultPathProvider.fileNameFormat.get() - .format(time); - } else { - // no refTime to use bounded insert query bounds - Date time = insertStartTime.getTime(); - timeString = DefaultPathProvider.fileNameFormat.get() - .format(time); - } - - String path = pluginName + timeString; - List list = pdoMap.get(path); - if (list == null) { - list = new ArrayList(pdos.size()); - pdoMap.put(path, list); - } - list.add(pdo); - } - - } - - for (Map.Entry> entry : pdoMap - .entrySet()) { - String path = archivePath + File.separator + pluginName - + File.separator + entry.getKey(); - - // remove .h5 - int index = path.lastIndexOf('.'); - if ((index > 0) && ((path.length() - index) < 5)) { - // ensure its end of string in case extension is - // dropped/changed - path = path.substring(0, index); - } - - path += ".bin.gz"; - - File file = new File(path); - - if (file.exists()) { - // pull the - } - - // Thrift serialize pdo list - byte[] data = SerializationUtil.transformToThrift(entry - .getValue()); - - SerializationUtil.transformFromThrift(data); - - // save list to disk (in gz format?) - FileUtil.bytes2File(data, file, true); - } - } - - } - - @SuppressWarnings("unchecked") - public List getRecordsToArchive( - Calendar insertStartTime, Calendar insertEndTime) + public int processArchiveRecords(Calendar insertStartTime, + Calendar insertEndTime, IDatabaseProcessor processor) throws DataAccessLayerException { DatabaseQuery dbQuery = new DatabaseQuery(this.getDaoClass()); dbQuery.addQueryParam("insertTime", insertStartTime, QueryOperand.GREATERTHANEQUALS); dbQuery.addQueryParam("insertTime", insertEndTime, QueryOperand.LESSTHAN); + dbQuery.addOrder("insertTime", true); dbQuery.addOrder("dataTime.refTime", true); - return (List) this.queryByCriteria(dbQuery); + return this.processByCriteria(dbQuery, processor); } protected static class DuplicateCheckStat { diff --git a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/processor/IDatabaseProcessor.java b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/processor/IDatabaseProcessor.java new file mode 100644 index 0000000000..9fd67b00cc --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/processor/IDatabaseProcessor.java @@ -0,0 +1,69 @@ +/** + * 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.database.processor; + +import java.util.List; + +/** + * Interface for working with a batched set of results inside a database + * session. Process can be called multiple times based on the batchSize of the + * processor. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Dec 9, 2013  2555      rjpeter     Initial creation
+ * 
+ * + * @author rjpeter + * @version 1.0 + */ + +public interface IDatabaseProcessor { + /** + * Perform any processing on this batch of objects. + * + * @param objects + * @return True if should continue processing, false otherwise. + */ + public boolean process(List objects); + + /** + * Perform any post processing if necessary. + */ + public void finish(); + + /** + * Get the batch size of the query. + * + * @return + */ + public int getBatchSize(); + + /** + * Set the batch size of the query. + * + * @param batchSize + */ + public void setBatchSize(int batchSize); +} diff --git a/edexOsgi/com.raytheon.uf.edex.dissemination/utility/edex_static/base/dissemination/handleOUP.py b/edexOsgi/com.raytheon.uf.edex.dissemination/utility/edex_static/base/dissemination/handleOUP.py index 0664a39c13..1c07e92756 100644 --- a/edexOsgi/com.raytheon.uf.edex.dissemination/utility/edex_static/base/dissemination/handleOUP.py +++ b/edexOsgi/com.raytheon.uf.edex.dissemination/utility/edex_static/base/dissemination/handleOUP.py @@ -35,6 +35,7 @@ # 08/17/12 DR 15304 D. Friedman Use unique output file names # 10/12/12 DR 15418 D. Friedman Use unique attachment file names # 11/20/13 DR 16777 D. Friedman Add a test mode. +# 12/05/16 DR 16842 D. Friedman Do not set product ID on MhsMessage # # @@ -412,7 +413,6 @@ def sendWANMsg(productId, prodPathName, receivingSite, handling, if attachedFilename: mhsMsg.addEnclosure(attachedFilename) - mhsMsg.setProductId(productId) #mhsMsg.setBodyFile(prodPathName) mhsMsg.addEnclosure(prodPathName) if priority == 0: diff --git a/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/DPADecoder-spring.xml b/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/DPADecoder-spring.xml index 7db114019d..e5e7eff311 100644 --- a/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/DPADecoder-spring.xml +++ b/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/DPADecoder-spring.xml @@ -18,11 +18,6 @@ - - - - diff --git a/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/hpeDHRDecoder-spring.xml b/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/hpeDHRDecoder-spring.xml index 40cdd388fc..c3e509e9dd 100644 --- a/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/hpeDHRDecoder-spring.xml +++ b/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/hpeDHRDecoder-spring.xml @@ -18,11 +18,6 @@ - - - - diff --git a/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/ohd-common.xml b/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/ohd-common.xml index 9a725f5707..a87ebe243a 100644 --- a/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/ohd-common.xml +++ b/edexOsgi/com.raytheon.uf.edex.ohd/res/spring/ohd-common.xml @@ -36,9 +36,18 @@ - - + + - - + + + + + + + + + \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.aww/res/spring/aww-common.xml b/ncep/gov.noaa.nws.ncep.edex.plugin.aww/res/spring/aww-common.xml index 69e7038955..1962c3d86c 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.aww/res/spring/aww-common.xml +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.aww/res/spring/aww-common.xml @@ -20,4 +20,9 @@ + + + + \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.nctext/res/spring/nctext-common.xml b/ncep/gov.noaa.nws.ncep.edex.plugin.nctext/res/spring/nctext-common.xml index f3432f11ea..ab1b4b5ece 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.nctext/res/spring/nctext-common.xml +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.nctext/res/spring/nctext-common.xml @@ -18,6 +18,8 @@ - - + + + \ No newline at end of file diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.nctext/res/spring/nctext-ingest.xml b/ncep/gov.noaa.nws.ncep.edex.plugin.nctext/res/spring/nctext-ingest.xml index d9bbe3e33f..5969e8d4be 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.nctext/res/spring/nctext-ingest.xml +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.nctext/res/spring/nctext-ingest.xml @@ -16,11 +16,6 @@ - - - - From 282d10fe6dcc026e8b3e6092626be86c45a03dd2 Mon Sep 17 00:00:00 2001 From: Steve Harris Date: Mon, 6 Jan 2014 14:08:08 -0500 Subject: [PATCH 08/62] 14.1.1-15 baseline Former-commit-id: f88ff2bde988b12b99f9b2f4472805808c9d60d5 [formerly 8bbd803ace38a9c4b322719ff8390c1dd9faeb36] [formerly d8e5799328e81f4107a217f39f550e9dbe4aac6f [formerly cb8eca2a0dfc0e2348301e8d9932db824ecaf34c]] Former-commit-id: d8e5799328e81f4107a217f39f550e9dbe4aac6f Former-commit-id: 35d8f5a2815b5d80d717501d8fff6d75a4b3c954 --- .../gfe/userPython/utilities/TkDefaults.py | 2 +- edexOsgi/build.edex/esb/conf/modes.xml | 1 + .../edex_static/base/gfe/isc/mergeGrid.py | 590 +-- .../hydroapps/whfs/bin/start_fcstservice | 1 + .../uengine/tasks/profile/MergeSounding.java | 3368 +++++++++-------- rpms/build/x86_64/build.sh | 4 +- 6 files changed, 2002 insertions(+), 1964 deletions(-) diff --git a/cave/build/static/common/cave/etc/gfe/userPython/utilities/TkDefaults.py b/cave/build/static/common/cave/etc/gfe/userPython/utilities/TkDefaults.py index a7d965d223..f54ccbaa03 100644 --- a/cave/build/static/common/cave/etc/gfe/userPython/utilities/TkDefaults.py +++ b/cave/build/static/common/cave/etc/gfe/userPython/utilities/TkDefaults.py @@ -2,7 +2,7 @@ from com.raytheon.viz.gfe import GFEPreference Options = [ - ('*visual', 'truecolor'), +# ('*visual', 'truecolor'), ('*background' , 'gray65'), ('*activeBackground' , 'gray83'), ('*blinkingHighlightColor' , 'CornSilk'), diff --git a/edexOsgi/build.edex/esb/conf/modes.xml b/edexOsgi/build.edex/esb/conf/modes.xml index babb2749d6..35b803374d 100644 --- a/edexOsgi/build.edex/esb/conf/modes.xml +++ b/edexOsgi/build.edex/esb/conf/modes.xml @@ -239,6 +239,7 @@ fssobs-ingest.xml fssobs-common.xml ldadmesonet-common.xml + manualIngest-common.xml dataaccess-common.xml ncgrib-common.xml nctext-common.xml diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/mergeGrid.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/mergeGrid.py index 709dca3594..48591a3fbb 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/mergeGrid.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/mergeGrid.py @@ -1,304 +1,304 @@ -## -# This software was developed and / or modified by Raytheon Company, +## +# 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. -# +# 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. -## - -import string, getopt, sys, time, gzip, os, iscTime, stat -import numpy -import LogStream, fcntl - -# -# merges two grids and histories together, input gridA is merged into gridB -# result is returned from mergeGrid. Grids are represented in the following -# manner: -# Scalar: (grid, history) -# Vector: ((magGrid, dirGrid), history) -# Weather: ((byteGrid, key), history) -# Discrete: ((byteGrid, key), history) -# -# SOFTWARE HISTORY -# -# Date Ticket# Engineer Description -# ------------ ---------- ----------- -------------------------- -# 07/06/09 1995 bphillip Initial Creation. -# 11/05/13 2517 randerso Improve memory utilization -# -# -# - - -class MergeGrid: - - #--------------------------------------------------------------------- - # Constructor - # Takes creationtime - seconds since Jan 1, 1970, to be used - # in the updating of the histories. - # siteID = site identifier for input grid - # inFillValue = input fill value indicator - # outFillValue = output fill value indicator - # areaMask = numerical mask of areas to merge from grid1 to grid2 - # gridType = 'SCALAR', 'VECTOR', 'WEATHER', 'DISCRETE' - #--------------------------------------------------------------------- - def __init__(self, creationTime, siteID, inFillValue, outFillValue, - areaMask, gridType, discreteKeys=None): - self.__creationTime = creationTime - self.__siteID = siteID - self.__inFillV = inFillValue - self.__outFillV = outFillValue - self.__areaMask = areaMask - self.__gridType = gridType - self.__discreteKeys = discreteKeys - - - - #--------------------------------------------------------------------- - # find key - # key = input key - # keymap = existing key maps (updated on exit) - # returns the index to use for the key. - #--------------------------------------------------------------------- - def __findKey(self, key, keyMap): - try: - index = keyMap.index(key) - return index - except: - keyMap.append(key) - return len(keyMap) - 1 - - #--------------------------------------------------------------------- - # commonize key - # wxA = input grid and key - # wxB = input grid and key - # returns a tuple (commonkey, gridA, gridB) where gridA and gridB - # now use the commonkey - #--------------------------------------------------------------------- - def __commonizeKey(self, wxA, wxB): - # make common key and make data changes in B - gridB = wxB[0] - key = wxA[1] - newGrid = numpy.zeros_like(gridB) - - for k in range(len(wxB[1])): - index = self.__findKey(wxB[1][k], key) - newGrid[gridB == k] = index - - return (key, wxA[0], newGrid) - - - #--------------------------------------------------------------------- - # update history strings - # historyA = history from input grid (None to delete history entry) - # historyB = history from base grid, list (None for no old grid.) - # returns an updated list of strings, each string is an encoded history - # returns None if no history is present. - #--------------------------------------------------------------------- - def __updateHistoryStrings(self, historyA, historyB): - - out = [] - - # removal any old entry - if historyB is not None: - for h in historyB: - index = string.find(h, ":" + self.__siteID + "_GRID") - if index == -1: - out.append(h) - - # if add mode, add in new entries - if historyA is not None: - for h in historyA: - out.append(h) - - if len(out) > 0: - return out - else: - return None - - #--------------------------------------------------------------------- - # merge scalar grid - # Note: gridA can be None, which indicates that the data - # is to be blanked out, i.e., made invalid. gridB can also be - # none, which indicates that there is no destination grid and one must - # be created. - #--------------------------------------------------------------------- - def __mergeScalarGrid(self, gridA, gridB): - if gridA is None and gridB is None: - return None - - # merge the grids - if gridA is not None: - mask = numpy.not_equal(gridA, self.__inFillV) - numpy.logical_and(mask, self.__areaMask, mask) - - if gridB is None: - return numpy.where(mask, gridA, self.__outFillV) - else: - return numpy.where(mask, gridA, gridB) - - # blank out the data - else: - return numpy.where(self.__areaMask, self.__outFillV, gridB) - - #--------------------------------------------------------------------- - # merge vector grid - # Note: gridA can be None, which indicates that the data - # is to be blanked out, i.e., made invalid. gridB can also be - # none, which indicates that there is no destination grid and one must - # be created. - #--------------------------------------------------------------------- - def __mergeVectorGrid(self, gridA, gridB): - if gridA is None and gridB is None: - return None - - # merge the grids - if gridA is not None: - mask = numpy.not_equal(gridA[0], self.__inFillV) - numpy.logical_and(mask, self.__areaMask, mask) - - if gridB is None: - magGrid = numpy.where(mask, gridA[0], self.__outFillV) - dirGrid = numpy.where(mask, gridA[1], 0.0) - else: - magGrid = numpy.where(mask, gridA[0], gridB[0]) - dirGrid = numpy.where(mask, gridA[1], gridB[1]) - return (magGrid, dirGrid) - - # blank out the data - else: - magGrid = numpy.where(self.__areaMask, self.__outFillV, gridB[0]) - dirGrid = numpy.where(self.__areaMask, 0.0, gridB[1]) - return (magGrid, dirGrid) - - - #--------------------------------------------------------------------- - # merge weather grid - # - # Note the outFillV is ignored for now, all out-of-bounds points will - # get the value. - #--------------------------------------------------------------------- - def __mergeWeatherGrid(self, gridA, gridB): - - if gridA is None and gridB is None: - return None - - noWx = "::::" - # merge the grids - if gridA is not None: - mask = numpy.not_equal(gridA[0], self.__inFillV) - numpy.logical_and(mask, self.__areaMask, mask) - - if gridB is None: #make an empty grid - noWxKeys = [] - noWxGrid = numpy.empty_like(gridA[0]) - noWxGrid.fill(self.__findKey(noWx, noWxKeys)) - gridB = (noWxGrid, noWxKeys) - (commonkey, remapG, dbG) = self.__commonizeKey(gridA, gridB) - mergedGrid = numpy.where(mask, remapG, dbG) - return (mergedGrid, commonkey) - - # blank out the data - else: - blankGrid = numpy.empty_like(gridB[0]) - blankGrid.fill(self.__findKey(noWx, gridB[1])) - key = gridB[1] - grid = numpy.where(self.__areaMask, blankGrid, gridB[0]) - return (grid, key) - - #--------------------------------------------------------------------- - # merge discrete grid - # - # Note the outFillV is ignored for now, all out-of-bounds points will - # get the first value in the discrete key. - #--------------------------------------------------------------------- - def __mergeDiscreteGrid(self, gridA, gridB): - if gridA is None and gridB is None: - return None - - noKey = self.__discreteKeys[0] - - # merge the grids - if gridA is not None: - mask = numpy.not_equal(gridA[0], self.__inFillV) - numpy.logical_and(mask, self.__areaMask) - - if gridB is None: #make an empty grid - noKeys = [] - noGrid = numpy.empty_like(gridA[0]) - noGrid.fill(self.__findKey(noKey, noKeys)) - gridB = (noGrid, noKeys) - - (commonkey, remapG, dbG) = \ - self.__commonizeKey(gridA, gridB) - mergedGrid = numpy.where(mask, remapG, dbG) - return (mergedGrid, commonkey) - - # blank out the data - else: - blankGrid = numpy.empty_like(gridB[0]) - blankGrid.fill(self.__findKey(noKey, gridB[1])) - key = gridB[1] - grid = numpy.where(self.__areaMask, blankGrid, gridB[0]) - return (grid, key) - - #--------------------------------------------------------------------- - # mergeGrid - # Merges the grid - # Scalar: (grid, history) - # Vector: ((magGrid, dirGrid), history) - # Weather: ((byteGrid, key), history) - # Discrete: ((byteGrid, key), history) - # gridA = input remapped grid, contains inFillV to denote invalid - # gridB = grid to have gridA mosaic'd into - # Note: gridA can be None, which indicates that the data - # is to be blanked out, i.e., made invalid. gridB can also be - # none, which indicates that there is no destination grid and one must - # be created. - #--------------------------------------------------------------------- - def mergeGrid(self, gridAIn, gridBIn): - # merge the grids - if gridAIn is not None: - gridA = gridAIn[0] - historyA = gridAIn[1] - else: - gridA = None - historyA = None - if gridBIn is not None: - gridB = gridBIn[0] - historyB = gridBIn[1] - else: - gridB = None - historyB = None - - if self.__gridType == 'SCALAR': - mergedGrid = self.__mergeScalarGrid(gridA, gridB) - - elif self.__gridType == 'VECTOR': - mergedGrid = self.__mergeVectorGrid(gridA, gridB) - - elif self.__gridType == 'WEATHER': - mergedGrid = self.__mergeWeatherGrid(gridA, gridB) - - elif self.__gridType == 'DISCRETE': - mergedGrid = self.__mergeDiscreteGrid(gridA, gridB) - - else: - mergedGrid = None - - # merge History - history = self.__updateHistoryStrings(historyA, historyB) - - return (mergedGrid, history) +# See the AWIPS II Master Rights File ("Master Rights File.pdf") for +# further licensing information. +## + +import string, getopt, sys, time, gzip, os, iscTime, stat +import numpy +import LogStream, fcntl + +# +# merges two grids and histories together, input gridA is merged into gridB +# result is returned from mergeGrid. Grids are represented in the following +# manner: +# Scalar: (grid, history) +# Vector: ((magGrid, dirGrid), history) +# Weather: ((byteGrid, key), history) +# Discrete: ((byteGrid, key), history) +# +# SOFTWARE HISTORY +# +# Date Ticket# Engineer Description +# ------------ ---------- ----------- -------------------------- +# 07/06/09 1995 bphillip Initial Creation. +# 11/05/13 2517 randerso Improve memory utilization +# +# +# + + +class MergeGrid: + + #--------------------------------------------------------------------- + # Constructor + # Takes creationtime - seconds since Jan 1, 1970, to be used + # in the updating of the histories. + # siteID = site identifier for input grid + # inFillValue = input fill value indicator + # outFillValue = output fill value indicator + # areaMask = numerical mask of areas to merge from grid1 to grid2 + # gridType = 'SCALAR', 'VECTOR', 'WEATHER', 'DISCRETE' + #--------------------------------------------------------------------- + def __init__(self, creationTime, siteID, inFillValue, outFillValue, + areaMask, gridType, discreteKeys=None): + self.__creationTime = creationTime + self.__siteID = siteID + self.__inFillV = inFillValue + self.__outFillV = outFillValue + self.__areaMask = areaMask + self.__gridType = gridType + self.__discreteKeys = discreteKeys + + + + #--------------------------------------------------------------------- + # find key + # key = input key + # keymap = existing key maps (updated on exit) + # returns the index to use for the key. + #--------------------------------------------------------------------- + def __findKey(self, key, keyMap): + try: + index = keyMap.index(key) + return index + except: + keyMap.append(key) + return len(keyMap) - 1 + + #--------------------------------------------------------------------- + # commonize key + # wxA = input grid and key + # wxB = input grid and key + # returns a tuple (commonkey, gridA, gridB) where gridA and gridB + # now use the commonkey + #--------------------------------------------------------------------- + def __commonizeKey(self, wxA, wxB): + # make common key and make data changes in B + gridB = wxB[0] + key = wxA[1] + newGrid = numpy.zeros_like(gridB) + + for k in range(len(wxB[1])): + index = self.__findKey(wxB[1][k], key) + newGrid[gridB == k] = index + + return (key, wxA[0], newGrid) + + + #--------------------------------------------------------------------- + # update history strings + # historyA = history from input grid (None to delete history entry) + # historyB = history from base grid, list (None for no old grid.) + # returns an updated list of strings, each string is an encoded history + # returns None if no history is present. + #--------------------------------------------------------------------- + def __updateHistoryStrings(self, historyA, historyB): + + out = [] + + # removal any old entry + if historyB is not None: + for h in historyB: + index = string.find(h, ":" + self.__siteID + "_GRID") + if index == -1: + out.append(h) + + # if add mode, add in new entries + if historyA is not None: + for h in historyA: + out.append(h) + + if len(out) > 0: + return out + else: + return None + + #--------------------------------------------------------------------- + # merge scalar grid + # Note: gridA can be None, which indicates that the data + # is to be blanked out, i.e., made invalid. gridB can also be + # none, which indicates that there is no destination grid and one must + # be created. + #--------------------------------------------------------------------- + def __mergeScalarGrid(self, gridA, gridB): + if gridA is None and gridB is None: + return None + + # merge the grids + if gridA is not None: + mask = numpy.not_equal(gridA, self.__inFillV) + numpy.logical_and(mask, self.__areaMask, mask) + + if gridB is None: + return numpy.where(mask, gridA, self.__outFillV) + else: + return numpy.where(mask, gridA, gridB) + + # blank out the data + else: + return numpy.where(self.__areaMask, self.__outFillV, gridB) + + #--------------------------------------------------------------------- + # merge vector grid + # Note: gridA can be None, which indicates that the data + # is to be blanked out, i.e., made invalid. gridB can also be + # none, which indicates that there is no destination grid and one must + # be created. + #--------------------------------------------------------------------- + def __mergeVectorGrid(self, gridA, gridB): + if gridA is None and gridB is None: + return None + + # merge the grids + if gridA is not None: + mask = numpy.not_equal(gridA[0], self.__inFillV) + numpy.logical_and(mask, self.__areaMask, mask) + + if gridB is None: + magGrid = numpy.where(mask, gridA[0], self.__outFillV) + dirGrid = numpy.where(mask, gridA[1], 0.0) + else: + magGrid = numpy.where(mask, gridA[0], gridB[0]) + dirGrid = numpy.where(mask, gridA[1], gridB[1]) + return (magGrid, dirGrid) + + # blank out the data + else: + magGrid = numpy.where(self.__areaMask, self.__outFillV, gridB[0]) + dirGrid = numpy.where(self.__areaMask, 0.0, gridB[1]) + return (magGrid, dirGrid) + + + #--------------------------------------------------------------------- + # merge weather grid + # + # Note the outFillV is ignored for now, all out-of-bounds points will + # get the value. + #--------------------------------------------------------------------- + def __mergeWeatherGrid(self, gridA, gridB): + + if gridA is None and gridB is None: + return None + + noWx = "::::" + # merge the grids + if gridA is not None: + mask = numpy.not_equal(gridA[0], self.__inFillV) + numpy.logical_and(mask, self.__areaMask, mask) + + if gridB is None: #make an empty grid + noWxKeys = [] + noWxGrid = numpy.empty_like(gridA[0]) + noWxGrid.fill(self.__findKey(noWx, noWxKeys)) + gridB = (noWxGrid, noWxKeys) + (commonkey, remapG, dbG) = self.__commonizeKey(gridA, gridB) + mergedGrid = numpy.where(mask, remapG, dbG) + return (mergedGrid, commonkey) + + # blank out the data + else: + blankGrid = numpy.empty_like(gridB[0]) + blankGrid.fill(self.__findKey(noWx, gridB[1])) + key = gridB[1] + grid = numpy.where(self.__areaMask, blankGrid, gridB[0]) + return (grid, key) + + #--------------------------------------------------------------------- + # merge discrete grid + # + # Note the outFillV is ignored for now, all out-of-bounds points will + # get the first value in the discrete key. + #--------------------------------------------------------------------- + def __mergeDiscreteGrid(self, gridA, gridB): + if gridA is None and gridB is None: + return None + + noKey = self.__discreteKeys[0] + + # merge the grids + if gridA is not None: + mask = numpy.not_equal(gridA[0], self.__inFillV) + numpy.logical_and(mask, self.__areaMask, mask) + + if gridB is None: #make an empty grid + noKeys = [] + noGrid = numpy.empty_like(gridA[0]) + noGrid.fill(self.__findKey(noKey, noKeys)) + gridB = (noGrid, noKeys) + + (commonkey, remapG, dbG) = \ + self.__commonizeKey(gridA, gridB) + mergedGrid = numpy.where(mask, remapG, dbG) + return (mergedGrid, commonkey) + + # blank out the data + else: + blankGrid = numpy.empty_like(gridB[0]) + blankGrid.fill(self.__findKey(noKey, gridB[1])) + key = gridB[1] + grid = numpy.where(self.__areaMask, blankGrid, gridB[0]) + return (grid, key) + + #--------------------------------------------------------------------- + # mergeGrid + # Merges the grid + # Scalar: (grid, history) + # Vector: ((magGrid, dirGrid), history) + # Weather: ((byteGrid, key), history) + # Discrete: ((byteGrid, key), history) + # gridA = input remapped grid, contains inFillV to denote invalid + # gridB = grid to have gridA mosaic'd into + # Note: gridA can be None, which indicates that the data + # is to be blanked out, i.e., made invalid. gridB can also be + # none, which indicates that there is no destination grid and one must + # be created. + #--------------------------------------------------------------------- + def mergeGrid(self, gridAIn, gridBIn): + # merge the grids + if gridAIn is not None: + gridA = gridAIn[0] + historyA = gridAIn[1] + else: + gridA = None + historyA = None + if gridBIn is not None: + gridB = gridBIn[0] + historyB = gridBIn[1] + else: + gridB = None + historyB = None + + if self.__gridType == 'SCALAR': + mergedGrid = self.__mergeScalarGrid(gridA, gridB) + + elif self.__gridType == 'VECTOR': + mergedGrid = self.__mergeVectorGrid(gridA, gridB) + + elif self.__gridType == 'WEATHER': + mergedGrid = self.__mergeWeatherGrid(gridA, gridB) + + elif self.__gridType == 'DISCRETE': + mergedGrid = self.__mergeDiscreteGrid(gridA, gridB) + + else: + mergedGrid = None + + # merge History + history = self.__updateHistoryStrings(historyA, historyB) + + return (mergedGrid, history) diff --git a/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/start_fcstservice b/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/start_fcstservice index 5bc6296ec2..1f765b2d1a 100644 --- a/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/start_fcstservice +++ b/nativeLib/files.native/awipsShare/hydroapps/whfs/bin/start_fcstservice @@ -19,5 +19,6 @@ export CLASSPATH=$DB_DRIVER_PATH CLASSPATH=$CLASSPATH:$WHFS_BIN_DIR/fcstservice.jar #Execute Lhvm +unset GNOME_DESKTOP_SESSION_ID xterm -T "fcstservice" -iconic \ -e $SYS_JAVA_DIR/bin/java ohd.hseb.fcstservice.LhvmApplicationWindow $JDBCURL & diff --git a/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/MergeSounding.java b/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/MergeSounding.java index a73f05cb1a..499a2c7789 100644 --- a/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/MergeSounding.java +++ b/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/MergeSounding.java @@ -1,14 +1,14 @@ package gov.noaa.nws.ncep.edex.uengine.tasks.profile; +import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; +import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer; + import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; //import edu.emory.mathcs.backport.java.util.Collections; -import gov.noaa.nws.ncep.common.tools.IDecoderConstantsN; -import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer; -import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer2; /** * @@ -29,9 +29,9 @@ import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer2; * 12/2010 301 T. Lee/NCEP Re-factored for BUFRUA * 5/10/2011 301 C. Chen added rhToDewpoint(), tempToVapr() * 02/28/2012 Chin Chen modify several sounding query algorithms for better performance - * 8/2012 T. Lee/NCEP Removed missing wind interpolation - * 8/2012 T. Lee/NCEP Fixed max wind merging; May fix NSHARP EL calculation - + * 8/2012 T. Lee/NCEP Removed missing wind interpolation + * 8/2012 T. Lee/NCEP Fixed max wind merging; May fix NSHARP EL calculation + * 12/2013 T. Lee/NCEP Fixed missing height at top level before sorting * * * @author T. Lee @@ -39,1664 +39,1700 @@ import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer2; */ public class MergeSounding { - final float RMISSD = IDecoderConstantsN.UAIR_FLOAT_MISSING; - final int IMISSD = IDecoderConstantsN.INTEGER_MISSING; - - /** - * Default constructor - */ - public MergeSounding() { - } - - /* - * Process native sounding data. Convert specific humidity to dew point - * temperature then compute the moist height. - */ - public List nativeModelSounding(List sls, - float elevation) { - spfhToDewpoint(sls); - constructHeight(sls, elevation); - return sls; - } - - /* - * Process upper air sounding data. Note that TTAA is the original/sorted - * data, while MAN is the TTAA without underground data and MAN_D is the - * TTAA for display, i.e., the first level is the surface level, any under - * -ground levels will be above the surface level. - */ - public List mergeUairSounding(String level, - List ttaa, Listttbb, - List ttcc, Listttdd, - List ppaa, Listppbb, - List ppcc, Listppdd, - List trop_a, List trop_c, - List wmax_a, List wmax_c, - float elevation ) { - List sndata = new ArrayList(); - List man = null; -//System.out.println ( "From mergeUairSounding " ); - /*///for debug -//System.out.println("TTAA:"); - for (NcSoundingLayer l: ttaa){ - //System.out.println("P="+l.getPressure()+"H="+l.getGeoHeight()+"T="+l.getTemperature()+"D="+l.getDewpoint()+"Wd="+l.getWindDirection()+"Ws="+l.getWindSpeed()); - } -//System.out.println("TTBB:"); - for (NcSoundingLayer l: ttbb){ - //System.out.println("P="+l.getPressure()+"H="+l.getGeoHeight()+"T="+l.getTemperature()+"D="+l.getDewpoint()+"Wd="+l.getWindDirection()+"Ws="+l.getWindSpeed()); - } -//System.out.println("PPAA:"); - for (NcSoundingLayer l: ppaa){ - //System.out.println("P="+l.getPressure()+"H="+l.getGeoHeight()+"T="+l.getTemperature()+"D="+l.getDewpoint()+"Wd="+l.getWindDirection()+"Ws="+l.getWindSpeed()); - } -//System.out.println("PPBB:"); - for (NcSoundingLayer l: ppbb){ - //System.out.println("P="+l.getPressure()+"H="+l.getGeoHeight()+"T="+l.getTemperature()+"D="+l.getDewpoint()+"Wd="+l.getWindDirection()+"Ws="+l.getWindSpeed()); - }*/ - // Return the specific levels requested by users - if ( ttaa.size() > 0 ) { - Collections.sort(ttaa, new reverseSortByPressure()); - //System.out.println("TTAA sounding: "); - //for ( NcSoundingLayer soundLy : ttaa ){ - // System.out.print(soundLy.getPressure() + " , "); - //} - //System.out.println(); - if (level.toUpperCase().equalsIgnoreCase("MAN")) { - return ttaa; - } - man = removeUnderGround(ttaa); - - } else { - man=ttaa; - if (level.toUpperCase().equalsIgnoreCase("MAN")) { - return setMissing(); - } - - } - - - // Sorting the data - - if ( ttbb.size() > 0) { - Collections.sort(ttbb, new reverseSortByPressure()); - //System.out.println("TTBB sounding: "); - //for ( NcSoundingLayer soundLy : ttbb ){ - // System.out.print(soundLy.getPressure() + " , "); - //} - //System.out.println(); - } - - if ( ttcc.size() > 0) { - Collections.sort(ttcc, new reverseSortByPressure()); - //System.out.println("TTCC sounding: "); - ////for ( NcSoundingLayer soundLy : ttcc ){ - // System.out.print(soundLy.getPressure() + " , "); - //} - //System.out.println(); - } - - if ( ttdd.size() > 0) { - Collections.sort(ttdd, new reverseSortByPressure()); - //System.out.println("TTDD sounding: "); - //for ( NcSoundingLayer soundLy : ttdd ){ - // System.out.print(soundLy.getPressure() + " , "); - //} - //System.out.println(); - } - - if ( ppaa.size() > 0 ) { - if (checkWindData(ppaa)) { - Collections.sort(ppaa, new MergeSounding.sortByHeight()); - //System.out.println("TTAA sounding: "); - //for ( NcSoundingLayer soundLy : ttaa ){ - // System.out.print(soundLy.getPressure() + " , "); - //} - //System.out.println(); - } else { - Collections.sort(ppaa, new MergeSounding.reverseSortByPressure()); - //System.out.println("TTAA sounding: "); - //for ( NcSoundingLayer soundLy : ttaa ){ - // System.out.print(soundLy.getPressure() + " , "); - //} - //System.out.println(); - } - } - - - if ( ppcc.size() > 0 ) { - if (checkWindData(ppcc)) { - Collections.sort(ppcc, new MergeSounding.sortByHeight()); - //System.out.println("PPCC sounding: "); - //for ( NcSoundingLayer soundLy : ppcc ){ - // System.out.print(soundLy.getPressure() + " , "); - // } - //System.out.println(); - } else { - Collections.sort(ppcc, new MergeSounding.reverseSortByPressure()); - //System.out.println("PPCC sounding: "); - //for ( NcSoundingLayer soundLy : ppcc ){ - // System.out.print(soundLy.getPressure() + " , "); - //} - //System.out.println(); - } - } - - if ( ppbb.size() > 0 ) { - if (checkWindData(ppbb)) { - Collections.sort(ppbb, new MergeSounding.sortByHeight()); - //System.out.println("PPBB sounding: "); - //for ( NcSoundingLayer soundLy : ppbb ){ - // System.out.print(soundLy.getPressure() + " , "); - //} - //System.out.println(); - } else { - Collections.sort(ppbb, new MergeSounding.reverseSortByPressure()); - //System.out.println("PPBB sounding: "); - //for ( NcSoundingLayer soundLy : ppbb ){ - // System.out.print(soundLy.getPressure() + " , "); - //} - //System.out.println(); - } - } - - if ( ppdd.size() > 0 ) { - - if (checkWindData(ppdd)) { - Collections.sort(ppdd, new MergeSounding.sortByHeight()); - //System.out.println("PPDD sounding: "); - //for ( NcSoundingLayer soundLy : ppdd ){ - // System.out.print(soundLy.getPressure() + " , "); - //} - //System.out.println(); - } else { - Collections.sort(ppdd, new MergeSounding.reverseSortByPressure()); - //System.out.println("PPDD sounding: "); - //for ( NcSoundingLayer soundLy : ppdd ){ - // System.out.print(soundLy.getPressure() + " , "); - //} - //System.out.println(); - } - - } - - // Find surface data, return if users request surface data only. - NcSoundingLayer sl = new NcSoundingLayer(); - sl = getSurfaceData(man, ttbb, ppbb, elevation); - sndata.add(0, sl); -//System.out.println ( "sndataSize in mergeUairSounding(), after calling getSurfaceData(): " + sndata.size() ); - if ( isNumber(level) >= 0 ) { - if ( equal(0.f, Float.valueOf(level.trim()).floatValue()) || - equal(sl.getPressure(), Float.valueOf(level.trim()).floatValue())) { - //System.out.println("Returning surface data...."); - return sndata; - } - } - - // Merge mandatory data -//System.out.println ( "Just before calling mergeMandatory() " ); - mergeMandatory(man, ttcc, sndata); - int sndataSize = sndata.size(); -//System.out.println ( "sndataSize in mergeUairSounding(), after calling mergeMandatory(): " + sndata.size() ); - - // Check if the single level is mandatory or not - if ( isNumber(level) >= 0 ) { - for ( int kk = 0; kk < sndata.size(); kk++) { - if ( equal(Float.valueOf(level.trim()).floatValue(), sndata.get(kk).getPressure())) { - sl.setPressure(sndata.get(kk).getPressure()); - sl.setTemperature(sndata.get(kk).getTemperature()); - sl.setDewpoint(sndata.get(kk).getDewpoint()); - sl.setWindDirection(sndata.get(kk).getWindDirection()); - sl.setWindSpeed(sndata.get(kk).getWindSpeed()); - sl.setGeoHeight(sndata.get(kk).getGeoHeight()); - sndata.clear(); - sndata.add(sl); - //System.out.println( "single layer of sounding added to sndata" ); - return sndata; - } - } - } - - // Merge mandatory winds - mergeMandatoryWinds (ppaa, ppcc, sndata); -//System.out.println ( "sndataSize in mergeUairSounding(), after calling mergeMandatoryWinds(): " + sndata.size() ); - // Merge tropopause - mergeTropSigTemp (trop_a, trop_c, sndata); -//System.out.println ( "sndataSize in mergeUairSounding(), after calling" + -// " mergeTropSigTemp() for merging trop_a and trop_c: " + sndata.size() ); - // Merge TTBB - mergeTropSigTemp (ttbb, ttdd, sndata); -//System.out.println ( "sndataSize in mergeUairSounding(), after calling" + -// " mergeTropSigTemp() for merging ttbb and ttdd: " + sndata.size() ); - // Construct height for ttbb - constructTtbbHeight(sndata); -//System.out.println ( "sndataSize in mergeUairSounding(), after calling" + -// " constructTtbbHeight(): " + sndata.size() ); - // Merge significant winds on pressure surfaces - if (!checkWindData(ppbb)) { - mergeSigMaxWindOnPressure(ppbb,ppdd,sndata); - //System.out.println ( "sndataSize in mergeUairSounding(), after calling" + -// " mergeSigMaxWindOnPressure() for merging ppbb and ppdd: " + sndata.size() ); - } - - mergeSigMaxWindOnPressure(wmax_a,wmax_c,sndata); -//System.out.println ( "sndataSize in mergeUairSounding(), after calling" + -// " mergeSigMaxWindOnPressure() for merging wmax_a and wmax_c: " + sndata.size() ); - - constructPpbbHeight(sndata); -//System.out.println ( "sndataSize in mergeUairSounding(), after calling" + -// " constructPpbbHeight()" + sndata.size() ); - if (checkWindData(ppbb)) { - mergeSigWindOnHeight(ppbb,ppdd,sndata); - //System.out.println ( "sndataSize in mergeUairSounding(), after calling" + -// " mergeSigWindOnHeight() for merging ppbb and ppdd: " + sndata.size() ); - constructPpbbPressure(sndata); - //System.out.println ( "sndataSize in mergeUairSounding(), after calling" + -// " constructPpbbPressure()" + sndata.size() ); - } - - // Reorder sounding profile so the first level is the surface data. - // No need to reorder now becuz surface data is always the 1st level. - //reOrderSounding(sndata); - - // Interpolate missing temperature, dew point and winds. - constructMissing(1,sndata); - constructMissing(2,sndata); - //constructMissing(3,sndata); - - // Return single level or add underground mandatory data to the sounding profile - if ( isNumber (level) == 0 ) { - float rlev = new Integer(Integer.parseInt(level.trim())).floatValue(); - return getSingLevel(rlev, sndata); - } else if ( isNumber (level) == 1 ) { - float rlev = new Float(Float.parseFloat(level.trim())); - return getSingLevel(rlev, sndata); - } else { - return addUnderGround(ttaa,sndata); - } - - } - - /* - * Check an alpha-numerical string is a number or characters. - */ - public int isNumber (String level) { - try { - if (Integer.parseInt(level) >=0 ) { - return 0; - } else { - return -1; - } - } catch (NumberFormatException nfe1){ - try { - if (Float.parseFloat(level) >= 0.f) { - return 1; - } else { - return -1; - } - } catch (NumberFormatException nfe2) { - try { - if (Double.parseDouble(level) >= 0.) { - return 2; - } else { - return -1; - } - } catch (NumberFormatException nfe3) { - return -1; - } - } - } - } - - /* - * convert specific humidity to dew point temperature. - */ - float elevation; - - public List spfhToDewpoint(List sndata) { - float spfh, pres; - float dwpc = RMISSD; - - for (NcSoundingLayer layer: sndata) { - if (layer.getDewpoint() == RMISSD) { - spfh = layer.getSpecHumidity(); - pres = layer.getPressure(); - - if (spfh == RMISSD || pres == RMISSD || spfh <= 0.f - || pres <= 0.f) { - continue; - } else { - float rmix = spfh / (1.f - spfh); - float e = (pres * rmix) / (.62197f + rmix); - e = e / (1.001f + ((pres - 100.f) / 900.f) * .0034f); - dwpc = (float) (Math.log(e / 6.112) * 243.5 / (17.67 - Math - .log((e / 6.112)))); - layer.setDewpoint(dwpc); - ////System.out.println("spfhToDewpoint dwpc: " + dwpc); - } - - } - } - return sndata; - } - /* - * computes DWPC from TMPC and RELH - * Note: If DWPC is less than -190 degrees C, it is treated as - * missing data - * Code is based on GEMPAK's prrhdp.f - */ - public List rhToDewpoint(List sndata) { - float rh, vapr,vaps, temp; - float dwpc = RMISSD; - - for (NcSoundingLayer layer: sndata) { - if (layer.getDewpoint() == RMISSD) { - rh = layer.getRelativeHumidity(); - temp = layer.getTemperature(); - - if (rh == RMISSD || temp == RMISSD ) { - continue; - } else { - vaps = tempToVapr(temp); - vapr = rh * vaps /100; - if(vapr < Math.exp(-30)) - continue; - else { - dwpc = (float) (243.5 * ( Math.log(6.112) - Math.log(vapr)) / (Math.log(vapr) - Math.log(6.112)-17.67)); - layer.setDewpoint(dwpc); - ////System.out.println("rhToDewpoint dwpc: " + dwpc); - } - } - } - } - return sndata; - } - /* - * computes VAPR from TMPC - * Code is based on GEMPAK's prvapr.f - */ - private float tempToVapr(float temp){ - return(float)(6.112 * Math.exp((17.67* temp)/(temp+243.5))); - } - - private void constructHeight(List sndata, float elev) { - - /* - * For native model sounding, using hypsometric equation to build height - */ - elevation = elev; - int lev = sndata.size(); - float tb = RMISSD, tdb = RMISSD, pb = RMISSD; - float tt = RMISSD, tdt = RMISSD, pt = RMISSD; - float dwptsf, psfc, tmpcsf, scaleh, mhgt = RMISSD; - - for (int k = 0; k < lev; k++) { - - if (k == 0) { - tmpcsf = sndata.get(k).getTemperature(); - dwptsf = sndata.get(k).getDewpoint(); - psfc = sndata.get(k).getPressure(); - tb = tmpcsf; - tt = tmpcsf; - tdb = dwptsf; - tdt = dwptsf; - pb = psfc; - pt = psfc; - - scaleh = scaleHeight(tb, tt, tdb, tdt, pb, pt); - mhgt = moistHeight(elevation, pb, pt, scaleh); - } else { - tt = sndata.get(k).getTemperature(); - tdt = sndata.get(k).getDewpoint(); - pt = sndata.get(k).getPressure(); - scaleh = scaleHeight(tb, tt, tdb, tdt, pb, pt); - - mhgt = moistHeight(mhgt, pb, pt, scaleh); - tb = tt; - tdb = tdt; - pb = pt; - - } - sndata.get(k).setGeoHeight(mhgt); - } - } - - /* - * Compute moist height. - */ - private float moistHeight(float zb, float pb, float pt, float scale) { -//System.out.println("From moistHeight: "); - if (zb == RMISSD || pb == RMISSD || pt == RMISSD || scale == RMISSD) { - return RMISSD; - } else { - //System.out.println("the computed moistHeight is " + (float) (zb + scale * Math.log(pb / pt))); - return (float) (zb + scale * Math.log(pb / pt)); - } - } - - /* - * Compute scale height. - */ - private float scaleHeight(float tb, float tt, float tdb, float tdt, - float pb, float pt) { -//System.out.println("From scaleHeight: " ); - final float RDGAS = 287.04f, GRAVTY = 9.80616f, RKAP = RDGAS / GRAVTY; - if (tb == RMISSD || tt == RMISSD || pb == RMISSD || pt == RMISSD) { - return RMISSD; - } else { - float tvb = virtualTemperature(tb, tdb, pb); - float tvt = virtualTemperature(tt, tdt, pt); - //System.out.println("tvb = " + tvb); - //System.out.println("tvt = " + tvt); - if (tvb == RMISSD || tvt == RMISSD) { - return RMISSD; - } else { - float tav = (tvb + tvt) / 2.0f; - - //System.out.println("tav = " + tav); - //System.out.println("RKAP * tav = " + RKAP * tav); - return (RKAP * tav); - } - } - } - - /* - * Compute virtual temperature - */ - private float virtualTemperature(float tt, float td, float pres) { - if (tt == RMISSD || pres == RMISSD) { - return RMISSD; - } else if (td == RMISSD) { - return celciusToKevin(tt); - } else { - float tmpk = celciusToKevin(tt); - float rmix = mixingRatio(td, pres); - if (rmix == RMISSD) { - return celciusToKevin(tt); - } else { - return tmpk * (1.f + .001f * rmix / .62197f) - / (1.f + .001f * rmix); - } - } - } - - /* - * Convert Celcius to Kelvin. - */ - float TMCK = 273.15f; - - private float celciusToKevin(float tc) { - if (tc == RMISSD) { - return RMISSD; - } else { - return (tc + TMCK); - } - } - - /* - * Compute mixing ratio from DWPC and PRES. - */ - private float mixingRatio(float td, float pres) { - if (td == RMISSD || pres == RMISSD) { - return RMISSD; - } else { - float vapr = vaporPressure(td); - if (vapr == RMISSD) { - return RMISSD; - } - - float corr = (1.001f + ((pres - 100.f) / 900.f) * .0034f); - - float e = corr * vapr; - if (e > (.5f * pres)) { - return RMISSD; - } else { - return .62197f * (e / (pres - e)) * 1000.f; - } - } - } - - /* - * Compute vapor pressure from DWPC. - */ - private float vaporPressure(float td) { - if (td == RMISSD) { - return RMISSD; - } else { - return (6.112f * (float) Math.exp((17.67 * td) / (td + 243.5))); - } - } - - /* - * Merge observed sounding data - */ - - /* - * Check significant wind data (PPBB/PPDD) to see if the data is reported on - * pressure or height surfaces. Return TRUE if reported on height. The - * input can be PPBB or PPDD winds. (MR_CHKW) - * - * Note that this is coded different from MR_CHKW, in that it will set zwind - * to false only if pressure is less than 0. An odd logic. - */ - public boolean checkWindData(List sndata) { - boolean zwind = true; - for (int kk = 0; kk < sndata.size(); kk++) { - if (sndata.get(kk).getPressure() != RMISSD) { - zwind = false; - } - } - return zwind; - } - - /* - * Find surface data. (MR_SRFC) - */ - final int NPARMS = 7; - - - public NcSoundingLayer getSurfaceData(List man, - List ttbb, List ppbb, float elevation ) { - float pres = RMISSD; - NcSoundingLayer sl_sfc = new NcSoundingLayer(); - - /* - * Check for surface information in mandatory data. - */ - if (man.size() < 1) { - for (int k = 0; k < NPARMS; k++) { - sl_sfc.setPressure(RMISSD); - sl_sfc.setTemperature(RMISSD); - sl_sfc.setDewpoint(RMISSD); - sl_sfc.setWindDirection(RMISSD); - sl_sfc.setWindSpeed(RMISSD); - sl_sfc.setGeoHeight(RMISSD); - sl_sfc.setOmega(RMISSD); - return sl_sfc; - } - } else { - - // If surface pressure is higher than 1080mb, set to missing. - // Note that GEMPAK sets it to 1060mb. - pres = man.get(0).getPressure(); - if (pres > 1080.) { - sl_sfc.setPressure(RMISSD); - } else { - sl_sfc.setPressure(pres); - } - sl_sfc.setTemperature(man.get(0).getTemperature()); - sl_sfc.setDewpoint(man.get(0).getDewpoint()); - sl_sfc.setWindDirection(man.get(0).getWindDirection()); - sl_sfc.setWindSpeed(man.get(0).getWindSpeed()); - sl_sfc.setGeoHeight(elevation); - sl_sfc.setOmega(man.get(0).getOmega()); - } - - /* - * Find the first reporting mandatory level above the surface. - */ - float pman = RMISSD; - int iman = 1; - while (pman == RMISSD && iman < man.size()) { - if (man.get(iman).getPressure() != RMISSD - && man.get(iman).getTemperature() != RMISSD - && man.get(iman).getGeoHeight() != RMISSD) { - pman = man.get(0).getPressure(); - } - iman++; - } - - /* - * If surface pressure is missing or is less than first reporting - * mandatory level, set all surface data to missing - */ - if (pres == RMISSD || (pres < pman && pman != RMISSD)) { - sl_sfc = setMissing().get(0); - } - - /* - * If the surface significant temperature data is not missing, use it to - * replace the surface pressure, temperature and dewpoint. The check for - * significant level pressure to be less than or equal to pman eliminates - * using wildly erroneous data. - */ - - if (ttbb.size() >= 1 && ttbb.get(0).getPressure() != RMISSD - && ttbb.get(0).getTemperature() != RMISSD) { - pman = sl_sfc.getPressure(); - float psql = ttbb.get(0).getPressure(); - if (pman == RMISSD || equal(pman, psql)) { - sl_sfc.setPressure(ttbb.get(0).getPressure()); - sl_sfc.setTemperature(ttbb.get(0).getTemperature()); - sl_sfc.setDewpoint(ttbb.get(0).getDewpoint()); - } - - } - - /* - * If the first significant level wind data is surface information, use - * it to replace the surface data if the pressure is at surface. - */ - - // PPBB reported on P-surfaces. - - if (checkWindData(ppbb)) { - if (ppbb.size() > 0 && ppbb.get(0).getGeoHeight() == 0. - && ppbb.get(0).getWindDirection() != RMISSD) { - sl_sfc.setWindDirection(ppbb.get(0).getWindDirection()); - sl_sfc.setWindSpeed(ppbb.get(0).getWindSpeed()); - } - - } else { - if (ppbb.size() > 0 && ppbb.get(0).getPressure() != RMISSD - && ppbb.get(0).getWindDirection() != RMISSD) { - pman = sl_sfc.getPressure(); - float psgl = Math.abs(ppbb.get(0).getPressure()); - if (pman == RMISSD || equal(pman, psgl)) { - sl_sfc.setPressure(psgl); - sl_sfc.setWindDirection(ppbb.get(0).getWindDirection()); - sl_sfc.setWindSpeed(ppbb.get(0).getWindSpeed()); - } - } - } - - /* - * Add surface data to station data. - */ - return sl_sfc; - } - - - private boolean equal(float x, float y) { - final float RDIFFD = .0001f; - if ( (x + y) == 0. ) { - return Math.abs(x-y) < RDIFFD; - } else { - return Math.abs(x - y) / Math.abs( (x+y) / 2.) < RDIFFD; - } - } - - /* - * Merge the mandatory below 100 mb data and the mandatory above data. sndata - * has surface observation ONLY. - * (MR_MAND) - */ - - public void mergeMandatory( - List man_a, List man_c, - List sndata ) { - - float plast; - if ( man_a.size() < 1 && man_c.size() < 1 ) { - return; - } - - if ( sndata.get(0).getPressure() == RMISSD) { - plast = 2000.f; - } else { - plast = sndata.get(0).getPressure(); - } - - /* - * Move the mandatory data below 100mb to the output array, sndata. - * Check that pressure is not missing and is decreasing. - */ - float pres; - if ( man_a.size() > 0 ) { - for (int kk = 0; kk < man_a.size(); kk++) { - pres = man_a.get(kk).getPressure(); - if (pres < plast && pres != RMISSD - && ( man_a.get(kk).getTemperature() != RMISSD - || man_a.get(kk).getWindDirection() != RMISSD)) { - addDataToList(kk, man_a, sndata); - plast = pres; - } - } - } - - /* - * Move the mandatory data above 100 mb to the output array. - */ - if ( man_c.size() > 0 ) { - for (int kk = 0; kk < man_c.size(); kk++) { - pres = man_c.get(kk).getPressure(); - if (pres < plast && pres != RMISSD - && man_c.get(kk).getTemperature() != RMISSD) { - addDataToList(kk, man_c, sndata); - plast = man_c.get(kk).getPressure(); - } - } - } - } - - /* - * Merge the mandatory below 100 mb wind data and the mandatory above wind - * data. (MR_MANW) - */ - public void mergeMandatoryWinds( List man_wa, - List man_wc, List sndata ) { - - if ( man_wa.size() < 1 && man_wc.size() < 1 ) { - return; - } - - /* - * Append data. - */ - if (man_wc.size() > 0) { - for (int kk = 0; kk < man_wc.size(); kk++) { - man_wa.add(man_wc.get(kk)); - } - } - /* - * Loop through mandatory wind data. - */ - for (int lev = 0; lev < man_wa.size(); lev++) { - - /* - * If this is the correct level, add wind data. - */ - boolean found = false; - float ppp = man_wa.get(lev).getPressure(); - for (int kk = 0; kk < sndata.size() && !found; kk++ ) { - float pres = sndata.get(kk).getPressure(); - if (equal(ppp,pres)) { - if (sndata.get(kk).getWindDirection() == RMISSD) { - sndata.get(kk).setWindDirection(man_wa.get(lev).getWindDirection()); - sndata.get(kk).setWindSpeed(man_wa.get(lev).getWindSpeed()); - } - found = true; - } - } - - /* - * If not found, add to the list - */ - if (!found) { - float ddd = man_wa.get(lev).getWindDirection(); - if (ppp != RMISSD && ddd != RMISSD) { - addDataToList(lev,man_wa,sndata); - } - } - } - } - - /* - * Merge tropopause, max wind and significant temperature data (TTBB) to the - * station data array. The input parameter could be tropopause data or - * significant temperature data. MR_TROP & MR_SIGT - */ - public List mergeTropSigTemp( List trop_a, - List trop_c, List sndata) { - if ( trop_a.size() < 1 && trop_c.size() < 1 ) { - return sndata; - } - - /* - * Append two lists of wind data. - */ - if ( trop_c.size() > 0 ) { - for (int kk = 0; kk < trop_c.size(); kk++) { - trop_a.add(trop_c.get(kk)); - } - } - - for (int lev = 0; lev < trop_a.size(); lev++) { - boolean found = false; - float ppp = trop_a.get(lev).getPressure(); - for (int kk = 0; kk < sndata.size() && !found; kk++) { - float pres = sndata.get(kk).getPressure(); - if (equal(ppp ,pres)) { - - // add data to missing - if (sndata.get(kk).getTemperature() == RMISSD) { - sndata.get(kk).setTemperature(trop_a.get(lev).getTemperature()); - sndata.get(kk).setDewpoint(trop_a.get(lev).getDewpoint()); - } - - if (sndata.get(kk).getWindDirection() == RMISSD) { - sndata.get(kk).setWindDirection( - trop_a.get(lev).getWindDirection()); - sndata.get(kk).setWindSpeed( - trop_a.get(lev).getWindSpeed()); - - } - found = true; - } - } - - /* - * if not found, add to the list - */ - if (!found) { - float ttt = trop_a.get(lev).getTemperature(); - if (ppp != RMISSD && ttt != RMISSD) { - addDataToList(lev,trop_a,sndata); - } - } - - } - - /* - * Sort the sounding data in descending order. - */ - Collections.sort(sndata, new reverseSortByPressure()); - return sndata; - } - - /* - * Compute height at significant temperature levels (TTBB) using a moist - * hydrostatic computation. (MR_SCMZ) - */ - public void constructTtbbHeight(List sndata) { - boolean mand = false; - boolean newblock = true; - int blev = 0, tlev = 0; - float[] scale = new float[200]; - float pb, zb, tb, tdb, zlev, plev; - float pt, zt = 0.f, tt, tdt, znew = 0.f; - - if ( sndata.size() <= 2) return; - - for (int nlev = 0; nlev < sndata.size(); nlev++) { -// //System.out.println("blev = " + blev ); - //System.out.println("nlev = " + nlev ); -// //System.out.println("tlev = " + tlev ); - if (newblock) { - if (sndata.get(nlev).getGeoHeight() != RMISSD - && sndata.get(nlev).getPressure() != RMISSD - && sndata.get(nlev).getTemperature() != RMISSD) { - - blev = nlev; - newblock = false; - // double h = sndata.get(nlev).getGeoHeight(); -// if ( h < 0 && h != -9999 ) - //System.out.println("if newblock - height is negative: " + h ); - } - } else { - if (sndata.get(nlev).getGeoHeight() != RMISSD - && sndata.get(nlev).getTemperature() != RMISSD) { - tlev = nlev; - mand = true; -//System.out.println("tlev is now set to nlev and its value is " + tlev ); - // double h = sndata.get(nlev).getGeoHeight(); - // if ( h < 0 && h != -9999 ) - //System.out.println("if not newblock - height is negative: " + h ); - } - } - - /* - * Compute scale height to this level - */ - if (mand) { - pb = sndata.get(blev).getPressure(); - zb = sndata.get(blev).getGeoHeight(); - tb = sndata.get(blev).getTemperature(); - tdb = sndata.get(blev).getDewpoint(); - zlev = sndata.get(blev).getGeoHeight(); - plev = sndata.get(blev).getPressure(); - - for (int kk = blev + 1; kk <= tlev; kk++) { - pt = sndata.get(kk).getPressure(); - zt = sndata.get(kk).getGeoHeight(); - tt = sndata.get(kk).getTemperature(); - tdt = sndata.get(kk).getDewpoint(); - scale[kk] = scaleHeight(tb, tt, tdb, tdt, pb, pt); - //System.out.println("scale[" + kk + "] = " + scale[kk]); - znew = moistHeight(zb, pb, pt, scale[kk]); - if (znew != RMISSD) { - pb = pt; - tb = tt; - tdb = tdt; - zb = znew; -// if ( znew < 0 ) - //System.out.println("negative moist height = " + znew ); - } - } - - /* - * Compute the scaling factor so the computed moist height is - * consistent at the mandatory level. Then recompute the height. - */ - float s = (zt - zlev) / (znew - zlev); - //System.out.println("scaling factor s = " + s); - float zbb = zlev; - float pbb = plev; - for (int kk = blev + 1; kk < tlev; kk++) { - pt = sndata.get(kk).getPressure(); - zt = sndata.get(kk).getGeoHeight(); - scale[kk] = scale[kk] * s; - //System.out.println("Now, scale[" + kk + "] = " + scale[kk]); - znew = moistHeight(zbb, pbb, pt, scale[kk]); - if (znew != RMISSD) { - pbb = pt; - zbb = znew; - sndata.get(kk).setGeoHeight(znew); -// double h = sndata.get(kk).getGeoHeight(); -// if ( h < 0 && h != RMISSD ) - //System.out.println("newly computed moist height is negative " + h ); - } - } - mand = false; - newblock = true; - - if ( (tlev+1) != sndata.size() ) { - if ( sndata.get(tlev+1).getGeoHeight() == RMISSD - && sndata.get(tlev+1).getPressure() != RMISSD - && sndata.get(tlev+1).getTemperature() != RMISSD) { - nlev--; - //System.out.println("after subtracting nlev, its value is : " + nlev ); - } - } - } - } - - // Compute height at the missing top levels - - if ( ( tlev + 1 ) < sndata.size() ) { - blev = tlev; - pb = sndata.get(blev).getPressure(); - zb = sndata.get(blev).getGeoHeight(); - tb = sndata.get(blev).getTemperature(); - tdb = sndata.get(blev).getDewpoint(); - zlev = sndata.get(blev).getGeoHeight(); - plev = sndata.get(blev).getPressure(); - for ( int kk = tlev+1; kk < sndata.size(); kk++ ) { - pt = sndata.get(kk).getPressure(); - zt = sndata.get(kk).getGeoHeight(); - tt = sndata.get(kk).getTemperature(); - tdt = sndata.get(kk).getDewpoint(); - float xxx = scaleHeight(tb, tt, tdb, tdt, pb, pt); - znew = moistHeight(zb, pb, pt, xxx); - if (znew != RMISSD) { - sndata.get(kk).setGeoHeight(znew); - pb = pt; - tb = tt; - tdb = tdt; - zb = znew; - } - } - } - - return; - } - - /* - * Merge the significant and maximum wind data on pressure surfaces. MR_PWND - */ - public void mergeSigMaxWindOnPressure(List sig_wa, - List sig_wc,List sndata) { - - /* - * Do nothing if wind report is reported on height surfaces. - */ - - if ( sig_wa.size() < 1 && sig_wc.size() < 1 ) { - return; - } - - /* - * Append two lists of wind data. - */ - if ( sig_wc.size() > 0) { - for (int kk = 0; kk < sig_wc.size(); kk++) { - sig_wa.add(sig_wc.get(kk)); - } - } - - /* - * Merging - */ - int nlevel = sndata.size(); - for (int kk = 0; kk < sig_wa.size(); kk++) { - boolean found = false; - for (int lev = 0; lev < nlevel; lev++) { - if (equal(sndata.get(lev).getPressure(),sig_wa.get(kk) - .getPressure())) { - - // add data to missing - if (sndata.get(lev).getWindDirection() == RMISSD) { - sndata.get(lev).setWindDirection( - sig_wa.get(kk).getWindDirection()); - sndata.get(lev).setWindSpeed( - sig_wa.get(kk).getWindSpeed()); - } - found = true; - } - } - - /* - * if not found, add to the list. - */ - if (!found) { - if ( ( sig_wa.get(kk).getWindDirection() != RMISSD - && sig_wa.get(kk).getPressure() != RMISSD )) { - - NcSoundingLayer sl = new NcSoundingLayer(); - sl.setPressure(sig_wa.get(kk).getPressure()); - sl.setTemperature(sig_wa.get(kk).getTemperature()); - sl.setDewpoint(sig_wa.get(kk).getDewpoint()); - sl.setWindDirection(sig_wa.get(kk).getWindDirection()); - sl.setWindSpeed(sig_wa.get(kk).getWindSpeed()); - sl.setGeoHeight(sig_wa.get(kk).getGeoHeight()); - sl.setOmega(sig_wa.get(kk).getOmega()); - sndata.add(sl); - } - } - Collections.sort(sndata, new reverseSortByPressure()); - } - return; - } - - /* - * Construct height at significant wind levels (PPBB) if reported on - * pressure levels. Using moist hydrostatic computation for missing height - * at top levels. MR_INTZ - */ - public void constructPpbbHeight(List sndata) { - int tlev = 0; -//System.out.println("From constructPpbbHeight(): " ); - for (int kk = sndata.size() - 1; kk >= 0; kk--) { - if (sndata.get(kk).getGeoHeight() != RMISSD) { - tlev = kk; - //System.out.println("tlev is set to " + tlev ); - break; - } - } - - float pb = RMISSD, pt = RMISSD, zt = RMISSD, zb = RMISSD; - int next; - - if ( sndata.size() <= 2) return; - - for (int kk = 0; kk < tlev; kk++) { - float pres = sndata.get(kk).getPressure(); - float hght = sndata.get(kk).getGeoHeight(); - if (pres == RMISSD) { - // DO NOTHING - } else if (hght != RMISSD) { - pb = pres; - zb = hght; - pt = 2000.f; - } else if (pb == RMISSD) { - // DO NOTHING - } else { - - /* - * Find next level with height and then interpolate the data. - */ - next = kk + 1; - while (pres <= pt) { - if (sndata.get(next).getGeoHeight() != RMISSD) { - pt = sndata.get(next).getPressure(); - zt = sndata.get(next).getGeoHeight(); - } else { - next++; - } - } - float hhh = (float) (zb + (zt - zb) - * (Math.log(pres / pb) / Math.log(pt / pb))); - sndata.get(kk).setGeoHeight(hhh); - } - } - - if (tlev == (sndata.size()-1) ) { - return; - } else { - - /* - * Compute moist hydrostatic height for missing height at top - * levels. - */ - float scale; - float tb, tdb; - float tt, tdt, mhght = 0.f; - pb = sndata.get(tlev).getPressure(); - zb = sndata.get(tlev).getGeoHeight(); - tb = sndata.get(tlev).getTemperature(); - tdb = sndata.get(tlev).getDewpoint(); - - for (int kk = tlev+1; kk < sndata.size(); kk++) { - if (sndata.get(kk).getGeoHeight() == RMISSD) { - pt = sndata.get(kk).getPressure(); - zt = sndata.get(kk).getGeoHeight(); - tt = sndata.get(kk).getTemperature(); - tdt = sndata.get(kk).getDewpoint(); - scale = scaleHeight(tb, tt, tdb, tdt, pb, pt); - mhght = moistHeight(zb, pb, pt, scale); - sndata.get(kk).setGeoHeight(mhght); - if (mhght != RMISSD) { - pb = pt; - zb = zt; - tb = tt; - tdb = tdt; - } - } - } - return; - } - } - - /* - * Merge significant wind on height surfaces. The argument is sndata. - */ - public void mergeSigWindOnHeight(List sig_wa, - List sig_wc,List sndata ) { - - /* - * The following code needs to be replaced by significant wind data from - * database. - */ - - /* - * Do nothing if wind report is not on height surfaces. - */ - if ( sig_wa.size() < 1 && sig_wc.size() < 1 ) { - return; - } - - /* - * Add two lists of wind data. - */ - if ( sig_wc.size() > 0 ) { - for (int kk = 0; kk < sig_wc.size(); kk++) { - sig_wa.add(sig_wc.get(kk)); - } - } - - int nlevel = sndata.size(); - for (int kk = 0; kk < sig_wa.size(); kk++) { - boolean found = false; - float zzz = sig_wa.get(kk).getGeoHeight(); - - // Check surface level independently because sometimes station - // report wind data twice at surface. We don't want the surface - // pressure to be missing. - if ( zzz == 0 ) { - if (sndata.get(0).getWindDirection() == RMISSD) { - sndata.get(0).setWindDirection( - sig_wa.get(0).getWindDirection()); - sndata.get(0).setWindSpeed( - sig_wa.get(kk).getWindSpeed()); - } - found = true; - } else { - for (int lev = 0; lev < nlevel; lev++) { - float hght = sndata.get(lev).getGeoHeight(); - if (equal(zzz,hght) || (zzz == 0 && lev == 0 && kk == 0)) { - // add data to missing - if (sndata.get(lev).getWindDirection() == RMISSD) { - sndata.get(lev).setWindDirection( - sig_wa.get(kk).getWindDirection()); - sndata.get(lev).setWindSpeed( - sig_wa.get(kk).getWindSpeed()); - } - found = true; - } - } - } - - /* - * if not found, add to the list. - */ - if (!found) { - if (sig_wa.get(kk).getWindDirection() != RMISSD - && sig_wa.get(kk).getGeoHeight() != RMISSD) { - NcSoundingLayer sl = new NcSoundingLayer(); - sl.setPressure(sig_wa.get(kk).getPressure()); - sl.setTemperature(sig_wa.get(kk).getTemperature()); - sl.setDewpoint(sig_wa.get(kk).getDewpoint()); - sl.setWindDirection(sig_wa.get(kk).getWindDirection()); - sl.setWindSpeed(sig_wa.get(kk).getWindSpeed()); - sl.setGeoHeight(sig_wa.get(kk).getGeoHeight()); - sl.setOmega(sig_wa.get(kk).getOmega()); - sndata.add(sl); - } - } - } - - /* - * Sorting the combined temperature and wind data based on Geopotential - * height. - */ - Collections.sort(sndata, new sortByHeight()); - return; - } - - // Sort by height - public static class sortByHeight implements Comparator { - public int compare(NcSoundingLayer l1, NcSoundingLayer l2) { - return Float.compare(l1.getGeoHeight(), l2.getGeoHeight()); - } - - } - - // Reverse sort by pressure - public static class reverseSortByPressure implements Comparator { - public int compare(NcSoundingLayer l1, NcSoundingLayer l2) { - return Float.compare(l2.getPressure(), l1.getPressure()); - } - - } - - /* - * Construct pressure at significant wind levels (PPBB) that are reported on - * height levels. MR_INTP - */ - public List constructPpbbPressure(List sndata) { - - if ( sndata.size() <= 2) return sndata; - - float pb = RMISSD, pt = RMISSD, zt = RMISSD, zb = RMISSD; - int blev = IMISSD, tlev = IMISSD; - for (int lev = 0; lev < sndata.size(); lev++) { - float pres = sndata.get(lev).getPressure(); - float hght = sndata.get(lev).getGeoHeight(); - if (pres != RMISSD && hght != RMISSD) { - tlev = lev; - pt = pres; - zt = hght; - } - - if (blev != IMISSD && tlev != IMISSD) { - for (int kk = blev + 1; kk < tlev; kk++) { - float z = sndata.get(kk).getGeoHeight(); - if (sndata.get(kk).getGeoHeight() != RMISSD) { - float ppp = (float) (pb * Math.exp((double) ((z - zb) - * Math.log(pt / pb) / (zt - zb)))); - sndata.get(kk).setPressure(ppp); - } - } - } - blev = tlev; - pb = pt; - zb = zt; - } - - ////System.out.println ( " tlev: " + tlev + " sndata.size() -1 " + (sndata.size()-1)); - - if (tlev == (sndata.size()-1) || tlev == IMISSD ) { - return sndata; - } else { - - /* - * Compute missing pressure at top - * levels. - */ - pb = sndata.get(tlev-1).getPressure(); - zb = sndata.get(tlev-1).getGeoHeight(); - - for (int kk = tlev+1; kk < sndata.size(); kk++) { - if (sndata.get(kk).getPressure() == RMISSD) { - pt = sndata.get(kk-1).getPressure(); - zt = sndata.get(kk-1).getGeoHeight(); - float zz = sndata.get(kk).getGeoHeight(); - float rmult = (float) ((zz- zb) / (zt - zb)); - sndata.get(kk).setPressure((float)(pb*(Math.pow(pt/pb,rmult)))); - pb = pt; - zb = zt; - } - } - } - return sndata; - } - - - - /* - * Reorder the sounding data so the first level is always the surface data. - */ - public List reOrderSounding(List sndata) { - List outdat = new ArrayList(); - float tt, td, dd, ff; - int klev = 0; - if ( sndata.size() <= 1) return sndata; - - /* - * Find the surface level - */ - for (int kk = 0; kk < sndata.size(); kk++) { - tt = sndata.get(kk).getTemperature(); - td = sndata.get(kk).getDewpoint(); - dd = sndata.get(kk).getWindDirection(); - ff = sndata.get(kk).getWindSpeed(); - if (tt == RMISSD && td == RMISSD && dd == RMISSD && ff == RMISSD) { - // DO NOTHING - } else { - klev = kk; - addDataToList(0, sndata, outdat); - } - } - - /* - * Reorder the data below the surface levels. - */ - for (int kk = 0; kk < klev; kk++) { - addDataToList(kk, sndata, outdat); - } - - for (int kk = klev + 1; kk < sndata.size(); kk++) { - addDataToList(kk, sndata, outdat); - } - return outdat; - } - - /* - * Construct missing temperature (iflag = 1), dewpoint temperature (iflag=2) - * and wind (iflag = 3). This method is called after reOrderSounding(). - * MR_MISS - */ - public List constructMissing(int iflag, - List sndata) { - float pb = RMISSD, pt = RMISSD, data = RMISSD, pres, tb, tt, tdb, tdt; - int jlev = IMISSD, tlev = IMISSD; - boolean contin = true; - if ( sndata.size() <= 2) return sndata; - for (int blev = 1; blev < sndata.size() - 1 && contin; blev++) { - jlev = blev; - - switch (iflag) { - case 1: { - data = sndata.get(blev).getTemperature(); - break; - } - case 2: { - data = sndata.get(blev).getDewpoint(); - break; - } - case 3: { - data = sndata.get(blev).getWindDirection(); - break; - } - default: { - //System.out.println("Invalid data flag"); - return sndata; - } - } - - if (data == RMISSD) { - - /* - * find data at level above. Data should already be at level - * below after reOrderSounding() call. - */ - boolean found = false; - while (!found) { - jlev++; - switch (iflag) { - case 1: { - data = sndata.get(jlev).getTemperature(); - break; - } - case 2: { - data = sndata.get(jlev).getDewpoint(); - break; - } - case 3: { - data = sndata.get(jlev).getWindDirection(); - break; - } - default: { - //System.out.println("Invalid data flag"); - } - } - int top = sndata.size(); - if (data != RMISSD || jlev+1 >= top) { - found = true; - tlev = jlev; - if (jlev >= top) { - tlev = IMISSD; - contin = false; - } - } - } - - /* - * Add check to eliminate dew point layer more than 100mb. - */ - if (iflag == 2 && tlev != IMISSD) { - if ((sndata.get(blev).getPressure() - sndata.get(tlev) - .getPressure()) > 100.) { - for (int kk = tlev; kk < sndata.size(); kk++) { - sndata.get(kk).setDewpoint(RMISSD); - } - tlev = IMISSD; - contin = false; - } - } - - /* - * Add check to eliminate interpolation of winds from below 100 - * mb to above 100 mb. This eliminates interpolation to very - * high level winds. - */ - /* if (iflag == 3 && tlev != IMISSD - && (sndata.get(blev - 1).getPressure() > 100.) - && (sndata.get(tlev).getPressure() < 100.)) { - tlev = IMISSD; - } - */ - /* - * Interpolate with respect to logP. - */ - - if (tlev != IMISSD) { - pb = sndata.get(blev - 1).getPressure(); - pres = sndata.get(blev).getPressure(); - pt = sndata.get(tlev).getPressure(); - float rmult = (float) (Math.log(pres / pb) / Math.log(pt / pb)); - switch (iflag) { - case 1: { - tb = sndata.get(blev - 1).getTemperature(); - tt = sndata.get(tlev).getTemperature(); - if ( tb != RMISSD && tt != RMISSD ) { - data = tb + (tt - tb) * rmult; - sndata.get(blev).setTemperature(data); - } - - tdb = sndata.get(blev - 1).getDewpoint(); - tdt = sndata.get(tlev).getDewpoint(); - if (tdb != RMISSD && tdt != RMISSD) { - data = tdb + (tdt - tdb) * rmult; - sndata.get(blev).setDewpoint(data); - } - break; - } - case 2: { - tdb = sndata.get(blev - 1).getDewpoint(); - tdt = sndata.get(tlev).getDewpoint(); - if (tdb != RMISSD && tdt != RMISSD) { - data = tdb + (tdt - tdb) * rmult; - sndata.get(blev).setDewpoint(data); - } - break; - } - case 3: { - float drctb = sndata.get(blev - 1).getWindDirection() ; - float drctt = sndata.get(tlev).getWindDirection() ; - - if ( drctt != RMISSD && drctb!= RMISSD ) { - drctb = drctb % 360.f; - drctt = drctt % 360.f; - if (Math.abs(drctb - drctt) > 180.f) { - if (drctb < drctt) { - drctb = drctb + 360.f; - } else { - drctt = drctt + 360.f; - } - } - float drct = ( drctb + (drctt - drctb) * rmult) % 360.f; - sndata.get(blev).setWindDirection(drct); - - // Interpolate wind speed - float spedb = sndata.get(blev - 1).getWindSpeed(); - float spedt = sndata.get(tlev).getWindSpeed(); - float sped = spedb + (spedt - spedb) * rmult; - sndata.get(blev).setWindSpeed(sped); - } - break; - - } - } - } - } - } - return sndata; - } - - - /* - * Re-order the data so the first level is always the ground level. MR_COND - */ - public List addUnderGround(List man, - List sndata ) { - - if (sndata.get(0).getPressure() == RMISSD || man.size() < 1 || sndata.size() <= 1) { - return sndata; - } - - int blev = 0; - boolean contin = true; - while ( blev < sndata.size() && contin ) { - if (man.get(blev).getPressure() > sndata.get(0).getPressure() ) { - blev++; - } else { - contin = false; - } - } - - if ( blev >= sndata.size()) { - return sndata; - } - - /* - * Added below-ground mandatory levels to sounding layers. - */ - List outdat = new ArrayList(); - - int nlev = sndata.size(); - - // write to surface data first - addDataToList (0, sndata, outdat); - - // add below-ground mandatory data - if (blev > 0 && blev < sndata.size()) { - for (int kk = 0; kk < blev; kk++ ) { - addDataToList(kk,man,outdat); - } - } - - // add the rest of the data - for (int kk = 1; kk < nlev; kk++) { - addDataToList(kk,sndata,outdat); - } - return outdat; - - } - - /* - * Re-order the data so the first level is always the ground level. MR_COND - */ - public List removeUnderGround(List sndata) { - List outdat = new ArrayList(); - /* - * Remove below-ground mandatory levels from sounding layers. Only the - * first 8 missing levels can be mandatory levels. - */ - if ( sndata.size() <= 1) return sndata; - for ( int kk = 0; kk < sndata.size(); kk++ ) { - if ( sndata.get(kk).getTemperature() <= RMISSD && - sndata.get(kk).getDewpoint() <= RMISSD && - sndata.get(kk).getWindDirection() <= RMISSD && - sndata.get(kk).getWindSpeed() <= RMISSD ) { - } else if ( sndata.get(kk).getPressure() <= RMISSD ) { - } else { - addDataToList(kk, sndata, outdat); - } - } - return outdat; - } - - /* - * Interpolate data to a single level, including surface. - */ - public List getSingLevel (float pres, List sndata) { - NcSoundingLayer sl = new NcSoundingLayer(); - List sls = new ArrayList(); - sndata = removeUnderGround(sndata); - if ( sndata.size() <= 1) return setMissing(); //Chin: check size again, after remove under ground lavel, size changed - - for ( int kk = 1;/*chin 0;*/ kk < sndata.size()-1; kk++ ) { - if (pres > sndata.get(0).getPressure()|| pres < 0.f) { - return setMissing(); - } else { - - if ( pres >= sndata.get(kk).getPressure()) { - float pt, pb, zt, zb, tt, tb, tdt, tdb, dt, db, st, sb; - pb = sndata.get(kk-1).getPressure(); - pt = sndata.get(kk).getPressure(); - tb = sndata.get(kk-1).getTemperature(); - tt = sndata.get(kk).getTemperature(); - tdb = sndata.get(kk-1).getDewpoint(); - tdt = sndata.get(kk).getDewpoint(); - db = sndata.get(kk-1).getWindDirection() % 360.f; - dt = sndata.get(kk).getWindDirection() % 360.f; - sb = sndata.get(kk-1).getWindSpeed(); - st = sndata.get(kk).getWindSpeed(); - zb = sndata.get(kk-1).getGeoHeight(); - zt = sndata.get(kk).getGeoHeight(); - sl.setPressure(pres); - - float rmult = (float) (Math.log(pres / pb) / Math.log(pt/ pb)); - sl.setTemperature(tb+(tt-tb)*rmult); - sl.setDewpoint(tdb+(tdt-tdb)*rmult); - if (Math.abs(db-dt) > 180.) { - if ( db < dt ) { - db = db + 360.f; - } else { - dt = dt + 360.f; - } - } - sl.setWindDirection(db+(dt-db)*rmult); - sl.setWindSpeed(sb+(st-sb)*rmult); - sl.setGeoHeight(zb+(zt-zb)*rmult); - sls.add(sl); - return sls; - } - } - } - return setMissing(); - } - - /* - * Add data to output sounding profile. - */ - public void addDataToList(int index, - List indat, List outdat) { - NcSoundingLayer sl = new NcSoundingLayer(); - sl.setPressure(indat.get(index).getPressure()); - sl.setTemperature(indat.get(index).getTemperature()); - sl.setDewpoint(indat.get(index).getDewpoint()); - sl.setWindDirection(indat.get(index).getWindDirection()); - sl.setWindSpeed(indat.get(index).getWindSpeed()); - sl.setGeoHeight(indat.get(index).getGeoHeight()); - sl.setOmega(indat.get(index).getOmega()); - outdat.add(sl); - } - - /* - * Set missing to output sounding profile. - */ - public List setMissing () { - List outdat = new ArrayList(); - NcSoundingLayer sl = new NcSoundingLayer(); - sl.setPressure(RMISSD); - sl.setTemperature(RMISSD); - sl.setDewpoint(RMISSD); - sl.setWindDirection(RMISSD); - sl.setWindSpeed(RMISSD); - sl.setGeoHeight(RMISSD); - sl.setOmega(RMISSD); - outdat.add(sl); - return outdat; - } + final float RMISSD = IDecoderConstantsN.UAIR_FLOAT_MISSING; + + final int IMISSD = IDecoderConstantsN.INTEGER_MISSING; + + /** + * Default constructor + */ + public MergeSounding() { + } + + /* + * Process native sounding data. Convert specific humidity to dew point + * temperature then compute the moist height. + */ + public List nativeModelSounding(List sls, + float elevation) { + spfhToDewpoint(sls); + constructHeight(sls, elevation); + return sls; + } + + /* + * Process upper air sounding data. Note that TTAA is the original/sorted + * data, while MAN is the TTAA without underground data and MAN_D is the + * TTAA for display, i.e., the first level is the surface level, any under + * -ground levels will be above the surface level. + */ + public List mergeUairSounding(String level, + List ttaa, List ttbb, + List ttcc, List ttdd, + List ppaa, List ppbb, + List ppcc, List ppdd, + List trop_a, List trop_c, + List wmax_a, List wmax_c, + float elevation) { + List sndata = new ArrayList(); + List man = null; + System.out.println("Enter mergeUairSounding....."); + + // Return the specific levels requested by users + if (ttaa.size() > 0) { + Collections.sort(ttaa, new reverseSortByPressure()); + // System.out.println(" TTAA sounding: "); + // printOut(ttaa); + + if (level.toUpperCase().equalsIgnoreCase("MAN")) { + return ttaa; + } + man = removeUnderGround(ttaa); + // System.out.println(" TTAA sounding above ground: "); + // printOut(man); + + } else { + if (ppaa.size() < 1 && ttbb.size() < 1) { + System.out + .println(" Missing TTAA/TTBB and PPAA data."); + return missingSounding(); + } else { + man = missingSounding(); + System.out.println(" Missing Mandatory (TTAA) Data!"); + } + } + + // Sorting the data + + if (ttbb.size() > 0) { + Collections.sort(ttbb, new reverseSortByPressure()); + // System.out.println(" TTBB sounding: "); + // printOut(ttbb); + } + + if (ttcc.size() > 0) { + Collections.sort(ttcc, new reverseSortByPressure()); + // System.out.println(" TTCC sounding: "); + // printOut(ttcc); + + } + + if (ttdd.size() > 0) { + Collections.sort(ttdd, new reverseSortByPressure()); + // System.out.println(" TTDD sounding: "); + // printOut(ttdd); + + } + + if (ppaa.size() > 0) { + if (checkWindData(ppaa)) { + Collections.sort(ppaa, new MergeSounding.sortByHeight()); + // System.out.println(" PPAA sounding by Height: "); + // printOut(ppaa); + + } else { + Collections.sort(ppaa, + new MergeSounding.reverseSortByPressure()); + // System.out.println(" PPAA sounding by Pressure: "); + // printOut(ppaa); + + } + } + + if (ppcc.size() > 0) { + if (checkWindData(ppcc)) { + Collections.sort(ppcc, new MergeSounding.sortByHeight()); + // System.out.println(" PPCC sounding by Height:"); + // printOut(ppcc); + + } else { + Collections.sort(ppcc, + new MergeSounding.reverseSortByPressure()); + // System.out.println(" PPCC sounding by Pressure: "); + // printOut(ppcc); + } + } + + if (ppbb.size() > 0) { + if (checkWindData(ppbb)) { + Collections.sort(ppbb, new MergeSounding.sortByHeight()); + // System.out.println(" PPBB sounding by Height:"); + // printOut(ppbb); + + } else { + Collections.sort(ppbb, + new MergeSounding.reverseSortByPressure()); + // System.out.println(" PPBB sounding by Pressure: "); + // printOut(ppbb); + } + } + + if (ppdd.size() > 0) { + if (checkWindData(ppdd)) { + Collections.sort(ppdd, new MergeSounding.sortByHeight()); + // System.out.println(" PPDD sounding by Height"); + // printOut(ppdd); + } else { + Collections.sort(ppdd, + new MergeSounding.reverseSortByPressure()); + // System.out.println(" PPDD sounding by Pressure: "); + // printOut(ppdd); + } + + } + + // Find surface data, return if users request surface data only. + NcSoundingLayer sl = new NcSoundingLayer(); + sl = getSurfaceData(man, ttbb, ppbb, elevation); + sndata.add(0, sl); + // System.out.println(" surface data "); + // printOut(sndata); + + if (isNumber(level) >= 0) { + if (equal(0.f, Float.valueOf(level.trim()).floatValue()) + || equal(sl.getPressure(), Float.valueOf(level.trim()) + .floatValue())) { + return sndata; + } + } + + // Merge mandatory data + mergeMandatory(man, ttcc, sndata); + // System.out.println("after merge Mandatory data: "); + // printOut(sndata); + + // Check if the single level is mandatory or not + if (isNumber(level) >= 0) { + for (int kk = 0; kk < sndata.size(); kk++) { + if (equal(Float.valueOf(level.trim()).floatValue(), + sndata.get(kk).getPressure())) { + sl.setPressure(sndata.get(kk).getPressure()); + sl.setTemperature(sndata.get(kk).getTemperature()); + sl.setDewpoint(sndata.get(kk).getDewpoint()); + sl.setWindDirection(sndata.get(kk).getWindDirection()); + sl.setWindSpeed(sndata.get(kk).getWindSpeed()); + sl.setGeoHeight(sndata.get(kk).getGeoHeight()); + sl.setOmega(sndata.get(kk).getOmega()); + sndata.clear(); + sndata.add(sl); + return sndata; + } + } + } + + // Merge mandatory winds + mergeMandatoryWinds(ppaa, ppcc, sndata); + // System.out.println("after merge PPAA/PPCC: "); + // printOut(sndata); + + // Merge tropopause + mergeTropSigTemp(trop_a, trop_c, sndata); + // System.out.println("after merge Tropause data: "); + // printOut(sndata); + + // Merge TTBB + mergeTropSigTemp(ttbb, ttdd, sndata); + // System.out.println("after merge TTBB/TTDD: "); + // printOut(sndata); + + constructTtbbHeight(sndata); + // System.out.println("after construct TTBB Height: "); + // printOut(sndata); + + if (!checkWindData(ppbb)) { + mergeSigMaxWindOnPressure(ppbb, ppdd, sndata); + // System.out.println("after merge TTBB/TTDD: "); + // printOut(sndata); + + } + + mergeSigMaxWindOnPressure(wmax_a, wmax_c, sndata); + // System.out.println("after merge max wind: "); + // printOut(sndata); + + constructPpbbHeight(sndata); + // System.out.println(" After contrstruct PPBB height: "); + // printOut(sndata); + + if (checkWindData(ppbb)) { + mergeSigWindOnHeight(ppbb, ppdd, sndata); + constructPpbbPressure(sndata); + // System.out.println("after merge PPBB/PPDD: "); + // printOut(sndata); + } + + // Reorder sounding profile so the first level is the surface data. + // No need to reorder now becuz surface data is always the 1st level. + // reOrderSounding(sndata); + + // Interpolate missing temperature, dew point and winds. + constructMissing(1, sndata); + constructMissing(2, sndata); + + // constructMissing(3,sndata); + // System.out.println("after contrstruct Missing data: "); + // printOut(sndata); + + // Return single level or add underground mandatory data to the sounding + // profile + + List sndout = new ArrayList(); + sndout = removeMissingPressure(sndata); + // System.out.println(" Missing pressure removed "); + // printOut(sndout); + if (isNumber(level) == 0) { + float rlev = new Integer(Integer.parseInt(level.trim())) + .floatValue(); + return getSingLevel(rlev, sndout); + } else if (isNumber(level) == 1) { + float rlev = new Float(Float.parseFloat(level.trim())); + return getSingLevel(rlev, sndout); + } else { + if (sndout.size() < 2) + System.out.println(" Not enough levels to plot the sounding! "); + return addUnderGround(ttaa, sndout); + } + } + + /* + * Check an alpha-numerical string is a number or characters. + */ + public int isNumber(String level) { + try { + if (Integer.parseInt(level) >= 0) { + return 0; + } else { + return -1; + } + } catch (NumberFormatException nfe1) { + try { + if (Float.parseFloat(level) >= 0.f) { + return 1; + } else { + return -1; + } + } catch (NumberFormatException nfe2) { + try { + if (Double.parseDouble(level) >= 0.) { + return 2; + } else { + return -1; + } + } catch (NumberFormatException nfe3) { + return -1; + } + } + } + } + + /* + * convert specific humidity to dew point temperature. + */ + float elevation; + + public List spfhToDewpoint(List sndata) { + float spfh, pres; + float dwpc = RMISSD; + + for (NcSoundingLayer layer : sndata) { + if (layer.getDewpoint() == RMISSD) { + spfh = layer.getSpecHumidity(); + pres = layer.getPressure(); + + if (spfh == RMISSD || pres == RMISSD || spfh <= 0.f + || pres <= 0.f) { + continue; + } else { + float rmix = spfh / (1.f - spfh); + float e = (pres * rmix) / (.62197f + rmix); + e = e / (1.001f + ((pres - 100.f) / 900.f) * .0034f); + dwpc = (float) (Math.log(e / 6.112) * 243.5 / (17.67 - Math + .log((e / 6.112)))); + layer.setDewpoint(dwpc); + // //System.out.println("spfhToDewpoint dwpc: " + dwpc); + } + + } + } + return sndata; + } + + /* + * computes DWPC from TMPC and RELH Note: If DWPC is less than -190 degrees + * C, it is treated as missing data Code is based on GEMPAK's prrhdp.f + */ + public List rhToDewpoint(List sndata) { + float rh, vapr, vaps, temp; + float dwpc = RMISSD; + + for (NcSoundingLayer layer : sndata) { + if (layer.getDewpoint() == RMISSD) { + rh = layer.getRelativeHumidity(); + temp = layer.getTemperature(); + + if (rh == RMISSD || temp == RMISSD) { + continue; + } else { + vaps = tempToVapr(temp); + vapr = rh * vaps / 100; + if (vapr < Math.exp(-30)) + continue; + else { + dwpc = (float) (243.5 * (Math.log(6.112) - Math + .log(vapr)) / (Math.log(vapr) - Math.log(6.112) - 17.67)); + layer.setDewpoint(dwpc); + // //System.out.println("rhToDewpoint dwpc: " + dwpc); + } + } + } + } + return sndata; + } + + /* + * computes VAPR from TMPC Code is based on GEMPAK's prvapr.f + */ + private float tempToVapr(float temp) { + return (float) (6.112 * Math.exp((17.67 * temp) / (temp + 243.5))); + } + + private void constructHeight(List sndata, float elev) { + + /* + * For native model sounding, using hypsometric equation to build height + */ + elevation = elev; + int lev = sndata.size(); + float tb = RMISSD, tdb = RMISSD, pb = RMISSD; + float tt = RMISSD, tdt = RMISSD, pt = RMISSD; + float dwptsf, psfc, tmpcsf, scaleh, mhgt = RMISSD; + + for (int k = 0; k < lev; k++) { + + if (k == 0) { + tmpcsf = sndata.get(k).getTemperature(); + dwptsf = sndata.get(k).getDewpoint(); + psfc = sndata.get(k).getPressure(); + tb = tmpcsf; + tt = tmpcsf; + tdb = dwptsf; + tdt = dwptsf; + pb = psfc; + pt = psfc; + + scaleh = scaleHeight(tb, tt, tdb, tdt, pb, pt); + mhgt = moistHeight(elevation, pb, pt, scaleh); + } else { + tt = sndata.get(k).getTemperature(); + tdt = sndata.get(k).getDewpoint(); + pt = sndata.get(k).getPressure(); + scaleh = scaleHeight(tb, tt, tdb, tdt, pb, pt); + + mhgt = moistHeight(mhgt, pb, pt, scaleh); + tb = tt; + tdb = tdt; + pb = pt; + + } + sndata.get(k).setGeoHeight(mhgt); + } + } + + /* + * Compute moist height. + */ + private float moistHeight(float zb, float pb, float pt, float scale) { + // System.out.println("From moistHeight: "); + if (zb == RMISSD || pb == RMISSD || pt == RMISSD || scale == RMISSD) { + return RMISSD; + } else { + // System.out.println("the computed moistHeight is " + (float) (zb + // + scale * Math.log(pb / pt))); + return (float) (zb + scale * Math.log(pb / pt)); + } + } + + /* + * Compute scale height. + */ + private float scaleHeight(float tb, float tt, float tdb, float tdt, + float pb, float pt) { + // System.out.println("From scaleHeight: " ); + final float RDGAS = 287.04f, GRAVTY = 9.80616f, RKAP = RDGAS / GRAVTY; + if (tb == RMISSD || tt == RMISSD || pb == RMISSD || pt == RMISSD) { + return RMISSD; + } else { + float tvb = virtualTemperature(tb, tdb, pb); + float tvt = virtualTemperature(tt, tdt, pt); + // System.out.println("tvb = " + tvb); + // System.out.println("tvt = " + tvt); + if (tvb == RMISSD || tvt == RMISSD) { + return RMISSD; + } else { + float tav = (tvb + tvt) / 2.0f; + + // System.out.println("tav = " + tav); + // System.out.println("RKAP * tav = " + RKAP * tav); + return (RKAP * tav); + } + } + } + + /* + * Compute virtual temperature + */ + private float virtualTemperature(float tt, float td, float pres) { + if (tt == RMISSD || pres == RMISSD) { + return RMISSD; + } else if (td == RMISSD) { + return celciusToKevin(tt); + } else { + float tmpk = celciusToKevin(tt); + float rmix = mixingRatio(td, pres); + if (rmix == RMISSD) { + return celciusToKevin(tt); + } else { + return tmpk * (1.f + .001f * rmix / .62197f) + / (1.f + .001f * rmix); + } + } + } + + /* + * Convert Celcius to Kelvin. + */ + float TMCK = 273.15f; + + private float celciusToKevin(float tc) { + if (tc == RMISSD) { + return RMISSD; + } else { + return (tc + TMCK); + } + } + + /* + * Compute mixing ratio from DWPC and PRES. + */ + private float mixingRatio(float td, float pres) { + if (td == RMISSD || pres == RMISSD) { + return RMISSD; + } else { + float vapr = vaporPressure(td); + if (vapr == RMISSD) { + return RMISSD; + } + + float corr = (1.001f + ((pres - 100.f) / 900.f) * .0034f); + + float e = corr * vapr; + if (e > (.5f * pres)) { + return RMISSD; + } else { + return .62197f * (e / (pres - e)) * 1000.f; + } + } + } + + /* + * Compute vapor pressure from DWPC. + */ + private float vaporPressure(float td) { + if (td == RMISSD) { + return RMISSD; + } else { + return (6.112f * (float) Math.exp((17.67 * td) / (td + 243.5))); + } + } + + /* + * Merge observed sounding data + */ + + /* + * Check wind data if the data is reported on pressure or height surfaces. + * Return TRUE if reported on height. (MR_CHKW) + * + * Note that this is coded different from MR_CHKW, in that it will set zwind + * to false only if pressure is less than 0. An odd logic. + */ + public boolean checkWindData(List sndata) { + boolean zwind = true; + for (int kk = 0; kk < sndata.size(); kk++) { + if (sndata.get(kk).getPressure() != RMISSD) { + zwind = false; + } + } + return zwind; + } + + /* + * Find surface data. (MR_SRFC) + */ + final int NPARMS = 7; + + public NcSoundingLayer getSurfaceData(List man, + List ttbb, List ppbb, + float elevation) { + float psfc = RMISSD; + NcSoundingLayer sl_sfc = new NcSoundingLayer(); + + /* + * Check for surface information in mandatory data. + */ + if (man == null || man.size() < 1) { + sl_sfc = missingSounding().get(0); + } else { + // If surface pressure is greater than 1080mb, set to missing. + // Otherwise + // surface pressure will be the first report level on TTAA. + // Note that GEMPAK sets it to 1060mb. + psfc = man.get(0).getPressure(); + if (psfc > 1080.) { + sl_sfc.setPressure(RMISSD); + } else { + sl_sfc.setPressure(psfc); + } + sl_sfc.setTemperature(man.get(0).getTemperature()); + sl_sfc.setDewpoint(man.get(0).getDewpoint()); + sl_sfc.setWindDirection(man.get(0).getWindDirection()); + sl_sfc.setWindSpeed(man.get(0).getWindSpeed()); + sl_sfc.setGeoHeight(elevation); + sl_sfc.setOmega(man.get(0).getOmega()); + } + + /* + * Find the first reporting mandatory level above the surface. + */ + float pman = RMISSD; + int iman = 1; + try { + while (pman == RMISSD && iman < man.size()) { + if (man.get(iman).getPressure() != RMISSD + && man.get(iman).getTemperature() != RMISSD + && man.get(iman).getGeoHeight() != RMISSD) { + pman = man.get(iman).getPressure(); + } + iman++; + } + } catch (Exception e) { + // do nothing + } + + /* + * If surface pressure is missing or is less than first reporting + * mandatory level, set surface data to missing. + */ + if (psfc == RMISSD || (psfc < pman && pman != RMISSD)) { + sl_sfc = missingSounding().get(0); + } + + /* + * Use TTBB/PPBB to get surface data if TTAA is missing. The check for + * significant level pressure to be less than or equal to psfc + * eliminates erroneous data. + */ + if (ttbb.size() > 0) { + psfc = sl_sfc.getPressure(); + float psql = ttbb.get(0).getPressure(); + + if (equal(psfc, psql) || psfc == RMISSD) { + if (psql != RMISSD && psfc == RMISSD) + sl_sfc.setPressure(psql); + + if (sl_sfc.getTemperature() == RMISSD) + sl_sfc.setTemperature(ttbb.get(0).getTemperature()); + + if (sl_sfc.getDewpoint() == RMISSD) + sl_sfc.setDewpoint(ttbb.get(0).getDewpoint()); + } + } + + /* + * If the first significant level wind data is surface information, use + * it to replace the surface data if the pressure is at surface. + */ + + // PPBB reported in Height. + if (checkWindData(ppbb)) { + if (ppbb.size() > 0) { + if (ppbb.get(0).getGeoHeight() == 0. + && sl_sfc.getWindDirection() == RMISSD) { + sl_sfc.setWindDirection(ppbb.get(0).getWindDirection()); + sl_sfc.setWindSpeed(ppbb.get(0).getWindSpeed()); + } + } + } else { + // PPBB reported in Pressure. + if (ppbb.size() > 0) { + if (ppbb.get(0).getPressure() != RMISSD + && sl_sfc.getPressure() == RMISSD) { + float psgl = Math.abs(ppbb.get(0).getPressure()); + sl_sfc.setPressure(psgl); + + if (ppbb.get(0).getWindDirection() != RMISSD + && sl_sfc.getWindDirection() == RMISSD) { + if (equal(psfc, psgl)) { + sl_sfc.setWindDirection(ppbb.get(0) + .getWindDirection()); + sl_sfc.setWindSpeed(ppbb.get(0).getWindSpeed()); + } + } + } + } + } + + /* + * Return surface data. + */ + return sl_sfc; + } + + private boolean equal(float x, float y) { + final float RDIFFD = .0001f; + if ((x + y) == 0.) { + return Math.abs(x - y) < RDIFFD; + } else { + return Math.abs(x - y) / Math.abs((x + y) / 2.) < RDIFFD; + } + } + + /* + * Merge the mandatory below 100 mb data and the mandatory above data. + * sndata has surface observation ONLY. (MR_MAND) + */ + + public void mergeMandatory(List man_a, + List man_c, List sndata) { + + float plast; + // if (man_a == null) { + // System.out.println(" NO data in Man \n"); + // } else { + // System.out.println(" Man not null \n"); + + // + if (man_a.size() < 1 && man_c.size() < 1) { + return; + } + + if (sndata.get(0).getPressure() == RMISSD) { + plast = 2000.f; + } else { + plast = sndata.get(0).getPressure(); + } + + /* + * Move the mandatory data below 100mb to the output array, sndata. + * Check that pressure is not missing and is decreasing. + */ + float pres; + if (man_a.size() > 0) { + for (int kk = 1; kk < man_a.size(); kk++) { + pres = man_a.get(kk).getPressure(); + if (pres < plast + && pres != RMISSD + && (man_a.get(kk).getTemperature() != RMISSD || man_a + .get(kk).getWindDirection() != RMISSD)) { + addDataToList(kk, man_a, sndata); + plast = pres; + } + } + } + + /* + * Move the mandatory data above 100 mb to the output array. + */ + if (man_c.size() > 0) { + for (int kk = 0; kk < man_c.size(); kk++) { + pres = man_c.get(kk).getPressure(); + if (pres < plast && pres != RMISSD + && man_c.get(kk).getTemperature() != RMISSD) { + addDataToList(kk, man_c, sndata); + plast = man_c.get(kk).getPressure(); + } + } + } + } + + /* + * Merge the mandatory below 100 mb wind data and the mandatory above wind + * data. (MR_MANW) + */ + public void mergeMandatoryWinds(List man_wa, + List man_wc, List sndata) { + + if (man_wa.size() < 1 && man_wc.size() < 1) { + return; + } + + /* + * Append data. + */ + if (man_wc.size() > 0) { + for (int kk = 0; kk < man_wc.size(); kk++) { + man_wa.add(man_wc.get(kk)); + } + } + /* + * Loop through mandatory wind data. + */ + for (int lev = 0; lev < man_wa.size(); lev++) { + + /* + * If this is the correct level, add wind data. + */ + boolean found = false; + float ppp = man_wa.get(lev).getPressure(); + for (int kk = 0; kk < sndata.size() && !found; kk++) { + float pres = sndata.get(kk).getPressure(); + if (equal(ppp, pres)) { + if (sndata.get(kk).getWindDirection() == RMISSD) { + sndata.get(kk).setWindDirection( + man_wa.get(lev).getWindDirection()); + sndata.get(kk).setWindSpeed( + man_wa.get(lev).getWindSpeed()); + } + found = true; + } + } + + /* + * If not found, add to the list + */ + if (!found) { + float ddd = man_wa.get(lev).getWindDirection(); + if (ppp != RMISSD && ddd != RMISSD) { + addDataToList(lev, man_wa, sndata); + } + } + } + } + + /* + * Merge tropopause, max wind and significant temperature data (TTBB) to the + * station data array. The input parameter could be tropopause data or + * significant temperature data. MR_TROP & MR_SIGT + */ + public List mergeTropSigTemp(List trop_a, + List trop_c, List sndata) { + if (trop_a.size() < 1 && trop_c.size() < 1) { + return sndata; + } + + /* + * Append two lists of wind data. + */ + if (trop_c.size() > 0) { + for (int kk = 0; kk < trop_c.size(); kk++) { + trop_a.add(trop_c.get(kk)); + } + } + + for (int lev = 0; lev < trop_a.size(); lev++) { + boolean found = false; + float ppp = trop_a.get(lev).getPressure(); + for (int kk = 0; kk < sndata.size() && !found; kk++) { + float pres = sndata.get(kk).getPressure(); + if (equal(ppp, pres)) { + + // add data to missing + if (sndata.get(kk).getTemperature() == RMISSD) { + sndata.get(kk).setTemperature( + trop_a.get(lev).getTemperature()); + sndata.get(kk).setDewpoint( + trop_a.get(lev).getDewpoint()); + } + + if (sndata.get(kk).getWindDirection() == RMISSD) { + sndata.get(kk).setWindDirection( + trop_a.get(lev).getWindDirection()); + sndata.get(kk).setWindSpeed( + trop_a.get(lev).getWindSpeed()); + + } + found = true; + } + } + + /* + * if not found, add to the list + */ + if (!found) { + float ttt = trop_a.get(lev).getTemperature(); + if (ppp != RMISSD && ttt != RMISSD) { + addDataToList(lev, trop_a, sndata); + } + } + + } + + /* + * Sort the sounding data in descending order. + */ + Collections.sort(sndata, new reverseSortByPressure()); + return sndata; + } + + /* + * Compute height at significant temperature levels (TTBB) using a moist + * hydrostatic computation. (MR_SCMZ) + */ + public void constructTtbbHeight(List sndata) { + boolean mand = false; + boolean newblock = true; + int blev = 0, tlev = 0; + float[] scale = new float[200]; + float pb, zb, tb, tdb, zlev, plev; + float pt, zt = 0.f, tt, tdt, znew = 0.f; + // System.out.println("In construct TTBB Height 1: "); + // printOut(sndata); + + if (sndata.size() <= 2) + return; + + for (int nlev = 0; nlev < sndata.size(); nlev++) { + if (newblock) { + if (sndata.get(nlev).getGeoHeight() != RMISSD + && sndata.get(nlev).getPressure() != RMISSD + && sndata.get(nlev).getTemperature() != RMISSD) { + + blev = nlev; + newblock = false; + } + } else { + if (sndata.get(nlev).getGeoHeight() != RMISSD + && sndata.get(nlev).getTemperature() != RMISSD) { + tlev = nlev; + mand = true; + } + } + + /* + * Compute scale height to this level + */ + if (mand) { + pb = sndata.get(blev).getPressure(); + zb = sndata.get(blev).getGeoHeight(); + tb = sndata.get(blev).getTemperature(); + tdb = sndata.get(blev).getDewpoint(); + zlev = sndata.get(blev).getGeoHeight(); + plev = sndata.get(blev).getPressure(); + + for (int kk = blev + 1; kk <= tlev; kk++) { + pt = sndata.get(kk).getPressure(); + zt = sndata.get(kk).getGeoHeight(); + tt = sndata.get(kk).getTemperature(); + tdt = sndata.get(kk).getDewpoint(); + scale[kk] = scaleHeight(tb, tt, tdb, tdt, pb, pt); + znew = moistHeight(zb, pb, pt, scale[kk]); + if (znew != RMISSD) { + pb = pt; + tb = tt; + tdb = tdt; + zb = znew; + } + } + + /* + * Compute the scaling factor so the computed moist height is + * consistent at the mandatory level. Then recompute the height. + */ + float s = (zt - zlev) / (znew - zlev); + float zbb = zlev; + float pbb = plev; + for (int kk = blev + 1; kk < tlev; kk++) { + pt = sndata.get(kk).getPressure(); + zt = sndata.get(kk).getGeoHeight(); + scale[kk] = scale[kk] * s; + znew = moistHeight(zbb, pbb, pt, scale[kk]); + if (znew != RMISSD) { + pbb = pt; + zbb = znew; + sndata.get(kk).setGeoHeight(znew); + } + } + mand = false; + newblock = true; + + if ((tlev + 1) != sndata.size()) { + if (sndata.get(tlev + 1).getGeoHeight() == RMISSD + && sndata.get(tlev + 1).getPressure() != RMISSD + && sndata.get(tlev + 1).getTemperature() != RMISSD) { + nlev--; + } + } + } + } + // System.out + // .println("In construct TTBB Height before check TOP missing level: "); + // printOut(sndata); + + // System.out.println(" TLEV: " + tlev + " sndata.size()" + + // sndata.size() + "\n"); + // Fill missing height at the top levels + fillMissingHeightAtTop(sndata); + + return; + } + + /* + * Merge the significant and maximum wind data on pressure surfaces. MR_PWND + */ + public void mergeSigMaxWindOnPressure(List sig_wa, + List sig_wc, List sndata) { + + if (sig_wa.size() < 1 && sig_wc.size() < 1) { + return; + } + + // System.out.println(" Windmax below trop \n"); + // printOut(sig_wa); + // System.out.println(" Windmax above trop \n"); + // printOut(sig_wc); + + /* + * Append two lists of wind data. + */ + if (sig_wc.size() > 0 && sig_wc.get(0).getPressure() != RMISSD) { + for (int kk = 0; kk < sig_wc.size(); kk++) { + sig_wa.add(sig_wc.get(kk)); + } + } + + /* + * Merging + */ + int nlevel = sndata.size(); + for (int kk = 0; kk < sig_wa.size(); kk++) { + boolean found = false; + for (int lev = 0; lev < nlevel; lev++) { + if (equal(sndata.get(lev).getPressure(), sig_wa.get(kk) + .getPressure())) { + + // add data to missing + if (sndata.get(lev).getWindDirection() == RMISSD) { + sndata.get(lev).setWindDirection( + sig_wa.get(kk).getWindDirection()); + sndata.get(lev).setWindSpeed( + sig_wa.get(kk).getWindSpeed()); + } + found = true; + } + } + // System.out.println("In mergeSigMaxWindOnPressure:); + // printOut(sndata); + + /* + * if not found, add to the list. + */ + if (!found) { + if ((sig_wa.get(kk).getWindDirection() != RMISSD && sig_wa.get( + kk).getPressure() != RMISSD)) { + + NcSoundingLayer sl = new NcSoundingLayer(); + sl.setPressure(sig_wa.get(kk).getPressure()); + sl.setTemperature(sig_wa.get(kk).getTemperature()); + sl.setDewpoint(sig_wa.get(kk).getDewpoint()); + sl.setWindDirection(sig_wa.get(kk).getWindDirection()); + sl.setWindSpeed(sig_wa.get(kk).getWindSpeed()); + sl.setGeoHeight(sig_wa.get(kk).getGeoHeight()); + sl.setOmega(sig_wa.get(kk).getOmega()); + sndata.add(sl); + nlevel++; + } + } + + Collections.sort(sndata, new reverseSortByPressure()); + } + fillMissingHeightAtTop(sndata); + // printOut(sndata); + return; + } + + /* + * Construct height at significant wind levels (PPBB) if reported on + * pressure levels. Using moist hydrostatic computation for missing height + * at top levels. MR_INTZ + */ + public void constructPpbbHeight(List sndata) { + int tlev = 0; + // System.out.println("From constructPpbbHeight(): " ); + for (int kk = sndata.size() - 1; kk >= 0; kk--) { + if (sndata.get(kk).getGeoHeight() != RMISSD) { + tlev = kk; + break; + } + } + + float pb = RMISSD, pt = RMISSD, zt = RMISSD, zb = RMISSD; + int next; + + if (sndata.size() <= 2) + return; + + for (int kk = 0; kk < tlev; kk++) { + float pres = sndata.get(kk).getPressure(); + float hght = sndata.get(kk).getGeoHeight(); + if (pres == RMISSD) { + // DO NOTHING + } else if (hght != RMISSD) { + pb = pres; + zb = hght; + pt = 2000.f; + } else if (pb == RMISSD) { + // DO NOTHING + } else { + + /* + * Find next level with height and then interpolate the data. + */ + next = kk + 1; + while (pres <= pt) { + if (sndata.get(next).getGeoHeight() != RMISSD) { + pt = sndata.get(next).getPressure(); + zt = sndata.get(next).getGeoHeight(); + } else { + next++; + } + } + float hhh = (float) (zb + (zt - zb) + * (Math.log(pres / pb) / Math.log(pt / pb))); + sndata.get(kk).setGeoHeight(hhh); + } + } + + fillMissingHeightAtTop(sndata); + } + + /* + * Merge significant wind on height surfaces. The argument is sndata. + */ + public void mergeSigWindOnHeight(List sig_wa, + List sig_wc, List sndata) { + + /* + * The following code needs to be replaced by significant wind data from + * database. + */ + + /* + * Do nothing if wind report is not on height surfaces. + */ + if (sig_wa.size() < 1 && sig_wc.size() < 1) { + return; + } + + /* + * Add two lists of wind data. + */ + if (sig_wc.size() > 0) { + for (int kk = 0; kk < sig_wc.size(); kk++) { + sig_wa.add(sig_wc.get(kk)); + } + } + // System.out.println(" in mergeSigWindOnHeight 0: "); + // printOut(sndata); + + int nlevel = sndata.size(); + for (int kk = 0; kk < sig_wa.size(); kk++) { + boolean found = false; + float zzz = sig_wa.get(kk).getGeoHeight(); + + // Check surface level independently because sometimes station + // report wind data twice at surface. We don't want the surface + // pressure to be missing. + if (zzz == 0) { + if (sndata.get(0).getWindDirection() == RMISSD) { + sndata.get(0).setWindDirection( + sig_wa.get(0).getWindDirection()); + sndata.get(0).setWindSpeed(sig_wa.get(kk).getWindSpeed()); + } + found = true; + } else { + for (int lev = 0; lev < nlevel; lev++) { + float hght = sndata.get(lev).getGeoHeight(); + if (equal(zzz, hght) || (zzz == 0 && lev == 0 && kk == 0)) { + // add data to missing + if (sndata.get(lev).getWindDirection() == RMISSD) { + sndata.get(lev).setWindDirection( + sig_wa.get(kk).getWindDirection()); + sndata.get(lev).setWindSpeed( + sig_wa.get(kk).getWindSpeed()); + } + found = true; + } + } + } + + // System.out.println(" in mergeSigWindOnHeight 1: "); + // printOut(sndata); + + /* + * if not found, add to the list. + */ + if (!found) { + if (sig_wa.get(kk).getWindDirection() != RMISSD + && sig_wa.get(kk).getGeoHeight() != RMISSD) { + NcSoundingLayer sl = new NcSoundingLayer(); + sl.setPressure(sig_wa.get(kk).getPressure()); + sl.setTemperature(sig_wa.get(kk).getTemperature()); + sl.setDewpoint(sig_wa.get(kk).getDewpoint()); + sl.setWindDirection(sig_wa.get(kk).getWindDirection()); + sl.setWindSpeed(sig_wa.get(kk).getWindSpeed()); + sl.setGeoHeight(sig_wa.get(kk).getGeoHeight()); + sl.setOmega(sig_wa.get(kk).getOmega()); + sndata.add(sl); + } + } + } + + /* + * Sorting the combined temperature and wind data based on Geopotential + * height. + */ + // System.out.println(" in mergeSigWindOnHeight 2: "); + // printOut(sndata); + + fillMissingHeightAtTop(sndata); + + Collections.sort(sndata, new sortByHeight()); + return; + } + + // Sort by height + public static class sortByHeight implements Comparator { + public int compare(NcSoundingLayer l1, NcSoundingLayer l2) { + return Float.compare(l1.getGeoHeight(), l2.getGeoHeight()); + } + + } + + // Reverse sort by pressure + public static class reverseSortByPressure implements + Comparator { + public int compare(NcSoundingLayer l1, NcSoundingLayer l2) { + return Float.compare(l2.getPressure(), l1.getPressure()); + } + + } + + /* + * Construct pressure at significant wind levels (PPBB) that are reported on + * height levels. MR_INTP + */ + public List constructPpbbPressure( + List sndata) { + + if (sndata.size() <= 2) + return sndata; + + float pb = RMISSD, pt = RMISSD, zt = RMISSD, zb = RMISSD; + int blev = IMISSD, tlev = IMISSD; + for (int lev = 0; lev < sndata.size(); lev++) { + float pres = sndata.get(lev).getPressure(); + float hght = sndata.get(lev).getGeoHeight(); + if (pres != RMISSD && hght != RMISSD) { + tlev = lev; + pt = pres; + zt = hght; + } + + if (blev != IMISSD && tlev != IMISSD) { + for (int kk = blev + 1; kk < tlev; kk++) { + float z = sndata.get(kk).getGeoHeight(); + if (sndata.get(kk).getGeoHeight() != RMISSD) { + float ppp = (float) (pb * Math.exp((double) ((z - zb) + * Math.log(pt / pb) / (zt - zb)))); + sndata.get(kk).setPressure(ppp); + } + } + } + blev = tlev; + pb = pt; + zb = zt; + } + + if (tlev == (sndata.size() - 1) || tlev == IMISSD) { + return sndata; + } else { + + /* + * Compute missing pressure at top levels. + */ + pb = sndata.get(tlev - 1).getPressure(); + zb = sndata.get(tlev - 1).getGeoHeight(); + + for (int kk = tlev + 1; kk < sndata.size(); kk++) { + if (sndata.get(kk).getPressure() == RMISSD) { + pt = sndata.get(kk - 1).getPressure(); + zt = sndata.get(kk - 1).getGeoHeight(); + float zz = sndata.get(kk).getGeoHeight(); + float rmult = (float) ((zz - zb) / (zt - zb)); + sndata.get(kk).setPressure( + (float) (pb * (Math.pow(pt / pb, rmult)))); + pb = pt; + zb = zt; + } + } + } + return sndata; + } + + /* + * Reorder the sounding data so the first level is always the surface data. + */ + public List reOrderSounding(List sndata) { + List outdat = new ArrayList(); + float tt, td, dd, ff; + int klev = 0; + if (sndata.size() <= 1) + return sndata; + + /* + * Find the surface level + */ + for (int kk = 0; kk < sndata.size(); kk++) { + tt = sndata.get(kk).getTemperature(); + td = sndata.get(kk).getDewpoint(); + dd = sndata.get(kk).getWindDirection(); + ff = sndata.get(kk).getWindSpeed(); + if (tt == RMISSD && td == RMISSD && dd == RMISSD && ff == RMISSD) { + // DO NOTHING + } else { + klev = kk; + addDataToList(0, sndata, outdat); + } + } + + /* + * Reorder the data below the surface levels. + */ + for (int kk = 0; kk < klev; kk++) { + addDataToList(kk, sndata, outdat); + } + + for (int kk = klev + 1; kk < sndata.size(); kk++) { + addDataToList(kk, sndata, outdat); + } + return outdat; + } + + /* + * Construct missing temperature (iflag = 1), dewpoint temperature (iflag=2) + * and wind (iflag = 3). This method is called after reOrderSounding(). + * MR_MISS + */ + public List constructMissing(int iflag, + List sndata) { + float pb = RMISSD, pt = RMISSD, data = RMISSD, pres, tb, tt, tdb, tdt; + int jlev = IMISSD, tlev = IMISSD; + boolean contin = true; + if (sndata.size() <= 2) + return sndata; + for (int blev = 1; blev < sndata.size() - 1 && contin; blev++) { + jlev = blev; + + switch (iflag) { + case 1: { + data = sndata.get(blev).getTemperature(); + break; + } + case 2: { + data = sndata.get(blev).getDewpoint(); + break; + } + case 3: { + data = sndata.get(blev).getWindDirection(); + break; + } + default: { + return sndata; + } + } + + if (data == RMISSD) { + + /* + * find data at level above. Data should already be at level + * below after reOrderSounding() call. + */ + boolean found = false; + while (!found) { + jlev++; + switch (iflag) { + case 1: { + data = sndata.get(jlev).getTemperature(); + break; + } + case 2: { + data = sndata.get(jlev).getDewpoint(); + break; + } + case 3: { + data = sndata.get(jlev).getWindDirection(); + break; + } + default: { + // System.out.println("Invalid data flag"); + } + } + int top = sndata.size(); + if (data != RMISSD || jlev + 1 >= top) { + found = true; + tlev = jlev; + if (jlev >= top) { + tlev = IMISSD; + contin = false; + } + } + } + + /* + * Add check to eliminate dew point layer more than 100mb. + */ + if (iflag == 2 && tlev != IMISSD) { + if ((sndata.get(blev).getPressure() - sndata.get(tlev) + .getPressure()) > 100.) { + for (int kk = tlev; kk < sndata.size(); kk++) { + sndata.get(kk).setDewpoint(RMISSD); + } + tlev = IMISSD; + contin = false; + } + } + + /* + * Add check to eliminate interpolation of winds from below 100 + * mb to above 100 mb. This eliminates interpolation to very + * high level winds. + */ + /* + * if (iflag == 3 && tlev != IMISSD && (sndata.get(blev - + * 1).getPressure() > 100.) && (sndata.get(tlev).getPressure() < + * 100.)) { tlev = IMISSD; } + */ + /* + * Interpolate with respect to logP. + */ + float rmult = RMISSD; + if (tlev != IMISSD) { + pb = sndata.get(blev - 1).getPressure(); + pres = sndata.get(blev).getPressure(); + pt = sndata.get(tlev).getPressure(); + if (pt != RMISSD && pb != RMISSD && pres != RMISSD) { + rmult = (float) (Math.log(pres / pb) / Math + .log(pt / pb)); + } + + switch (iflag) { + case 1: { + tb = sndata.get(blev - 1).getTemperature(); + tt = sndata.get(tlev).getTemperature(); + + if (tb != RMISSD && tt != RMISSD && rmult != RMISSD) { + data = tb + (tt - tb) * rmult; + + sndata.get(blev).setTemperature(data); + } + + tdb = sndata.get(blev - 1).getDewpoint(); + tdt = sndata.get(tlev).getDewpoint(); + if (tdb != RMISSD && tdt != RMISSD && rmult != RMISSD) { + data = tdb + (tdt - tdb) * rmult; + sndata.get(blev).setDewpoint(data); + } + break; + } + case 2: { + tdb = sndata.get(blev - 1).getDewpoint(); + tdt = sndata.get(tlev).getDewpoint(); + if (tdb != RMISSD && tdt != RMISSD && rmult != RMISSD) { + data = tdb + (tdt - tdb) * rmult; + sndata.get(blev).setDewpoint(data); + } + break; + } + case 3: { + float drctb = sndata.get(blev - 1).getWindDirection(); + float drctt = sndata.get(tlev).getWindDirection(); + + if (drctt != RMISSD && drctb != RMISSD + && rmult != RMISSD) { + drctb = drctb % 360.f; + drctt = drctt % 360.f; + if (Math.abs(drctb - drctt) > 180.f) { + if (drctb < drctt) { + drctb = drctb + 360.f; + } else { + drctt = drctt + 360.f; + } + } + float drct = (drctb + (drctt - drctb) * rmult) % 360.f; + sndata.get(blev).setWindDirection(drct); + + // Interpolate wind speed + float spedb = sndata.get(blev - 1).getWindSpeed(); + float spedt = sndata.get(tlev).getWindSpeed(); + float sped = spedb + (spedt - spedb) * rmult; + sndata.get(blev).setWindSpeed(sped); + } + break; + + } + } + } + } + } + return sndata; + } + + /* + * Re-order the data so the first level is always the ground level. MR_COND + */ + public List addUnderGround(List man, + List sndata) { + if (sndata == null || sndata.size() < 2) + return sndata; + if (sndata.get(0).getPressure() == RMISSD || man.size() < 1) + return sndata; + + int blev = 0; + boolean contin = true; + while (blev < sndata.size() && contin) { + if (man.get(blev).getPressure() > sndata.get(0).getPressure()) { + blev++; + if (blev >= man.size()) + contin = false; + } else { + contin = false; + } + } + + if (blev >= sndata.size()) { + return sndata; + } + + /* + * Added below-ground mandatory levels to sounding layers. + */ + List outdat = new ArrayList(); + + int nlev = sndata.size(); + + // write to surface data first + addDataToList(0, sndata, outdat); + + // add below-ground mandatory data + if (blev > 0 && blev < sndata.size()) { + for (int kk = 0; kk < blev; kk++) { + addDataToList(kk, man, outdat); + } + } + + // add the rest of the data + for (int kk = 1; kk < nlev; kk++) { + addDataToList(kk, sndata, outdat); + } + return outdat; + + } + + /* + * Re-order the data so the first level is always the ground level. MR_COND + */ + public List removeUnderGround(List sndata) { + List outdat = new ArrayList(); + /* + * Remove below-ground mandatory levels from sounding layers. Only the + * first 8 missing levels can be mandatory levels. + */ + if (sndata.size() <= 1) + return sndata; + for (int kk = 0; kk < sndata.size(); kk++) { + if (sndata.get(kk).getTemperature() <= RMISSD + && sndata.get(kk).getDewpoint() <= RMISSD + && sndata.get(kk).getWindDirection() <= RMISSD + && sndata.get(kk).getWindSpeed() <= RMISSD) { + } else if (sndata.get(kk).getPressure() <= RMISSD) { + } else { + addDataToList(kk, sndata, outdat); + } + } + return outdat; + } + + /* + * Interpolate data to a single level, including surface. + */ + public List getSingLevel(float pres, + List sndata) { + NcSoundingLayer sl = new NcSoundingLayer(); + List sls = new ArrayList(); + sndata = removeUnderGround(sndata); + if (sndata.size() <= 1) + return missingSounding(); // Chin: check size again, after remove + // underground level, size changed + + for (int kk = 1; /* chin 0; */kk < sndata.size() - 1; kk++) { + if (pres > sndata.get(0).getPressure() || pres < 0.f) { + return missingSounding(); + } else { + + if (pres >= sndata.get(kk).getPressure()) { + float pt, pb, zt, zb, tt, tb, tdt, tdb, dt, db, st, sb; + pb = sndata.get(kk - 1).getPressure(); + pt = sndata.get(kk).getPressure(); + tb = sndata.get(kk - 1).getTemperature(); + tt = sndata.get(kk).getTemperature(); + tdb = sndata.get(kk - 1).getDewpoint(); + tdt = sndata.get(kk).getDewpoint(); + db = sndata.get(kk - 1).getWindDirection() % 360.f; + dt = sndata.get(kk).getWindDirection() % 360.f; + sb = sndata.get(kk - 1).getWindSpeed(); + st = sndata.get(kk).getWindSpeed(); + zb = sndata.get(kk - 1).getGeoHeight(); + zt = sndata.get(kk).getGeoHeight(); + sl.setPressure(pres); + + float rmult = (float) (Math.log(pres / pb) / Math.log(pt + / pb)); + sl.setTemperature(tb + (tt - tb) * rmult); + sl.setDewpoint(tdb + (tdt - tdb) * rmult); + if (Math.abs(db - dt) > 180.) { + if (db < dt) { + db = db + 360.f; + } else { + dt = dt + 360.f; + } + } + sl.setWindDirection(db + (dt - db) * rmult); + sl.setWindSpeed(sb + (st - sb) * rmult); + sl.setGeoHeight(zb + (zt - zb) * rmult); + sls.add(sl); + return sls; + } + } + } + return missingSounding(); + } + + /* + * Add data to output sounding profile. + */ + public void addDataToList(int index, List indat, + List outdat) { + NcSoundingLayer sl = new NcSoundingLayer(); + sl.setPressure(indat.get(index).getPressure()); + sl.setTemperature(indat.get(index).getTemperature()); + sl.setDewpoint(indat.get(index).getDewpoint()); + sl.setWindDirection(indat.get(index).getWindDirection()); + sl.setWindSpeed(indat.get(index).getWindSpeed()); + sl.setGeoHeight(indat.get(index).getGeoHeight()); + sl.setOmega(indat.get(index).getOmega()); + outdat.add(sl); + } + + /* + * Set missing to output sounding profile. + */ + public List missingSounding() { + List outdat = new ArrayList(); + NcSoundingLayer sl = new NcSoundingLayer(); + sl.setPressure(RMISSD); + sl.setTemperature(RMISSD); + sl.setDewpoint(RMISSD); + sl.setWindDirection(RMISSD); + sl.setWindSpeed(RMISSD); + sl.setGeoHeight(RMISSD); + sl.setOmega(RMISSD); + outdat.add(sl); + return outdat; + } + + /* + * Print the sounding data out. + */ + public void printOut(List sndata) { + for (NcSoundingLayer soundLy : sndata) { + System.out.print(" PRES: " + soundLy.getPressure() + " HGHT: " + + soundLy.getGeoHeight() + " TMPC: " + + soundLy.getTemperature() + " DWPC: " + + soundLy.getDewpoint() + " DRCT: " + + soundLy.getWindDirection() + " SPED: " + + soundLy.getWindSpeed() + " OMEG " + soundLy.getOmega() + + "\n"); + } + } + + /* + * Extrapolate missing height at the top level before sorting the data by + * height. + */ + private void fillMissingHeightAtTop(List sndata) { + int blev, kk; + float pb, zb, tb, tdb; + float pt, tt, tdt; + float znew; + boolean contin; + + int miss = 0; + contin = true; + if (sndata.get(sndata.size() - 1).getGeoHeight() != RMISSD) + return; + for (kk = sndata.size() - 1; kk > 0 && contin; kk--) { + if (sndata.get(kk).getGeoHeight() == RMISSD) { + miss++; + if (kk == 0) + return; + + if (sndata.get(kk - 1).getGeoHeight() != RMISSD) + contin = false; + } + } + + miss++; + if (miss > 0) { + blev = sndata.size() - miss; + pb = sndata.get(blev).getPressure(); + zb = sndata.get(blev).getGeoHeight(); + tb = sndata.get(blev).getTemperature(); + tdb = sndata.get(blev).getDewpoint(); + + for (kk = blev + 1; kk < sndata.size(); kk++) { + pt = sndata.get(kk).getPressure(); + tt = sndata.get(kk).getTemperature(); + tdt = sndata.get(kk).getDewpoint(); + float xxx = scaleHeight(tb, tt, tdb, tdt, pb, pt); + znew = moistHeight(zb, pb, pt, xxx); + if (znew == RMISSD) { + xxx = scaleHeight(tb, tb, tdb, tdb, pb, pt); + znew = moistHeight(zb, pb, pt, xxx); + } + + if (znew != RMISSD) { + sndata.get(kk).setGeoHeight(znew); + pb = pt; + tb = tt; + tdb = tdt; + zb = znew; + } + } + } + } + + /* + * Remove missing pressure from the sounding profile. + */ + public List removeMissingPressure( + List sndin) { + List sndout = new ArrayList(); + + for (int kk = 0; kk < sndin.size(); kk++) { + if (sndin.get(kk).getPressure() > 0.) { + addDataToList(kk, sndin, sndout); + } + } + return sndout; + } } diff --git a/rpms/build/x86_64/build.sh b/rpms/build/x86_64/build.sh index 3773113a32..2224eb264a 100644 --- a/rpms/build/x86_64/build.sh +++ b/rpms/build/x86_64/build.sh @@ -412,13 +412,13 @@ if [ "${1}" = "-viz" ]; then #buildRPM "awips2-common-base" #buildRPM "awips2-python-dynamicserialize" #buildRPM "awips2-python" - #buildRPM "awips2-adapt-native" + buildRPM "awips2-adapt-native" #unpackHttpdPypies #if [ $? -ne 0 ]; then # exit 1 #fi #buildRPM "awips2-httpd-pypies" - #buildRPM "awips2-hydroapps-shared" + buildRPM "awips2-hydroapps-shared" #buildRPM "awips2-rcm" #buildRPM "awips2-tools" #buildRPM "awips2-cli" From cf385ac2c364ab84b70f26f0eb9c764f014cbdaa Mon Sep 17 00:00:00 2001 From: Ben Steffensmeier Date: Mon, 6 Jan 2014 15:33:22 -0600 Subject: [PATCH 09/62] Issue #2537 Increase efficiency of DAF geometry requests when geometries are reused. Change-Id: Idf0822745cdf3d52668223038f83c76e3de1c55c Former-commit-id: 3f3f74087a7a13081ecf4ec01d1805861253617e [formerly fa46a08fec22c6d683a893fa9fd3fa87554ef21c] [formerly ed2e34e5aaa2ef671f9f1b6eb8c9505ceaa273ca [formerly 05c62ceb516807719a1649e0559a395ce604aee9]] Former-commit-id: ed2e34e5aaa2ef671f9f1b6eb8c9505ceaa273ca Former-commit-id: 7dd641f5cc936afc54fd25e5ac9de44aed9c2aca --- .../response/GeometryResponseData.java | 21 +++++++------- .../response/GetGeometryDataResponse.java | 28 ++++++++++++++++--- .../response/GeometryResponseData.py | 11 ++++---- .../response/GetGeometryDataResponse.py | 7 +++++ .../ufpy/dataaccess/PyGeometryData.py | 7 ++--- .../ufpy/dataaccess/ThriftClientRouter.py | 11 ++++++-- 6 files changed, 60 insertions(+), 25 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.common.dataaccess/src/com/raytheon/uf/common/dataaccess/response/GeometryResponseData.java b/edexOsgi/com.raytheon.uf.common.dataaccess/src/com/raytheon/uf/common/dataaccess/response/GeometryResponseData.java index a2878bf5dd..7e24fae949 100644 --- a/edexOsgi/com.raytheon.uf.common.dataaccess/src/com/raytheon/uf/common/dataaccess/response/GeometryResponseData.java +++ b/edexOsgi/com.raytheon.uf.common.dataaccess/src/com/raytheon/uf/common/dataaccess/response/GeometryResponseData.java @@ -34,9 +34,10 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * SOFTWARE HISTORY * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Jun 03, 2013 dgilling Initial creation + * Date Ticket# Engineer Description + * ------------- -------- ----------- -------------------------- + * Jun 03, 2013 dgilling Initial creation + * Jan 06, 2014 2537 bsteffen Store geometry index instead of WKT. * * * @@ -51,13 +52,13 @@ public class GeometryResponseData extends AbstractResponseData { private Map dataMap; @DynamicSerializeElement - private String geometryWKT; + private int geometryWKTindex; public GeometryResponseData() { // no-op, for serialization } - public GeometryResponseData(final IGeometryData data) { + public GeometryResponseData(final IGeometryData data, final int geometryWKTindex) { super(data); Set parameters = data.getParameters(); @@ -75,7 +76,7 @@ public class GeometryResponseData extends AbstractResponseData { } dataMap.put(param, dataTuple); } - geometryWKT = data.getGeometry().toText(); + this.geometryWKTindex = geometryWKTindex; } public Map getDataMap() { @@ -86,11 +87,11 @@ public class GeometryResponseData extends AbstractResponseData { this.dataMap = dataMap; } - public String getGeometryWKT() { - return geometryWKT; + public int getGeometryWKTindex() { + return geometryWKTindex; } - public void setGeometryWKT(String geometry) { - this.geometryWKT = geometry; + public void setGeometryWKTindex(int geometryWKTindex) { + this.geometryWKTindex = geometryWKTindex; } } diff --git a/edexOsgi/com.raytheon.uf.common.dataaccess/src/com/raytheon/uf/common/dataaccess/response/GetGeometryDataResponse.java b/edexOsgi/com.raytheon.uf.common.dataaccess/src/com/raytheon/uf/common/dataaccess/response/GetGeometryDataResponse.java index 4300c7143d..646c73cfa8 100644 --- a/edexOsgi/com.raytheon.uf.common.dataaccess/src/com/raytheon/uf/common/dataaccess/response/GetGeometryDataResponse.java +++ b/edexOsgi/com.raytheon.uf.common.dataaccess/src/com/raytheon/uf/common/dataaccess/response/GetGeometryDataResponse.java @@ -34,9 +34,10 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * SOFTWARE HISTORY * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Jun 3, 2013 dgilling Initial creation + * Date Ticket# Engineer Description + * ------------- -------- ----------- -------------------------- + * Jun 3, 2013 dgilling Initial creation + * Jan 06, 2014 2537 bsteffen Share geometry WKT. * * * @@ -47,6 +48,9 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @DynamicSerialize public class GetGeometryDataResponse { + @DynamicSerializeElement + private List geometryWKTs; + @DynamicSerializeElement private List geoData; @@ -55,9 +59,16 @@ public class GetGeometryDataResponse { } public GetGeometryDataResponse(final Collection geoData) { + this.geometryWKTs = new ArrayList(); this.geoData = new ArrayList(geoData.size()); for (IGeometryData element : geoData) { - this.geoData.add(new GeometryResponseData(element)); + String wkt = element.getGeometry().toText(); + int index = geometryWKTs.indexOf(wkt); + if (index == -1) { + index = geometryWKTs.size(); + geometryWKTs.add(wkt); + } + this.geoData.add(new GeometryResponseData(element, index)); } } @@ -68,4 +79,13 @@ public class GetGeometryDataResponse { public void setGeoData(List geoData) { this.geoData = geoData; } + + public List getGeometryWKTs() { + return geometryWKTs; + } + + public void setGeometryWKTs(List geometryWKTs) { + this.geometryWKTs = geometryWKTs; + } + } diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataaccess/response/GeometryResponseData.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataaccess/response/GeometryResponseData.py index 8df2cd336c..9a1c69758f 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataaccess/response/GeometryResponseData.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataaccess/response/GeometryResponseData.py @@ -26,6 +26,7 @@ # Date Ticket# Engineer Description # ------------ ---------- ----------- -------------------------- # 06/04/13 #2023 dgilling Initial Creation. +# 01/06/14 #2537 bsteffen Store geometry index instead of WKT. # # @@ -37,7 +38,7 @@ class GeometryResponseData(AbstractResponseData): def __init__(self): super(GeometryResponseData, self).__init__() self.dataMap = None - self.geometryWKT = None + self.geometryWKTindex = None def getDataMap(self): return self.dataMap @@ -45,8 +46,8 @@ class GeometryResponseData(AbstractResponseData): def setDataMap(self, dataMap): self.dataMap = dataMap - def getGeometryWKT(self): - return self.geometryWKT + def getGeometryWKTindex(self): + return self.geometryWKTindex - def setGeometryWKT(self, geometryWKT): - self.geometryWKT = geometryWKT + def setGeometryWKTindex(self, geometryWKTindex): + self.geometryWKTindex = geometryWKTindex diff --git a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataaccess/response/GetGeometryDataResponse.py b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataaccess/response/GetGeometryDataResponse.py index e1f635f301..2107a0704f 100644 --- a/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataaccess/response/GetGeometryDataResponse.py +++ b/pythonPackages/dynamicserialize/dstypes/com/raytheon/uf/common/dataaccess/response/GetGeometryDataResponse.py @@ -23,8 +23,15 @@ class GetGeometryDataResponse(object): def __init__(self): + self.geometryWKTs = None self.geoData = None + def getGeometryWKTs(self): + return self.geometryWKTs + + def setGeometryWKTs(self, geometryWKTs): + self.geometryWKTs = geometryWKTs + def getGeoData(self): return self.geoData diff --git a/pythonPackages/ufpy/dataaccess/PyGeometryData.py b/pythonPackages/ufpy/dataaccess/PyGeometryData.py index abe70ce534..934182ef77 100644 --- a/pythonPackages/ufpy/dataaccess/PyGeometryData.py +++ b/pythonPackages/ufpy/dataaccess/PyGeometryData.py @@ -28,19 +28,18 @@ # Date Ticket# Engineer Description # ------------ ---------- ----------- -------------------------- # 06/03/13 dgilling Initial Creation. +# 01/06/14 #2537 bsteffen Share geometry WKT. # # from ufpy.dataaccess import IGeometryData from ufpy.dataaccess import PyData -import shapely.wkt - class PyGeometryData(IGeometryData, PyData.PyData): - def __init__(self, geoDataRecord): + def __init__(self, geoDataRecord, geometry): PyData.PyData.__init__(self, geoDataRecord) - self.__geometry = shapely.wkt.loads(geoDataRecord.getGeometryWKT()) + self.__geometry = geometry self.__dataMap = {} tempDataMap = geoDataRecord.getDataMap() for key, value in tempDataMap.items(): diff --git a/pythonPackages/ufpy/dataaccess/ThriftClientRouter.py b/pythonPackages/ufpy/dataaccess/ThriftClientRouter.py index 8e8fac6dd4..941e57e19d 100644 --- a/pythonPackages/ufpy/dataaccess/ThriftClientRouter.py +++ b/pythonPackages/ufpy/dataaccess/ThriftClientRouter.py @@ -28,10 +28,12 @@ # Date Ticket# Engineer Description # ------------ ---------- ----------- -------------------------- # 05/21/13 #2023 dgilling Initial Creation. +# 01/06/14 #2537 bsteffen Share geometry WKT. # import numpy +import shapely.wkt from dynamicserialize.dstypes.com.raytheon.uf.common.dataaccess.impl import DefaultDataRequest from dynamicserialize.dstypes.com.raytheon.uf.common.dataaccess.request import GetAvailableLocationNamesRequest @@ -43,6 +45,7 @@ from ufpy import ThriftClient from ufpy.dataaccess import PyGeometryData from ufpy.dataaccess import PyGridData + class ThriftClientRouter(object): def __init__(self, host='localhost'): @@ -97,10 +100,14 @@ class ThriftClientRouter(object): except TypeError: geoDataRequest.setRequestedPeriod(times) response = self._client.sendRequest(geoDataRequest) - + geometries = [] + for wkt in response.getGeometryWKTs(): + geometries.append(shapely.wkt.loads(wkt)) + retVal = [] for geoDataRecord in response.getGeoData(): - retVal.append(PyGeometryData.PyGeometryData(geoDataRecord)) + geom = geometries[geoDataRecord.getGeometryWKTindex()] + retVal.append(PyGeometryData.PyGeometryData(geoDataRecord, geom)) return retVal def getAvailableLocationNames(self, request): From 9913e51429e21af30b84afcceef24c7649639b7e Mon Sep 17 00:00:00 2001 From: Ben Steffensmeier Date: Fri, 3 Jan 2014 14:17:21 -0600 Subject: [PATCH 10/62] Issue #2537 Split modelsounding into common/edex plugins. Change-Id: I34aa58bc13736109bd71f0b0085df6548c4623a8 Former-commit-id: f516a684d4f16088be7b5eafc9a184b0d2b0687e [formerly f520a26fbd445f38dcf51c446d4cdbd5d2a6d1d5] [formerly d79f804d4e01de7c6cd3bd63863fdc5a4b90e0ec [formerly e80e4aa972c394d699feba553d8d13e4f9dd3a03]] Former-commit-id: d79f804d4e01de7c6cd3bd63863fdc5a4b90e0ec Former-commit-id: fac9fd296f571e96f3c104ddd8f55f5c411c4757 --- .../plugin.xml | 6 +- .../feature.xml | 4 +- deltaScripts/14.2.1/mdlsndTimeColumns.sh | 7 + ...f.common.serialization.ISerializableObject | 1 - .../modelsounding/SoundingTemporalData.java | 122 --- .../ModelSoundingPointDataTransform.java | 408 --------- .../modelsounding/common/SoilLevel.java | 96 -- .../modelsounding/common/SoundingLevel.java | 332 ------- .../modelsounding/common/SoundingSite.java | 864 ------------------ .../.classpath | 7 + .../.project | 28 + .../.settings/org.eclipse.jdt.core.prefs | 7 + .../META-INF/MANIFEST.MF | 18 + .../build.properties | 5 + .../modelsounding-common-dataaccess.xml | 0 .../ModelSoundingParameters.java | 159 ++++ .../ModelSoundingPointDataTransform.java | 200 ++++ .../modelsounding/SoundingLevel.java | 166 ++++ .../modelsounding/SoundingSite.java | 759 +++++++++++++++ .../uf/common/pointdata/PointDataView.java | 25 +- .../feature.xml | 9 +- .../res/spring/manualIngest-spring.xml | 2 +- .../.classpath | 0 .../.project | 2 +- .../.settings/org.eclipse.jdt.core.prefs | 0 .../META-INF/MANIFEST.MF | 13 +- .../build.properties | 0 ...com.raytheon.edex.plugin.modelsounding.ecl | 0 .../res/pointdata/modelsounding.xml | 0 .../res/pointdata/modelsoundingdb.xml | 0 .../res/spring/modelsounding-common.xml | 6 +- .../res/spring/modelsounding-ingest.xml | 4 +- .../modelsounding/ModelSoundingDecoder.java | 8 +- .../ModelSoundingPersistenceManager.java | 2 +- .../modelsounding/ModelSoundingSeparator.java | 2 +- .../ModelSoundingStorageContainer.java | 2 +- .../SoundingModelTemporalData.java | 24 +- .../common/ModelSoundingPathProvider.java | 14 +- .../modelsounding/common/SoundingModels.java | 2 +- .../modelsounding/dao/ModelSoundingDAO.java | 32 +- .../decoder/ModelSoundingDataAdapter.java | 260 +++--- .../decoder/SoundingStations.java | 25 +- .../ingest/ModelBufrSubscriber.java | 8 +- .../base/path/modelsoundingPathKeys.xml | 0 .../base/distribution/modelsounding.xml | 0 .../modelsounding/modelBufrStationList.txt | 0 .../plugin-filters/modelSounding_filters.xml | 0 .../uf/edex/pointdata/PointDataPluginDao.java | 27 +- .../META-INF/MANIFEST.MF | 5 +- .../tasks/profile/PfcSoundingQuery.java | 172 ++-- .../META-INF/MANIFEST.MF | 4 +- 51 files changed, 1671 insertions(+), 2166 deletions(-) create mode 100644 deltaScripts/14.2.1/mdlsndTimeColumns.sh delete mode 100644 edexOsgi/com.raytheon.edex.plugin.modelsounding/META-INF/services/com.raytheon.uf.common.serialization.ISerializableObject delete mode 100644 edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/SoundingTemporalData.java delete mode 100644 edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/ModelSoundingPointDataTransform.java delete mode 100644 edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoilLevel.java delete mode 100644 edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingLevel.java delete mode 100644 edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingSite.java create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/.classpath create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/.project create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/.settings/org.eclipse.jdt.core.prefs create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/META-INF/MANIFEST.MF create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/build.properties rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.common.dataplugin.modelsounding}/res/spring/modelsounding-common-dataaccess.xml (100%) create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/ModelSoundingParameters.java create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/ModelSoundingPointDataTransform.java create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/SoundingLevel.java create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/SoundingSite.java rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/.classpath (100%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/.project (91%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/.settings/org.eclipse.jdt.core.prefs (100%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/META-INF/MANIFEST.MF (66%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/build.properties (100%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/com.raytheon.edex.plugin.modelsounding.ecl (100%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/res/pointdata/modelsounding.xml (100%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/res/pointdata/modelsoundingdb.xml (100%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/res/spring/modelsounding-common.xml (73%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/res/spring/modelsounding-ingest.xml (94%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding/src/com/raytheon => com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf}/edex/plugin/modelsounding/ModelSoundingDecoder.java (97%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding/src/com/raytheon => com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf}/edex/plugin/modelsounding/ModelSoundingPersistenceManager.java (99%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding/src/com/raytheon => com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf}/edex/plugin/modelsounding/ModelSoundingSeparator.java (99%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding/src/com/raytheon => com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf}/edex/plugin/modelsounding/ModelSoundingStorageContainer.java (97%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding/src/com/raytheon => com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf}/edex/plugin/modelsounding/SoundingModelTemporalData.java (82%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding/src/com/raytheon => com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf}/edex/plugin/modelsounding/common/ModelSoundingPathProvider.java (79%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding/src/com/raytheon => com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf}/edex/plugin/modelsounding/common/SoundingModels.java (97%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding/src/com/raytheon => com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf}/edex/plugin/modelsounding/dao/ModelSoundingDAO.java (76%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding/src/com/raytheon => com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf}/edex/plugin/modelsounding/decoder/ModelSoundingDataAdapter.java (69%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding/src/com/raytheon => com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf}/edex/plugin/modelsounding/decoder/SoundingStations.java (85%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding/src/com/raytheon => com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf}/edex/plugin/modelsounding/ingest/ModelBufrSubscriber.java (98%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/utility/common_static/base/path/modelsoundingPathKeys.xml (100%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/utility/edex_static/base/distribution/modelsounding.xml (100%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/utility/edex_static/base/modelsounding/modelBufrStationList.txt (100%) rename edexOsgi/{com.raytheon.edex.plugin.modelsounding => com.raytheon.uf.edex.plugin.modelsounding}/utility/edex_static/base/plugin-filters/modelSounding_filters.xml (100%) diff --git a/cave/com.raytheon.uf.viz.d2d.xy.adapters/plugin.xml b/cave/com.raytheon.uf.viz.d2d.xy.adapters/plugin.xml index 544c7f5099..f7c1b6cc0d 100644 --- a/cave/com.raytheon.uf.viz.d2d.xy.adapters/plugin.xml +++ b/cave/com.raytheon.uf.viz.d2d.xy.adapters/plugin.xml @@ -10,7 +10,7 @@ @@ -175,7 +175,7 @@ diff --git a/cave/com.raytheon.uf.viz.sounding.feature/feature.xml b/cave/com.raytheon.uf.viz.sounding.feature/feature.xml index aac57ce122..ef654dd1a4 100644 --- a/cave/com.raytheon.uf.viz.sounding.feature/feature.xml +++ b/cave/com.raytheon.uf.viz.sounding.feature/feature.xml @@ -23,11 +23,11 @@ + unpack="true"/> - * - * SOFTWARE HISTORY - * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Jul 3, 2013 2161 bkowal Initial creation - * - * - * - * @author bkowal - * @version 1.0 - */ - -public class SoundingTemporalData { - private Calendar obsTime; - - private DataTime dt; - - private long refTime; - - private long validTime; - - private int forecastHr; - - /** - * - */ - public SoundingTemporalData() { - this.obsTime = null; - this.dt = null; - this.refTime = -1L; - this.validTime = -1L; - this.forecastHr =-1; - } - - public Calendar getObsTime() { - return obsTime; - } - - public void setObsTime(Calendar obsTime) { - this.obsTime = obsTime; - } - - public DataTime getDt() { - return dt; - } - - public void setDt(DataTime dt) { - this.dt = dt; - } - - public long getRefTime() { - return refTime; - } - - public void setRefTime(long refTime) { - this.refTime = refTime; - } - - public long getValidTime() { - return validTime; - } - - public void setValidTime(long validTime) { - this.validTime = validTime; - } - - public int getForecastHr() { - return forecastHr; - } - - public void setForecastHr(int forecastHr) { - this.forecastHr = forecastHr; - } - - @Override - public boolean equals(Object object) { - SoundingTemporalData otherIndex = (SoundingTemporalData) object; - - return (otherIndex.refTime == this.refTime) - && (otherIndex.forecastHr == this.forecastHr); - } - - @Override - public String toString() { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("refTime = "); - stringBuilder.append(this.refTime); - stringBuilder.append(", forecastHr = "); - stringBuilder.append(this.forecastHr); - - return stringBuilder.toString(); - } -} diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/ModelSoundingPointDataTransform.java b/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/ModelSoundingPointDataTransform.java deleted file mode 100644 index b62bf3ed84..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/ModelSoundingPointDataTransform.java +++ /dev/null @@ -1,408 +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.edex.plugin.modelsounding.common; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Set; - -import com.raytheon.uf.common.pointdata.PointDataContainer; -import com.raytheon.uf.common.pointdata.PointDataView; -import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; -import com.raytheon.uf.common.time.DataTime; -import com.raytheon.uf.edex.pointdata.PointDataQuery; - -/** - * - * A class for converting point data into sounding sites. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Apr 6, 2011            bsteffen     Initial creation
- * 
- * 
- * - * @author bsteffen - * @version 1.0 - */ -public class ModelSoundingPointDataTransform { - - // Record parameters - public static final String P_WMO_HEADER = "wmoHeader"; - - public static final String P_DATAURI = "dataURI"; - - public static final String P_STATION_NUMBER = "wmoStaNum"; - - public static final String P_LATITUDE = "latitude"; - - public static final String P_LONGITUDE = "longitude"; - - public static final String P_ELEVATION = "elevation"; - - public static final String P_STATION_ID = "stationId"; - - public static final String P_REF_TIME = "refTime"; - - public static final String P_FORECAST_HOUR = "forecastHr"; - - public static final String P_NUM_LEVELS = "numProfLvls"; - - // Level parameters - public static final String P_LVL_PRESS = "pressure"; - - public static final String P_LVL_TEMP = "temperature"; - - public static final String P_LVL_SPEC_HUM = "specHum"; - - public static final String P_LVL_OMEGA = "omega"; - - public static final String P_LVL_U_COMP = "uComp"; - - public static final String P_LVL_V_COMP = "vComp"; - - public static final String P_LVL_CLOUD_COVER = "cldCvr"; - - // Surface parameters - public static final String P_SFC_PRESS = "sfcPress"; - - public static final String P_SEA_LEVEL_PRESS = "seaLvlPress"; - - public static final String P_LOW_CLOUD = "lowCld"; - - public static final String P_MID_CLOUD = "midCld"; - - public static final String P_HIGH_CLOUD = "hiCld"; - - public static final String P_CLOUD_PRESS = "prCloud"; - - public static final String P_VISIBILITY = "vsby"; - - public static final String P_U_STORM = "uStorm"; - - public static final String P_V_STORM = "vStorm"; - - public static final String P_STORM_REL_HELI = "srHel"; - - public static final String P_TOTAL_PRECIP = "totPrecip"; - - public static final String P_CONV_PRECIP = "convPrecip"; - - public static final String P_SNOW_FALL = "snowFall"; - - public static final String P_U_COMP_10M = "u10"; - - public static final String P_V_COMP_10M = "v10"; - - public static final String P_TEMP_2M = "temp2"; - - public static final String P_SPEC_HUM_2M = "q2"; - - public static final String P_SNOW_TYPE = "snowTyp"; - - public static final String P_ICE_TYPE = "iceTyp"; - - public static final String P_FREEZING_RAIN_TYPE = "frzgRainTyp"; - - public static final String P_RAIN_TYPE = "rainType"; - - // This list deliberately omits data which can be pulled from the dataURI - // including location and time information - public static final List ALL_DATA = Arrays.asList(P_WMO_HEADER, - P_DATAURI, P_ELEVATION, P_STATION_NUMBER, P_NUM_LEVELS, P_LVL_PRESS, P_LVL_TEMP, - P_LVL_SPEC_HUM, P_LVL_OMEGA, P_LVL_U_COMP, P_LVL_V_COMP, - P_LVL_CLOUD_COVER, P_SFC_PRESS, P_SEA_LEVEL_PRESS, P_LOW_CLOUD, - P_MID_CLOUD, P_HIGH_CLOUD, P_CLOUD_PRESS, P_VISIBILITY, P_U_STORM, - P_V_STORM, P_STORM_REL_HELI, P_TOTAL_PRECIP, P_CONV_PRECIP, - P_SNOW_FALL, P_U_COMP_10M, P_V_COMP_10M, P_TEMP_2M, P_SPEC_HUM_2M, - P_SNOW_TYPE, P_ICE_TYPE, P_FREEZING_RAIN_TYPE, P_RAIN_TYPE); - - public static final List LVL_PARAMETERS = Arrays.asList( - P_LVL_PRESS, P_LVL_TEMP, P_LVL_SPEC_HUM, P_LVL_OMEGA, P_LVL_U_COMP, - P_LVL_V_COMP, P_LVL_CLOUD_COVER); - - /** - * Use all point data parameters to build sounding sites for all sites which - * match the query defined by fields, values, and operands. - * - */ - public static List getSoundingSites(List fields, - List values, List operands) throws Exception { - return getSoundingSites(fields, values, operands, ALL_DATA); - } - - /** - * Use the specified point data parameters to build sounding sites for all - * sites which match the query defined by fields, values, and operands. - * - */ - public static List getSoundingSites(List fields, - List values, List operands, List parameters) - throws Exception { - StringBuilder parametersString = new StringBuilder(); - for (String parameter : parameters) { - if (parametersString.length() > 0) { - parametersString.append(","); - } - parametersString.append(parameter); - } - if (!parameters.contains(P_NUM_LEVELS)) { - // if you have any level based parameters you must include num - // levels - for (String lvlParam : LVL_PARAMETERS) { - if (parameters.contains(lvlParam)) { - parametersString.append(","); - parametersString.append(P_NUM_LEVELS); - break; - } - } - } - PointDataQuery pdq = new PointDataQuery("modelsounding"); - pdq.setParameters(parametersString.toString()); - for (int i = 0; i < fields.size(); i++) { - Object value = values.get(i); - String valueString = String.valueOf(value); - // TODO more generic support of different objects and/or allow - // PointDataQuery to handle Objects instead of just String - if (value instanceof Date) { - valueString = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") - .format(value); - } - pdq.addParameter(fields.get(i), valueString, operands.get(i)); - - } - pdq.requestAllLevels(); - PointDataContainer pdc = pdq.execute(); - if (pdc == null) { - return Collections.emptyList(); - } - return getSoundingSites(pdc); - } - - /** - * Build sounding sites from the data in the container. - * - * @param pdc - * @return - */ - public static List getSoundingSites(PointDataContainer pdc) { - List sites = new ArrayList( - pdc.getCurrentSz()); - for (int i = 0; i < pdc.getCurrentSz(); i++) { - sites.add(getSoundingSite(pdc.readRandom(i))); - } - return sites; - } - - /** - * Build a single sounding site from the data in the view. - * - * @param pdv - * @return - */ - public static SoundingSite getSoundingSite(PointDataView pdv) { - // All the code from here on is boilerplate code for determining what - // parameters are in the view and setting the appropriate field in the - // Sounding Site. - Set parameters = pdv.getContainer().getParameters(); - SoundingSite site = null; - if (parameters.contains(P_DATAURI)) { - // Parsing from the dataURI gets several fields for us. - site = new SoundingSite(pdv.getString(P_DATAURI)); - site.setFcstSeconds((long) site.getDataTime().getFcstTime()); - } else { - site = new SoundingSite(); - site.setLocation(new SurfaceObsLocation()); - // All of these things would have been in dataURI - if (parameters.contains(P_LATITUDE)) { - site.getLocation().setLatitude( - pdv.getNumber(P_LATITUDE).doubleValue()); - } - if (parameters.contains(P_LONGITUDE)) { - site.getLocation().setLongitude( - pdv.getNumber(P_LONGITUDE).doubleValue()); - } - if (parameters.contains(P_STATION_ID)) { - site.getLocation().setStationId(pdv.getString(P_STATION_ID)); - } - if (parameters.contains(P_FORECAST_HOUR)) { - if (parameters.contains(P_REF_TIME)) { - Date refTime = new Date(pdv.getNumber(P_REF_TIME) - .longValue() * 1000); - int fcstTime = pdv.getNumber(P_FORECAST_HOUR).intValue() * 3600; - site.setDataTime(new DataTime(refTime, fcstTime)); - } - site.setFcstSeconds(pdv.getNumber(P_FORECAST_HOUR).longValue() * 3600); - } else if (parameters.contains(P_REF_TIME)) { - // This might not be the best idea most people will want - // forecast time also - site.setDataTime(new DataTime(new Date(pdv - .getNumber(P_REF_TIME).longValue() * 1000))); - } - } - // Record parameters - if (parameters.contains(P_WMO_HEADER)) { - site.setWmoHeader(pdv.getString(P_WMO_HEADER)); - } - if (parameters.contains(P_STATION_NUMBER)) { - site.setSiteId(String.format("%06d", pdv - .getNumber(P_STATION_NUMBER).intValue())); - } - populateLevels(site, pdv); - - // Surface parameters - if (parameters.contains(P_ELEVATION)) { - site.getLocation().setElevation(pdv.getNumber(P_ELEVATION).intValue()); - } - if (parameters.contains(P_SFC_PRESS)) { - site.setPressSfc(pdv.getNumber(P_SFC_PRESS).intValue()); - } - if (parameters.contains(P_SEA_LEVEL_PRESS)) { - site.setPressSLP(pdv.getNumber(P_SEA_LEVEL_PRESS).intValue()); - } - if (parameters.contains(P_LOW_CLOUD)) { - site.setCldAmtLo(pdv.getNumber(P_LOW_CLOUD).intValue()); - } - if (parameters.contains(P_MID_CLOUD)) { - site.setCldAmtMd(pdv.getNumber(P_MID_CLOUD).intValue()); - } - if (parameters.contains(P_HIGH_CLOUD)) { - site.setCldAmtHi(pdv.getNumber(P_HIGH_CLOUD).intValue()); - } - if (parameters.contains(P_CLOUD_PRESS)) { - site.setPressCldBase(pdv.getNumber(P_CLOUD_PRESS).intValue()); - } - if (parameters.contains(P_VISIBILITY)) { - site.setHorzVis(pdv.getNumber(P_VISIBILITY).doubleValue()); - } - if (parameters.contains(P_U_STORM)) { - site.setStormUComp(pdv.getNumber(P_U_STORM).doubleValue()); - } - if (parameters.contains(P_V_STORM)) { - site.setStormVComp(pdv.getNumber(P_V_STORM).doubleValue()); - } - if (parameters.contains(P_STORM_REL_HELI)) { - site.setStormRelHeli(pdv.getNumber(P_STORM_REL_HELI).doubleValue()); - } - if (parameters.contains(P_TOTAL_PRECIP)) { - site.setTotPrecip1Hr(pdv.getNumber(P_TOTAL_PRECIP).doubleValue()); - } - if (parameters.contains(P_CONV_PRECIP)) { - site.setPrecipConv1Hr(pdv.getNumber(P_CONV_PRECIP).doubleValue()); - } - if (parameters.contains(P_SNOW_FALL)) { - site.setSnowWaterEquiv(pdv.getNumber(P_SNOW_FALL).doubleValue()); - } - if (parameters.contains(P_U_COMP_10M)) { - site.setUc10M(pdv.getNumber(P_U_COMP_10M).doubleValue()); - } - if (parameters.contains(P_V_COMP_10M)) { - site.setVc10M(pdv.getNumber(P_V_COMP_10M).doubleValue()); - } - if (parameters.contains(P_TEMP_2M)) { - site.setTemp2M(pdv.getNumber(P_TEMP_2M).doubleValue()); - } - if (parameters.contains(P_SPEC_HUM_2M)) { - site.setSpecHum2M(pdv.getNumber(P_SPEC_HUM_2M).doubleValue()); - } - if (parameters.contains(P_SNOW_TYPE)) { - site.setSnowType(pdv.getNumber(P_SNOW_TYPE).intValue()); - } - if (parameters.contains(P_ICE_TYPE)) { - site.setIceType(pdv.getNumber(P_ICE_TYPE).intValue()); - } - if (parameters.contains(P_FREEZING_RAIN_TYPE)) { - site.setFzRainType(pdv.getNumber(P_FREEZING_RAIN_TYPE).intValue()); - } - if (parameters.contains(P_RAIN_TYPE)) { - site.setRainType(pdv.getNumber(P_RAIN_TYPE).intValue()); - } - return site; - } - - private static void populateLevels(SoundingSite site, PointDataView pdv) { - // Level Parameters - Set parameters = pdv.getContainer().getParameters(); - if (parameters.contains(P_NUM_LEVELS)) { - int numLevels = pdv.getInt(P_NUM_LEVELS); - Number[] pressure = null; - Number[] temperature = null; - Number[] specHum = null; - Number[] omega = null; - Number[] uComp = null; - Number[] vComp = null; - Number[] cloudCover = null; - if (parameters.contains(P_LVL_PRESS)) { - pressure = pdv.getNumberAllLevels(P_LVL_PRESS); - } - if (parameters.contains(P_LVL_TEMP)) { - temperature = pdv.getNumberAllLevels(P_LVL_TEMP); - } - if (parameters.contains(P_LVL_SPEC_HUM)) { - specHum = pdv.getNumberAllLevels(P_LVL_SPEC_HUM); - } - if (parameters.contains(P_LVL_OMEGA)) { - omega = pdv.getNumberAllLevels(P_LVL_OMEGA); - } - if (parameters.contains(P_LVL_U_COMP)) { - uComp = pdv.getNumberAllLevels(P_LVL_U_COMP); - } - if (parameters.contains(P_LVL_V_COMP)) { - vComp = pdv.getNumberAllLevels(P_LVL_V_COMP); - } - if (parameters.contains(P_LVL_CLOUD_COVER)) { - cloudCover = pdv.getNumberAllLevels(P_LVL_CLOUD_COVER); - } - for (int j = 0; j < numLevels; j++) { - SoundingLevel level = new SoundingLevel(); - if (pressure != null) { - level.setPressure(pressure[j].intValue()); - } - if (temperature != null) { - level.setTemperature(temperature[j].doubleValue()); - } - if (specHum != null) { - level.setSpecificHumidity(specHum[j].doubleValue()); - } - if (omega != null) { - level.setOmega(omega[j].doubleValue()); - } - if (uComp != null) { - level.setUcWind(uComp[j].doubleValue()); - } - if (vComp != null) { - level.setVcWind(vComp[j].doubleValue()); - } - if (cloudCover != null) { - level.setLyrCldCvr(cloudCover[j].intValue()); - } - site.addLevel(level); - } - } - } -} diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoilLevel.java b/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoilLevel.java deleted file mode 100644 index 930cfaefc2..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoilLevel.java +++ /dev/null @@ -1,96 +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.edex.plugin.modelsounding.common; - -import java.io.Serializable; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; - -import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; -import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; - -/** - * SoilLevel contains the data for a single soil level forecast. - * - *
- * SOFTWARE HISTORY
- * Date          Ticket#  Engineer    Description
- * ------------- -------- ----------- --------------------------
- * Mar 03, 2008  1026     jkorman     Initial implementation.
- * Dec 02, 2013  2537     bsteffen    Remove ISerializableObject
- * 
- * 
- * - * @author jkorman - * @version 1.0 - */ -@DynamicSerialize -@XmlAccessorType(XmlAccessType.NONE) -public class SoilLevel implements Serializable { - - private static final long serialVersionUID = 1L; - - @DynamicSerializeElement - @XmlAttribute - private Double lyrSoilMoist; - - @DynamicSerializeElement - @XmlAttribute - private Double lyrSoilTemp; - - /** - * Construct an empty instance. - */ - public SoilLevel() { - } - - /** - * @return the lyrSoilMoist - */ - public Double getLyrSoilMoist() { - return lyrSoilMoist; - } - - /** - * @param lyrSoilMoist - * the lyrSoilMoist to set - */ - public void setLyrSoilMoist(Double lyrSoilMoist) { - this.lyrSoilMoist = lyrSoilMoist; - } - - /** - * @return the lyrSoilTemp - */ - public Double getLyrSoilTemp() { - return lyrSoilTemp; - } - - /** - * @param lyrSoilTemp - * the lyrSoilTemp to set - */ - public void setLyrSoilTemp(Double lyrSoilTemp) { - this.lyrSoilTemp = lyrSoilTemp; - } - -} diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingLevel.java b/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingLevel.java deleted file mode 100644 index 2be9a656b8..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingLevel.java +++ /dev/null @@ -1,332 +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.edex.plugin.modelsounding.common; - -import java.io.Serializable; - -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; - -import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; -import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; - -/** - * SoundingLevel contains the data for a single vertical level forecast. - * - *
- * SOFTWARE HISTORY
- * Date          Ticket#  Engineer    Description
- * ------------- -------- ----------- --------------------------
- * Mar 03, 2008  1026     jkorman     Initial implementation.
- * Dec 02, 2013  2537     bsteffen    Remove ISerializableObject
- * 
- * 
- * - * @author jkorman - * @version 1.0 - */ -@DynamicSerialize -@XmlAccessorType(XmlAccessType.NONE) -public class SoundingLevel implements Serializable { - - private static final long serialVersionUID = 1L; - - @DynamicSerializeElement - @XmlAttribute - private Integer pressure; - - @DynamicSerializeElement - @XmlAttribute - private Double temperature; - - @DynamicSerializeElement - @XmlAttribute - private Double ucWind; - - @DynamicSerializeElement - @XmlAttribute - private Double vcWind; - - @DynamicSerializeElement - @XmlAttribute - private Double specificHumidity; - - @DynamicSerializeElement - @XmlAttribute - private Double omega; - - @DynamicSerializeElement - @XmlAttribute - private Double cldH2OMxRatio; - - @DynamicSerializeElement - @XmlAttribute - private Double iceMxRatio; - - @DynamicSerializeElement - @XmlAttribute - private Integer lyrCldCvr; - - @DynamicSerializeElement - @XmlAttribute - private Double lyrTurbKE; - - @DynamicSerializeElement - @XmlAttribute - private Double convLatHeat; - - @DynamicSerializeElement - @XmlAttribute - private Double staLatHeat; - - @DynamicSerializeElement - @XmlAttribute - private Double swHeatRate; - - @DynamicSerializeElement - @XmlAttribute - private Double lwHeatRate; - - /** - * Construct an empty instance. - */ - public SoundingLevel() { - } - - /** - * @return the pressure - */ - public Integer getPressure() { - return pressure; - } - - /** - * @param pressure - * the pressure to set - */ - public void setPressure(Integer pressure) { - this.pressure = pressure; - } - - /** - * @return the temperature - */ - public Double getTemperature() { - return temperature; - } - - /** - * @param temperature - * the temperature to set - */ - public void setTemperature(Double temperature) { - this.temperature = temperature; - } - - /** - * Get the u wind component of the horizontal wind. - * - * @return the uWind - */ - public Double getUcWind() { - return ucWind; - } - - /** - * Set the u wind component of the horizontal wind. - * - * @param wind - * the uWind to set - */ - public void setUcWind(Double wind) { - ucWind = wind; - } - - /** - * Get the v wind component of the horizontal wind. - * - * @return the vWind - */ - public Double getVcWind() { - return vcWind; - } - - /** - * Set the v wind component of the horizontal wind. - * - * @param wind - * the vWind to set - */ - public void setVcWind(Double wind) { - vcWind = wind; - } - - /** - * @return the specificHumidity - */ - public Double getSpecificHumidity() { - return specificHumidity; - } - - /** - * @param specificHumidity - * the specificHumidity to set - */ - public void setSpecificHumidity(Double specificHumidity) { - this.specificHumidity = specificHumidity; - } - - /** - * @return the omega - */ - public Double getOmega() { - return omega; - } - - /** - * @param omega - * the omega to set - */ - public void setOmega(Double omega) { - this.omega = omega; - } - - /** - * @return the cldH2OMxRatio - */ - public Double getCldH2OMxRatio() { - return cldH2OMxRatio; - } - - /** - * @param cldH2OMxRatio - * the cldH2OMxRatio to set - */ - public void setCldH2OMxRatio(Double cldH2OMxRatio) { - this.cldH2OMxRatio = cldH2OMxRatio; - } - - /** - * @return the iceMxRatio - */ - public Double getIceMxRatio() { - return iceMxRatio; - } - - /** - * @param iceMxRatio - * the iceMxRatio to set - */ - public void setIceMxRatio(Double iceMxRatio) { - this.iceMxRatio = iceMxRatio; - } - - /** - * @return the lyrCldCvr - */ - public Integer getLyrCldCvr() { - return lyrCldCvr; - } - - /** - * @param lyrCldCvr - * the lyrCldCvr to set - */ - public void setLyrCldCvr(Integer lyrCldCvr) { - this.lyrCldCvr = lyrCldCvr; - } - - /** - * @return the convLatHeat - */ - public Double getConvLatHeat() { - return convLatHeat; - } - - /** - * @param convLatHeat - * the convLatHeat to set - */ - public void setConvLatHeat(Double convLatHeat) { - this.convLatHeat = convLatHeat; - } - - /** - * @return the staLatHeat - */ - public Double getStaLatHeat() { - return staLatHeat; - } - - /** - * @param staLatHeat - * the staLatHeat to set - */ - public void setStaLatHeat(Double staLatHeat) { - this.staLatHeat = staLatHeat; - } - - /** - * @return the swHeatRate - */ - public Double getSwHeatRate() { - return swHeatRate; - } - - /** - * @param swHeatRate - * the swHeatRate to set - */ - public void setSwHeatRate(Double swHeatRate) { - this.swHeatRate = swHeatRate; - } - - /** - * @return the lwHeatRate - */ - public Double getLwHeatRate() { - return lwHeatRate; - } - - /** - * @param lwHeatRate - * the lwHeatRate to set - */ - public void setLwHeatRate(Double lwHeatRate) { - this.lwHeatRate = lwHeatRate; - } - - /** - * @return the lyrTurbKE - */ - public Double getLyrTurbKE() { - return lyrTurbKE; - } - - /** - * @param lyrTurbKE - * the lyrTurbKE to set - */ - public void setLyrTurbKE(Double lyrTurbKE) { - this.lyrTurbKE = lyrTurbKE; - } - -} diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingSite.java b/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingSite.java deleted file mode 100644 index ffd83c6878..0000000000 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingSite.java +++ /dev/null @@ -1,864 +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.edex.plugin.modelsounding.common; - -import java.util.Calendar; -import java.util.HashSet; -import java.util.Set; - -import javax.persistence.Access; -import javax.persistence.AccessType; -import javax.persistence.Column; -import javax.persistence.Embedded; -import javax.persistence.Entity; -import javax.persistence.SequenceGenerator; -import javax.persistence.Table; -import javax.persistence.Transient; -import javax.persistence.UniqueConstraint; -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 org.hibernate.annotations.Index; - -import com.raytheon.uf.common.dataplugin.PluginDataObject; -import com.raytheon.uf.common.dataplugin.annotations.DataURI; -import com.raytheon.uf.common.dataplugin.persist.IPersistable; -import com.raytheon.uf.common.dataplugin.persist.PersistablePluginDataObject; -import com.raytheon.uf.common.geospatial.ISpatialEnabled; -import com.raytheon.uf.common.pointdata.IPointData; -import com.raytheon.uf.common.pointdata.PointDataView; -import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; -import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; -import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; -import com.vividsolutions.jts.geom.Geometry; - -/** - * The SoundingSite class encapsulates the location and time information for a - * model sounding forecast as well as providing a container for the vertical - * level data above the location. - * - *
- * SOFTWARE HISTORY
- * Date          Ticket#  Engineer    Description
- * ------------- -------- ----------- --------------------------
- * Mar 03, 2008  1026     jkorman     Initial implementation.
- * Apr 04, 2013  1846     bkowal      Added an index on refTime and
- *                                    forecastTime
- * Apr 12, 2013  1857     bgonzale    Added SequenceGenerator annotation.
- * May 07, 2013  1869     bsteffen    Remove dataURI column from
- *                                    PluginDataObject.
- * Aug 30, 2013  2298     rjpeter     Make getPluginName abstract
- * Dec 02, 2013  2537     bsteffen    Remove IDecoderGettable
- * 
- * 
- * - * @author jkorman - * @version 1.0 - */ -@Entity -@SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "modelsoundingseq") -@Table(name = "modelsounding", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) }) -/* - * Both refTime and forecastTime are included in the refTimeIndex since - * forecastTime is unlikely to be used. - */ -@org.hibernate.annotations.Table(appliesTo = "modelsounding", indexes = { @Index(name = "modelsounding_refTimeIndex", columnNames = { - "refTime", "forecastTime" }) }) -@DynamicSerialize -@XmlAccessorType(XmlAccessType.NONE) -@XmlRootElement -public class SoundingSite extends PersistablePluginDataObject implements - ISpatialEnabled, IPointData, IPersistable { - - private static final long serialVersionUID = 1L; - - // The profiler observation time. - @Column - @DynamicSerializeElement - @XmlElement - private Calendar timeObs; - - @Column - @DynamicSerializeElement - @XmlElement - private Long fcstSeconds; - - // These site ids are not strictly ICAO ids! - @Column - @DynamicSerializeElement - @XmlElement - private String siteId; - - @DataURI(position = 1) - @Column - @DynamicSerializeElement - @XmlElement - private String reportType; - - @Embedded - @DataURI(position = 2, embedded = true) - @XmlElement - @DynamicSerializeElement - private SurfaceObsLocation location; - - @Embedded - @DynamicSerializeElement - private PointDataView pointDataView; - - // Text of the WMO header - @Column - @DynamicSerializeElement - @XmlElement - private String wmoHeader; - - @DynamicSerializeElement - @XmlElement - @Transient - private Integer pressSLP; - - @DynamicSerializeElement - @XmlElement - @Transient - private Integer pressSfc; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double precipTot3Hr; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double precipConv3Hr; - - @DynamicSerializeElement - @XmlElement - @Transient - private Integer cldAmtLo; - - @DynamicSerializeElement - @XmlElement - @Transient - private Integer cldAmtMd; - - @DynamicSerializeElement - @XmlElement - @Transient - private Integer cldAmtHi; - - @DynamicSerializeElement - @XmlElement - @Transient - private Integer pressCldBase; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double uc10M; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double vc10M; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double temp2M; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double specHum2M; - - @DynamicSerializeElement - @XmlElement - @Transient - private Integer snowType; - - @DynamicSerializeElement - @XmlElement - @Transient - private Integer iceType; - - @DynamicSerializeElement - @XmlElement - @Transient - private Integer fzRainType; - - @DynamicSerializeElement - @XmlElement - @Transient - private Integer rainType; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double horzVis; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double stormUComp; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double stormVComp; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double stormRelHeli; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double totPrecip1Hr; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double precipConv1Hr; - - @DynamicSerializeElement - @XmlElement - @Transient - private Double snowWaterEquiv; - - // the level data - @Transient - private Set soundingLevels; - - // the level data - @Transient - private Set soilLevels; - - /** - * Create an empty ProfilerObs object. - */ - public SoundingSite() { - } - - /** - * Constructor for DataURI construction through base class. This is used by - * the notification service. - * - * @param uri - * A data uri applicable to this class. - * @param tableDef - * The table definitions for this class. - */ - public SoundingSite(String uri) { - super(uri); - } - - /** - * Get the observation time for this data. - * - * @return The data observation time. - */ - public Calendar getTimeObs() { - return timeObs; - } - - /** - * Set the observation time for this data. - * - * @param timeObs - * The data observation time. - */ - public void setTimeObs(Calendar timeObs) { - this.timeObs = timeObs; - } - - /** - * @return the fcstSeconds - */ - public Long getFcstSeconds() { - return fcstSeconds; - } - - /** - * @param fcstSeconds - * the fcstSeconds to set - */ - public void setFcstSeconds(Long fcstSeconds) { - this.fcstSeconds = fcstSeconds; - } - - /** - * Get this observation's geometry. - * - * @return The geometry for this observation. - */ - public Geometry getGeometry() { - return location.getGeometry(); - } - - /** - * Get the geometry latitude. - * - * @return The geometry latitude. - */ - public double getLatitude() { - return location.getLatitude(); - } - - /** - * Get the geometry longitude. - * - * @return The geometry longitude. - */ - public double getLongitude() { - return location.getLongitude(); - } - - /** - * Get the station identifier for this observation. - * - * @return the stationId - */ - public String getStationId() { - return location.getStationId(); - } - - /** - * Get the elevation, in meters, of the observing platform or location. - * - * @return The observation elevation, in meters. - */ - public Integer getElevation() { - return location.getElevation(); - } - - /** - * Was this location defined from the station catalog? False if not. - * - * @return Was this location defined from the station catalog? - */ - public Boolean getLocationDefined() { - return location.getLocationDefined(); - } - - /** - * Set the WMOHeader of the file that contained this data. - * - * @return The wmoHeader - */ - public String getWmoHeader() { - return wmoHeader; - } - - /** - * Get the WMOHeader of the file that contained this data. - * - * @param wmoHeader - * The WMOHeader to set - */ - public void setWmoHeader(String wmoHeader) { - this.wmoHeader = wmoHeader; - } - - /** - * - * @param level - * A sounding data level to add. - */ - public void addLevel(SoundingLevel level) { - if (soundingLevels == null) { - soundingLevels = new HashSet(); - } - soundingLevels.add(level); - } - - /** - * Get all levels contained by this object. - * - * @return the levels - */ - public Set getLevels() { - return soundingLevels; - } - - /** - * Set the level data into this object. - * - * @param levels - * the levels to set - */ - public void setLevels(Set levels) { - soundingLevels = levels; - } - - /** - * - * @param level - * A soil data level to add. - */ - public void addSoilLevel(SoilLevel level) { - if (soilLevels == null) { - soilLevels = new HashSet(); - } - soilLevels.add(level); - } - - /** - * @return the soilLevels - */ - public Set getSoilLevels() { - return soilLevels; - } - - /** - * @param soilLevels - * the soilLevels to set - */ - public void setSoilLevels(Set levels) { - soilLevels = levels; - } - - /** - * @return the siteId - */ - public String getSiteId() { - return siteId; - } - - /** - * @param siteId - * the siteId to set - */ - public void setSiteId(String siteId) { - this.siteId = siteId; - } - - /** - * @return the reportType - */ - public String getReportType() { - return reportType; - } - - /** - * @param reportType - * the reportType to set - */ - public void setReportType(String reportType) { - this.reportType = reportType; - } - - /** - * @return the soundingLevels - */ - public Set getSoundingLevels() { - return soundingLevels; - } - - /** - * @param soundingLevels - * the soundingLevels to set - */ - public void setSoundingLevels(Set soundingLevels) { - this.soundingLevels = soundingLevels; - } - - /** - * @return the pressSLP - */ - public Integer getPressSLP() { - return pressSLP; - } - - /** - * @param pressSLP - * the pressSLP to set - */ - public void setPressSLP(Integer pressSLP) { - this.pressSLP = pressSLP; - } - - /** - * @return the pressSfc - */ - public Integer getPressSfc() { - return pressSfc; - } - - /** - * @param pressSfc - * the pressSfc to set - */ - public void setPressSfc(Integer pressSfc) { - this.pressSfc = pressSfc; - } - - /** - * @return the precipTot3Hr - */ - public Double getPrecipTot3Hr() { - return precipTot3Hr; - } - - /** - * @param precipTot3Hr - * the precipTot3Hr to set - */ - public void setPrecipTot3Hr(Double precipTot3Hr) { - this.precipTot3Hr = precipTot3Hr; - } - - /** - * @return the precipConv3Hr - */ - public Double getPrecipConv3Hr() { - return precipConv3Hr; - } - - /** - * @param precipConv3Hr - * the precipConv3Hr to set - */ - public void setPrecipConv3Hr(Double precipConv3Hr) { - this.precipConv3Hr = precipConv3Hr; - } - - /** - * @return the cldAmtLo - */ - public Integer getCldAmtLo() { - return cldAmtLo; - } - - /** - * @param cldAmtLo - * the cldAmtLo to set - */ - public void setCldAmtLo(Integer cldAmtLo) { - this.cldAmtLo = cldAmtLo; - } - - /** - * @return the cldAmtMd - */ - public Integer getCldAmtMd() { - return cldAmtMd; - } - - /** - * @param cldAmtMd - * the cldAmtMd to set - */ - public void setCldAmtMd(Integer cldAmtMd) { - this.cldAmtMd = cldAmtMd; - } - - /** - * @return the cldAmtHi - */ - public Integer getCldAmtHi() { - return cldAmtHi; - } - - /** - * @param cldAmtHi - * the cldAmtHi to set - */ - public void setCldAmtHi(Integer cldAmtHi) { - this.cldAmtHi = cldAmtHi; - } - - /** - * @return the pressCldBase - */ - public Integer getPressCldBase() { - return pressCldBase; - } - - /** - * @param pressCldBase - * the pressCldBase to set - */ - public void setPressCldBase(Integer pressCldBase) { - this.pressCldBase = pressCldBase; - } - - /** - * @return the uc10Meter - */ - public Double getUc10M() { - return uc10M; - } - - /** - * @param uc10Meter - * the uc10Meter to set - */ - public void setUc10M(Double uc10Meter) { - this.uc10M = uc10Meter; - } - - /** - * @return the vc10M - */ - public Double getVc10M() { - return vc10M; - } - - /** - * @param vc10M - * the vc10M to set - */ - public void setVc10M(Double vc10M) { - this.vc10M = vc10M; - } - - /** - * @return the temp2M - */ - public Double getTemp2M() { - return temp2M; - } - - /** - * @param temp2M - * the temp2M to set - */ - public void setTemp2M(Double temp2M) { - this.temp2M = temp2M; - } - - /** - * @return the specHum2M - */ - public Double getSpecHum2M() { - return specHum2M; - } - - /** - * @param specHum2M - * the specHum2M to set - */ - public void setSpecHum2M(Double specHum2M) { - this.specHum2M = specHum2M; - } - - /** - * @return the snowType - */ - public Integer getSnowType() { - return snowType; - } - - /** - * @param snowType - * the snowType to set - */ - public void setSnowType(Integer snowType) { - this.snowType = snowType; - } - - /** - * @return the iceType - */ - public Integer getIceType() { - return iceType; - } - - /** - * @param iceType - * the iceType to set - */ - public void setIceType(Integer iceType) { - this.iceType = iceType; - } - - /** - * @return the fzRainType - */ - public Integer getFzRainType() { - return fzRainType; - } - - /** - * @param fzRainType - * the fzRainType to set - */ - public void setFzRainType(Integer fzRainType) { - this.fzRainType = fzRainType; - } - - /** - * @return the rainType - */ - public Integer getRainType() { - return rainType; - } - - /** - * @param rainType - * the rainType to set - */ - public void setRainType(Integer rainType) { - this.rainType = rainType; - } - - /** - * @return the horzVis - */ - public Double getHorzVis() { - return horzVis; - } - - /** - * @param horzVis - * the horzVis to set - */ - public void setHorzVis(Double horzVis) { - this.horzVis = horzVis; - } - - /** - * @return the stormUComp - */ - public Double getStormUComp() { - return stormUComp; - } - - /** - * @param stormUComp - * the stormUComp to set - */ - public void setStormUComp(Double stormUComp) { - this.stormUComp = stormUComp; - } - - /** - * @return the stormVComp - */ - public Double getStormVComp() { - return stormVComp; - } - - /** - * @param stormVComp - * the stormVComp to set - */ - public void setStormVComp(Double stormVComp) { - this.stormVComp = stormVComp; - } - - /** - * @return the stormRelHeli - */ - public Double getStormRelHeli() { - return stormRelHeli; - } - - /** - * @param stormRelHeli - * the stormRelHeli to set - */ - public void setStormRelHeli(Double stormRelHeli) { - this.stormRelHeli = stormRelHeli; - } - - /** - * @return the totPrecip1Hr - */ - public Double getTotPrecip1Hr() { - return totPrecip1Hr; - } - - /** - * @param totPrecip1Hr - * the totPrecip1Hr to set - */ - public void setTotPrecip1Hr(Double totPrecip1Hr) { - this.totPrecip1Hr = totPrecip1Hr; - } - - /** - * @return the precipConv1Hr - */ - public Double getPrecipConv1Hr() { - return precipConv1Hr; - } - - /** - * @param precipConv1Hr - * the precipConv1Hr to set - */ - public void setPrecipConv1Hr(Double precipConv1Hr) { - this.precipConv1Hr = precipConv1Hr; - } - - /** - * @return the snowWaterEquiv - */ - public Double getSnowWaterEquiv() { - return snowWaterEquiv; - } - - /** - * @param snowWaterEquiv - * the snowWaterEquiv to set - */ - public void setSnowWaterEquiv(Double snowWaterEquiv) { - this.snowWaterEquiv = snowWaterEquiv; - } - - @Override - public SurfaceObsLocation getSpatialObject() { - return location; - } - - public SurfaceObsLocation getLocation() { - return location; - } - - public void setLocation(SurfaceObsLocation location) { - this.location = location; - } - - @Override - public PointDataView getPointDataView() { - return this.pointDataView; - } - - @Override - public void setPointDataView(PointDataView pointDataView) { - this.pointDataView = pointDataView; - } - - @Override - @Column - @Access(AccessType.PROPERTY) - public String getDataURI() { - return super.getDataURI(); - } - - @Override - public String getPluginName() { - return "modelsounding"; - } -} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/.classpath b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/.classpath new file mode 100644 index 0000000000..ad32c83a78 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/.project b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/.project new file mode 100644 index 0000000000..03ad4f580e --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/.project @@ -0,0 +1,28 @@ + + + com.raytheon.uf.common.dataplugin.modelsounding + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/.settings/org.eclipse.jdt.core.prefs b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..c537b63063 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..64cb28447d --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/META-INF/MANIFEST.MF @@ -0,0 +1,18 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Model Sounding Data Plugin +Bundle-SymbolicName: com.raytheon.uf.common.dataplugin.modelsounding +Bundle-Version: 1.14.0.qualifier +Bundle-Vendor: RAYTHEON +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-ActivationPolicy: lazy +Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization +Require-Bundle: com.raytheon.uf.common.dataplugin, + com.raytheon.uf.common.pointdata, + com.raytheon.uf.common.geospatial, + com.raytheon.uf.common.time, + com.raytheon.uf.common.dataaccess, + com.raytheon.uf.common.dataquery, + com.raytheon.uf.common.serialization, + com.raytheon.uf.common.serialization.comm +Export-Package: com.raytheon.uf.common.dataplugin.modelsounding diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/build.properties b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/build.properties new file mode 100644 index 0000000000..5791d48d5f --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + res/ diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/res/spring/modelsounding-common-dataaccess.xml b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/res/spring/modelsounding-common-dataaccess.xml similarity index 100% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/res/spring/modelsounding-common-dataaccess.xml rename to edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/res/spring/modelsounding-common-dataaccess.xml diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/ModelSoundingParameters.java b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/ModelSoundingParameters.java new file mode 100644 index 0000000000..a54265ca75 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/ModelSoundingParameters.java @@ -0,0 +1,159 @@ +/** + * 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.modelsounding; + +import java.util.Arrays; +import java.util.List; + +/** + * This class holds constants for all the point data parameters for model + * sounding. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Dec 18, 2013  2537     bsteffen    Initial creation
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public class ModelSoundingParameters { + + /* Record parameters */ + @Deprecated + public static final String DATAURI = "dataURI"; + + public static final String WMO_HEADER = "wmoHeader"; + + public static final String STATION_NUMBER = "wmoStaNum"; + + public static final String LATITUDE = "latitude"; + + public static final String LONGITUDE = "longitude"; + + public static final String ELEVATION = "elevation"; + + public static final String STATION_ID = "stationId"; + + public static final String REF_TIME = "refTime"; + + public static final String FORECAST_HOUR = "forecastHr"; + + /* Surface parameters */ + public static final String SEA_LEVEL_PRESS = "seaLvlPress"; + + public static final String SFC_PRESS = "sfcPress"; + + public static final String LOW_CLOUD = "lowCld"; + + public static final String MID_CLOUD = "midCld"; + + public static final String HIGH_CLOUD = "hiCld"; + + public static final String CLOUD_PRESS = "prCloud"; + + public static final String VISIBILITY = "vsby"; + + public static final String U_STORM = "uStorm"; + + public static final String V_STORM = "vStorm"; + + public static final String STORM_REL_HELI = "srHel"; + + public static final String TOTAL_PRECIP = "totPrecip"; + + public static final String CONV_PRECIP = "convPrecip"; + + public static final String SNOW_WATER = "snowWater"; + + public static final String SNOW_FALL = "snowFall"; + + public static final String SNOW_FLUX = "snowFlux"; + + public static final String SNOW_MELT = "snowMelt"; + + public static final String U_COMP_10M = "u10"; + + public static final String V_COMP_10M = "v10"; + + public static final String SENS_HEAT = "sensHeat"; + + public static final String SUB_SFC_HEAT = "subSfcHeat"; + + public static final String SKIN_TEMP = "skinTemp"; + + public static final String MIN_TEMP = "minTemp"; + + public static final String MAX_TEMP = "maxTemp"; + + public static final String TEMP_2M = "temp2"; + + public static final String SPEC_HUM_2M = "q2"; + + public static final String THETA_10M = "Theta10"; + + public static final String SPEC_HUM_10M = "q10"; + + public static final String SNOW_TYPE = "snowTyp"; + + public static final String ICE_TYPE = "iceTyp"; + + public static final String FREEZING_RAIN_TYPE = "frzgRainTyp"; + + public static final String RAIN_TYPE = "rainType"; + + /* Level parameters */ + public static final String NUM_LEVELS = "numProfLvls"; + + public static final String LVL_PRESS = "pressure"; + + public static final String LVL_TEMP = "temperature"; + + public static final String LVL_SPEC_HUM = "specHum"; + + public static final String LVL_OMEGA = "omega"; + + public static final String LVL_U_COMP = "uComp"; + + public static final String LVL_V_COMP = "vComp"; + + public static final String LVL_CLOUD_COVER = "cldCvr"; + + public static final List ALL_DATA = Arrays.asList(WMO_HEADER, + STATION_NUMBER, LATITUDE, LONGITUDE, ELEVATION, STATION_ID, + REF_TIME, FORECAST_HOUR, SEA_LEVEL_PRESS, SFC_PRESS, LOW_CLOUD, + MID_CLOUD, HIGH_CLOUD, CLOUD_PRESS, VISIBILITY, U_STORM, V_STORM, + STORM_REL_HELI, TOTAL_PRECIP, CONV_PRECIP, SNOW_WATER, SNOW_FALL, + SNOW_FLUX, SNOW_MELT, U_COMP_10M, V_COMP_10M, SENS_HEAT, + SUB_SFC_HEAT, SKIN_TEMP, MIN_TEMP, MAX_TEMP, TEMP_2M, SPEC_HUM_2M, + THETA_10M, SPEC_HUM_10M, SNOW_TYPE, ICE_TYPE, FREEZING_RAIN_TYPE, + RAIN_TYPE, NUM_LEVELS, LVL_PRESS, LVL_TEMP, LVL_SPEC_HUM, + LVL_OMEGA, LVL_U_COMP, LVL_V_COMP, LVL_CLOUD_COVER); + + public static final List LVL_PARAMETERS = Arrays.asList(LVL_PRESS, + LVL_TEMP, LVL_SPEC_HUM, LVL_OMEGA, LVL_U_COMP, LVL_V_COMP, + LVL_CLOUD_COVER); + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/ModelSoundingPointDataTransform.java b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/ModelSoundingPointDataTransform.java new file mode 100644 index 0000000000..fd45a331cd --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/ModelSoundingPointDataTransform.java @@ -0,0 +1,200 @@ +/** + * 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.modelsounding; + +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.ALL_DATA; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.DATAURI; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.ELEVATION; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.FORECAST_HOUR; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.LATITUDE; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.LONGITUDE; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.LVL_PARAMETERS; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.NUM_LEVELS; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.REF_TIME; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.STATION_ID; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.STATION_NUMBER; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.WMO_HEADER; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.dataquery.requests.RequestConstraint; +import com.raytheon.uf.common.pointdata.PointDataContainer; +import com.raytheon.uf.common.pointdata.PointDataServerRequest; +import com.raytheon.uf.common.pointdata.PointDataView; +import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; +import com.raytheon.uf.common.serialization.comm.RequestRouter; +import com.raytheon.uf.common.time.DataTime; + +/** + * + * A class for converting point data into sounding sites. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Apr 06, 2011           bsteffen    Initial creation
+ * Dec 02, 2013  2537     bsteffen    Move to common
+ * 
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ +public class ModelSoundingPointDataTransform { + + /** + * Use all point data parameters to build sounding sites for all sites which + * match the query defined by fields, values, and operands. + * + */ + public static List getSoundingSites( + Map constraints) throws Exception { + return getSoundingSites(constraints, ALL_DATA); + } + + /** + * Use the specified point data parameters to build sounding sites for all + * sites which match the query defined by fields, values, and operands. + * + */ + public static List getSoundingSites( + Map constraints, List parameters) + throws Exception { + Set parametersSet = new HashSet(parameters); + if (!parametersSet.contains(NUM_LEVELS)) { + /* + * if you have any level based parameters you must include num + * levels + */ + for (String lvlParam : LVL_PARAMETERS) { + if (parametersSet.contains(lvlParam)) { + parametersSet.add(NUM_LEVELS); + break; + } + } + } + /* copy to avoid modification */ + Map fullConstraints = new HashMap( + constraints); + fullConstraints.put(PluginDataObject.PLUGIN_NAME_ID, + new RequestConstraint(SoundingSite.PLUGIN_ID)); + fullConstraints.put(PointDataServerRequest.REQUEST_MODE_KEY, + new RequestConstraint(PointDataServerRequest.REQUEST_MODE_2D)); + fullConstraints.put(PointDataServerRequest.REQUEST_PARAMETERS_KEY, + new RequestConstraint(parametersSet)); + PointDataServerRequest pdr = new PointDataServerRequest(); + pdr.setRcMap(fullConstraints); + PointDataContainer pdc = (PointDataContainer) RequestRouter.route(pdr); + if (pdc == null) { + return Collections.emptyList(); + } + return getSoundingSites(pdc); + } + + /** + * Build sounding sites from the data in the container. + * + * @param pdc + * @return + */ + public static List getSoundingSites(PointDataContainer pdc) { + List sites = new ArrayList( + pdc.getCurrentSz()); + for (int i = 0; i < pdc.getCurrentSz(); i++) { + sites.add(getSoundingSite(pdc.readRandom(i))); + } + return sites; + } + + /** + * Build a single sounding site from the data in the view. + * + * @param pdv + * @return + */ + public static SoundingSite getSoundingSite(PointDataView pdv) { + // All the code from here on is boilerplate code for determining what + // parameters are in the view and setting the appropriate field in the + // Sounding Site. + Set parameters = pdv.getContainer().getParameters(); + SoundingSite site = null; + if (parameters.contains(DATAURI)) { + // Parsing from the dataURI gets several fields for us. + site = new SoundingSite(pdv.getString(DATAURI)); + } else { + site = new SoundingSite(); + site.setLocation(new SurfaceObsLocation()); + // All of these things would have been in dataURI + if (parameters.contains(LATITUDE)) { + site.getLocation().setLatitude( + pdv.getNumber(LATITUDE).doubleValue()); + } + if (parameters.contains(LONGITUDE)) { + site.getLocation().setLongitude( + pdv.getNumber(LONGITUDE).doubleValue()); + } + if (parameters.contains(STATION_ID)) { + site.getLocation().setStationId(pdv.getString(STATION_ID)); + } + if (parameters.contains(FORECAST_HOUR)) { + if (parameters.contains(REF_TIME)) { + Date refTime = new Date( + pdv.getNumber(REF_TIME).longValue() * 1000); + int fcstTime = pdv.getNumber(FORECAST_HOUR).intValue() * 3600; + site.setDataTime(new DataTime(refTime, fcstTime)); + } + } else if (parameters.contains(REF_TIME)) { + // This might not be the best idea most people will want + // forecast time also + site.setDataTime(new DataTime(new Date(pdv.getNumber(REF_TIME) + .longValue() * 1000))); + } + } + site.setPointDataView(pdv); + + if (parameters.contains(ELEVATION)) { + site.getLocation() + .setElevation(pdv.getNumber(ELEVATION).intValue()); + } + // Record parameters + if (parameters.contains(WMO_HEADER)) { + site.setWmoHeader(pdv.getString(WMO_HEADER)); + } + if (parameters.contains(STATION_NUMBER)) { + site.setSiteId(String.format("%06d", pdv.getNumber(STATION_NUMBER) + .intValue())); + } + + return site; + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/SoundingLevel.java b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/SoundingLevel.java new file mode 100644 index 0000000000..717f463bbd --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/SoundingLevel.java @@ -0,0 +1,166 @@ +/** + * 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.modelsounding; + +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.LVL_CLOUD_COVER; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.LVL_OMEGA; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.LVL_PRESS; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.LVL_SPEC_HUM; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.LVL_TEMP; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.LVL_U_COMP; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.LVL_V_COMP; + +import java.io.Serializable; + +import com.raytheon.uf.common.pointdata.PointDataView; + +/** + * SoundingLevel contains the data for a single vertical level forecast. + * + *
+ * SOFTWARE HISTORY
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- -----------------------------------------
+ * Mar 03, 2008  1026     jkorman     Initial implementation.
+ * Dec 02, 2013  2537     bsteffen    Move to common, remove unnecessary 
+ *                                    fields, remove ISerializableObject
+ * 
+ * 
+ * + * @author jkorman + * @version 1.0 + */ +public class SoundingLevel implements Serializable { + + private static final long serialVersionUID = 1L; + + private final PointDataView pointDataView; + + private final int index; + + SoundingLevel(PointDataView pointDataView, int index) { + this.index = index; + this.pointDataView = pointDataView; + } + + /** @return the pressure */ + public float getPressure() { + return pointDataView.getFloat(LVL_PRESS, index); + } + + /** + * @param pressure + * the pressure to set + */ + public void setPressure(float pressure) { + pointDataView.setFloat(LVL_PRESS, pressure, index); + } + + /** @return the temperature */ + public float getTemperature() { + return pointDataView.getFloat(LVL_TEMP, index); + } + + /** + * @param temperature + * the temperature to set + */ + public void setTemperature(float temperature) { + pointDataView.setFloat(LVL_TEMP, temperature, index); + } + + /** + * Get the u wind component of the horizontal wind. + * + * @return the uWind + */ + public float getUcWind() { + return pointDataView.getFloat(LVL_U_COMP, index); + } + + /** + * Set the u wind component of the horizontal wind. + * + * @param wind + * the uWind to set + */ + public void setUcWind(float wind) { + pointDataView.setFloat(LVL_U_COMP, wind, index); + } + + /** + * Get the v wind component of the horizontal wind. + * + * @return the vWind + */ + public float getVcWind() { + return pointDataView.getFloat(LVL_V_COMP, index); + } + + /** + * Set the v wind component of the horizontal wind. + * + * @param wind + * the vWind to set + */ + public void setVcWind(float wind) { + pointDataView.setFloat(LVL_V_COMP, wind, index); + } + + /** @return the specificHumidity */ + public float getSpecificHumidity() { + return pointDataView.getFloat(LVL_SPEC_HUM, index); + } + + /** + * @param specificHumidity + * the specificHumidity to set + */ + public void setSpecificHumidity(float specificHumidity) { + pointDataView.setFloat(LVL_SPEC_HUM, specificHumidity, index); + } + + /** @return the omega */ + public float getOmega() { + return pointDataView.getFloat(LVL_OMEGA, index); + } + + /** + * @param omega + * the omega to set + */ + public void setOmega(float omega) { + pointDataView.setFloat(LVL_OMEGA, omega, index); + } + + /** @return the lyrCldCvr */ + public float getLyrCldCvr() { + return pointDataView.getFloat(LVL_CLOUD_COVER, index); + } + + /** + * @param lyrCldCvr + * the lyrCldCvr to set + */ + public void setLyrCldCvr(float lyrCldCvr) { + pointDataView.setFloat(LVL_CLOUD_COVER, lyrCldCvr, index); + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/SoundingSite.java b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/SoundingSite.java new file mode 100644 index 0000000000..95bf99c34f --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.modelsounding/src/com/raytheon/uf/common/dataplugin/modelsounding/SoundingSite.java @@ -0,0 +1,759 @@ +/** + * 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.modelsounding; + +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.CLOUD_PRESS; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.CONV_PRECIP; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.FREEZING_RAIN_TYPE; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.HIGH_CLOUD; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.ICE_TYPE; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.LOW_CLOUD; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.MAX_TEMP; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.MID_CLOUD; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.MIN_TEMP; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.NUM_LEVELS; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.RAIN_TYPE; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.SEA_LEVEL_PRESS; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.SENS_HEAT; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.SFC_PRESS; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.SKIN_TEMP; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.SNOW_FALL; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.SNOW_FLUX; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.SNOW_MELT; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.SNOW_TYPE; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.SNOW_WATER; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.SPEC_HUM_10M; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.SPEC_HUM_2M; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.STORM_REL_HELI; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.SUB_SFC_HEAT; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.TEMP_2M; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.THETA_10M; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.TOTAL_PRECIP; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.U_COMP_10M; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.U_STORM; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.VISIBILITY; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.V_COMP_10M; +import static com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters.V_STORM; + +import java.util.Calendar; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.Access; +import javax.persistence.AccessType; +import javax.persistence.Column; +import javax.persistence.Embedded; +import javax.persistence.Entity; +import javax.persistence.SequenceGenerator; +import javax.persistence.Table; +import javax.persistence.Transient; +import javax.persistence.UniqueConstraint; + +import org.hibernate.annotations.Index; + +import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.dataplugin.annotations.DataURI; +import com.raytheon.uf.common.dataplugin.persist.IPersistable; +import com.raytheon.uf.common.dataplugin.persist.PersistablePluginDataObject; +import com.raytheon.uf.common.geospatial.ISpatialEnabled; +import com.raytheon.uf.common.pointdata.IPointData; +import com.raytheon.uf.common.pointdata.PointDataView; +import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; +import com.vividsolutions.jts.geom.Geometry; + +/** + * The SoundingSite class encapsulates the location and time information for a + * model sounding forecast as well as providing a container for the vertical + * level data above the location. + * + *
+ * SOFTWARE HISTORY
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- -----------------------------------------
+ * Mar 03, 2008  1026     jkorman     Initial implementation.
+ * Apr 04, 2013  1846     bkowal      Added an index on refTime and
+ *                                    forecastTime
+ * Apr 12, 2013  1857     bgonzale    Added SequenceGenerator annotation.
+ * May 07, 2013  1869     bsteffen    Remove dataURI column from
+ *                                    PluginDataObject.
+ * Aug 30, 2013  2298     rjpeter     Make getPluginName abstract
+ * Dec 02, 2013  2537     bsteffen    Move to common, remove IDecoderGettable,
+ *                                    remove unnecessary fields.
+ * 
+ * 
+ * + * @author jkorman + * @version 1.0 + */ +@Entity +@SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "modelsoundingseq") +@Table(name = "modelsounding", uniqueConstraints = { @UniqueConstraint(columnNames = { "dataURI" }) }) +/* + * Both refTime and forecastTime are included in the refTimeIndex since + * forecastTime is unlikely to be used. + */ +@org.hibernate.annotations.Table(appliesTo = "modelsounding", indexes = { @Index(name = "modelsounding_refTimeIndex", columnNames = { + "refTime", "forecastTime" }) }) +@DynamicSerialize +public class SoundingSite extends PersistablePluginDataObject implements + ISpatialEnabled, IPointData, IPersistable { + + public static String PLUGIN_ID = "modelsounding"; + + private static final long serialVersionUID = 1L; + + // These site ids are not strictly ICAO ids! + @Column + @DynamicSerializeElement + private String siteId; + + @DataURI(position = 1) + @Column + @DynamicSerializeElement + private String reportType; + + @Embedded + @DataURI(position = 2, embedded = true) + @DynamicSerializeElement + private SurfaceObsLocation location; + + @Embedded + @DynamicSerializeElement + private PointDataView pointDataView; + + // Text of the WMO header + @Column + @DynamicSerializeElement + private String wmoHeader; + + // the level data + @Transient + private Set levels; + + /** + * Create an empty ProfilerObs object. + */ + public SoundingSite() { + } + + /** + * Constructor for DataURI construction through base class. This is used by + * the notification service. + * + * @param uri + * A data uri applicable to this class. + * @param tableDef + * The table definitions for this class. + */ + public SoundingSite(String uri) { + super(uri); + } + + /** + * Get the observation time for this data. + * + * @return The data observation time. + */ + public Calendar getTimeObs() { + return dataTime.getRefTimeAsCalendar(); + } + + /** + * @return the fcstSeconds + */ + public Long getFcstSeconds() { + return (long) dataTime.getFcstTime(); + } + + /** + * Get this observation's geometry. + * + * @return The geometry for this observation. + */ + public Geometry getGeometry() { + return location.getGeometry(); + } + + /** + * Get the geometry latitude. + * + * @return The geometry latitude. + */ + public double getLatitude() { + return location.getLatitude(); + } + + /** + * Get the geometry longitude. + * + * @return The geometry longitude. + */ + public double getLongitude() { + return location.getLongitude(); + } + + /** + * Get the station identifier for this observation. + * + * @return the stationId + */ + public String getStationId() { + return location.getStationId(); + } + + /** + * Get the elevation, in meters, of the observing platform or location. + * + * @return The observation elevation, in meters. + */ + public Integer getElevation() { + return location.getElevation(); + } + + /** + * Was this location defined from the station catalog? False if not. + * + * @return Was this location defined from the station catalog? + */ + public Boolean getLocationDefined() { + return location.getLocationDefined(); + } + + /** + * Set the WMOHeader of the file that contained this data. + * + * @return The wmoHeader + */ + public String getWmoHeader() { + return wmoHeader; + } + + /** + * Get the WMOHeader of the file that contained this data. + * + * @param wmoHeader + * The WMOHeader to set + */ + public void setWmoHeader(String wmoHeader) { + this.wmoHeader = wmoHeader; + } + + private void populateLevels(){ + if (levels == null) { + int count = pointDataView.getInt(NUM_LEVELS); + if (count < 0) { + count = 0; + } + levels = new HashSet(count, 1.0f); + for(int i = 0 ; i < count ; i += 1){ + levels.add(new SoundingLevel(pointDataView, i)); + } + } + } + + public SoundingLevel addLevel() { + populateLevels(); + SoundingLevel level = new SoundingLevel(pointDataView, levels.size()); + levels.add(level); + pointDataView.setInt(NUM_LEVELS, levels.size()); + return level; + } + + /** + * Get all levels contained by this object. + * + * @return the levels + */ + public Set getLevels() { + populateLevels(); + return Collections.unmodifiableSet(levels); + } + + /** + * @return the siteId + */ + public String getSiteId() { + return siteId; + } + + /** + * @param siteId + * the siteId to set + */ + public void setSiteId(String siteId) { + this.siteId = siteId; + } + + /** + * @return the reportType + */ + public String getReportType() { + return reportType; + } + + /** + * @param reportType + * the reportType to set + */ + public void setReportType(String reportType) { + this.reportType = reportType; + } + + /** @return the pressSLP */ + public float getPressSLP() { + return pointDataView.getFloat(SEA_LEVEL_PRESS); + } + + /** + * @param pressSLP + * the pressSLP to set + */ + public void setPressSLP(float pressSLP) { + pointDataView.setFloat(SEA_LEVEL_PRESS, pressSLP); + } + + /** @return the pressSfc */ + public float getPressSfc() { + return pointDataView.getFloat(SFC_PRESS); + } + + /** + * @param pressSfc + * the pressSfc to set + */ + public void setPressSfc(float pressSfc) { + pointDataView.setFloat(SFC_PRESS, pressSfc); + } + + /** @return the cldAmtLo */ + public float getCldAmtLo() { + return pointDataView.getFloat(LOW_CLOUD); + } + + /** + * @param cldAmtLo + * the cldAmtLo to set + */ + public void setCldAmtLo(float cldAmtLo) { + pointDataView.setFloat(LOW_CLOUD, cldAmtLo); + } + + /** @return the cldAmtMd */ + public float getCldAmtMd() { + return pointDataView.getFloat(MID_CLOUD); + } + + /** + * @param cldAmtMd + * the cldAmtMd to set + */ + public void setCldAmtMd(float cldAmtMd) { + pointDataView.setFloat(MID_CLOUD, cldAmtMd); + } + + /** @return the cldAmtHi */ + public float getCldAmtHi() { + return pointDataView.getFloat(HIGH_CLOUD); + } + + /** + * @param cldAmtHi + * the cldAmtHi to set + */ + public void setCldAmtHi(float cldAmtHi) { + pointDataView.setFloat(HIGH_CLOUD, cldAmtHi); + } + + /** @return the pressCldBase */ + public float getPressCldBase() { + return pointDataView.getFloat(CLOUD_PRESS); + } + + /** + * @param pressCldBase + * the pressCldBase to set + */ + public void setPressCldBase(float pressCldBase) { + pointDataView.setFloat(CLOUD_PRESS, pressCldBase); + } + + /** @return the uc10Meter */ + public float getUc10M() { + return pointDataView.getFloat(U_COMP_10M); + } + + /** + * @param uc10Meter + * the uc10Meter to set + */ + public void setUc10M(float uc10M) { + pointDataView.setFloat(U_COMP_10M, uc10M); + } + + /** @return the vc10M */ + public float getVc10M() { + return pointDataView.getFloat(V_COMP_10M); + } + + /** + * @param vc10M + * the vc10M to set + */ + public void setVc10M(float vc10M) { + pointDataView.setFloat(V_COMP_10M, vc10M); + } + + /** @return the sensHeat */ + public float getSensHeat() { + return pointDataView.getFloat(SENS_HEAT); + } + + /** + * @param sensHeat + * the sensHeat to set + */ + public void setSensHeat(float sensHeat) { + pointDataView.setFloat(SENS_HEAT, sensHeat); + } + + /** @return the subSfcHeat */ + public float getSubSfcHeat() { + return pointDataView.getFloat(SUB_SFC_HEAT); + } + + /** + * @param subSfcHeat + * the subSfcHeat to set + */ + public void setSubSfcHeat(float subSfcHeat) { + pointDataView.setFloat(SUB_SFC_HEAT, subSfcHeat); + } + + /** @return the minTemp */ + public float getMinTemp() { + return pointDataView.getFloat(MIN_TEMP); + } + + /** + * @param minTemp + * the minTemp to set + */ + public void setMinTemp(float minTemp) { + pointDataView.setFloat(MIN_TEMP, minTemp); + } + + /** @return the maxTemp */ + public float getMaxTemp() { + return pointDataView.getFloat(MAX_TEMP); + } + + /** + * @param maxTemp + * the maxTemp to set + */ + public void setMaxTemp(float maxTemp) { + pointDataView.setFloat(MAX_TEMP, maxTemp); + } + + /** @return the skinTemp */ + public float getSkinTemp() { + return pointDataView.getFloat(SKIN_TEMP); + } + + /** + * @param skinTemp + * the skinTemp to set + */ + public void setSkinTemp(float skinTemp) { + pointDataView.setFloat(SKIN_TEMP, skinTemp); + } + + /** @return the temp2M */ + public float getTemp2M() { + return pointDataView.getFloat(TEMP_2M); + } + + /** + * @param temp2M + * the temp2M to set + */ + public void setTemp2M(float temp2M) { + pointDataView.setFloat(TEMP_2M, temp2M); + } + + /** @return the specHum2M */ + public float getSpecHum2M() { + return pointDataView.getFloat(SPEC_HUM_2M); + } + + /** + * @param specHum2M + * the specHum2M to set + */ + public void setSpecHum2M(float specHum2M) { + pointDataView.setFloat(SPEC_HUM_2M, specHum2M); + } + + /** @return the specHum10M */ + public float getSpecHum10M() { + return pointDataView.getFloat(SPEC_HUM_10M); + } + + /** + * @param specHum10M + * the specHum10M to set + */ + public void setSpecHum10M(float specHum10M) { + pointDataView.setFloat(SPEC_HUM_10M, specHum10M); + } + + /** @return the theta10M */ + public float getTheta10M() { + return pointDataView.getFloat(THETA_10M); + } + + /** + * @param theta10M + * the theta10M to set + */ + public void setTheta10M(float theta10M) { + pointDataView.setFloat(THETA_10M, theta10M); + } + + /** @return the snowType */ + public int getSnowType() { + return pointDataView.getInt(SNOW_TYPE); + } + + /** + * @param snowType + * the snowType to set + */ + public void setSnowType(int snowType) { + pointDataView.setInt(SNOW_TYPE, snowType); + } + + /** @return the iceType */ + public int getIceType() { + return pointDataView.getInt(ICE_TYPE); + } + + /** + * @param iceType + * the iceType to set + */ + public void setIceType(int iceType) { + pointDataView.setInt(ICE_TYPE, iceType); + } + + /** @return the fzRainType */ + public int getFzRainType() { + return pointDataView.getInt(FREEZING_RAIN_TYPE); + } + + /** + * @param fzRainType + * the fzRainType to set + */ + public void setFzRainType(int fzRainType) { + pointDataView.setInt(FREEZING_RAIN_TYPE, fzRainType); + } + + /** @return the rainType */ + public int getRainType() { + return pointDataView.getInt(RAIN_TYPE); + } + + /** + * @param rainType + * the rainType to set + */ + public void setRainType(int rainType) { + pointDataView.setInt(RAIN_TYPE, rainType); + } + + /** @return the horzVis */ + public float getHorzVis() { + return pointDataView.getFloat(VISIBILITY); + } + + /** + * @param horzVis + * the horzVis to set + */ + public void setHorzVis(float horzVis) { + pointDataView.setFloat(VISIBILITY, horzVis); + } + + /** @return the stormUComp */ + public float getStormUComp() { + return pointDataView.getFloat(U_STORM); + } + + /** + * @param stormUComp + * the stormUComp to set + */ + public void setStormUComp(float stormUComp) { + pointDataView.setFloat(U_STORM, stormUComp); + } + + /** @return the stormVComp */ + public float getStormVComp() { + return pointDataView.getFloat(V_STORM); + } + + /** + * @param stormVComp + * the stormVComp to set + */ + public void setStormVComp(float stormVComp) { + pointDataView.setFloat(V_STORM, stormVComp); + } + + /** @return the stormRelHeli */ + public float getStormRelHeli() { + return pointDataView.getFloat(STORM_REL_HELI); + } + + /** + * @param stormRelHeli + * the stormRelHeli to set + */ + public void setStormRelHeli(float stormRelHeli) { + pointDataView.setFloat(STORM_REL_HELI, stormRelHeli); + } + + /** @return the totPrecip */ + public float getTotPrecip() { + return pointDataView.getFloat(TOTAL_PRECIP); + } + + /** + * @param totPrecip + * the totPrecip to set + */ + public void setTotPrecip(float totPrecip) { + pointDataView.setFloat(TOTAL_PRECIP, totPrecip); + } + + /** @return the precipConv */ + public float getPrecipConv() { + return pointDataView.getFloat(CONV_PRECIP); + } + + /** + * @param precipConv + * the precipConv to set + */ + public void setPrecipConv(float precipConv) { + pointDataView.setFloat(CONV_PRECIP, precipConv); + } + + /** @return the snowWaterEquiv */ + public float getSnowWaterEquiv() { + return pointDataView.getFloat(SNOW_WATER); + } + + /** + * @param snowWaterEquiv + * the snowWaterEquiv to set + */ + public void setSnowWaterEquiv(float snowWaterEquiv) { + pointDataView.setFloat(SNOW_WATER, snowWaterEquiv); + } + + /** @return the snowFall */ + public float getSnowFall() { + return pointDataView.getFloat(SNOW_FALL); + } + + /** + * @param snowFall + * the snowFall to set + */ + public void setSnowFall(float snowFall) { + pointDataView.setFloat(SNOW_FALL, snowFall); + } + + /** + * @param snowMelt + * the snowMelt to set + */ + public void setSnowMelt(float snowMelt) { + pointDataView.setFloat(SNOW_MELT, snowMelt); + } + + /** @return the snowFlux */ + public float getSnowMFlux() { + return pointDataView.getFloat(SNOW_FLUX); + } + + /** + * @param snowFlux + * the snowFlux to set + */ + public void setSnowFlux(float snowFlux) { + pointDataView.setFloat(SNOW_FLUX, snowFlux); + } + + /** @return the snowMelt */ + public float getSnowMelt() { + return pointDataView.getFloat(SNOW_MELT); + } + + @Override + public SurfaceObsLocation getSpatialObject() { + return location; + } + + public SurfaceObsLocation getLocation() { + return location; + } + + public void setLocation(SurfaceObsLocation location) { + this.location = location; + } + + @Override + public PointDataView getPointDataView() { + return this.pointDataView; + } + + @Override + public void setPointDataView(PointDataView pointDataView) { + this.pointDataView = pointDataView; + } + + @Override + @Column + @Access(AccessType.PROPERTY) + public String getDataURI() { + return super.getDataURI(); + } + + @Override + public String getPluginName() { + return PLUGIN_ID; + } +} diff --git a/edexOsgi/com.raytheon.uf.common.pointdata/src/com/raytheon/uf/common/pointdata/PointDataView.java b/edexOsgi/com.raytheon.uf.common.pointdata/src/com/raytheon/uf/common/pointdata/PointDataView.java index 6ff3ba757e..5032bb3617 100644 --- a/edexOsgi/com.raytheon.uf.common.pointdata/src/com/raytheon/uf/common/pointdata/PointDataView.java +++ b/edexOsgi/com.raytheon.uf.common.pointdata/src/com/raytheon/uf/common/pointdata/PointDataView.java @@ -39,9 +39,10 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; *
  * 
  * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Apr 8, 2009            chammack     Initial creation
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Apr 08, 2009           chammack    Initial creation
+ * Dec 20, 2013  2537     bsteffen    add getFloat on a specified level.
  * 
  * 
* @@ -224,6 +225,24 @@ public class PointDataView { } } + public float getFloat(String parameter, int level) { + AbstractPointDataObject p = getParamSafe(parameter); + + if (!(p instanceof FloatPointDataObject)) { + return p.getNumber(getIndex(p) + level).floatValue(); + } else if (level == 0) { + return ((FloatPointDataObject) p).getFloat(getIndex(p)); + } else if (level >= p.getDescription().getDimensionAsInt()) { + throw new IllegalArgumentException("Level " + level + + " exceeds maxLevel size " + + p.getDescription().getDimensionAsInt()); + } else if (p.getDimensions() != 2) { + throw new IllegalArgumentException("Data is not two dimensional"); + } else { + return ((FloatPointDataObject) p).getFloat(getIndex(p) + level); + } + } + public long getLong(String parameter) { AbstractPointDataObject p = getParamSafe(parameter); diff --git a/edexOsgi/com.raytheon.uf.edex.dataplugins.feature/feature.xml b/edexOsgi/com.raytheon.uf.edex.dataplugins.feature/feature.xml index 62ff4907e1..5f6129c8a4 100644 --- a/edexOsgi/com.raytheon.uf.edex.dataplugins.feature/feature.xml +++ b/edexOsgi/com.raytheon.uf.edex.dataplugins.feature/feature.xml @@ -172,7 +172,14 @@ unpack="false"/> + + - + diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/.classpath b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/.classpath similarity index 100% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/.classpath rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/.classpath diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/.project b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/.project similarity index 91% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/.project rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/.project index cb6eef6b02..eaee34c76a 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/.project +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/.project @@ -1,6 +1,6 @@ - com.raytheon.edex.plugin.modelsounding + com.raytheon.uf.edex.plugin.modelsounding diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/.settings/org.eclipse.jdt.core.prefs b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/.settings/org.eclipse.jdt.core.prefs similarity index 100% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/.settings/org.eclipse.jdt.core.prefs rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/.settings/org.eclipse.jdt.core.prefs diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/META-INF/MANIFEST.MF similarity index 66% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/META-INF/MANIFEST.MF rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/META-INF/MANIFEST.MF index 50736c45b8..200fbd6852 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/META-INF/MANIFEST.MF @@ -1,8 +1,8 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Modelsounding Plug-in -Bundle-SymbolicName: com.raytheon.edex.plugin.modelsounding -Bundle-Version: 1.13.1.qualifier +Bundle-SymbolicName: com.raytheon.uf.edex.plugin.modelsounding +Bundle-Version: 1.14.0.qualifier Bundle-Vendor: RAYTHEON Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.6 @@ -11,6 +11,7 @@ Require-Bundle: com.raytheon.uf.edex.core, com.raytheon.uf.edex.database, com.raytheon.uf.edex.pointdata, com.raytheon.uf.edex.decodertools, + com.raytheon.uf.common.dataplugin.modelsounding, com.raytheon.uf.common.dataplugin, com.raytheon.uf.common.datastorage, com.raytheon.uf.common.geospatial, @@ -20,8 +21,8 @@ Require-Bundle: com.raytheon.uf.edex.core, com.raytheon.uf.common.site Import-Package: com.raytheon.edex.esb, com.raytheon.edex.plugin -Export-Package: com.raytheon.edex.plugin.modelsounding, - com.raytheon.edex.plugin.modelsounding.common, - com.raytheon.edex.plugin.modelsounding.dao, - com.raytheon.edex.plugin.modelsounding.decoder +Export-Package: com.raytheon.uf.edex.plugin.modelsounding, + com.raytheon.uf.edex.plugin.modelsounding.common, + com.raytheon.uf.edex.plugin.modelsounding.dao, + com.raytheon.uf.edex.plugin.modelsounding.decoder diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/build.properties b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/build.properties similarity index 100% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/build.properties rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/build.properties diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/com.raytheon.edex.plugin.modelsounding.ecl b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/com.raytheon.edex.plugin.modelsounding.ecl similarity index 100% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/com.raytheon.edex.plugin.modelsounding.ecl rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/com.raytheon.edex.plugin.modelsounding.ecl diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/res/pointdata/modelsounding.xml b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/pointdata/modelsounding.xml similarity index 100% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/res/pointdata/modelsounding.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/pointdata/modelsounding.xml diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/res/pointdata/modelsoundingdb.xml b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/pointdata/modelsoundingdb.xml similarity index 100% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/res/pointdata/modelsoundingdb.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/pointdata/modelsoundingdb.xml diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/res/spring/modelsounding-common.xml b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/spring/modelsounding-common.xml similarity index 73% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/res/spring/modelsounding-common.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/spring/modelsounding-common.xml index a354739422..5e294f68ab 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/res/spring/modelsounding-common.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/spring/modelsounding-common.xml @@ -8,9 +8,9 @@ - - - + + + diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/res/spring/modelsounding-ingest.xml b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/spring/modelsounding-ingest.xml similarity index 94% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/res/spring/modelsounding-ingest.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/spring/modelsounding-ingest.xml index 73770c7c57..0230b80501 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/res/spring/modelsounding-ingest.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/res/spring/modelsounding-ingest.xml @@ -4,11 +4,11 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> + class="com.raytheon.uf.edex.plugin.modelsounding.ModelSoundingPersistenceManager"> diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingDecoder.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingDecoder.java similarity index 97% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingDecoder.java rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingDecoder.java index 5a114f9782..34dadeefe6 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingDecoder.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingDecoder.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.edex.plugin.modelsounding; +package com.raytheon.uf.edex.plugin.modelsounding; import java.util.ArrayList; import java.util.HashMap; @@ -29,9 +29,8 @@ import java.util.Set; import com.raytheon.edex.esb.Headers; import com.raytheon.edex.plugin.AbstractDecoder; -import com.raytheon.edex.plugin.modelsounding.common.SoundingSite; -import com.raytheon.edex.plugin.modelsounding.decoder.ModelSoundingDataAdapter; import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.dataplugin.modelsounding.SoundingSite; import com.raytheon.uf.common.pointdata.PointDataContainer; import com.raytheon.uf.common.pointdata.PointDataDescription; import com.raytheon.uf.common.status.IUFStatusHandler; @@ -45,6 +44,7 @@ import com.raytheon.uf.edex.decodertools.bufr.descriptors.IDescriptorFactoryDele import com.raytheon.uf.edex.decodertools.bufr.descriptors.IDescriptorFactorySelector; import com.raytheon.uf.edex.decodertools.bufr.packets.BUFRSublistPacket; import com.raytheon.uf.edex.decodertools.bufr.packets.IBUFRDataPacket; +import com.raytheon.uf.edex.plugin.modelsounding.decoder.ModelSoundingDataAdapter; import com.raytheon.uf.edex.wmo.message.WMOHeader; /** @@ -158,7 +158,7 @@ public class ModelSoundingDecoder extends AbstractDecoder implements WMOHeader wmoHeader = new WMOHeader(data, headers); - if ((wmoHeader != null) && (wmoHeader.isValid())) { + if (wmoHeader.isValid()) { try { Set dataSet = new HashSet(); diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingPersistenceManager.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingPersistenceManager.java similarity index 99% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingPersistenceManager.java rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingPersistenceManager.java index def698c26c..ca867f24d9 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingPersistenceManager.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingPersistenceManager.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.edex.plugin.modelsounding; +package com.raytheon.uf.edex.plugin.modelsounding; import java.util.Iterator; import java.util.LinkedHashMap; diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingSeparator.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingSeparator.java similarity index 99% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingSeparator.java rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingSeparator.java index b969cfa227..a8e7fad84b 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingSeparator.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingSeparator.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.edex.plugin.modelsounding; +package com.raytheon.uf.edex.plugin.modelsounding; import java.util.ArrayList; import java.util.List; diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingStorageContainer.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingStorageContainer.java similarity index 97% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingStorageContainer.java rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingStorageContainer.java index f187d71ca3..e8d783d253 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ModelSoundingStorageContainer.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ModelSoundingStorageContainer.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.edex.plugin.modelsounding; +package com.raytheon.uf.edex.plugin.modelsounding; import java.util.LinkedList; import java.util.List; diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/SoundingModelTemporalData.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/SoundingModelTemporalData.java similarity index 82% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/SoundingModelTemporalData.java rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/SoundingModelTemporalData.java index ab769f4e67..abb99d4cc2 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/SoundingModelTemporalData.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/SoundingModelTemporalData.java @@ -17,12 +17,10 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.edex.plugin.modelsounding; +package com.raytheon.uf.edex.plugin.modelsounding; -import java.util.Calendar; - -import com.raytheon.edex.plugin.modelsounding.common.SoundingModels; import com.raytheon.uf.common.time.DataTime; +import com.raytheon.uf.edex.plugin.modelsounding.common.SoundingModels; /** * Stores temporal information associated with sounding data. @@ -31,9 +29,11 @@ import com.raytheon.uf.common.time.DataTime; * * SOFTWARE HISTORY * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Jul 3, 2013 2161 bkowal Initial creation + * Date Ticket# Engineer Description + * ------------- -------- ----------- -------------------------- + * Jul 03, 2013 2161 bkowal Initial creation + * Dec 02, 2013 2537 bsteffen Remove obsTime and fcstseconds from + * SoundingSite. * * * @@ -42,7 +42,6 @@ import com.raytheon.uf.common.time.DataTime; */ public class SoundingModelTemporalData { - private Calendar obsTime; private DataTime dt; @@ -58,21 +57,12 @@ public class SoundingModelTemporalData { * */ public SoundingModelTemporalData() { - this.obsTime = null; this.dt = null; this.refTime = -1L; this.validTime = -1L; this.forecastHr = -1; } - public Calendar getObsTime() { - return obsTime; - } - - public void setObsTime(Calendar obsTime) { - this.obsTime = obsTime; - } - public DataTime getDt() { return dt; } diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/ModelSoundingPathProvider.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/common/ModelSoundingPathProvider.java similarity index 79% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/ModelSoundingPathProvider.java rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/common/ModelSoundingPathProvider.java index fb7851aa5f..a27b079b36 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/ModelSoundingPathProvider.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/common/ModelSoundingPathProvider.java @@ -17,10 +17,12 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.edex.plugin.modelsounding.common; +package com.raytheon.uf.edex.plugin.modelsounding.common; +import com.raytheon.uf.common.dataplugin.modelsounding.SoundingSite; import com.raytheon.uf.common.dataplugin.persist.DefaultPathProvider; import com.raytheon.uf.common.dataplugin.persist.IPersistable; +import com.raytheon.uf.common.time.util.TimeUtil; /** * Path Provider for Model Sounding Data. @@ -29,9 +31,10 @@ import com.raytheon.uf.common.dataplugin.persist.IPersistable; * * SOFTWARE HISTORY * - * Date Ticket# Engineer Description - * ------------ ---------- ----------- -------------------------- - * Apr 26, 2013 bkowal Initial creation + * Date Ticket# Engineer Description + * ------------- -------- ----------- -------------------------- + * Apr 26, 2013 bkowal Initial creation + * Dec 02, 2013 2537 bsteffen Remove fcstseconds from SoundingSite. * * * @@ -54,7 +57,8 @@ public class ModelSoundingPathProvider extends DefaultPathProvider { public String getHDFFileName(String pluginName, IPersistable persistable) { SoundingSite soundingSite = (SoundingSite) persistable; - long forecastHour = soundingSite.getFcstSeconds() / 3600; + long forecastHour = soundingSite.getDataTime().getFcstTime() + / TimeUtil.SECONDS_PER_HOUR; StringBuilder stringBuilder = new StringBuilder(pluginName); stringBuilder.append(FILENAME_SEPARATOR); diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingModels.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/common/SoundingModels.java similarity index 97% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingModels.java rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/common/SoundingModels.java index 774ab48add..40191a26f8 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/common/SoundingModels.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/common/SoundingModels.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.edex.plugin.modelsounding.common; +package com.raytheon.uf.edex.plugin.modelsounding.common; /** * diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/dao/ModelSoundingDAO.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/dao/ModelSoundingDAO.java similarity index 76% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/dao/ModelSoundingDAO.java rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/dao/ModelSoundingDAO.java index cea1445598..099b67b0de 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/dao/ModelSoundingDAO.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/dao/ModelSoundingDAO.java @@ -17,15 +17,18 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.edex.plugin.modelsounding.dao; +package com.raytheon.uf.edex.plugin.modelsounding.dao; import java.io.File; import java.util.List; -import com.raytheon.edex.plugin.modelsounding.common.ModelSoundingPathProvider; -import com.raytheon.edex.plugin.modelsounding.common.SoundingSite; import com.raytheon.uf.common.dataplugin.PluginException; +import com.raytheon.uf.common.dataplugin.modelsounding.SoundingSite; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.edex.database.DataAccessLayerException; +import com.raytheon.uf.edex.plugin.modelsounding.common.ModelSoundingPathProvider; import com.raytheon.uf.edex.pointdata.PointDataPluginDao; import com.raytheon.uf.edex.wmo.message.WMOHeader; @@ -34,13 +37,14 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * *
  * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * 20080303           1026 jkorman     Initial implementation.
- * 20130426           1861 bkowal      Added report type and forecast seconds as
- *                                     required keys for the hdf5 file name. Create
- *                                     a new method to generate hdf5 file names that
- *                                     will use the path provider.
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- -----------------------------------------
+ * Mar 03, 2008  1026     jkorman     Initial implementation.
+ * Apr 26, 2013  1861     bkowal      Added report type and forecast seconds as
+ *                                    required keys for the hdf5 file name. 
+ *                                    Create a new method to generate hdf5 file
+ *                                    names that will use the path provider.
+ * Dec 02, 2013  2537     bsteffen    Remove fcstseconds from SoundingSite.
  * 
  * 
* @@ -49,6 +53,9 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; */ public class ModelSoundingDAO extends PointDataPluginDao { + private static final transient IUFStatusHandler statusHandler = UFStatus + .getHandler(ModelSoundingDAO.class); + /** * Creates a new BufrMOSDao object. * @@ -72,7 +79,7 @@ public class ModelSoundingDAO extends PointDataPluginDao { try { obs = queryBySingleCriteria("dataURI", dataURI); } catch (DataAccessLayerException e) { - e.printStackTrace(); + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); } if ((obs != null) && (obs.size() > 0)) { report = (SoundingSite) obs.get(0); @@ -125,7 +132,8 @@ public class ModelSoundingDAO extends PointDataPluginDao { @Override public String[] getKeysRequiredForFileName() { - return new String[] { "reportType", "dataTime.refTime", "fcstSeconds" }; + return new String[] { "reportType", "dataTime.refTime", + "dataTime.fcstTime" }; } @Override diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/decoder/ModelSoundingDataAdapter.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/decoder/ModelSoundingDataAdapter.java similarity index 69% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/decoder/ModelSoundingDataAdapter.java rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/decoder/ModelSoundingDataAdapter.java index e7aecde92e..1b0a752203 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/decoder/ModelSoundingDataAdapter.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/decoder/ModelSoundingDataAdapter.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.edex.plugin.modelsounding.decoder; +package com.raytheon.uf.edex.plugin.modelsounding.decoder; import static com.raytheon.uf.edex.decodertools.bufr.packets.DataPacketTypes.RepSubList; @@ -25,9 +25,8 @@ import java.io.File; import java.util.Calendar; import java.util.List; -import com.raytheon.edex.plugin.modelsounding.SoundingModelTemporalData; -import com.raytheon.edex.plugin.modelsounding.common.SoundingModels; -import com.raytheon.edex.plugin.modelsounding.common.SoundingSite; +import com.raytheon.uf.common.dataplugin.modelsounding.SoundingLevel; +import com.raytheon.uf.common.dataplugin.modelsounding.SoundingSite; import com.raytheon.uf.common.geospatial.spi.SPIContainer; import com.raytheon.uf.common.geospatial.spi.SPIEntry; import com.raytheon.uf.common.localization.LocalizationContext; @@ -36,7 +35,7 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; import com.raytheon.uf.common.localization.PathManager; import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.pointdata.PointDataContainer; -import com.raytheon.uf.common.pointdata.PointDataDescription.Type; +import com.raytheon.uf.common.pointdata.PointDataDescription; import com.raytheon.uf.common.pointdata.PointDataView; import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; import com.raytheon.uf.common.status.IUFStatusHandler; @@ -47,6 +46,8 @@ import com.raytheon.uf.edex.decodertools.bufr.descriptors.BUFRDescriptor; import com.raytheon.uf.edex.decodertools.bufr.packets.BUFRSublistPacket; import com.raytheon.uf.edex.decodertools.bufr.packets.IBUFRDataPacket; import com.raytheon.uf.edex.decodertools.core.IDecoderConstants; +import com.raytheon.uf.edex.plugin.modelsounding.SoundingModelTemporalData; +import com.raytheon.uf.edex.plugin.modelsounding.common.SoundingModels; import com.raytheon.uf.edex.wmo.message.WMOHeader; /** @@ -62,7 +63,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * work without dataURI. * Jul 03, 2013 2161 bkowal Relocated the logic used to retrieve * temporal information into its own function. - * Dec 02, 2013 2537 bsteffen Switch logger to ufstatus. + * Dec 02, 2013 2537 bsteffen Use SoundingSite setters instead of view. * * * @@ -100,9 +101,7 @@ public class ModelSoundingDataAdapter { public static void updateStationList() { SoundingStations ss = new SoundingStations(MODEL_STATION_LIST); synchronized (LOCK) { - if (ss != null) { - stationsList = ss; - } + stationsList = ss; } } @@ -110,9 +109,7 @@ public class ModelSoundingDataAdapter { SoundingStations ss = new SoundingStations(MODEL_STATION_LIST); SPIContainer spi = populateSPIData(); synchronized (LOCK) { - if (ss != null) { - stationsList = ss; - } + stationsList = ss; if ((spi != null) && (spi.isLoaded())) { SPI_DATA = spi; } @@ -146,7 +143,6 @@ public class ModelSoundingDataAdapter { } SoundingModelTemporalData soundingTemporalData = new SoundingModelTemporalData(); - soundingTemporalData.setObsTime(obsTime); DataTime dt = new DataTime(obsTime, forecastSeconds.intValue()); soundingTemporalData.setDt(dt); @@ -194,30 +190,23 @@ public class ModelSoundingDataAdapter { switch (model) { case MODEL_GFS: { obsData.setReportType(model.getReportType()); - obsData = getGFSSiteData(dataList, obsData, view); + obsData = getGFSSiteData(dataList, obsData); break; } case MODEL_ETA: { obsData.setReportType(model.getReportType()); - obsData = getETASiteData(dataList, obsData, view); + obsData = getETASiteData(dataList, obsData); break; } } obsData.setWmoHeader(wmoHeader.getWmoHeader()); - if (soundingTemporalData != null) { + obsData.setDataTime(soundingTemporalData.getDt()); - obsData.setTimeObs(soundingTemporalData.getObsTime()); + view.setLong("validTime", + soundingTemporalData.getValidTime()); - obsData.setDataTime(soundingTemporalData.getDt()); - - view.setLong("validTime", - soundingTemporalData.getValidTime()); - - } - - obsData.setPointDataView(view); } } catch (Throwable t) { logger.error("Error decoding BUFR data", t); @@ -248,11 +237,10 @@ public class ModelSoundingDataAdapter { SurfaceObsLocation location = new SurfaceObsLocation(); IBUFRDataPacket dp = dataList.get(index++); - int d = dp.getReferencingDescriptor().getDescriptor(); - if (d == BUFRDescriptor.createDescriptor(0, 4, 194)) { - obsData.setFcstSeconds((dp.getValue() != null) ? ((Double) dp - .getValue()).longValue() : null); - } + /* + * dp is forecastHr packet, already handled in + * SoundingModelTemporalData + */ int wmoStaNum = getInt(dataList.get(index++), -9999); view.setInt("wmoStaNum", wmoStaNum); @@ -271,7 +259,7 @@ public class ModelSoundingDataAdapter { } Double lat = null; dp = dataList.get(index++); - d = dp.getReferencingDescriptor().getDescriptor(); + int d = dp.getReferencingDescriptor().getDescriptor(); if (d == BUFRDescriptor.createDescriptor(0, 5, 2)) { lat = (Double) dp.getValue(); } @@ -290,6 +278,8 @@ public class ModelSoundingDataAdapter { location.setElevation(stationHeight); } obsData.setLocation(location); + + obsData.setPointDataView(view); } else { obsData = null; } @@ -307,7 +297,7 @@ public class ModelSoundingDataAdapter { */ @SuppressWarnings("unchecked") private static SoundingSite getGFSSiteData(List dataList, - SoundingSite siteData, PointDataView view) { + SoundingSite siteData) { if ((dataList != null) && (siteData != null)) { // get the replication sublist for the sounding data @@ -318,43 +308,41 @@ public class ModelSoundingDataAdapter { List subList = (List) p .getValue(); - int index = 0; for (IBUFRDataPacket pList : subList) { List sList = (List) pList .getValue(); - createGFSLevel(sList, view, index++); + createGFSLevel(sList, siteData.addLevel()); } // for - view.setInt("numProfLvls", index); } - setViewData("seaLvlPress", view, dataList.get(6)); - setViewData("sfcPress", view, dataList.get(7)); + siteData.setPressSLP(extractFloat(dataList.get(6))); + siteData.setPressSfc(extractFloat(dataList.get(7))); // [0 12 061] Skin temperature - setViewData("skinTemp", view, dataList.get(8)); + siteData.setSkinTemp(extractFloat(dataList.get(8))); // ************************************************************* - setViewData("totPrecip", view, dataList.get(11)); - setViewData("convPrecip", view, dataList.get(12)); - setViewData("snowFall", view, dataList.get(13)); + siteData.setTotPrecip(extractFloat(dataList.get(11))); + siteData.setPrecipConv(extractFloat(dataList.get(12))); + siteData.setSnowFall(extractFloat(dataList.get(13))); // ************************************************************* - setViewData("lowCld", view, dataList.get(14)); - setViewData("midCld", view, dataList.get(15)); - setViewData("hiCld", view, dataList.get(16)); + siteData.setCldAmtLo(extractFloat(dataList.get(14))); + siteData.setCldAmtLo(extractFloat(dataList.get(15))); + siteData.setCldAmtLo(extractFloat(dataList.get(16))); // ************************************************************* - setViewData("u10", view, dataList.get(17)); - setViewData("v10", view, dataList.get(18)); - setViewData("temp2", view, dataList.get(19)); - setViewData("q2", view, dataList.get(20)); + siteData.setUc10M(extractFloat(dataList.get(17))); + siteData.setVc10M(extractFloat(dataList.get(18))); + siteData.setTemp2M(extractFloat(dataList.get(19))); + siteData.setSpecHum2M(extractFloat(dataList.get(20))); // ************************************************************* // Snow precipitation type - setViewData("snowTyp", view, dataList.get(21)); + siteData.setSnowType(extractInteger(dataList.get(21))); // Ice pellet precipitation type - setViewData("iceTyp", view, dataList.get(21)); + siteData.setIceType(extractInteger(dataList.get(21))); // Freezing rain precipitation type - setViewData("frzgRainTyp", view, dataList.get(23)); + siteData.setFzRainType(extractInteger(dataList.get(23))); // Rain precipitation type - setViewData("rainType", view, dataList.get(24)); + siteData.setRainType(extractInteger(dataList.get(24))); } return siteData; } @@ -364,33 +352,27 @@ public class ModelSoundingDataAdapter { * * @param levelList * A sublist containing level data. - * @param elev - * The current elevation to use. - * @return The populated level data. + * @param level + * The current level to populate. */ private static void createGFSLevel(List levelList, - PointDataView view, int index) { + SoundingLevel level) { if (levelList != null) { - setViewData("pressure", view, levelList.get(0), index); - setViewData("temperature", view, levelList.get(1), index); - setViewData("uComp", view, levelList.get(2), index); - setViewData("vComp", view, levelList.get(3), index); - setViewData("specHum", view, levelList.get(4), index); - setViewData("omega", view, levelList.get(5), index); + level.setPressure(extractFloat(levelList.get(0))); + level.setTemperature(extractFloat(levelList.get(1))); + level.setUcWind(extractFloat(levelList.get(2))); + level.setVcWind(extractFloat(levelList.get(3))); + level.setSpecificHumidity(extractFloat(levelList.get(4))); + level.setOmega(extractFloat(levelList.get(5))); } } - /** - * - * @param levelList - * @return - */ private static void createETALevel(List levelList, - PointDataView view, int index) { + SoundingLevel level) { // go get the common data. - createGFSLevel(levelList, view, index); - setViewData("cldCvr", view, levelList.get(11), index); + createGFSLevel(levelList, level); + level.setLyrCldCvr(extractFloat(levelList.get(11))); } /** @@ -402,7 +384,7 @@ public class ModelSoundingDataAdapter { */ @SuppressWarnings("unchecked") private static SoundingSite getETASiteData(List dataList, - SoundingSite siteData, PointDataView view) { + SoundingSite siteData) { if ((dataList != null) && (siteData != null)) { // get the replication sublist for the sounding data @@ -413,141 +395,109 @@ public class ModelSoundingDataAdapter { List subList = (List) p .getValue(); - int index = 0; for (IBUFRDataPacket pList : subList) { List sList = (List) pList .getValue(); - createETALevel(sList, view, index++); + createETALevel(sList, siteData.addLevel()); } // for - view.setInt("numProfLvls", index); } // ************************************************************* // [0 10 051] Pressure reduced to mean sea level - setViewData("seaLvlPress", view, dataList.get(8)); + siteData.setPressSLP(extractFloat(dataList.get(8))); // [0 10 195] Surface pressure - setViewData("sfcPress", view, dataList.get(9)); + siteData.setPressSfc(extractFloat(dataList.get(9))); // [0 12 061] Skin temperature - setViewData("skinTemp", view, dataList.get(10)); + siteData.setSkinTemp(extractFloat(dataList.get(10))); // [0 12 196] 1-hour minimum temperature at lowest model level - setViewData("minTemp", view, dataList.get(11)); + siteData.setMinTemp(extractFloat(dataList.get(11))); // [0 12 197] 1-hour maximum temperature at lowest model level - setViewData("maxTemp", view, dataList.get(12)); + siteData.setMaxTemp(extractFloat(dataList.get(12))); // ************************************************************* // [0 13 019] Total precipitation past 1 hour - setViewData("totPrecip", view, dataList.get(14)); + siteData.setTotPrecip(extractFloat(dataList.get(14))); // [0 13 208] Convective precipitation in past 1 hour - setViewData("convPrecip", view, dataList.get(15)); + siteData.setPrecipConv(extractFloat(dataList.get(15))); // ************************************************************* // [0 12 201] 1-hour average sensible heat flux - setViewData("sensHeat", view, dataList.get(18)); + siteData.setSensHeat(extractFloat(dataList.get(18))); // [0 12 202] 1-hour average sub-surface heat flux - setViewData("subSfcHeat", view, dataList.get(19)); + siteData.setSubSfcHeat(extractFloat(dataList.get(19))); // [0 12 203] 1-hour average snow phase change heat flux - setViewData("snowFlux", view, dataList.get(20)); + siteData.setSnowFlux(extractFloat(dataList.get(20))); // ************************************************************* // [0 13 216] 1-hour accumulated snowfall - setViewData("snowWater", view, dataList.get(29)); + siteData.setSnowWaterEquiv(extractFloat(dataList.get(29))); // [0 13 210] Snow water equivalent - setViewData("snowFall", view, dataList.get(27)); + siteData.setSnowFall(extractFloat(dataList.get(27))); // [0 13 218] 1-hour accumulated snow melt - setViewData("snowMelt", view, dataList.get(30)); + siteData.setSnowMelt(extractFloat(dataList.get(30))); // ************************************************************* // % Amount of low clouds - setViewData("lowCld", view, dataList.get(46)); + siteData.setCldAmtLo(extractFloat(dataList.get(46))); // % Amount of mid clouds - setViewData("midCld", view, dataList.get(47)); + siteData.setCldAmtMd(extractFloat(dataList.get(47))); // % Amount of high clouds - setViewData("hiCld", view, dataList.get(48)); + siteData.setCldAmtHi(extractFloat(dataList.get(48))); // ************************************************************* // u component at 10 meters - setViewData("u10", view, dataList.get(35)); + siteData.setUc10M(extractFloat(dataList.get(35))); // v component at 10 meters - setViewData("v10", view, dataList.get(36)); + siteData.setVc10M(extractFloat(dataList.get(36))); // Potential temperature at 10 m - setViewData("Theta10", view, dataList.get(37)); + siteData.setTheta10M(extractFloat(dataList.get(37))); // Specific humidity at 10 m - setViewData("q10", view, dataList.get(38)); + siteData.setSpecHum10M(extractFloat(dataList.get(38))); // ************************************************************* // Dry-bulb temperature at 2 m - setViewData("temp2", view, dataList.get(39)); + siteData.setTemp2M(extractFloat(dataList.get(39))); // Specific humidity at 2 m - setViewData("q2", view, dataList.get(40)); + siteData.setSpecHum2M(extractFloat(dataList.get(40))); // ************************************************************* // Snow precipitation type - setViewData("snowTyp", view, dataList.get(50)); + siteData.setSnowType(extractInteger(dataList.get(50))); // Ice pellet precipitation type - setViewData("iceTyp", view, dataList.get(51)); + siteData.setIceType(extractInteger(dataList.get(51))); // Freezing rain precipitation type - setViewData("frzgRainTyp", view, dataList.get(52)); + siteData.setFzRainType(extractInteger(dataList.get(52))); // Rain precipitation type - setViewData("rainType", view, dataList.get(53)); + siteData.setRainType(extractInteger(dataList.get(53))); - setViewData("uStorm", view, dataList.get(54)); - setViewData("vStorm", view, dataList.get(55)); + siteData.setStormUComp(extractFloat(dataList.get(54))); + siteData.setStormVComp(extractFloat(dataList.get(55))); // Storm relative helicity - setViewData("srHel", view, dataList.get(56)); - setViewData("prCloud", view, dataList.get(57)); - setViewData("vsby", view, dataList.get(58)); + siteData.setStormRelHeli(extractFloat(dataList.get(56))); + siteData.setPressCldBase(extractFloat(dataList.get(57))); + siteData.setHorzVis(extractFloat(dataList.get(58))); } return siteData; } - /** - * - * @param parmName - * @param view - * @param packet - */ - private static void setViewData(String parmName, PointDataView view, - IBUFRDataPacket packet) { - setViewData(parmName, view, packet, 0); + private static int extractInteger(IBUFRDataPacket packet) { + if (packet == null) { + return PointDataDescription.FILL_VALUE_INT; + } else { + Object val = packet.getValue(); + if (val instanceof Number) { + return ((Number) val).intValue(); + } else { + return PointDataDescription.FILL_VALUE_INT; + } + } } - /** - * - * @param parmName - * @param view - * @param packet - */ - private static void setViewData(String parmName, PointDataView view, - IBUFRDataPacket packet, int index) { - if (packet != null) { - Type t = view.getType(parmName); - Object o = packet.getValue(); - if (o != null) { - switch (t) { - case STRING: { - if (o instanceof String) { - view.setString(parmName, (String) o, index); - } - } - case INT: { - if (o instanceof Double) { - view.setInt(parmName, ((Double) o).intValue(), index); - } else if (o instanceof Long) { - view.setInt(parmName, ((Long) o).intValue(), index); - } - } - case LONG: { - if (o instanceof Double) { - view.setLong(parmName, ((Double) o).longValue(), index); - } else if (o instanceof Long) { - view.setLong(parmName, ((Long) o).longValue(), index); - } - } - case FLOAT: { - if (o instanceof Double) { - view.setFloat(parmName, ((Double) o).floatValue(), - index); - } else if (o instanceof Long) { - view.setFloat(parmName, ((Long) o).floatValue(), index); - } - } - } + private static float extractFloat(IBUFRDataPacket packet) { + if (packet == null) { + return PointDataDescription.FILL_VALUE_INT; + } else { + Object val = packet.getValue(); + if (val instanceof Number) { + return ((Number) val).floatValue(); + } else { + return PointDataDescription.FILL_VALUE_INT; } } } diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/decoder/SoundingStations.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/decoder/SoundingStations.java similarity index 85% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/decoder/SoundingStations.java rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/decoder/SoundingStations.java index 27e38a97c8..5a59ffb314 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/decoder/SoundingStations.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/decoder/SoundingStations.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.edex.plugin.modelsounding.decoder; +package com.raytheon.uf.edex.plugin.modelsounding.decoder; import static com.raytheon.uf.common.localization.LocalizationContext.LocalizationType.EDEX_STATIC; @@ -37,6 +37,7 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; /** * Loads a map from a file for mapping wmo numbers to icaos. @@ -91,28 +92,26 @@ public class SoundingStations { String line = null; while ((line = bf.readLine()) != null) { - if (line != null) { - // filter out comments - if ((!line.startsWith("#")) - && (line.length() > 22)) { - String wmo = line.substring(0, 13).trim(); - String pICAO = line.substring(15, 19) - .trim(); - stationMap.put(wmo, pICAO); - } + // filter out comments + if ((!line.startsWith("#")) && (line.length() > 22)) { + String wmo = line.substring(0, 13).trim(); + String pICAO = line.substring(15, 19).trim(); + stationMap.put(wmo, pICAO); } } } logger.debug(String.format("Read %d stationIds from %s.", count, path)); } catch (IOException ioe) { - ioe.printStackTrace(); + logger.handle(Priority.PROBLEM, ioe.getLocalizedMessage(), + ioe); } finally { if (bf != null) { try { bf.close(); } catch (IOException ioe) { - ioe.printStackTrace(); + logger.handle(Priority.PROBLEM, + ioe.getLocalizedMessage(), ioe); } } } @@ -155,7 +154,7 @@ public class SoundingStations { try { fis = new FileInputStream(file); } catch (FileNotFoundException e) { - e.printStackTrace(); + logger.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); } return fis; } diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ingest/ModelBufrSubscriber.java b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ingest/ModelBufrSubscriber.java similarity index 98% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ingest/ModelBufrSubscriber.java rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ingest/ModelBufrSubscriber.java index 88143e3e6b..5b73b17636 100644 --- a/edexOsgi/com.raytheon.edex.plugin.modelsounding/src/com/raytheon/edex/plugin/modelsounding/ingest/ModelBufrSubscriber.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/src/com/raytheon/uf/edex/plugin/modelsounding/ingest/ModelBufrSubscriber.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.edex.plugin.modelsounding.ingest; +package com.raytheon.uf.edex.plugin.modelsounding.ingest; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -27,7 +27,6 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; -import com.raytheon.edex.plugin.modelsounding.decoder.ModelSoundingDataAdapter; import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.LocalizationContext; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; @@ -38,6 +37,7 @@ import com.raytheon.uf.common.site.ingest.INationalDatasetSubscriber; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.edex.plugin.modelsounding.decoder.ModelSoundingDataAdapter; /** * Subscriber to update the local model sounding sites whenever the national spi @@ -207,10 +207,8 @@ public class ModelBufrSubscriber implements INationalDatasetSubscriber { } } } - - } catch (FileNotFoundException e) { - statusHandler.handle(Priority.SIGNIFICANT, "modelBufr:Could not read File ", e); } catch (IOException e) { + statusHandler.handle(Priority.SIGNIFICANT, "modelBufr:Could not read File ", e); } } diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/utility/common_static/base/path/modelsoundingPathKeys.xml b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/utility/common_static/base/path/modelsoundingPathKeys.xml similarity index 100% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/utility/common_static/base/path/modelsoundingPathKeys.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/utility/common_static/base/path/modelsoundingPathKeys.xml diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/utility/edex_static/base/distribution/modelsounding.xml b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/utility/edex_static/base/distribution/modelsounding.xml similarity index 100% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/utility/edex_static/base/distribution/modelsounding.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/utility/edex_static/base/distribution/modelsounding.xml diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/utility/edex_static/base/modelsounding/modelBufrStationList.txt b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/utility/edex_static/base/modelsounding/modelBufrStationList.txt similarity index 100% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/utility/edex_static/base/modelsounding/modelBufrStationList.txt rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/utility/edex_static/base/modelsounding/modelBufrStationList.txt diff --git a/edexOsgi/com.raytheon.edex.plugin.modelsounding/utility/edex_static/base/plugin-filters/modelSounding_filters.xml b/edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/utility/edex_static/base/plugin-filters/modelSounding_filters.xml similarity index 100% rename from edexOsgi/com.raytheon.edex.plugin.modelsounding/utility/edex_static/base/plugin-filters/modelSounding_filters.xml rename to edexOsgi/com.raytheon.uf.edex.plugin.modelsounding/utility/edex_static/base/plugin-filters/modelSounding_filters.xml diff --git a/edexOsgi/com.raytheon.uf.edex.pointdata/src/com/raytheon/uf/edex/pointdata/PointDataPluginDao.java b/edexOsgi/com.raytheon.uf.edex.pointdata/src/com/raytheon/uf/edex/pointdata/PointDataPluginDao.java index a6986c3c30..10bbac2471 100644 --- a/edexOsgi/com.raytheon.uf.edex.pointdata/src/com/raytheon/uf/edex/pointdata/PointDataPluginDao.java +++ b/edexOsgi/com.raytheon.uf.edex.pointdata/src/com/raytheon/uf/edex/pointdata/PointDataPluginDao.java @@ -66,15 +66,16 @@ import com.raytheon.uf.edex.database.plugin.PluginDao; *
  * 
  * SOFTWARE HISTORY
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Apr 13, 2009            chammack     Initial creation
- * Jan 14, 2013 1469       bkowal       Removed the hdf5 data directory.
- * Feb 27, 2013 1638       mschenke    Switched logger to use statusHandler
- * Apr 15, 2013 1868       bsteffen    Rewrite mergeAll in PluginDao.
- * Apr 29, 2013 1861       bkowal      Refactor hdf5 filename generation during reads
- *                                     into its own method so modelsounding dao can
- *                                     override it.
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- -----------------------------------------
+ * Apr 13, 2009           chammack    Initial creation
+ * Jan 14, 2013  1469     bkowal      Removed the hdf5 data directory.
+ * Feb 27, 2013  1638     mschenke    Switched logger to use statusHandler
+ * Apr 15, 2013  1868     bsteffen    Rewrite mergeAll in PluginDao.
+ * Apr 29, 2013  1861     bkowal      Refactor hdf5 filename generation during
+ *                                    reads into its own method so modelsounding
+ *                                    dao can override it.
+ * Jan 03, 2014  2309     bsteffen    Allow fcstTime in hdf5 path.
  * 
  * 
* @@ -487,7 +488,13 @@ public abstract class PointDataPluginDao extends try { if (obj.containsKey("dataTime.refTime")) { Date d = (Date) obj.remove("dataTime.refTime"); - DataTime dt = new DataTime(d); + DataTime dt = null; + if (obj.containsKey("dataTime.fcstTime")) { + int fcstTime = (Integer) obj.remove("dataTime.fcstTime"); + dt = new DataTime(d, fcstTime); + }else{ + dt = new DataTime(d); + } obj.put("dataTime", dt); } bm.putAll(obj); diff --git a/ncep/gov.noaa.nws.ncep.edex.uengine/META-INF/MANIFEST.MF b/ncep/gov.noaa.nws.ncep.edex.uengine/META-INF/MANIFEST.MF index c4b8f5e341..77c9afff10 100644 --- a/ncep/gov.noaa.nws.ncep.edex.uengine/META-INF/MANIFEST.MF +++ b/ncep/gov.noaa.nws.ncep.edex.uengine/META-INF/MANIFEST.MF @@ -18,7 +18,7 @@ Require-Bundle: com.raytheon.edex.uengine, gov.noaa.nws.ncep.common.dataplugin.mcidas;bundle-version="1.0.0", com.raytheon.uf.common.dataplugin.radar;bundle-version="1.0.0", com.raytheon.uf.common.dataplugin.satellite;bundle-version="1.0.0", - com.raytheon.edex.plugin.modelsounding;bundle-version="1.12.1174", + com.raytheon.uf.common.dataplugin.modelsounding, com.raytheon.edex.plugin.bufrua;bundle-version="1.12.1174", com.raytheon.uf.common.dataplugin.level;bundle-version="1.12.1174", com.raytheon.uf.edex.pointdata;bundle-version="1.12.1174", @@ -28,8 +28,7 @@ Export-Package: gov.noaa.nws.ncep.edex.uengine.output, gov.noaa.nws.ncep.edex.uengine.tasks.radar, gov.noaa.nws.ncep.edex.uengine.tasks.response, gov.noaa.nws.ncep.edex.uengine.utility -Import-Package: com.raytheon.edex.plugin.modelsounding.common, - com.raytheon.uf.common.dataplugin.bufrua, +Import-Package: com.raytheon.uf.common.dataplugin.bufrua, com.raytheon.uf.common.dataplugin.bufrua.dao, com.raytheon.uf.common.dataplugin.level, com.raytheon.uf.common.pointdata, diff --git a/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/PfcSoundingQuery.java b/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/PfcSoundingQuery.java index 4223d48f01..a746ba2e79 100644 --- a/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/PfcSoundingQuery.java +++ b/ncep/gov.noaa.nws.ncep.edex.uengine/src/gov/noaa/nws/ncep/edex/uengine/tasks/profile/PfcSoundingQuery.java @@ -1,4 +1,5 @@ package gov.noaa.nws.ncep.edex.uengine.tasks.profile; + /** * * gov.noaa.nws.ncep.edex.uengine.tasks.profile.PfcSoundingQuery @@ -14,6 +15,7 @@ package gov.noaa.nws.ncep.edex.uengine.tasks.profile; * 09/13/2010 301 Chin Chen Initial coding * 12/16/2010 301 Chin Chen add support of PFC (NAM and GFS) model sounding data * 02/28/2012 Chin Chen modify several sounding query algorithms for better performance + * 12/20/2013 2537 bsteffen Update ModelSoundingPointDataTransform * * * * @@ -23,26 +25,33 @@ package gov.noaa.nws.ncep.edex.uengine.tasks.profile; import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingLayer; import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile; +import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile.PfcSndType; +import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile.SndQueryKeyType; import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingStnInfo; import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingStnInfoCollection; import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingTimeLines; -import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile.PfcSndType; -import gov.noaa.nws.ncep.edex.common.sounding.NcSoundingProfile.SndQueryKeyType; import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + import javax.measure.converter.UnitConverter; import javax.measure.unit.NonSI; import javax.measure.unit.SI; - -import com.raytheon.edex.plugin.modelsounding.common.ModelSoundingPointDataTransform; -import com.raytheon.edex.plugin.modelsounding.common.SoundingLevel; -import com.raytheon.edex.plugin.modelsounding.common.SoundingSite; +import com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingParameters; +import com.raytheon.uf.common.dataplugin.modelsounding.ModelSoundingPointDataTransform; +import com.raytheon.uf.common.dataplugin.modelsounding.SoundingLevel; +import com.raytheon.uf.common.dataplugin.modelsounding.SoundingSite; +import com.raytheon.uf.common.dataquery.requests.RequestConstraint; +import com.raytheon.uf.common.dataquery.requests.RequestConstraint.ConstraintType; +import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.edex.database.dao.CoreDao; import com.raytheon.uf.edex.database.dao.DaoConfig; import com.vividsolutions.jts.geom.Coordinate; @@ -376,46 +385,35 @@ public class PfcSoundingQuery { List soundLyList = new ArrayList(); if(sndTypeStr.equals(PfcSndType.GFSSND.toString()) || sndTypeStr.equals(PfcSndType.NAMSND.toString())){ - List fields = new ArrayList(); - List values = new ArrayList(); - List lSndSiteRecords = null; - List operands = new ArrayList(); + Map constraints = new HashMap(); + List lSndSiteRecords = null; if(queryType==SndQueryKeyType.STNID){ - fields.add("location.stationId");// the location.stationId String field name defined in SoundingSite class and decoded modelsounding table. - values.add(stn); - operands.add("="); + // the location.stationId String field name defined in SoundingSite class and decoded modelsounding table. + constraints.put("location.stationId", new RequestConstraint(stn)); } else if(queryType==SndQueryKeyType.STNNUM){ - fields.add("siteid");// the siteid String field name defined in SoundingSite class and decoded in modelsounding table. - values.add(stn); - operands.add("="); + // the siteid String field name defined in SoundingSite class and decoded in modelsounding table. + constraints.put("siteid", new RequestConstraint(stn)); + } else if(queryType==SndQueryKeyType.LATLON){ - fields.add("location.latitude");// the location.latitude field name defined in SoundingSite class and decoded modelsounding table - values.add(lat-0.1); - operands.add(">="); - fields.add("location.latitude");// the location.latitude field name defined in SoundingSite class and decoded modelsounding table - values.add(lat+0.1); - operands.add("<="); - fields.add("location.longitude");// the location.longitude field name defined in SoundingSite class and decoded modelsounding table - values.add(lon-0.1); - operands.add(">="); - fields.add("location.longitude");// the location.longitude field name defined in SoundingSite class and decoded modelsounding table - values.add(lon+0.1); - operands.add("<="); - + // the location.latitude field name defined in SoundingSite class and decoded modelsounding table + constraints.put("location.latitude", new RequestConstraint(Double.toString(lat-0.1), Double.toString(lat+0.1))); + // the location.longitude field name defined in SoundingSite class and decoded modelsounding table + constraints.put("location.longitude", new RequestConstraint(Double.toString(lon-0.1), Double.toString(lon+0.1))); } else { System.out.println("request query type "+ queryType+ " is not supported in this API" ); return pf; } - fields.add("dataTime.refTime");// the refTime time field name defined in SoundingSite and decoded modelsounding table - values.add(refTimeCal.getTime()); //refTime data type defined in SoundingSite is "Date" - operands.add("="); - fields.add("dataTime.validPeriod.start");// the rangeStart field name defined in SoundingSite and decoded modelsounding table - values.add(validTimeCal.getTime()); //rangestart data type defined in SoundingSite is "Date" - operands.add("="); + // the refTime time field name defined in SoundingSite and decoded modelsounding table + // refTime data type defined in SoundingSite is "Date" + constraints.put("dataTime.refTime", new RequestConstraint(TimeUtil.formatCalendar(refTimeCal))); + // the rangeStart field name defined in SoundingSite and decoded modelsounding table + //rangestart data type defined in SoundingSite is "Date" + constraints.put("dataTime.validPeriod.start", new RequestConstraint(TimeUtil.formatCalendar(validTimeCal))); + //String d=""; //String d1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(validTimeCal.getTime()); @@ -426,22 +424,22 @@ public class PfcSoundingQuery { // d = d+","+d2; //} - //values.add(d); //rangestart data type defined in SoundingSite is "Date" - //operands.add("in"); - for (int i=0; i < fields.size(); i++) { - System.out.println("field "+ fields.get(i) + " value "+ values.get(i)); + // //rangestart data type defined in SoundingSite is "Date" + // constraints.put("dataTime.validPeriod.start", new RequestConstraint(d, ConstraintType.IN)); + for (Entry entry : constraints.entrySet()) { + System.out.println("field "+ entry.getKey() + " value "+ entry.getValue().getConstraintValue()); } List parameters = new ArrayList(12); - parameters.addAll(ModelSoundingPointDataTransform.LVL_PARAMETERS); - parameters.add(ModelSoundingPointDataTransform.P_LATITUDE); - parameters.add(ModelSoundingPointDataTransform.P_LONGITUDE); - parameters.add(ModelSoundingPointDataTransform.P_ELEVATION); - parameters.add(ModelSoundingPointDataTransform.P_STATION_ID); - parameters.add(ModelSoundingPointDataTransform.P_STATION_NUMBER); - parameters.add(ModelSoundingPointDataTransform.P_DATAURI); + parameters.addAll(ModelSoundingParameters.LVL_PARAMETERS); + parameters.add(ModelSoundingParameters.LATITUDE); + parameters.add(ModelSoundingParameters.LONGITUDE); + parameters.add(ModelSoundingParameters.ELEVATION); + parameters.add(ModelSoundingParameters.STATION_ID); + parameters.add(ModelSoundingParameters.STATION_NUMBER); + parameters.add(ModelSoundingParameters.DATAURI); try { - lSndSiteRecords = ModelSoundingPointDataTransform.getSoundingSites(fields, values, operands, parameters); + lSndSiteRecords = ModelSoundingPointDataTransform.getSoundingSites(constraints, parameters); System.out.println("sounding site record size = "+ lSndSiteRecords.size()); if(lSndSiteRecords.size() > 0){ //set pf data @@ -460,12 +458,12 @@ public class PfcSoundingQuery { for (SoundingLevel level : lSndSiteRecords.get(0).getLevels()) { NcSoundingLayer soundingLy = new NcSoundingLayer(); - soundingLy.setOmega(level.getOmega().floatValue()); + soundingLy.setOmega(level.getOmega()); soundingLy.setTemperature((float)kelvinToCelsius.convert(level.getTemperature())); - soundingLy.setPressure(level.getPressure().floatValue()/100); - soundingLy.setWindU((float)metersPerSecondToKnots.convert(level.getUcWind().floatValue())); // HDF5 data in unit of m/s, convert to Knots 4/12/2012 - soundingLy.setWindV((float)metersPerSecondToKnots.convert(level.getVcWind().floatValue())); - soundingLy.setSpecHumidity(level.getSpecificHumidity().floatValue()); + soundingLy.setPressure(level.getPressure()/100); + soundingLy.setWindU((float)metersPerSecondToKnots.convert(level.getUcWind())); // HDF5 data in unit of m/s, convert to Knots 4/12/2012 + soundingLy.setWindV((float)metersPerSecondToKnots.convert(level.getVcWind())); + soundingLy.setSpecHumidity(level.getSpecificHumidity()); soundLyList.add(soundingLy); } @@ -515,10 +513,8 @@ public class PfcSoundingQuery { List pfs = new ArrayList(); if(sndTypeStr.equals(PfcSndType.GFSSND.toString()) || sndTypeStr.equals(PfcSndType.NAMSND.toString())){ - List fields = new ArrayList(); - List values = new ArrayList(); - List lSndSiteRecords = null; - List operands = new ArrayList(); + Map constraints = new HashMap(); + List lSndSiteRecords = null; MergeSounding ms = new MergeSounding(); @@ -531,61 +527,57 @@ public class PfcSoundingQuery { } latStr=latStr.substring(0, latStr.length()-1);//get rid of last "," lonStr=lonStr.substring(0, lonStr.length()-1);//get rid of last "," - fields.add("location.latitude"); - values.add(latStr); - operands.add("in"); - fields.add("location.longitude"); - values.add(lonStr); - operands.add("in"); + constraints.put("location.latitude", new RequestConstraint(latStr, ConstraintType.IN)); + constraints.put("location.longitude", new RequestConstraint(lonStr, ConstraintType.IN)); } else if(stnIdArr != null){ - fields.add("location.stationId");// the rangeStart field name defined in SoundingSite and decoded modelsounding table String stnIdStr=""; for (String stnStr: stnIdArr){ stnIdStr = stnIdStr+stnStr; stnIdStr= stnIdStr+","; } stnIdStr=stnIdStr.substring(0, stnIdStr.length()-1);//get rid of last "," - values.add(stnIdStr); //rangestart data type defined in SoundingSite is "Date" - operands.add("in"); + // the rangeStart field name defined in SoundingSite and decoded modelsounding table + //rangestart data type defined in SoundingSite is "Date" + constraints.put("location.stationId", new RequestConstraint(stnIdStr, ConstraintType.IN)); } else { return pfs; } - fields.add("dataTime.refTime");// the refTime time field name defined in SoundingSite and decoded modelsounding table - values.add(refTimeStr); //refTime data type defined in SoundingSite is "Date" - operands.add("="); - // the rangeStart field name defined in SoundingSite and decoded modelsounding table. It is forcast time. - fields.add("dataTime.validPeriod.start"); + // the refTime time field name defined in SoundingSite and decoded modelsounding table + //refTime data type defined in SoundingSite is "Date" + constraints.put("dataTime.refTime", new RequestConstraint(refTimeStr)); + String d=""; for (String timeStr: soundingTimeAry){ d = d+timeStr; d= d+","; } d=d.substring(0, d.length()-1);//get rid of last "," - values.add(d); //rangestart data type defined in SoundingSite is "Date" - operands.add("in"); - //for (int i=0; i < fields.size(); i++) { - // System.out.println("getPfcSndDataGeneric: field ="+ fields.get(i) + " value= "+ values.get(i) + " operand= "+operands.get(i)); - //} + // the rangeStart field name defined in SoundingSite and decoded modelsounding table. It is forcast time. + //rangestart data type defined in SoundingSite is "Date" + constraints.put("dataTime.validPeriod.start", new RequestConstraint(d, ConstraintType.IN)); + //for (Entry entry : constraints.entrySet()) { + // System.out.println("getPfcSndDataGeneric: field "+ entry.getKey() + " value "+ entry.getValue().getConstraintValue() + " operand= "+ entry.getValue().getConstraintType()); + //} List parameters = new ArrayList(12); - parameters.addAll(ModelSoundingPointDataTransform.LVL_PARAMETERS); - parameters.add(ModelSoundingPointDataTransform.P_LATITUDE); - parameters.add(ModelSoundingPointDataTransform.P_LONGITUDE); - parameters.add(ModelSoundingPointDataTransform.P_ELEVATION); - parameters.add(ModelSoundingPointDataTransform.P_STATION_ID); - parameters.add(ModelSoundingPointDataTransform.P_STATION_NUMBER); - parameters.add(ModelSoundingPointDataTransform.P_REF_TIME); - parameters.add(ModelSoundingPointDataTransform.P_FORECAST_HOUR); + parameters.addAll(ModelSoundingParameters.LVL_PARAMETERS); + parameters.add(ModelSoundingParameters.LATITUDE); + parameters.add(ModelSoundingParameters.LONGITUDE); + parameters.add(ModelSoundingParameters.ELEVATION); + parameters.add(ModelSoundingParameters.STATION_ID); + parameters.add(ModelSoundingParameters.STATION_NUMBER); + parameters.add(ModelSoundingParameters.REF_TIME); + parameters.add(ModelSoundingParameters.FORECAST_HOUR); try { long t01 = System.currentTimeMillis(); - lSndSiteRecords = ModelSoundingPointDataTransform.getSoundingSites(fields, values, operands, parameters); + lSndSiteRecords = ModelSoundingPointDataTransform.getSoundingSites(constraints, parameters); long t02 = System.currentTimeMillis(); //System.out.println("getPfcSndDataGeneric sounding site record size = "+ lSndSiteRecords.size()+ // " took "+(t02-t01)+ " ms"); - for(SoundingSite sndSite:lSndSiteRecords){ + for (SoundingSite sndSite : lSndSiteRecords) { //set pf data NcSoundingProfile pf = new NcSoundingProfile(); pf.setStationLatitude(sndSite.getLatitude()); @@ -603,12 +595,12 @@ public class PfcSoundingQuery { for (SoundingLevel sndLevel : sndSite.getLevels()) { NcSoundingLayer soundingLy = new NcSoundingLayer(); - soundingLy.setOmega(sndLevel.getOmega().floatValue()); + soundingLy.setOmega(sndLevel.getOmega()); soundingLy.setTemperature((float)kelvinToCelsius.convert(sndLevel.getTemperature())); - soundingLy.setPressure(sndLevel.getPressure().floatValue()/100); - soundingLy.setWindU((float)metersPerSecondToKnots.convert(sndLevel.getUcWind().floatValue())); // HDF5 data in unit of m/s, convert to Knots 4/12/2012 - soundingLy.setWindV((float)metersPerSecondToKnots.convert(sndLevel.getVcWind().floatValue())); - soundingLy.setSpecHumidity(sndLevel.getSpecificHumidity().floatValue()); + soundingLy.setPressure(sndLevel.getPressure()/100); + soundingLy.setWindU((float)metersPerSecondToKnots.convert(sndLevel.getUcWind())); // HDF5 data in unit of m/s, convert to Knots 4/12/2012 + soundingLy.setWindV((float)metersPerSecondToKnots.convert(sndLevel.getVcWind())); + soundingLy.setSpecHumidity(sndLevel.getSpecificHumidity()); soundLyList.add(soundingLy); } Collections.sort(soundLyList,reversePressureComparator()); diff --git a/ncep/gov.noaa.nws.ncep.ui.nsharp/META-INF/MANIFEST.MF b/ncep/gov.noaa.nws.ncep.ui.nsharp/META-INF/MANIFEST.MF index 6984f951dd..a5a74224b5 100644 --- a/ncep/gov.noaa.nws.ncep.ui.nsharp/META-INF/MANIFEST.MF +++ b/ncep/gov.noaa.nws.ncep.ui.nsharp/META-INF/MANIFEST.MF @@ -22,9 +22,7 @@ Require-Bundle: org.eclipse.ui;bundle-version="3.4.1", com.raytheon.viz.core.graphing Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-ActivationPolicy: lazy -Import-Package: com.raytheon.edex.plugin.modelsounding.common, - com.raytheon.edex.plugin.modelsounding.dao, - com.raytheon.uf.common.serialization.comm, +Import-Package: com.raytheon.uf.common.serialization.comm, com.raytheon.uf.common.sounding, com.raytheon.uf.edex.pointdata, com.raytheon.uf.viz.core, From de5d7565e2180f027c232ee09717ac78a9eade8b Mon Sep 17 00:00:00 2001 From: Nate Jensen Date: Tue, 7 Jan 2014 12:38:49 -0600 Subject: [PATCH 11/62] Issue #2359 prevent obnoxious ncep decoder null pointer exceptions Change-Id: I731614a8a6c9ec38bb6c1b29c4d9f6ca5a7c03d7 Former-commit-id: 52293fd15436af7f0f2aa105bf781483d1de2e52 [formerly 2c0e3f05cafa33684760be15a40dc853e210560b] [formerly e509a2883f21e9ed25b9e6de13c270fc523067e2 [formerly 514d0cfecd3eb8c81a6d2120406225856d964c9e]] Former-commit-id: e509a2883f21e9ed25b9e6de13c270fc523067e2 Former-commit-id: 488956a259f06006dc5253c38fb6cc5845c046e1 --- .../nws/ncep/edex/tools/decoder/LatLonLocTbl.java | 7 ++++--- .../plugin/convsigmet/util/ConvSigmetParser.java | 14 +++++++++----- .../ncep/edex/plugin/ffg/decoder/FfgDecoder.java | 5 +++-- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/tools/decoder/LatLonLocTbl.java b/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/tools/decoder/LatLonLocTbl.java index da8833bdb0..a2d41c0eda 100644 --- a/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/tools/decoder/LatLonLocTbl.java +++ b/ncep/gov.noaa.nws.ncep.edex.common/src/gov/noaa/nws/ncep/edex/tools/decoder/LatLonLocTbl.java @@ -11,6 +11,7 @@ * and add xml for VORs and * Intlsig gempak tables. * 30 Sep 2009 3102 jkorman Changed printlns to logging statements. + * 07 Jan 2014 njensen Better error messages * * * @@ -148,11 +149,11 @@ public class LatLonLocTbl { point = new LatLonPoint(vor.getLatitude(), vor.getLongitude(), LatLonPoint.INDEGREES); } else { - logger.debug(" - DID NOT find station ID in vors.xml"); + logger.warn(" - DID NOT find station ID " + navaid + " in vors.xml"); } // If there's an offset direction/bearing, process it - if (location.length() > 3) { + if (location.length() > 3 && point != null) { String u = location.substring(0, location.length() - 3); Pattern p = Pattern.compile("^([0-9]+)\\s*([A-Z]+)"); @@ -176,7 +177,7 @@ public class LatLonLocTbl { return point; } catch (Exception e) { logger.error("[Error decoding location in LatLonLocTbl: " - + location + "]"); + + location + "]", e); return null; } } diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.convsigmet/src/gov/noaa/nws/ncep/edex/plugin/convsigmet/util/ConvSigmetParser.java b/ncep/gov.noaa.nws.ncep.edex.plugin.convsigmet/src/gov/noaa/nws/ncep/edex/plugin/convsigmet/util/ConvSigmetParser.java index 7ee0be193e..d8c478e8bd 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.convsigmet/src/gov/noaa/nws/ncep/edex/plugin/convsigmet/util/ConvSigmetParser.java +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.convsigmet/src/gov/noaa/nws/ncep/edex/plugin/convsigmet/util/ConvSigmetParser.java @@ -13,6 +13,7 @@ * 09/2009 87/114 L. Lin Add latitude/longitude to location table * 07/2011 87/114 F. J. Yen Fix the day of the end time when it is * not the same as the day of the start time. + * Jan 07, 2014 njensen Handle if one or more locations not found in LatLonLocTbl * * * This code has been developed by the SIB for use in the AWIPS2 system. @@ -631,16 +632,19 @@ public class ConvSigmetParser { // Get a latLonPoint for this station ID from "vors" // location table point = LatLonLocTbl.getLatLonPoint(Location, "vors"); - currentLocation.setLatitude(point + if(point != null) { + currentLocation.setLatitude(point .getLatitude(LatLonPoint.INDEGREES)); - currentLocation.setLongitude(point + currentLocation.setLongitude(point .getLongitude(LatLonPoint.INDEGREES)); - currentLocation.setIndex(idxLocation + 1); - idxLocation++; + currentLocation.setIndex(idxLocation + 1); + idxLocation++; - sectionTable.addConvSigmetLocation(currentLocation); + sectionTable.addConvSigmetLocation(currentLocation); + } } + hasLocationLine = (idxLocation > 0); } else { hasLocationLine = false; } diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.ffg/src/gov/noaa/nws/ncep/edex/plugin/ffg/decoder/FfgDecoder.java b/ncep/gov.noaa.nws.ncep.edex.plugin.ffg/src/gov/noaa/nws/ncep/edex/plugin/ffg/decoder/FfgDecoder.java index 8ef4672403..d4f5bc8b9d 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.ffg/src/gov/noaa/nws/ncep/edex/plugin/ffg/decoder/FfgDecoder.java +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.ffg/src/gov/noaa/nws/ncep/edex/plugin/ffg/decoder/FfgDecoder.java @@ -18,6 +18,7 @@ * 05/2010 14 T. Lee Migration to TO11DR11 * 06/2010 14 T. Lee Added traceId output * Aug 30, 2013 2298 rjpeter Make getPluginName abstract + * Jan 07, 2013 njensen Null check on traceId * * * @author T.Lee @@ -61,7 +62,7 @@ public class FfgDecoder extends AbstractDecoder { if (headers != null) { traceId = (String) headers.get("traceId"); - if (traceId.compareTo(lastTraceId) != 0) { + if (traceId != null && traceId.compareTo(lastTraceId) != 0) { System.out .println(" Start decode FFG file: " + traceId + " \n"); lastTraceId = traceId; @@ -148,4 +149,4 @@ public class FfgDecoder extends AbstractDecoder { } return new PluginDataObject[] { record }; } -} \ No newline at end of file +} From f1e731e85717cd2e42ba2705cdc6223f19adf9c7 Mon Sep 17 00:00:00 2001 From: Nate Jensen Date: Tue, 7 Jan 2014 13:25:45 -0600 Subject: [PATCH 12/62] Issue #2359 minor request JVM startup safety Change-Id: I17a5f3217ac5a2f2d53660bdb45a6009c8f27004 Former-commit-id: 459771f66d425cc440916b229da1387e86941a80 [formerly 24560cf307943a2ddce26a5581bc02b688521403] [formerly f83a4736531b4d326450c8801380856f98ebc958 [formerly 3916523cd702e367a6d66743b0517872475a0c36]] Former-commit-id: f83a4736531b4d326450c8801380856f98ebc958 Former-commit-id: ccfb2504cb6ff37909ad2a284b4b353c226805ca --- .../res/spring/warning-request.xml | 2 +- .../res/spring/database-common.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.warning/res/spring/warning-request.xml b/edexOsgi/com.raytheon.edex.plugin.warning/res/spring/warning-request.xml index 1452dd7209..785245cee0 100644 --- a/edexOsgi/com.raytheon.edex.plugin.warning/res/spring/warning-request.xml +++ b/edexOsgi/com.raytheon.edex.plugin.warning/res/spring/warning-request.xml @@ -10,5 +10,5 @@ - + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.database/res/spring/database-common.xml b/edexOsgi/com.raytheon.uf.edex.database/res/spring/database-common.xml index 1e235cb53f..993ed67877 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/res/spring/database-common.xml +++ b/edexOsgi/com.raytheon.uf.edex.database/res/spring/database-common.xml @@ -7,7 +7,7 @@ - + From 0e559a5a6660c86f1baacb43e561672f69598616 Mon Sep 17 00:00:00 2001 From: Roger Ferrel Date: Tue, 7 Jan 2014 14:37:28 -0600 Subject: [PATCH 13/62] Issue #2658 Changes to ACARSPersistObs to ignore cutoff time when allowing archive. Change-Id: I63d6f21ca9fe35b806b321677382460c762c4907 Former-commit-id: b49329067a6752259ba404610f5f73876a674ef6 [formerly 4102c38bc692baa9e78466d77f509e439c6def4c] [formerly 3528dc0eb0e5d2f42edb842d6a8dea9631bb3592 [formerly fb4e61235f1bf65a4b3337514277dcbca2d82f8d]] Former-commit-id: 3528dc0eb0e5d2f42edb842d6a8dea9631bb3592 Former-commit-id: 44af3ecf0a7e2ebdd74d49c0ced09f650d9463a2 --- .../plugin/acarssounding/ACARSPersistObs.java | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.acarssounding/src/com/raytheon/uf/edex/plugin/acarssounding/ACARSPersistObs.java b/edexOsgi/com.raytheon.uf.edex.plugin.acarssounding/src/com/raytheon/uf/edex/plugin/acarssounding/ACARSPersistObs.java index 44ab92fb0f..eb541e45bb 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.acarssounding/src/com/raytheon/uf/edex/plugin/acarssounding/ACARSPersistObs.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.acarssounding/src/com/raytheon/uf/edex/plugin/acarssounding/ACARSPersistObs.java @@ -35,11 +35,12 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; import com.raytheon.uf.common.localization.PathManager; import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.edex.decodertools.time.TimeTools; import com.raytheon.uf.edex.plugin.acarssounding.tools.ACARSSoundingTools; import com.raytheon.uf.edex.plugin.acarssounding.tools.SoundingBuilder; /** - * TODO Add Description + * Class to process ACARS' persistent objects. * *
  * 
@@ -48,6 +49,7 @@ import com.raytheon.uf.edex.plugin.acarssounding.tools.SoundingBuilder;
  * Date         Ticket#    Engineer    Description
  * ------------ ---------- ----------- --------------------------
  * Nov 17, 2009            jkorman     Initial creation
+ * Jan 07, 2014 2658       rferrel     Ignore cut off time when allowing archive data.
  * 
  * 
* @@ -58,11 +60,12 @@ import com.raytheon.uf.edex.plugin.acarssounding.tools.SoundingBuilder; public class ACARSPersistObs { public static final int BASE_DIR_NULL = 1; + public static final int DATA_DIR_NULL = 2; - + public static final int NO_BASE_DIR = 3; + public static final int NO_DATA_DIR = 4; - private Log logger = LogFactory.getLog(getClass()); @@ -73,7 +76,7 @@ public class ACARSPersistObs { // If a required resource is not available, // Set failSafe to true. This will "short circuit" processing. private boolean failSafe = false; - + private int failReason = 0; /** @@ -111,16 +114,23 @@ public class ACARSPersistObs { FileWriter writer = null; try { writer = new FileWriter(out, out.exists()); - long cTime = ACARSSoundingTools.getCutoffTime(ACARSSoundingTools.CUTOFF_HOURS); + + // Value to ignore cut off time when archive allowed. + long cTime = Long.MIN_VALUE; + + if (!TimeTools.allowArchive()) { + cTime = ACARSSoundingTools + .getCutoffTime(ACARSSoundingTools.CUTOFF_HOURS); + } for (PluginDataObject pdo : input) { - if(pdo.getDataTime().getRefTime().getTime() > cTime) { + if (pdo.getDataTime().getRefTime().getTime() > cTime) { try { ACARSRecord acars = (ACARSRecord) pdo; writer.write(String.format( - ACARSSoundingTools.OUT_FMT, acars - .getTimeObs().getTimeInMillis(), + ACARSSoundingTools.OUT_FMT, + acars.getTimeObs().getTimeInMillis(), acars.getDataURI())); } catch (Exception ee) { @@ -152,6 +162,7 @@ public class ACARSPersistObs { /** * Get the failure reason. + * * @return */ public int getFailReason() { @@ -190,9 +201,4 @@ public class ACARSPersistObs { logger.error("Attempting to setup files", e); } } - - public static final void main(String[] args) { - System.out.println(ACARSSoundingTools.getFileName()); - } - } From d477169f0d1920b0e9761e464f317d649c9bcdea Mon Sep 17 00:00:00 2001 From: Nate Jensen Date: Tue, 7 Jan 2014 17:53:43 -0600 Subject: [PATCH 14/62] Issue #2359 change some log statements to debug Change-Id: Ie549917b36268d3f5983f3946701418e7e3b5163 Former-commit-id: b3d6ba3bc9f4074e5b38ec8b85f483db3037d483 [formerly bfa6c60c66684db185fb5abaafebe6328e824aac] [formerly cb52747de2fb7df8dd6a1b803e4b04c67cbdb72b [formerly 146a9cca0ffa68f44068c620a3fa693c46db9031]] Former-commit-id: cb52747de2fb7df8dd6a1b803e4b04c67cbdb72b Former-commit-id: ded9b32ea1371519d7859f2eddf0e61f3aa5c6b2 --- .../com/raytheon/uf/edex/dat/utils/FreezingLevel.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.dat.utils/src/com/raytheon/uf/edex/dat/utils/FreezingLevel.java b/edexOsgi/com.raytheon.uf.edex.dat.utils/src/com/raytheon/uf/edex/dat/utils/FreezingLevel.java index 9b5af71041..1415a59ff2 100644 --- a/edexOsgi/com.raytheon.uf.edex.dat.utils/src/com/raytheon/uf/edex/dat/utils/FreezingLevel.java +++ b/edexOsgi/com.raytheon.uf.edex.dat.utils/src/com/raytheon/uf/edex/dat/utils/FreezingLevel.java @@ -53,8 +53,9 @@ import com.vividsolutions.jts.geom.Coordinate; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * 19Nov 2011 dhladky Initial creation + * 19Nov 2011 dhladky Initial creation * 29 Jan 2013 15729 wkwock fix the algorithm + * Jan 07, 2013 njensen Change some logs to debug * * * @@ -172,7 +173,7 @@ public class FreezingLevel { //do a bi-linear interpolation amount the nearest 4 points value = (p1*p4*value1)+(p2*p4*value0)+(p1*p3*value3)+(p2*p3*value2); - logger.info("bi-linear interpolation: "+value+"-->("+value0+","+value1+ + logger.debug("bi-linear interpolation: "+value+"-->("+value0+","+value1+ ","+value2+","+value3+") at "+xyLoc); } catch (Exception e) { logger.error("No Grib value available....." + modelName + " " @@ -241,7 +242,7 @@ public class FreezingLevel { .get(ktopLevel) - ghValue) * ((273.16 - tValues .get(jtopLevel)) / (tValue - tValues .get(jtopLevel))))) * .00328; - logger.error("***Freezing level: "+fLevel+"=" + logger.debug("***Freezing level: "+fLevel+"=" + "(" + ghValues.get(ktopLevel) + " - ((" + ghValues.get(ktopLevel) + " - " + ghValue + ") * ((273.16 - " @@ -260,7 +261,7 @@ public class FreezingLevel { if (foundValFlag==0) {//this means all tValue are <= 273.16 freezingMap.put(coor, 0.0f); - logger.error("*** FreezingLevel = 0.0"); + logger.debug("*** FreezingLevel = 0.0"); } } @@ -349,7 +350,7 @@ public class FreezingLevel { paramXML.setModelName(model); paramXML.setParameterName(param); String sql = getSQL(interval, model, param, refTime); - logger.info("Freezing level sql="+sql); + logger.debug("Freezing level sql="+sql); GridRecord modelRec = DATUtils.getMostRecentGridRecord(interval, sql, paramXML); From 89c27cc6839f7003fa955fabdbbcf21f23fcc86b Mon Sep 17 00:00:00 2001 From: Ron Anderson Date: Wed, 8 Jan 2014 08:49:32 -0600 Subject: [PATCH 15/62] Issue #2509 Fix merge error in iscMosaic (fix indentation) Change-Id: I1745af1a51d6fffe221168cc8dca217d2f309007 Former-commit-id: b0fa3c6514ced1002e653ba7465f9e67248bd7f3 [formerly 4da9799eaf89353d07d130eb29cd1022201ace72] [formerly 82d3277785ec66a3e9db55fac338f14b5e1c6e9c [formerly 94c97fee9c6925ac9e73530bd18ec03d8cab4a40]] Former-commit-id: 82d3277785ec66a3e9db55fac338f14b5e1c6e9c Former-commit-id: 4fe580f47bcb1d7b3c8feeb4c551617278940623 --- .../utility/edex_static/base/gfe/isc/iscMosaic.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py index 318dea933a..19405007dc 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py @@ -744,7 +744,7 @@ class IscMosaic: grid = self.__validateAdjustWeatherKeys(grid, self.__parmName, tr) - grid = self.__remap(self.__dbwe, grid, inGeoDict, inFillV) + grid = self.__remap(self.__dbwe, grid, inGeoDict, inFillV) # if rate parm, then may need to adjust the values if self.__rateParm and inTimes[i] != tr: From 59fc27dafbd196e30b57d022da69cb3cfb681f4e Mon Sep 17 00:00:00 2001 From: Nate Jensen Date: Wed, 8 Jan 2014 08:56:02 -0600 Subject: [PATCH 16/62] Issue #2581 fix yet another LSR decoding error Change-Id: I74e6d8c3d5c6bf71ebbc3fe32ea93ea688c6bcb5 Former-commit-id: 79c97921486171017ff9e55a373e926a193f287d [formerly 3ac67a743f9bb62419af423fe3dee5ab171cd80b] [formerly 968e51040d7265c2874a3d9be1cdfcdc2d3c5b23 [formerly 3f2c97439a1dbbbc94285343b3b558dead63a0f6]] Former-commit-id: 968e51040d7265c2874a3d9be1cdfcdc2d3c5b23 Former-commit-id: 79836008d76937cd84c991837664f75547d424e8 --- .../raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java b/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java index 2be084a2f0..9e75eac277 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java @@ -54,6 +54,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * Dec 09, 2013 2581 njensen Reuse patterns for efficiency * Check entire time line looking for latlon + * Jan 07, 2013 2581 njensen Check to end of string for source, not a set length * * * @@ -92,8 +93,6 @@ public class LSRParser { private static int SOURCE = 53; // source - private static int SOURCE_LENGTH = 16; // source max length - private static final Pattern LATLON_PTRN = Pattern .compile("((([0-8][0-9]|90).\\d{2,2}[NS]) ++(1?+\\d{2,2}.\\d{2,2}[EW])())"); @@ -419,11 +418,10 @@ public class LSRParser { ss = dateLine.substring(STATE, STATE + STATE_LENGTH).trim(); rpt.setStateLoc(ss); - ss = dateLine.substring(SOURCE, SOURCE + SOURCE_LENGTH) - .trim(); + ss = dateLine.substring(SOURCE).trim(); rpt.setSource(ss); } catch (Exception e) { - logger.error("Bad date " + ss); + logger.error("Bad line " + dateLine); } } } From 3e0ef451a14a821699192062115ed5fc0313db4d Mon Sep 17 00:00:00 2001 From: David Gillingham Date: Wed, 8 Jan 2014 11:02:03 -0600 Subject: [PATCH 17/62] Issue #2657: Update convertCDL2XML for unified grid. Former-commit-id: 476fcb7980d95893c70d7c68306b6a5d1e2afea9 [formerly ed22a86d9f9641b6b34abcba5502ce1c9aa15899] [formerly d6397522c4c65fa9489d6aa8ae5ecb20d0bfee4e [formerly 247536f4d83c7f7de449707916d2950ae74be551]] Former-commit-id: d6397522c4c65fa9489d6aa8ae5ecb20d0bfee4e Former-commit-id: 777c1fba86d4f6aff98fe993fe379747f4f05a5f --- .../impl/src/convertcdl2xml/convertCDL2XML.py | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.tools.cli/impl/src/convertcdl2xml/convertCDL2XML.py b/edexOsgi/com.raytheon.uf.tools.cli/impl/src/convertcdl2xml/convertCDL2XML.py index 1deccb002b..3fe34fd6e0 100644 --- a/edexOsgi/com.raytheon.uf.tools.cli/impl/src/convertcdl2xml/convertCDL2XML.py +++ b/edexOsgi/com.raytheon.uf.tools.cli/impl/src/convertcdl2xml/convertCDL2XML.py @@ -19,7 +19,7 @@ ## ## -# Converts A1 CDL files to A2-formatted gribParamInfo XML files. +# Converts A1 CDL files to A2-formatted gridParamInfo XML files. # # # SOFTWARE HISTORY @@ -27,7 +27,8 @@ # Date Ticket# Engineer Description # ------------ ---------- ----------- -------------------------- # 08/30/12 #1117 dgilling Initial Creation. -# +# 01/08/14 #2657 dgilling Use new unified grid tags, +# code cleanup. # ## @@ -35,7 +36,6 @@ import errno import glob import logging import os -import os.path import re import subprocess import sys @@ -61,7 +61,9 @@ def main(): logger.info("Starting convertCDL2XML...") with open(os.devnull, 'w') as DEVNULL: - if subprocess.call("type ncgen", stdout=DEVNULL, stderr=subprocess.STDOUT, shell=True) != 0: + try: + subprocess.check_call("type ncgen", stdout=DEVNULL, stderr=subprocess.STDOUT, shell=True) + except subprocess.CalledProcessError: logger.error("This script requires the ncgen program to run. Please install before running this script again.") sys.exit(-1) @@ -83,16 +85,12 @@ def main(): def __initLogger(): + logging.basicConfig(format="%(asctime)s %(name)s %(levelname)s: %(message)s", + datefmt="%H:%M:%S", + level=logging.INFO) global logger logger = logging.getLogger("convertCDL2XML") - logger.setLevel(logging.DEBUG) - ch = logging.StreamHandler() - ch.setLevel(logging.INFO) - # Uncomment line below to enable debug-level logging - # ch.setLevel(logging.DEBUG) - formatter = logging.Formatter("%(asctime)s %(name)s %(levelname)s: %(message)s", "%H:%M:%S") - ch.setFormatter(formatter) - logger.addHandler(ch) + def __parseArgs(): parser = UsageArgumentParser.UsageArgumentParser(conflict_handler="resolve") @@ -158,7 +156,9 @@ def __convertFile(cdlFile, outputDir): def __convertToCdf(cdlFile, outputDir): outFile = os.path.join(outputDir, 'tmpFile.nc') cmd = ['ncgen', '-x', '-o', outFile, cdlFile] - if subprocess.call(cmd) != 0: + try: + subprocess.check_call(cmd) + except subprocess.CalledProcessError: logger.error("Could not create temporary CDF file for [" + cdlFile + "].") return None return outFile @@ -271,17 +271,17 @@ def __getParmAtts(ncVar, varName, ncFile): return attrMap def __createXML(cdfData): - root = ET.Element('gribParamInfo', {'xmlns:ns2': 'group'}) - + root = ET.Element('gridParamInfo', {'xmlns:ns2': 'group'}) + fcstTimes = ET.SubElement(root, 'valtimeMINUSreftime') for time in cdfData['valtimeMINUSreftime']: child = ET.SubElement(fcstTimes, 'fcst') child.text = str(time) - + for parm in cdfData['parmNames']: atts = {'xsi:type': "parameterInfo", 'xmlns:xsi': "http://www.w3.org/2001/XMLSchema-instance"} - parmRoot = ET.SubElement(root, 'gribParameterInfo', atts) + parmRoot = ET.SubElement(root, 'gridParameterInfo', atts) for key in ['short_name', 'long_name', 'units', 'udunits', 'uiname', 'valid_range', 'fillValue', 'n3D', 'levelsDesc', 'levels']: if key in cdfData[parm]: if key == 'valid_range': @@ -297,7 +297,7 @@ def __createXML(cdfData): else: child = ET.SubElement(parmRoot, key) child.text = str(cdfData[parm][key]) - + return root if __name__ == '__main__': From 5c85734e026d0724694b733c06e64c8018c01347 Mon Sep 17 00:00:00 2001 From: Brad Gonzales Date: Wed, 8 Jan 2014 13:14:40 -0600 Subject: [PATCH 18/62] Issue #2645 Prevent the recurring time in SubscriptionNotifyTask from being killed by an exception thrown from run. Fix issue where the InMemoryBandwidthBucketAllocationAssociator was not updating the in memory allocation when the db value status was updated. Added RegistryBandwidthRecord to the list of classes to init by HibernateBandwidthDbInit. Updates to hibernate.cfg.xml for Richard. Change-Id: I0eb7b0a34e48f6b8db8065dee45966c48ef38617 Former-commit-id: 02910c2a8c926a6d338bb10ce4ea86f04363660e [formerly 07a4420596112764a32436a762d8aa428418cf00] [formerly 12860c79f9a1a61df1f55e8252da2fb5a7c627af [formerly e0dbe59a7dc418e3b8ed62396b6ef2047b5990fd]] Former-commit-id: 12860c79f9a1a61df1f55e8252da2fb5a7c627af Former-commit-id: be6f12e9c24d507acceb1d43451faa0fa4ea76a3 --- .../esb/conf/db/hibernateConfig/metadata/hibernate.cfg.xml | 4 ++-- .../bandwidth/hibernate/HibernateBandwidthDbInit.java | 2 ++ .../InMemoryBandwidthBucketAllocationAssociator.java | 3 +++ .../retrieval/handlers/SubscriptionNotifyTask.java | 6 ++++++ 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/metadata/hibernate.cfg.xml b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/metadata/hibernate.cfg.xml index 655aba8686..90ad0d838f 100644 --- a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/metadata/hibernate.cfg.xml +++ b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/metadata/hibernate.cfg.xml @@ -62,7 +62,7 @@ 60 ${db.metadata.pool.timeout} - 10 + ${db.metadata.pool.max} 5 ${db.metadata.pool.min} ${db.metadata.pool.max} @@ -71,7 +71,7 @@ org.hibernate.transaction.JDBCTransactionFactory false false - false + false diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/hibernate/HibernateBandwidthDbInit.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/hibernate/HibernateBandwidthDbInit.java index a525a14b2a..76ad17564e 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/hibernate/HibernateBandwidthDbInit.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/hibernate/HibernateBandwidthDbInit.java @@ -44,6 +44,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.dao.SubscriptionRetrievalAttr * Apr 30, 2013 1960 djohnson Extend the generalized DbInit. * Jun 24, 2013 2106 djohnson Add {@link BandwidthBucket} to annotated classes. * Jul 11, 2013 2106 djohnson Add {@link SubscriptionRetrievalAttributes}. + * Jan 08, 2013 2645 bgonzale Added RegistryBandwidthRecord to configuration annotated class list. * * * @author jspinks @@ -82,6 +83,7 @@ public class HibernateBandwidthDbInit extends DbInit implements aConfig.addAnnotatedClass(com.raytheon.uf.edex.datadelivery.bandwidth.dao.SubscriptionRetrieval.class); aConfig.addAnnotatedClass(com.raytheon.uf.edex.datadelivery.bandwidth.dao.BandwidthAllocation.class); aConfig.addAnnotatedClass(com.raytheon.uf.edex.datadelivery.bandwidth.dao.SubscriptionRetrievalAttributes.class); + aConfig.addAnnotatedClass(com.raytheon.uf.edex.datadelivery.bandwidth.registry.RegistryBandwidthRecord.class); return aConfig; } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/InMemoryBandwidthBucketAllocationAssociator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/InMemoryBandwidthBucketAllocationAssociator.java index 27d494d938..b10f659f31 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/InMemoryBandwidthBucketAllocationAssociator.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/InMemoryBandwidthBucketAllocationAssociator.java @@ -43,6 +43,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.dao.IBandwidthDao; * Jun 25, 2013 2106 djohnson Extracted from {@link BandwidthBucket} and {@link RetrievalPlan}. * Dec 17, 2013 2636 bgonzale Prevent stale BandwidthAllocation updates by retrieving * them from the dao before updating. + * Jan 08, 2013 2645 bgonzale Update allocations in the multimap when setting status to PROCESSING. * * * @@ -146,6 +147,8 @@ public class InMemoryBandwidthBucketAllocationAssociator implements // mapping allocations.remove(o.getId(), o); } else { + // update it + allocation = o; allocation.setStatus(RetrievalStatus.PROCESSING); bandwidthDao.createOrUpdate(allocation); } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/handlers/SubscriptionNotifyTask.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/handlers/SubscriptionNotifyTask.java index 110d1247d2..867adfcf9f 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/handlers/SubscriptionNotifyTask.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/handlers/SubscriptionNotifyTask.java @@ -43,6 +43,7 @@ import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecord; * Nov 25, 2012 1268 dhladky Added additional fields to process subscription tracking * Feb 05, 2013 1580 mpduff EventBus refactor. * Mar 05, 2013 1647 djohnson Debug log running message. + * Jan 08, 2013 2645 bgonzale Catch all exceptions in run to prevent the recurring timer from failing. * * * @@ -325,6 +326,11 @@ public class SubscriptionNotifyTask implements Runnable { } catch (DataAccessLayerException e) { statusHandler.handle(Priority.ERROR, "Unable to contact the database", e); + } catch (Exception e) { + statusHandler + .handle(Priority.ERROR, + "Unexpected error during Subscription Notify Task processing...", + e); } } } From 0e081e8ee269ada763b3ba219c0cada56a6dd796 Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Thu, 9 Jan 2014 10:15:48 -0600 Subject: [PATCH 19/62] Issue #2642 - Make shared sub deletions remove the site from the list Former-commit-id: 0cb61d4d50e89d2f20e8cf367852e759bdeefec3 [formerly 6cff7aaf0c9a6390eb55412ec2a93b373957080b] [formerly 4e6b4eaa4c03261a02fd283d278b4364642d1127 [formerly a8f57c338a8a06c6d40842f56c329fd9f215bc5b]] Former-commit-id: 4e6b4eaa4c03261a02fd283d278b4364642d1127 Former-commit-id: fdef5e97e21bc6cb8c0513a5a9274df4f3f3dcfd --- .../subscription/SubscriptionManagerDlg.java | 189 ++++++++++++++---- .../subscription/SubscriptionTableComp.java | 108 +++++++++- 2 files changed, 258 insertions(+), 39 deletions(-) diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionManagerDlg.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionManagerDlg.java index e8030d8188..0b81c53cd4 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionManagerDlg.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionManagerDlg.java @@ -54,6 +54,7 @@ import org.eclipse.swt.widgets.TableColumn; import com.raytheon.uf.common.auth.AuthException; import com.raytheon.uf.common.auth.user.IUser; +import com.raytheon.uf.common.datadelivery.registry.SharedSubscription; import com.raytheon.uf.common.datadelivery.registry.Subscription; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; import com.raytheon.uf.common.datadelivery.request.DataDeliveryPermission; @@ -71,6 +72,7 @@ import com.raytheon.uf.common.site.SiteMap; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.viz.core.VizApp; import com.raytheon.uf.viz.core.auth.UserController; import com.raytheon.uf.viz.core.localization.LocalizationManager; import com.raytheon.uf.viz.datadelivery.actions.DataBrowserAction; @@ -144,6 +146,7 @@ import com.raytheon.viz.ui.presenter.IDisplay; * Nov 06, 2013 2358 mpduff Resurrected file management code. * Nov 08, 2013 2506 bgonzale Removed send notification when a subscription is deleted. * Dec 05, 2013 2570 skorolev Show All subscriptions. + * Jan 08, 2014 2642 mpduff Update dialog for permissions, adding site to shared * * * @author mpduff @@ -253,6 +256,27 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements /** Option to select all groups of subscriptions */ private final String ALL_SUBSCRIPTIONS = "All Subscriptions"; + /** Edit menu */ + private MenuItem editMI; + + /** Copy menu */ + private MenuItem copyMI; + + /** Delete menu */ + private MenuItem deleteMI; + + /** Edit group menu */ + private MenuItem editGroupMI; + + /** Delete group menu */ + private MenuItem deleteGroupMI; + + /** Group menu */ + private MenuItem groupMI; + + /** New menu */ + private MenuItem newMI; + /** * Constructor * @@ -263,7 +287,8 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements public SubscriptionManagerDlg(Shell parent, ISubscriptionManagerFilter filter) { super(parent, SWT.DIALOG_TRIM | SWT.MIN | SWT.RESIZE, - CAVE.INDEPENDENT_SHELL | CAVE.PERSPECTIVE_INDEPENDENT); + CAVE.INDEPENDENT_SHELL | CAVE.PERSPECTIVE_INDEPENDENT + | CAVE.DO_NOT_BLOCK); this.filter = filter; @@ -320,6 +345,7 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements createBottomButtons(); + enableMenus(true); } /* @@ -351,7 +377,7 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements Menu fileMenu = new Menu(menuBar); fileMenuItem.setMenu(fileMenu); - MenuItem newMI = new MenuItem(fileMenu, SWT.NONE); + newMI = new MenuItem(fileMenu, SWT.NONE); newMI.setText("New Subscription..."); newMI.addSelectionListener(new SelectionAdapter() { @Override @@ -360,7 +386,7 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements } }); - MenuItem groupMI = new MenuItem(fileMenu, SWT.NONE); + groupMI = new MenuItem(fileMenu, SWT.NONE); groupMI.setText("New Group..."); groupMI.addSelectionListener(new SelectionAdapter() { @Override @@ -510,7 +536,7 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements Menu editMenu = new Menu(menuBar); editMenuItem.setMenu(editMenu); - MenuItem editMI = new MenuItem(editMenu, SWT.NONE); + editMI = new MenuItem(editMenu, SWT.NONE); editMI.setText("Edit Subscription..."); editMI.addSelectionListener(new SelectionAdapter() { @Override @@ -519,7 +545,7 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements } }); - MenuItem copyMI = new MenuItem(editMenu, SWT.NONE); + copyMI = new MenuItem(editMenu, SWT.NONE); copyMI.setText("Copy Subscription..."); copyMI.addSelectionListener(new SelectionAdapter() { @Override @@ -528,8 +554,8 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements } }); - MenuItem deleteMI = new MenuItem(editMenu, SWT.NONE); - deleteMI.setText("Delete Subscription"); + deleteMI = new MenuItem(editMenu, SWT.NONE); + deleteMI.setText("Delete/Remove from Subscription"); deleteMI.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent event) { @@ -537,7 +563,7 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements } }); - MenuItem editGroupMI = new MenuItem(editMenu, SWT.NONE); + editGroupMI = new MenuItem(editMenu, SWT.NONE); editGroupMI.setText("Edit Group..."); editGroupMI.addSelectionListener(new SelectionAdapter() { @Override @@ -546,7 +572,7 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements } }); - MenuItem deleteGroupMI = new MenuItem(editMenu, SWT.NONE); + deleteGroupMI = new MenuItem(editMenu, SWT.NONE); deleteGroupMI.setText("Delete Group..."); deleteGroupMI.addSelectionListener(new SelectionAdapter() { @Override @@ -607,6 +633,7 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements @Override public void widgetSelected(SelectionEvent event) { handleFilterSelection(); + enableMenus(officeCbo.getText().equals(CURRENT_SITE)); } }); @@ -702,7 +729,6 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements * true for create dialog and false for edit */ private void handleGroupCreate(boolean create) { - final String permission = DataDeliveryPermission.SUBSCRIPTION_CREATE .toString(); IUser user = UserController.getUserObject(); @@ -940,52 +966,78 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements try { if (DataDeliveryServices.getPermissionsService() .checkPermission(user, msg, permission).isAuthorized()) { - String message = null; + ArrayList deleteList = new ArrayList(); + final List subsToDelete = new ArrayList(); + final List subsToUpdate = new ArrayList(); - if (selectionCount > 1) { - message = "Are you sure you want to delete these subscriptions?"; - } else { - message = "Are you sure you want to delete this subscription?"; + for (int idx : tableComp.getTable().getSelectionIndices()) { + SubscriptionManagerRowData removedItem = tableComp + .getSubscriptionData().getDataRow(idx); + Subscription sub = removedItem.getSubscription(); + if (sub instanceof SharedSubscription) { + sub.getOfficeIDs().remove(CURRENT_SITE); + if (sub.getOfficeIDs().size() > 0) { + subsToUpdate.add(sub); + } else { + subsToDelete.add(sub); + } + } else { + subsToDelete.add(removedItem.getSubscription()); + } + + deleteList.add(removedItem); } + + String message = getMessage(subsToDelete, subsToUpdate); int choice = DataDeliveryUtils.showMessage(shell, SWT.YES | SWT.NO, "Delete Confirmation", message); if (choice == SWT.YES) { - ArrayList deleteList = new ArrayList(); - final List subsToDelete = new ArrayList(); - for (int idx : tableComp.getTable().getSelectionIndices()) { - SubscriptionManagerRowData removedItem = tableComp - .getSubscriptionData().getDataRow(idx); - subsToDelete.add(removedItem.getSubscription()); - deleteList.add(removedItem); - } - + // remove the rows from the table tableComp.getSubscriptionData().removeAll(deleteList); - // Should we be using this or the LocalizationManager, or - // UserController.getUserObject().getUniqueID() - final String username = System.getenv().get("LOGNAME"); + final String username = LocalizationManager.getInstance() + .getCurrentUser(); Job job = new Job("Deleting Subscriptions...") { @Override protected IStatus run(IProgressMonitor monitor) { DataDeliveryGUIUtils.markBusyInUIThread(shell); - List exceptions = deleteSubscriptions( - username, subsToDelete); + List exceptions = new ArrayList( + 0); + if (!subsToDelete.isEmpty()) { + exceptions = deleteSubscriptions(username, + subsToDelete); + } + if (!subsToUpdate.isEmpty()) { + exceptions.addAll(updateSubscriptions(username, + subsToUpdate)); + } for (RegistryHandlerException t : exceptions) { statusHandler.handle(Priority.ERROR, "Failed to delete some subscriptions: " + t.getLocalizedMessage(), t); } + return Status.OK_STATUS; } }; job.addJobChangeListener(new JobChangeAdapter() { @Override public void done(IJobChangeEvent event) { + VizApp.runAsync(new Runnable() { + @Override + public void run() { + handleRefresh(); + } + }); + DataDeliveryGUIUtils.markNotBusyInUIThread(shell); } }); job.schedule(); + } else { + // Refresh the table to reset any objects edited + handleRefresh(); } } } catch (AuthException e) { @@ -993,6 +1045,35 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements } } + /** + * Get the delete confirmation message. + * + * @param subsToDelete + * subscription list to delete + * @param subsToUpdate + * subscription list to update + * @return The confirmation message + */ + private String getMessage(List subsToDelete, + List subsToUpdate) { + StringBuilder sb = new StringBuilder(); + if (!subsToDelete.isEmpty()) { + sb.append("The following subscriptions will be deleted:\n"); + for (Subscription sub : subsToDelete) { + sb.append(sub.getName()).append("\n"); + } + } + + if (!subsToUpdate.isEmpty()) { + sb.append("\nThe following subscriptions will be removed:\n"); + for (Subscription sub : subsToUpdate) { + sb.append(sub.getName()).append("\n"); + } + } + + return sb.toString(); + } + /** * Handle filtering the subscription table using combo box selections. */ @@ -1199,16 +1280,12 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements Set sites = siteData.keySet(); officeNames = sites.toArray(new String[sites.size()]); - String[] officeAll = new String[officeNames.length + 1]; - officeAll[0] = ALL; - - System.arraycopy(officeNames, 0, officeAll, 1, officeNames.length); - officeCbo.setItems(officeAll); + officeCbo.setItems(officeNames); String site = CURRENT_SITE; if (this.selectedOffice != null) { - for (String item : officeAll) { + for (String item : officeNames) { if (item.equals(selectedOffice)) { site = item; break; @@ -1319,7 +1396,6 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements */ private List deleteSubscriptions(String username, List subscriptions) { - List exceptions = new ArrayList(); ISubscriptionHandler handler = RegistryObjectHandlers @@ -1333,6 +1409,32 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements return exceptions; } + /** + * Update subscriptions. + * + * @param username + * User updating the subscriptions + * @param subscriptions + * Subscriptions to update + * @return List of errors that occurred + */ + private List updateSubscriptions(String username, + List subscriptions) { + List exceptions = new ArrayList(); + + ISubscriptionHandler handler = RegistryObjectHandlers + .get(ISubscriptionHandler.class); + for (Subscription sub : subscriptions) { + try { + handler.update(sub); + } catch (RegistryHandlerException e) { + exceptions.add(e); + } + } + + return exceptions; + } + /** * {@inheritDoc} */ @@ -1389,4 +1491,19 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements loadGroupNames(); loadOfficeNames(); } + + /** + * Enable/Disable menus. + */ + private void enableMenus(boolean enable) { + copyMI.setEnabled(enable); + deleteGroupMI.setEnabled(enable); + editMI.setEnabled(enable); + copyMI.setEnabled(enable); + deleteMI.setEnabled(enable); + editGroupMI.setEnabled(enable); + groupMI.setEnabled(enable); + newMI.setEnabled(enable); + tableComp.enableMenus(enable); + } } diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionTableComp.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionTableComp.java index e37b1800ea..7d446d14f6 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionTableComp.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionTableComp.java @@ -46,7 +46,9 @@ import org.eclipse.swt.widgets.TableItem; import com.raytheon.uf.common.auth.AuthException; import com.raytheon.uf.common.auth.user.IUser; import com.raytheon.uf.common.datadelivery.registry.PendingSubscription; +import com.raytheon.uf.common.datadelivery.registry.SharedSubscription; 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.ISubscriptionHandler; import com.raytheon.uf.common.datadelivery.request.DataDeliveryPermission; import com.raytheon.uf.common.datadelivery.service.BaseSubscriptionNotificationResponse; @@ -57,6 +59,7 @@ import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.viz.core.VizApp; import com.raytheon.uf.viz.core.auth.UserController; +import com.raytheon.uf.viz.core.localization.LocalizationManager; import com.raytheon.uf.viz.core.notification.NotificationMessage; import com.raytheon.uf.viz.core.notification.NotificationMessageContainsType; import com.raytheon.uf.viz.datadelivery.common.ui.IGroupAction; @@ -106,6 +109,7 @@ import com.raytheon.uf.viz.datadelivery.utils.DataDeliveryUtils.TABLE_TYPE; * Jul 29, 2013 2232 mpduff IndexOutOfBoundsException check. * Jul 26, 2031 2232 mpduff Refactored Data Delivery permissions. * Oct 11, 2013 2386 mpduff Refactor DD Front end. + * Jan 08, 2014 2642 mpduff * @version 1.0 */ @@ -115,6 +119,10 @@ public class SubscriptionTableComp extends TableComp implements IGroupAction { private final IUFStatusHandler statusHandler = UFStatus .getHandler(SubscriptionTableComp.class); + /** Current site constant */ + private final String CURRENT_SITE = LocalizationManager.getInstance() + .getCurrentSite(); + /** Pop up menu object. */ private Menu popupMenu; @@ -152,6 +160,9 @@ public class SubscriptionTableComp extends TableComp implements IGroupAction { /** The subscription type. */ private SubscriptionType subType = SubscriptionType.VIEWER; + /** Currently selected site */ + private boolean currentSiteSelected; + /** * Constructor. * @@ -668,7 +679,7 @@ public class SubscriptionTableComp extends TableComp implements IGroupAction { if (subType == SubscriptionType.MANAGER) { MenuItem editItem = new MenuItem(popupMenu, SWT.PUSH); editItem.setText("Edit..."); - editItem.setEnabled(menuItemsEnabled); + editItem.setEnabled(menuItemsEnabled && this.currentSiteSelected); editItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -679,13 +690,32 @@ public class SubscriptionTableComp extends TableComp implements IGroupAction { // Add the selected row to a subscription group MenuItem groupItem = new MenuItem(popupMenu, SWT.PUSH); groupItem.setText("Add to Group..."); - groupItem.setEnabled(menuItemsEnabled); + groupItem.setEnabled(menuItemsEnabled && this.currentSiteSelected); groupItem.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { handleGroupAdd(); } }); + + /* + * If a single shared sub is selected and another site's subs are + * loaded then allow the user to add their site to the shared sub. + */ + if (table.getSelectionCount() == 1) { + final Subscription sub = getSelectedSubscription(); + if (sub instanceof SharedSubscription) { + MenuItem addToShared = new MenuItem(popupMenu, SWT.PUSH); + addToShared.setText("Add site to shared");// subscription"); + addToShared.setEnabled(true); + addToShared.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + handleAddSiteToShared(sub); + } + }); + } + } } table.setMenu(popupMenu); @@ -786,4 +816,76 @@ public class SubscriptionTableComp extends TableComp implements IGroupAction { ISubscriptionManagerFilter subscriptionFilter) { this.subscriptionFilter = subscriptionFilter; } -} + + /** + * Enable based on the current site selected in the SubscriptionManagerDlg. + * + * @param enable + * true to enable the menu + */ + protected void enableMenus(boolean enable) { + this.currentSiteSelected = enable; + } + + /** + * Add the current site ID to the shared subscription. + * + * @param sub + * The subscription to add the current site + */ + private void handleAddSiteToShared(final Subscription sub) { + final Shell shell = table.getShell(); + Job job = new Job("Updating Subscription...") { + @Override + protected IStatus run(IProgressMonitor monitor) { + try { + DataDeliveryGUIUtils.markBusyInUIThread(shell); + final String permission = DataDeliveryPermission.SUBSCRIPTION_EDIT + .toString(); + IUser user = UserController.getUserObject(); + String msg = user.uniqueId() + + " is not authorized to add site to existing shared subscriptions.\nPermission: " + + permission; + + try { + if (DataDeliveryServices.getPermissionsService() + .checkPermissions(user, msg, permission) + .isAuthorized()) { + sub.getOfficeIDs().add(CURRENT_SITE); + DataDeliveryHandlers.getSubscriptionHandler() + .update(sub); + } + } catch (AuthException e) { + statusHandler.handle(Priority.PROBLEM, + "Error occurred in authorization request", e); + } catch (RegistryHandlerException e) { + statusHandler.handle(Priority.PROBLEM, + e.getLocalizedMessage(), e); + } + + return Status.OK_STATUS; + } catch (Exception e) { + statusHandler.handle(Priority.PROBLEM, + "Unexpected Exception", e); + return Status.CANCEL_STATUS; + } + } + }; + job.addJobChangeListener(new JobChangeAdapter() { + @Override + public void done(IJobChangeEvent event) { + try { + VizApp.runAsync(new Runnable() { + @Override + public void run() { + populateTable(); + } + }); + } finally { + DataDeliveryGUIUtils.markNotBusyInUIThread(shell); + } + } + }); + job.schedule(); + } +} \ No newline at end of file From 1c3b700563ab9954820611e1baf231de4bf49637 Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Wed, 8 Jan 2014 09:10:23 -0600 Subject: [PATCH 20/62] Issue #2643 - Fixed the mouse checking on DD maps Former-commit-id: 7b8964d9b2b2231031d6524bd25b81113a118931 [formerly 4fe2dc76af01d4d8048db83557b1f845320244fd] [formerly 56499a77c3f457ec4aa1c5e443db99330ac345ee [formerly 775e99924e098387e4ca5042823ef20d1a0d2afe]] Former-commit-id: 56499a77c3f457ec4aa1c5e443db99330ac345ee Former-commit-id: 09c5f2939580b2ec2d79d952998c10ce603f0ba9 --- .../viz/datadelivery/rsc/DrawBoxResource.java | 158 +++++++----------- 1 file changed, 65 insertions(+), 93 deletions(-) diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/rsc/DrawBoxResource.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/rsc/DrawBoxResource.java index 6340c8023d..2a80624e48 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/rsc/DrawBoxResource.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/rsc/DrawBoxResource.java @@ -23,7 +23,6 @@ import java.util.ArrayList; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.RGB; -import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.graphics.Region; import org.eclipse.swt.widgets.Shell; @@ -58,6 +57,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Oct 10, 2013 2428 skorolev Fixed memory leak for Regions * Oct 24, 2013 2486 skorolev Fixed an error of editing subset box. * Nov 06, 2013 2486 skorolev Corrected the regions and zoom handling defects. + * Jan 08, 2014 2643 mpduff Changed the way mouse interactions are handled. * * * @@ -124,9 +124,6 @@ public class DrawBoxResource extends /** The x value of the 360 degree longitude line */ private double x360; - /** Map pixel rectangle */ - private Rectangle mapRctgl; - /** * @param resourceData * @param loadProperties @@ -165,7 +162,7 @@ public class DrawBoxResource extends double[] lr = descriptor.worldToPixel(new double[] { c2.x, c2.y }); PixelExtent pe = new PixelExtent(ul[0], lr[0], ul[1], lr[1]); target.drawRect(pe, boxColor, 3, 1); - getMapRectangle(); + setCorners(); } } @@ -190,8 +187,7 @@ public class DrawBoxResource extends double[] point360 = getResourceContainer().translateInverseClick(c); this.x360 = Math.round(point360[0]); - getMapRectangle(); - + setCorners(); } /* @@ -225,18 +221,17 @@ public class DrawBoxResource extends @Override public boolean handleMouseDown(int x, int y, int mouseButton) { if (mouseButton == 1) { - // handle mouse only in the map space - if (mapRctgl.contains(x, y)) { + // translateClick returns null if point is not in the map space + Coordinate coord = getResourceContainer().translateClick(x, y); + if (coord != null) { if (!resizingBox) { x1 = x; y1 = y; - c1 = getResourceContainer().translateClick(x, y); - if (c1 != null) { - c1.x = spatialUtils.convertToEasting(c1.x); - if (spatialUtils.getLongitudinalShift() > 0 - && x >= x360) { - c1.x += 360; - } + c1 = (Coordinate) coord.clone(); + c1.x = spatialUtils.convertToEasting(c1.x); + if (spatialUtils.getLongitudinalShift() > 0 + && x >= x360) { + c1.x += 360; } } } @@ -256,34 +251,31 @@ public class DrawBoxResource extends public boolean handleMouseDownMove(int x, int y, int mouseButton) { if (mouseButton == 1) { drawingBox = true; - // handle mouse only in the map space - if (mapRctgl.contains(x, y)) { + // translateClick returns null if point is not in the map space + Coordinate c = getResourceContainer().translateClick(x, y); + if (c != null) { if (resizingBox) { - Coordinate c = getResourceContainer().translateClick(x, - y); - if (c != null) { - if (boxSide == 0) { - c1.y = c.y; - y1 = y; - } else if (boxSide == 1) { - c1.x = c.x; - x1 = x; - c1.x = spatialUtils.convertToEasting(c1.x); - if (spatialUtils.getLongitudinalShift() > 0 - && x >= x360) { - c1.x += 360; - } - } else if (boxSide == 2) { - c2.y = c.y; - y2 = y; - } else if (boxSide == 3) { - c2.x = c.x; - x2 = x; - c2.x = spatialUtils.convertToEasting(c2.x); - if (spatialUtils.getLongitudinalShift() > 0 - && x >= x360) { - c2.x += 360; - } + if (boxSide == 0) { + c1.y = c.y; + y1 = y; + } else if (boxSide == 1) { + c1.x = c.x; + x1 = x; + c1.x = spatialUtils.convertToEasting(c1.x); + if (spatialUtils.getLongitudinalShift() > 0 + && x >= x360) { + c1.x += 360; + } + } else if (boxSide == 2) { + c2.y = c.y; + y2 = y; + } else if (boxSide == 3) { + c2.x = c.x; + x2 = x; + c2.x = spatialUtils.convertToEasting(c2.x); + if (spatialUtils.getLongitudinalShift() > 0 + && x >= x360) { + c2.x += 360; } } } else { @@ -298,7 +290,6 @@ public class DrawBoxResource extends x2 = x; y2 = y; } - fireBoxChangedEvent(); target.setNeedsRefresh(true); } @@ -347,37 +338,34 @@ public class DrawBoxResource extends @Override public boolean handleMouseUp(int x, int y, int mouseButton) { if (mouseButton == 1) { - // handle mouse only in the map space - if (mapRctgl.contains(x, y)) { + // translateClick returns null if point is not in the map space + Coordinate c = getResourceContainer().translateClick(x, y); + if (c != null) { if (resizingBox) { - Coordinate c = getResourceContainer().translateClick(x, - y); - if (c != null) { - c.x = spatialUtils.convertToEasting(c.x); - if (spatialUtils.getLongitudinalShift() > 0 - && x >= x360) { - c.x += 360; - } - if (boxSide == 0) { - c1.y = c.y; - y1 = y; - } else if (boxSide == 1) { - c1.x = c.x; - x1 = x; - } else if (boxSide == 2) { - c2.y = c.y; - y2 = y; - } else if (boxSide == 3) { - c2.x = c.x; - x2 = x; - } + c.x = spatialUtils.convertToEasting(c.x); + if (spatialUtils.getLongitudinalShift() > 0 + && x >= x360) { + c.x += 360; + } + if (boxSide == 0) { + c1.y = c.y; + y1 = y; + } else if (boxSide == 1) { + c1.x = c.x; + x1 = x; + } else if (boxSide == 2) { + c2.y = c.y; + y2 = y; + } else if (boxSide == 3) { + c2.x = c.x; + x2 = x; } } else { - if (drawingBox) { - x2 = x; - y2 = y; - c2 = getResourceContainer().translateClick(x, y); - if (c2 != null) { + c2 = getResourceContainer().translateClick(x, y); + if (c2 != null) { + if (drawingBox) { + x2 = x; + y2 = y; c2.x = spatialUtils.convertToEasting(c2.x); if (spatialUtils.getLongitudinalShift() > 0 && x >= x360) { @@ -388,14 +376,14 @@ public class DrawBoxResource extends c1 = getResourceContainer().translateClick(x, y); } } + createRegions(); + target.setNeedsRefresh(true); + fireBoxChangedEvent(); } - createRegions(); - target.setNeedsRefresh(true); - fireBoxChangedEvent(); drawingBox = false; } else if (mouseButton == 2) { super.handleMouseUp(x, y, 1); - getMapRectangle(); + setCorners(); } return true; } @@ -554,23 +542,7 @@ public class DrawBoxResource extends /** * Get map's rectangle in pixels after changing. */ - private void getMapRectangle() { - Coordinate top = new Coordinate(); - top.x = spatialUtils.getUpperLeft().x; - top.y = spatialUtils.getUpperLeft().y; - double[] pointTop = getResourceContainer().translateInverseClick(top); - int xTop = (int) Math.round(pointTop[0]); - int yTop = (int) Math.round(pointTop[1]); - - Coordinate bot = new Coordinate(); - bot.x = spatialUtils.getLowerRight().x; - bot.y = spatialUtils.getLowerRight().y; - double[] pointBot = getResourceContainer().translateInverseClick(bot); - int xBottom = (int) Math.round(pointBot[0]); - int yBottom = (int) Math.round(pointBot[1]); - - mapRctgl = new Rectangle(xTop, yTop, (xBottom - xTop), (yBottom - yTop)); - + private void setCorners() { // Re-calculate regions if ((c1 != null) && (c2 != null)) { double[] luBox = getResourceContainer().translateInverseClick(c1); From 05b6508299663df446f1aa2df846f144f730ab72 Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Tue, 7 Jan 2014 12:18:06 -0600 Subject: [PATCH 21/62] Issue #2636 - Fix data set availability offset. Now uses average offset of last 10 data set matches Former-commit-id: 30b65a4fe785033dc6f3472645370a96a23d1040 [formerly 183ca614df3da7aa1cd213b20fbe6db4e3d4d260] [formerly a264cb06a167e022e8038a24ddafa649d1b3feeb [formerly b841e795f2a18bf902ec373c9f79b191db177fde]] Former-commit-id: a264cb06a167e022e8038a24ddafa649d1b3feeb Former-commit-id: 4620b69f08c8355989bfd2c12c4eae813aaf350e --- .../registry/DataSetMetaData.java | 30 +++- .../registry/GriddedDataSetMetaData.java | 45 ++++++ .../bandwidth-datadelivery-edex-impl.xml | 6 - .../res/spring/bandwidth-datadelivery.xml | 1 - .../bandwidth/IBandwidthManager.java | 4 +- .../SimpleSubscriptionAggregator.java | 15 +- .../util/AveragingAvailablityCalculator.java | 122 +++++++++++----- .../bandwidth/util/BandwidthDaoUtil.java | 23 ++- .../bandwidth/util/BandwidthUtil.java | 38 ++--- .../util/IDataSetAvailablityCalculator.java | 37 ----- .../bandwidth/util/NameProviderKey.java | 117 +++++++++++++++ ...roviderDataTypeAvailabilityCalculator.java | 128 ---------------- .../util/SimpleAvailablityCalculator.java | 42 ------ .../opendap/OpenDAPMetaDataParser.java | 4 +- .../uf/edex/registry/ebxml/dao/DbInit.java | 5 +- .../AveragingAvailabilityCalculatorTest.java | 138 ++++++++++++++++++ .../bandwidth/util/BandwidthDaoUtilTest.java | 30 ++-- ...derDataTypeAvailabilityCalculatorTest.java | 111 -------------- 18 files changed, 476 insertions(+), 420 deletions(-) delete mode 100644 edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/IDataSetAvailablityCalculator.java create mode 100644 edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/NameProviderKey.java delete mode 100644 edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/ProviderDataTypeAvailabilityCalculator.java delete mode 100644 edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/SimpleAvailablityCalculator.java create mode 100644 tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/AveragingAvailabilityCalculatorTest.java delete mode 100644 tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/ProviderDataTypeAvailabilityCalculatorTest.java diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/DataSetMetaData.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/DataSetMetaData.java index 38845a22d5..a862c7908d 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/DataSetMetaData.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/DataSetMetaData.java @@ -41,13 +41,15 @@ import com.raytheon.uf.common.time.util.ImmutableDate; * Oct 16, 2012 0726 djohnson Override {@link #toString()}. * Nov 19, 2012 1166 djohnson Clean up JAXB representation of registry objects. * Sept, 30 2013 1797 dhladky Made generic based on Time + * Dec 20, 2013 2636 mpduff Add a dataset availability offset * * * @author dhladky * @version 1.0 */ @XmlAccessorType(XmlAccessType.NONE) -@XmlSeeAlso({ GriddedDataSetMetaData.class, OpenDapGriddedDataSetMetaData.class, PointDataSetMetaData.class }) +@XmlSeeAlso({ GriddedDataSetMetaData.class, + OpenDapGriddedDataSetMetaData.class, PointDataSetMetaData.class }) @RegistryObject({ "url" }) public abstract class DataSetMetaData { public static final String DATE_SLOT = "date"; @@ -55,13 +57,12 @@ public abstract class DataSetMetaData { public static final String DATA_SET_NAME_SLOT = "dataSetName"; public static final String PROVIDER_NAME_SLOT = "providerName"; - + /** * Compares the two instances of {@link DataSetMetaData} by their applicable * date fields. */ - public static Comparator> DATE_COMPARATOR = new Comparator>() - { + public static Comparator> DATE_COMPARATOR = new Comparator>() { @Override public int compare(DataSetMetaData o1, DataSetMetaData o2) { @@ -109,6 +110,11 @@ public abstract class DataSetMetaData { @DynamicSerializeElement private ImmutableDate date; + @XmlElement + @DynamicSerializeElement + @SlotAttribute + protected int availabilityOffset; + public DataSetMetaData() { } @@ -159,7 +165,6 @@ public abstract class DataSetMetaData { public void setProviderName(String providerName) { this.providerName = providerName; } - /** * Get the date this object starts on. In the gridded world, this would @@ -182,6 +187,21 @@ public abstract class DataSetMetaData { this.date = date; } + /** + * @return the availabilityOffset + */ + public int getAvailabilityOffset() { + return availabilityOffset; + } + + /** + * @param availabilityOffset + * the availabilityOffset to set + */ + public void setAvailabilityOffset(int availabilityOffset) { + this.availabilityOffset = availabilityOffset; + } + @Override public boolean equals(Object obj) { if (obj instanceof DataSetMetaData) { diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/GriddedDataSetMetaData.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/GriddedDataSetMetaData.java index ebd2a54edf..b36cb9905e 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/GriddedDataSetMetaData.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/GriddedDataSetMetaData.java @@ -27,6 +27,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Aug 20, 2012 0743 djohnson Store cycle in a slot. * Nov 19, 2012 1166 djohnson Clean up JAXB representation of registry objects. * Sept 30, 2013 1797 dhladky Generics + * Dec 20, 2013 2636 mpduff Add equals/hashcode. * * * @@ -85,4 +86,48 @@ public abstract class GriddedDataSetMetaData extends return cycle; } + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = super.hashCode(); + result = prime * result + cycle; + result = prime * result + + ((levelTypes == null) ? 0 : levelTypes.hashCode()); + return result; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!super.equals(obj)) { + return false; + } + if (!(obj instanceof GriddedDataSetMetaData)) { + return false; + } + GriddedDataSetMetaData other = (GriddedDataSetMetaData) obj; + if (cycle != other.cycle) { + return false; + } + if (levelTypes == null) { + if (other.levelTypes != null) { + return false; + } + } else if (!levelTypes.equals(other.levelTypes)) { + return false; + } + return true; + } } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl.xml index 7881c85f3a..2d4d87e504 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl.xml @@ -50,10 +50,4 @@
- - - - - \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery.xml index 1b40381388..2dbdd53ad3 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery.xml @@ -49,7 +49,6 @@ - diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/IBandwidthManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/IBandwidthManager.java index 11e708c7c2..8224ebac21 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/IBandwidthManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/IBandwidthManager.java @@ -42,7 +42,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.interfaces.ISubscriptionAggre * Oct 30, 2012 1286 djohnson Initial creation * Jul 10, 2013 2106 djohnson Remove EDEX instance specific methods. * 10/23/2013 2385 bphillip Change schedule method to scheduleAdhoc - * + * Jan 06, 2014 2636 mpduff Update javadoc * * * @author djohnson @@ -52,7 +52,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.interfaces.ISubscriptionAggre public interface IBandwidthManager { /** - * Schedule all cycles of a Subscription. + * Schedule all retrievals of a Subscription. * * @param subscription * @return A list of bandwidth allocations that are not scheduled diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/processing/SimpleSubscriptionAggregator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/processing/SimpleSubscriptionAggregator.java index 1afc2e32b8..44dbddb54b 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/processing/SimpleSubscriptionAggregator.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/processing/SimpleSubscriptionAggregator.java @@ -4,6 +4,7 @@ import java.util.ArrayList; import java.util.List; import com.raytheon.uf.common.datadelivery.registry.Subscription; +import com.raytheon.uf.common.registry.handler.RegistryHandlerException; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; @@ -32,7 +33,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthUtil; * Nov 20, 2012 1286 djohnson Change some logging to debug. * Jun 13, 2013 2095 djohnson No need to query the database, we are only receiving new bandwidth subscriptions. * Jul 11, 2013 2106 djohnson aggregate() signature changed. - * + * Jan 06, 2014 2636 mpduff Changed how data set offset is set. * * * @author jspinks @@ -80,8 +81,16 @@ public class SimpleSubscriptionAggregator implements ISubscriptionAggregator { subscriptionRetrieval.setSubscriptionLatency(BandwidthUtil .getSubscriptionLatency(sub)); - subscriptionRetrieval.setDataSetAvailablityDelay(BandwidthUtil - .getDataSetAvailablityDelay(sub)); + + int offset = 0; + try { + offset = BandwidthUtil.getDataSetAvailablityOffset(sub, + subDao.getBaseReferenceTime()); + } catch (RegistryHandlerException e) { + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), + e); + } + subscriptionRetrieval.setDataSetAvailablityDelay(offset); subscriptionRetrievals.add(subscriptionRetrieval); diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/AveragingAvailablityCalculator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/AveragingAvailablityCalculator.java index f46717d6ed..1f13c14edf 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/AveragingAvailablityCalculator.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/AveragingAvailablityCalculator.java @@ -3,11 +3,20 @@ */ package com.raytheon.uf.edex.datadelivery.bandwidth.util; +import java.util.Calendar; import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import com.raytheon.uf.common.datadelivery.registry.DataSetMetaData; +import com.raytheon.uf.common.datadelivery.registry.GriddedDataSetMetaData; import com.raytheon.uf.common.datadelivery.registry.Subscription; -import com.raytheon.uf.edex.datadelivery.bandwidth.dao.BandwidthDataSetUpdate; -import com.raytheon.uf.edex.datadelivery.bandwidth.dao.IBandwidthDao; +import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; +import com.raytheon.uf.common.registry.handler.RegistryHandlerException; +import com.raytheon.uf.common.util.CollectionUtil; /** * @@ -20,67 +29,102 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.dao.IBandwidthDao; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 9, 2012 1286 djohnson Add SW history. + * Jan 06, 2014 2636 mpduff Changed how offset is determined. * * * * @author djohnson * @version 1.0 */ -public class AveragingAvailablityCalculator implements - IDataSetAvailablityCalculator { +public class AveragingAvailablityCalculator { + LoadingCache> cache = CacheBuilder + .newBuilder().maximumSize(1000) + .expireAfterWrite(30, TimeUnit.MINUTES) + .build(new CacheLoader>() { + @Override + public List load(NameProviderKey key) + throws RegistryHandlerException { + return handler.getByDataSet(key.getName(), + key.getProvider()); + } + }); - private static final int DATASET_AVAILABLE_DEFAULT = 60; - - private final IBandwidthDao bandwidthDao; + private final IDataSetMetaDataHandler handler; /** * Constructor. * - * @param dao - * dao + * @param handler + * The DataSetMetaDataHandler */ - public AveragingAvailablityCalculator(IBandwidthDao dao) { - this.bandwidthDao = dao; + public AveragingAvailablityCalculator(IDataSetMetaDataHandler handler) { + this.handler = handler; } /** - * Retrieve the DataSet availability latency for a particular dataset. This - * time encompasses the number of minutes after the dataset base time that - * data is typically available. + * Get the average dataset offset for the provided subscription * - * @param providerName - * The provider name for the dataset. + * @param subscription + * The subscription * - * @param dataSetName - * The dataset name. + * @param referenceTime + * The base reference time * * @return The number of minutes of latency to expect. + * @throws RegistryHandlerException */ - @Override - public int getDataSetAvailablityDelay(Subscription subscription) { - // Use a default of 60 minutes.. - int delay = DATASET_AVAILABLE_DEFAULT; - List recs = bandwidthDao - .getBandwidthDataSetUpdate(subscription.getProvider(), - subscription.getDataSetName()); + public int getDataSetAvailablityOffset(Subscription subscription, + Calendar referenceTime) throws RegistryHandlerException { + int offset = 0; + NameProviderKey key = new NameProviderKey( + subscription.getDataSetName(), subscription.getProvider()); + List records = null; - long totalLatency = 0; - int recordcount = 0; - // Average out a maximum of twenty records - for (BandwidthDataSetUpdate rec : recs) { - long diff = (rec.getUpdateTime().getTimeInMillis() - rec - .getDataSetBaseTime().getTimeInMillis()) / 60000; - // Make sure some funky dates don't mess with the average.. - totalLatency += Math.max(0, diff); - if (recordcount++ > 20) { - break; + try { + records = cache.get(key); + if (!CollectionUtil.isNullOrEmpty(records)) { + DataSetMetaData md = records.get(0); + if (md instanceof GriddedDataSetMetaData) { + offset = getOffsetForGrid(records, referenceTime); + } + // No availability delay for point data. + } + } catch (ExecutionException e) { + throw new RegistryHandlerException(e); + } + + return offset; + } + + /** + * Get the availability offset for gridded data. + * + * @param records + * List of DataSetMetaData records + * @param referenceTime + * The data's base reference time + * @return The offset in minutes + */ + private int getOffsetForGrid(List records, + Calendar referenceTime) { + int cycle = referenceTime.get(Calendar.HOUR_OF_DAY); + int count = 0; + int total = 0; + for (DataSetMetaData md : records) { + GriddedDataSetMetaData gmd = (GriddedDataSetMetaData) md; + if (gmd.getCycle() == cycle) { + total += gmd.getAvailabilityOffset(); + count++; + if (count == 10) { + break; + } } } - // Make sure we did some kind of calculation. - if (totalLatency > 0) { - delay = (int) (totalLatency / recordcount); + if (count > 0) { + return total / count; } - return delay; + + return 0; } } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java index 3d8882a343..229ab109cf 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java @@ -76,7 +76,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.retrieval.RetrievalStatus; * Nov 20, 2013 2448 bgonzale Fix for subscription start time set to first cycle time. * Fix for subscription end time set to end of day. * Dec 02, 2013 2545 mpduff Fix for delay starting retrievals, execute adhoc upon subscribing. - * + * Dec 20, 2013 2636 mpduff Fix dataset offset. * * * @author djohnson @@ -297,18 +297,27 @@ public class BandwidthDaoUtil { // Now walk the subscription times and throw away anything outside the // plan hours, taking into account the availability delay... - int availabilityDelay = BandwidthUtil - .getDataSetAvailablityDelay(subscription); + int availabilityOffset = 0; Iterator itr = subscriptionTimes.iterator(); while (itr.hasNext()) { - + availabilityOffset = 0; Calendar time = itr.next(); - Calendar withAvailabilityDelay = TimeUtil.newCalendar(time); - withAvailabilityDelay.add(Calendar.MINUTE, availabilityDelay); + + try { + availabilityOffset = BandwidthUtil.getDataSetAvailablityOffset( + subscription, time); + } catch (RegistryHandlerException e) { + // Error occurred querying the registry. Log and continue on + statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), + e); + } + + Calendar withAvailabilityOffset = TimeUtil.newCalendar(time); + withAvailabilityOffset.add(Calendar.MINUTE, availabilityOffset); // We allow base reference times that are still possible to retrieve // within the availability window to be included - if (withAvailabilityDelay.before(planStart) || time.after(planEnd)) { + if (withAvailabilityOffset.before(planStart) || time.after(planEnd)) { itr.remove(); } } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthUtil.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthUtil.java index 26bf352156..eaaa7be9f5 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthUtil.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthUtil.java @@ -6,6 +6,8 @@ import java.util.Date; import com.raytheon.uf.common.datadelivery.registry.DataSetMetaData; import com.raytheon.uf.common.datadelivery.registry.DataType; import com.raytheon.uf.common.datadelivery.registry.Subscription; +import com.raytheon.uf.common.datadelivery.registry.handlers.DataDeliveryHandlers; +import com.raytheon.uf.common.registry.handler.RegistryHandlerException; import com.raytheon.uf.common.serialization.SerializationException; import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.edex.datadelivery.bandwidth.dao.BandwidthDataSetUpdate; @@ -29,6 +31,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.dao.BandwidthSubscription; * Jun 25, 2013 2106 djohnson CheapClone was cheap in ease, not performance. * Jul 11, 2013 2106 djohnson Use SubscriptionPriority enum. * Oct 30, 2013 2448 dhladky Moved methods to TimeUtil. + * Dec 20, 2013 2636 mpduff Changed dataset delay to offset. * * * @@ -49,15 +52,15 @@ public class BandwidthUtil { // algorithms can be injected with Spring.. private static final BandwidthUtil instance = new BandwidthUtil(); - // An implementation of the data set availability delay calculator - // injected with Spring. - private IDataSetAvailablityCalculator dataSetAvailabilityCalculator; + private final AveragingAvailablityCalculator dataSetAvailabilityCalculator; private ISubscriptionLatencyCalculator subscriptionLatencyCalculator; private ISubscriptionRescheduleStrategy subscriptionRescheduleStrategy; private BandwidthUtil() { + dataSetAvailabilityCalculator = new AveragingAvailablityCalculator( + DataDeliveryHandlers.getDataSetMetaDataHandler()); }; public static int getSubscriptionLatency(Subscription subscription) { @@ -71,7 +74,7 @@ public class BandwidthUtil { public static Calendar max(Date lhs, Calendar rhs) { return max(TimeUtil.newCalendar(lhs), rhs); } - + public static Calendar max(Calendar lhs, Calendar rhs) { Calendar calendar = null; if (lhs != null && rhs != null) { @@ -112,22 +115,21 @@ public class BandwidthUtil { } /** - * Calculate the number of minutes of delay between a Subscriptions base + * Calculate the number of minutes of offset between a Subscriptions base * reference time and the time the data should be available. * * @param subscription * The Subscription Object to obtain the availability for. - * - * @return The delay in minutes. + * @param referenceTime + * Data reference time + * @return The offset in minutes. + * @throws RegistryHandlerException */ - public static int getDataSetAvailablityDelay(Subscription subscription) { + public static int getDataSetAvailablityOffset( + Subscription subscription, Calendar referenceTime) + throws RegistryHandlerException { return instance.dataSetAvailabilityCalculator - .getDataSetAvailablityDelay(subscription); - } - - public void setDataSetAvailabilityCalculator( - IDataSetAvailablityCalculator dataSetAvailabilityCalculator) { - this.dataSetAvailabilityCalculator = dataSetAvailabilityCalculator; + .getDataSetAvailablityOffset(subscription, referenceTime); } /** @@ -268,16 +270,16 @@ public class BandwidthUtil { .subscriptionRequiresReschedule(subscription, old); } - /** * Sets up the activePeriod Start/End to plan Start/End calendar */ - public static Calendar planToPeriodCompareCalendar(Calendar planCalendar, Calendar activePeriod) { - + public static Calendar planToPeriodCompareCalendar(Calendar planCalendar, + Calendar activePeriod) { + Calendar cal = TimeUtil.newCalendar(planCalendar); cal.set(Calendar.MONTH, activePeriod.get(Calendar.MONTH)); cal.set(Calendar.DAY_OF_MONTH, activePeriod.get(Calendar.DAY_OF_MONTH)); - + return cal; } } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/IDataSetAvailablityCalculator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/IDataSetAvailablityCalculator.java deleted file mode 100644 index e01dc6fa88..0000000000 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/IDataSetAvailablityCalculator.java +++ /dev/null @@ -1,37 +0,0 @@ -/** - * - */ -package com.raytheon.uf.edex.datadelivery.bandwidth.util; - -import com.raytheon.uf.common.datadelivery.registry.Subscription; - -/** - * Interface for a pluggable implementation for calculating a data sets - * availability. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Nov 9, 2012  1286      djohnson     Added SW histor, rename to comply with AWIPS standards.
- * 
- * 
- * - * @author jspinks - * @version 1.0 - */ -public interface IDataSetAvailablityCalculator { - - /** - * Calculate the number of minutes of delay between a Subscriptions base - * reference time and the time the data should be available. - * - * @param subscription - * The Subscription Object to obtain the availability for. - * - * @return The delay in minutes. - */ - int getDataSetAvailablityDelay(Subscription subscription); -} diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/NameProviderKey.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/NameProviderKey.java new file mode 100644 index 0000000000..b056948a7b --- /dev/null +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/NameProviderKey.java @@ -0,0 +1,117 @@ +/** + * 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.datadelivery.bandwidth.util; + +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; + +/** + * Object holding name and provider Strings to act as a hash key. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Dec 20, 2013   2636     mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ + +public class NameProviderKey { + + private final String name; + + private final String provider; + + /** + * Constructor. + * + * @param name + * The name + * @param provider + * The provider + */ + public NameProviderKey(String name, String provider) { + this.name = name; + this.provider = provider; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @return the provider + */ + public String getProvider() { + return provider; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return this.name + " " + this.provider; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + HashCodeBuilder builder = new HashCodeBuilder(); + builder.append(name); + builder.append(provider); + + return builder.hashCode(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + if (!(obj instanceof NameProviderKey)) { + return false; + } + NameProviderKey other = (NameProviderKey) obj; + + EqualsBuilder builder = new EqualsBuilder(); + builder.append(this.name, other.getName()); + builder.append(this.provider, other.getProvider()); + + return builder.isEquals(); + } +} diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/ProviderDataTypeAvailabilityCalculator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/ProviderDataTypeAvailabilityCalculator.java deleted file mode 100644 index ea7562b3dd..0000000000 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/ProviderDataTypeAvailabilityCalculator.java +++ /dev/null @@ -1,128 +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.edex.datadelivery.bandwidth.util; - -import java.util.concurrent.ExecutionException; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import com.google.common.eventbus.Subscribe; -import com.raytheon.uf.common.datadelivery.registry.DataDeliveryRegistryObjectTypes; -import com.raytheon.uf.common.datadelivery.registry.DataType; -import com.raytheon.uf.common.datadelivery.registry.Provider; -import com.raytheon.uf.common.datadelivery.registry.ProviderType; -import com.raytheon.uf.common.datadelivery.registry.Subscription; -import com.raytheon.uf.common.datadelivery.registry.handlers.IProviderHandler; -import com.raytheon.uf.common.event.EventBus; -import com.raytheon.uf.common.registry.event.RegistryEvent; -import com.raytheon.uf.common.registry.handler.RegistryHandlerException; - -/** - * Uses provider configured values for the availability delay. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jun 05, 2013 2038       djohnson     Initial creation
- * 
- * 
- * - * @author djohnson - * @version 1.0 - */ - -public class ProviderDataTypeAvailabilityCalculator implements - IDataSetAvailablityCalculator { - - private static final Provider PROVIDER_NOT_FOUND = new Provider(); - - private final LoadingCache providerCache; - - /** - * Constructor. - */ - public ProviderDataTypeAvailabilityCalculator( - final IProviderHandler providerHandler) { - - // TODO: This should probably be moved inside the registry handler - // itself - this.providerCache = CacheBuilder.newBuilder().build( - new CacheLoader() { - @Override - public Provider load(String key) - throws RegistryHandlerException { - Provider provider = providerHandler - .getByName(key); - if (provider == null) { - provider = PROVIDER_NOT_FOUND; - } - return provider; - } - }); - - EventBus.register(this); - } - - /** - * {@inheritDoc} - */ - @Override - public int getDataSetAvailablityDelay(Subscription subscription) { - final String providerName = subscription.getProvider(); - final DataType dataType = subscription.getDataSetType(); - - try { - Provider provider = this.providerCache.get(providerName); - - if (provider == PROVIDER_NOT_FOUND) { - throw new IllegalArgumentException( - "No availability delay registered for provider " - + providerName + " for data type " + dataType); - } - - final ProviderType providerType = provider - .getProviderType(dataType); - - if (providerType == null) { - throw new IllegalArgumentException( - "No availability delay registered for provider " - + providerName + " for data type " + dataType); - } - return providerType.getAvailabilityDelay(); - } catch (ExecutionException e) { - throw new IllegalStateException( - "Exception querying for the provider!", e); - } - } - - @Subscribe - public void registryEventListener(RegistryEvent re) { - final String objectType = re.getObjectType(); - - // If a provider event happens then expire the entire cache - if (DataDeliveryRegistryObjectTypes.PROVIDER.equals(objectType)) { - providerCache.invalidateAll(); - } - } -} diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/SimpleAvailablityCalculator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/SimpleAvailablityCalculator.java deleted file mode 100644 index bd02d5e650..0000000000 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/SimpleAvailablityCalculator.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * - */ -package com.raytheon.uf.edex.datadelivery.bandwidth.util; - -import com.raytheon.uf.common.datadelivery.registry.Subscription; - -/** - * @author jspinks - * - */ -public class SimpleAvailablityCalculator implements - IDataSetAvailablityCalculator { - - private int delay; - - public int getDelay() { - return delay; - } - - public void setDelay(int delay) { - this.delay = delay; - } - - /** - * Retrieve the DataSet availability latency for a particular dataset. This - * time encompasses the number of minutes after the dataset base time that - * data is typically available. - * - * @param providerName - * The provider name for the dataset. - * - * @param dataSetName - * The dataset name. - * - * @return The number of minutes of latency to expect. - */ - @Override - public int getDataSetAvailablityDelay(Subscription subscription) { - return delay; - } -} diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java index a0e7d74242..f1bd4d778e 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java @@ -94,7 +94,7 @@ import dods.dap.DAS; * Jan 24, 2013 1527 dhladky Changed 0DEG to FRZ * Sept 25, 2013 1797 dhladky separated time from gridded time * Oct 10, 2013 1797 bgonzale Refactored registry Time objects. - * Dec 18, 2013 2636 mpduff Calculate a data availability delay for the dataset. + * Dec 18, 2013 2636 mpduff Calculate a data availability delay for the dataset and dataset meta data. * * * @@ -267,6 +267,7 @@ class OpenDAPMetaDataParser extends MetaDataParser { long now = TimeUtil.newGmtCalendar().getTimeInMillis(); long offset = (now - startMillis) / TimeUtil.MILLIS_PER_MINUTE; dataSet.setAvailabilityOffset((int) offset); + gdsmd.setAvailabilityOffset((int) offset); if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { statusHandler.debug("Dataset Name: " @@ -776,5 +777,4 @@ class OpenDAPMetaDataParser extends MetaDataParser { return parsedMetadatas; } - } diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/dao/DbInit.java b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/dao/DbInit.java index ac663cba3d..1f7fcff981 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/dao/DbInit.java +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/dao/DbInit.java @@ -90,6 +90,7 @@ import com.raytheon.uf.edex.registry.ebxml.init.RegistryInitializedListener; * they can't fail the ebxml schema creation/population. * Nov 01, 2013 2361 njensen Use EbxmlJaxbManager instead of SerializationUtil * Nov 14, 2013 2552 bkowal EbxmlJaxbManager is now accessed via getInstance + * Dec 20, 2013 2636 mpduff Set initialized to true before postInitialized is called. * * * @author bphillip @@ -346,9 +347,9 @@ public class DbInit extends com.raytheon.uf.edex.database.init.DbInit implements statusHandler.fatal("Error initializing EBXML database!", e); } - myself.postInitDb(); - INITIALIZED = true; + + myself.postInitDb(); } } diff --git a/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/AveragingAvailabilityCalculatorTest.java b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/AveragingAvailabilityCalculatorTest.java new file mode 100644 index 0000000000..9f2f3e146f --- /dev/null +++ b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/AveragingAvailabilityCalculatorTest.java @@ -0,0 +1,138 @@ +/** + * 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.datadelivery.bandwidth.util; + +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +import org.junit.Before; +import org.junit.Test; + +import com.raytheon.uf.common.datadelivery.registry.DataSetMetaData; +import com.raytheon.uf.common.datadelivery.registry.GriddedDataSetMetaData; +import com.raytheon.uf.common.datadelivery.registry.OpenDapGriddedDataSetMetaData; +import com.raytheon.uf.common.datadelivery.registry.PointDataSetMetaData; +import com.raytheon.uf.common.datadelivery.registry.SiteSubscription; +import com.raytheon.uf.common.datadelivery.registry.Subscription; +import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; +import com.raytheon.uf.common.registry.handler.RegistryHandlerException; +import com.raytheon.uf.common.time.util.ImmutableDate; +import com.raytheon.uf.common.time.util.TimeUtil; +import com.raytheon.uf.common.util.registry.RegistryException; + +/** + * Test dataset offset average calculations. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Dec 20, 2013   2636     mpduff      Initial creation
+ * 
+ * 
+ * + * @author mpduff + * @version 1.0 + */ + +public class AveragingAvailabilityCalculatorTest { + + private static final String NAME = "DataSetName"; + + private static final String NOMADS = "NOMADS"; + + private static final String MADIS = "MADIS"; + + private static final int[] offsets = new int[] { 5, 4, 6, 7, 9, 5, 4, 5, 6, + 4, 3, 6, 2 }; + + private final IDataSetMetaDataHandler handler = mock(IDataSetMetaDataHandler.class); + + private final AveragingAvailablityCalculator availabilityCalculator = new AveragingAvailablityCalculator( + handler); + + @Before + public void setUp() throws RegistryException, RegistryHandlerException { + List gmdList = new ArrayList(); + List pointList = new ArrayList(); + + Calendar cal = TimeUtil.newGmtCalendar(); + cal.set(Calendar.MONTH, 2); + cal.set(Calendar.DATE, 20); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MILLISECOND, 0); + + // Create 20 DataSetMetaData objects, 10 each for grid and point + for (int i = 0; i < offsets.length; i++) { + cal.add(Calendar.DATE, -1); + DataSetMetaData gmd = new OpenDapGriddedDataSetMetaData(); + gmd.setAvailabilityOffset(offsets[i]); + gmd.setDate(new ImmutableDate(cal.getTime())); + ((GriddedDataSetMetaData) gmd).setCycle(cal + .get(Calendar.HOUR_OF_DAY)); + gmdList.add(gmd); + + DataSetMetaData pmd = new PointDataSetMetaData(); + pmd.setAvailabilityOffset(offsets[i]); + pmd.setDate(new ImmutableDate(cal.getTime())); + pointList.add(pmd); + } + + when(handler.getByDataSet(NAME, NOMADS)).thenReturn(gmdList); + when(handler.getByDataSet(NAME, MADIS)).thenReturn(pointList); + } + + @Test + public void testGridCalculation() throws RegistryHandlerException { + Calendar refTime = TimeUtil.newGmtCalendar(); + refTime.set(Calendar.MONTH, 2); + refTime.set(Calendar.DATE, 21); + + Subscription subscription = new SiteSubscription(); + subscription.setProvider(NOMADS); + subscription.setDataSetName(NAME); + int offset = availabilityCalculator.getDataSetAvailablityOffset( + subscription, refTime); + + assertTrue("Average not correct.", offset == getAvg()); + } + + /** + * Get the average. The average calculator uses the last 10 values in the + * avg calculation. + * + * @return the average + */ + private int getAvg() { + int total = 0; + for (int i = 0; i < 10; i++) { + total += offsets[i]; + } + return total / 10; + } +} diff --git a/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtilTest.java b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtilTest.java index 0b6cbe927f..b757a704c3 100644 --- a/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtilTest.java +++ b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtilTest.java @@ -82,6 +82,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.retrieval.RetrievalStatus; * Jun 05, 2013 2038 djohnson Use public API for getting retrieval times. * Jun 25, 2013 2106 djohnson RetrievalPlan uses setters instead of constructor injection now. * Sept 25, 2013 1797 dhladky separated time and gridded time + * Jan 07, 2014 2636 mpduff Removed dataset availability offset calculator (not used). * * * @@ -106,11 +107,6 @@ public class BandwidthDaoUtilTest { public void setUp() { TimeUtilTest.freezeTime(TimeUtil.MILLIS_PER_DAY * 2); - SimpleAvailablityCalculator dataSetAvailabilityCalculator = new SimpleAvailablityCalculator(); - dataSetAvailabilityCalculator.setDelay(0); - - BandwidthUtil.getInstance().setDataSetAvailabilityCalculator( - dataSetAvailabilityCalculator); PathManagerFactoryTest.initLocalization(); IPathManager pm = PathManagerFactory.getPathManager(); @@ -156,11 +152,11 @@ public class BandwidthDaoUtilTest { .withActivePeriodStart(plan.getPlanStart().getTime()) .withActivePeriodEnd(plan.getPlanEnd().getTime()) .withSubscriptionStart(TimeUtil.newImmutableDate()).build(); - ((GriddedTime)subscription.getTime()).setCycleTimes( - Arrays.asList(Integer.valueOf(9), Integer.valueOf(0))); + ((GriddedTime) subscription.getTime()).setCycleTimes(Arrays.asList( + Integer.valueOf(9), Integer.valueOf(0))); - TreeSet cycles = new TreeSet(((GriddedTime)subscription.getTime()) - .getCycleTimes()); + TreeSet cycles = new TreeSet( + ((GriddedTime) subscription.getTime()).getCycleTimes()); SortedSet subscriptionTimes = bandwidthDaoUtil .getRetrievalTimes(subscription, cycles); @@ -178,11 +174,11 @@ public class BandwidthDaoUtilTest { Subscription subscription = new SubscriptionBuilder() .withSubscriptionStart(startsTwoDaysIntoPlan) .withSubscriptionEnd(plan.getPlanEnd().getTime()).build(); - ((GriddedTime)subscription.getTime()).setCycleTimes( - Arrays.asList(Integer.valueOf(9), Integer.valueOf(0))); + ((GriddedTime) subscription.getTime()).setCycleTimes(Arrays.asList( + Integer.valueOf(9), Integer.valueOf(0))); - TreeSet cycles = new TreeSet(((GriddedTime)subscription.getTime()) - .getCycleTimes()); + TreeSet cycles = new TreeSet( + ((GriddedTime) subscription.getTime()).getCycleTimes()); SortedSet subscriptionTimes = bandwidthDaoUtil .getRetrievalTimes(subscription, cycles); @@ -203,11 +199,11 @@ public class BandwidthDaoUtilTest { Subscription subscription = new SubscriptionBuilder() .withSubscriptionStart(plan.getPlanStart().getTime()) .withSubscriptionEnd(endsOneDayBeforePlan).build(); - ((GriddedTime)subscription.getTime()).setCycleTimes( - Arrays.asList(Integer.valueOf(9), Integer.valueOf(0))); + ((GriddedTime) subscription.getTime()).setCycleTimes(Arrays.asList( + Integer.valueOf(9), Integer.valueOf(0))); - TreeSet cycles = new TreeSet(((GriddedTime)subscription.getTime()) - .getCycleTimes()); + TreeSet cycles = new TreeSet( + ((GriddedTime) subscription.getTime()).getCycleTimes()); SortedSet subscriptionTimes = bandwidthDaoUtil .getRetrievalTimes(subscription, cycles); diff --git a/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/ProviderDataTypeAvailabilityCalculatorTest.java b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/ProviderDataTypeAvailabilityCalculatorTest.java deleted file mode 100644 index 56dad4aa99..0000000000 --- a/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/ProviderDataTypeAvailabilityCalculatorTest.java +++ /dev/null @@ -1,111 +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.edex.datadelivery.bandwidth.util; - -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -import java.util.Arrays; - -import org.junit.Before; -import org.junit.Test; - -import com.raytheon.uf.common.datadelivery.registry.DataType; -import com.raytheon.uf.common.datadelivery.registry.Provider; -import com.raytheon.uf.common.datadelivery.registry.ProviderType; -import com.raytheon.uf.common.datadelivery.registry.SiteSubscription; -import com.raytheon.uf.common.datadelivery.registry.Subscription; -import com.raytheon.uf.common.datadelivery.registry.handlers.IProviderHandler; -import com.raytheon.uf.common.registry.handler.RegistryHandlerException; -import com.raytheon.uf.common.util.registry.RegistryException; - -/** - * Test {@link ProviderDataTypeAvailabilityCalculator}. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date         Ticket#    Engineer    Description
- * ------------ ---------- ----------- --------------------------
- * Jun 05, 2013 2038       djohnson     Initial creation
- * 
- * 
- * - * @author djohnson - * @version 1.0 - */ - -public class ProviderDataTypeAvailabilityCalculatorTest { - - private static final int ONE_HUNDRED = 100; - - private static final String PROVIDER_NAME = "someProviderName"; - - private static final Provider provider = new Provider(); - static { - provider.setName(PROVIDER_NAME); - provider.setProviderType(Arrays. asList(new ProviderType( - DataType.GRID, "grid", ONE_HUNDRED))); - } - - private final IProviderHandler providerHandler = mock(IProviderHandler.class); - - private final ProviderDataTypeAvailabilityCalculator availabilityCalculator = new ProviderDataTypeAvailabilityCalculator( - providerHandler); - - @Before - public void setUp() throws RegistryException, RegistryHandlerException { - when(providerHandler.getByName(PROVIDER_NAME)).thenReturn(provider); - } - - @Test - public void returnsConfiguredAvailabilityWhenRegistered() { - Subscription subscription = new SiteSubscription(); - subscription.setProvider(PROVIDER_NAME); - subscription.setDataSetType(DataType.GRID); - - assertThat( - availabilityCalculator.getDataSetAvailablityDelay(subscription), - is(equalTo(ONE_HUNDRED))); - } - - @Test(expected = IllegalArgumentException.class) - public void throwsIllegalArgumentExceptionWhenProviderNotRegistered() { - Subscription subscription = new SiteSubscription(); - subscription.setProvider("someOtherProviderName"); - subscription.setDataSetType(DataType.GRID); - - availabilityCalculator.getDataSetAvailablityDelay(subscription); - } - - @Test(expected = IllegalArgumentException.class) - public void throwsIllegalArgumentExceptionWhenDataTypeNotRegistered() { - Subscription subscription = new SiteSubscription(); - subscription.setProvider(PROVIDER_NAME); - subscription.setDataSetType(DataType.POINT); - - availabilityCalculator.getDataSetAvailablityDelay(subscription); - } - -} From d2f74b62382399c7e983689fae8758835b89d392 Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Thu, 9 Jan 2014 13:02:08 -0600 Subject: [PATCH 22/62] Issue #2633 - Keep graph data visible while resizing. Keep bottom of graph visible. Former-commit-id: e4f56affd39cbfb9bc6f6d7d49e982a72ba189ac [formerly 16a8f16ee4c4358fba2e77f34cf89e2dd9c12622] [formerly 9b5adfaba22f368a9e9f935ebec5126f63a41847 [formerly 87dd0df07a9ef0e7881ed0cf7b8aa1d41f0c9d4d]] Former-commit-id: 9b5adfaba22f368a9e9f935ebec5126f63a41847 Former-commit-id: 7a1712acd64998691727972b5e551f895e7952fe --- .../viz/datadelivery/bandwidth/ui/BandwidthCanvasComp.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/BandwidthCanvasComp.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/BandwidthCanvasComp.java index 118714b9b7..726ef4999d 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/BandwidthCanvasComp.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/bandwidth/ui/BandwidthCanvasComp.java @@ -102,7 +102,8 @@ import com.raytheon.uf.viz.datadelivery.utils.DataDeliveryUtils; * Oct 28, 2013 2430 mpduff Add % of bandwidth utilized graph. * Nov 19, 2013 1531 mpduff Made graph resizable. * Nov 25, 2013 2545 mpduff Default to Opsnet if Network not available yet. - * Dec 17, 2013 2633 mpduff Fix redraw problems. + * Dec 17, 2013 2633 mpduff Fix redraw problems.. + * Jan 09, 2013 2633 mpduff On resize keep graph at bottom so data are always visible. * * * @author lvenable @@ -1479,6 +1480,9 @@ public class BandwidthCanvasComp extends Composite implements IDialogClosed, cornerPointOffset.y = 0; } + cornerPointOffset.y = (graphCanvasSettings.getImageHeight() - graphCanvasSettings + .getCanvasHeight()) * -1; + verticalSlider.setSelection(cornerPointOffset.y * -1); horizontalSlider.setSelection(cornerPointOffset.x * -1); From 8b5ce7c07fc033092464b7d1fdcd25491f8b4717 Mon Sep 17 00:00:00 2001 From: Nate Jensen Date: Fri, 10 Jan 2014 08:57:18 -0600 Subject: [PATCH 23/62] Issue #2359 log exceptions in FFTI processing Change-Id: Iec1c743352187de071f4b9840f1672bff531ba94 Former-commit-id: 1d9229a4a6b26f934557b7805c5456dec5c984be [formerly d289eb1b55a562d4c1426d7ffd99a4ecd79619b0] [formerly 43b75928e4aedb5413284177be9ec8360c85494c [formerly 2abd0cc65b6fe98dc95e11b5b8d53a325c0f2074]] Former-commit-id: 43b75928e4aedb5413284177be9ec8360c85494c Former-commit-id: daba59930ddc2b074eefff72896b0242de99b59b --- .../uf/edex/plugin/ffmp/common/FFTI.java | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java index e1e2d24d97..04fb10c755 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.ffmp/src/com/raytheon/uf/edex/plugin/ffmp/common/FFTI.java @@ -53,8 +53,9 @@ import com.raytheon.uf.edex.plugin.ffmp.FFMPGenerator; * ------------ ---------- ----------- -------------------------- * Apr 01, 2011 dhladky Initial creation * July 13, 2012 dhladky Revamped to help memory - * 02/01/13 1569 D. Hladky Added constants + * 02/01/13 1569 D. Hladky Added constants * 02/25/13 1660 D. Hladky Moved FFTI processing to help with mosaic memory usage + * 01/10/14 2359 njensen Fix exception logging * * * @@ -235,8 +236,8 @@ public class FFTI implements Runnable { for (int j = 0; j < sites.size(); j++) { - FFTIAccum faccum = ffmpgen.getAccumulationForSite(displayName, - sites.get(j), dataKey, duration, + FFTIAccum faccum = ffmpgen.getAccumulationForSite( + displayName, sites.get(j), dataKey, duration, source.getUnit()); if (faccum != null) { @@ -278,8 +279,8 @@ public class FFTI implements Runnable { source = ffmpgen.getSourceConfig().getSourceByDisplayName( fftiSourceKey); - accum = ffmpgen.getAccumulationForSite(fftiSourceKey, fftiSiteKey, - fftiSiteKey, duration, source.getUnit()); + accum = ffmpgen.getAccumulationForSite(fftiSourceKey, + fftiSiteKey, fftiSiteKey, duration, source.getUnit()); if (accum != null) { accum.setUnit(source.getUnit()); @@ -430,11 +431,11 @@ public class FFTI implements Runnable { } } } catch (Exception e) { - statusHandler.handle( - Priority.ERROR, - "Failed to evaluate Ratio/Diff. " - + attribute.getAttributeName() + ": " + displayName - + "\n" + e); + statusHandler + .handle(Priority.ERROR, + "Failed to evaluate Ratio/Diff. " + + attribute.getAttributeName() + ": " + + displayName, e); } } @@ -521,8 +522,10 @@ public class FFTI implements Runnable { } } catch (Exception e) { statusHandler - .handle(Priority.ERROR, "failed to transmit FFTI alert. " - + attribute.getAttributeName() + " Value: " + value); + .handle(Priority.ERROR, + "failed to transmit FFTI alert. " + + attribute.getAttributeName() + " Value: " + + value, e); } } @@ -576,8 +579,10 @@ public class FFTI implements Runnable { } } catch (Exception e) { statusHandler - .handle(Priority.ERROR, "failed to transmit FFTI alert. " - + attribute.getAttributeName() + " Value: " + value); + .handle(Priority.ERROR, + "failed to transmit FFTI alert. " + + attribute.getAttributeName() + " Value: " + + value, e); } } @@ -649,8 +654,8 @@ public class FFTI implements Runnable { ffmpgen.logger.debug("FFTI: finsihed evaluating sources"); } } catch (Exception e) { - statusHandler.handle(Priority.ERROR, "failed to evaluate FFTI. " - + e); + statusHandler + .handle(Priority.ERROR, "failed to evaluate FFTI. ", e); } finally { ffmpgen.fftiSources.clear(); ffmpgen.fftiDone = true; @@ -787,7 +792,8 @@ public class FFTI implements Runnable { * @return */ public static Double getGap(FFMPDataContainer qpeContainer, - SourceXML ffmpQSource, Date curdate, double duration, String qSiteKey) { + SourceXML ffmpQSource, Date curdate, double duration, + String qSiteKey) { long timeBack = (long) (duration * TimeUtil.MILLIS_PER_HOUR); Date backDate = new Date(curdate.getTime() - timeBack); @@ -841,4 +847,4 @@ public class FFTI implements Runnable { return sourceLengths; } -} \ No newline at end of file +} From ea07460e3e7ac68b2485214e35312a20ca7eeb54 Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Fri, 10 Jan 2014 10:55:17 -0600 Subject: [PATCH 24/62] Issue #2636 - change log statements, add missing copyright headers Former-commit-id: 8993103c453f816597263a93ca964584c0ccdaf8 [formerly 12a8618c42f5c21f8675e4e90df1d5655f1223ab] [formerly 3be3a8ac0deb420831cb741f4a0f0f6af77dfd65 [formerly 8bf5a8185c09e9d368afc8e8e7409222164159aa]] Former-commit-id: 3be3a8ac0deb420831cb741f4a0f0f6af77dfd65 Former-commit-id: e121eb5dbd08dae8c0761b3c9e0f1c0fc9552eed --- .../SimpleSubscriptionAggregator.java | 25 +++++++++++++++++-- .../util/AveragingAvailablityCalculator.java | 18 ++++++++++++- .../bandwidth/util/BandwidthDaoUtil.java | 6 +++-- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/processing/SimpleSubscriptionAggregator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/processing/SimpleSubscriptionAggregator.java index 44dbddb54b..ab73784e6a 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/processing/SimpleSubscriptionAggregator.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/processing/SimpleSubscriptionAggregator.java @@ -1,3 +1,22 @@ +/** + * 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.datadelivery.bandwidth.processing; import java.util.ArrayList; @@ -87,8 +106,10 @@ public class SimpleSubscriptionAggregator implements ISubscriptionAggregator { offset = BandwidthUtil.getDataSetAvailablityOffset(sub, subDao.getBaseReferenceTime()); } catch (RegistryHandlerException e) { - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); + statusHandler + .handle(Priority.PROBLEM, + "Unable to retrieve data availability offset, using 0 for the offset.", + e); } subscriptionRetrieval.setDataSetAvailablityDelay(offset); diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/AveragingAvailablityCalculator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/AveragingAvailablityCalculator.java index 1f13c14edf..fe19b06633 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/AveragingAvailablityCalculator.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/AveragingAvailablityCalculator.java @@ -1,6 +1,22 @@ /** + * 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.datadelivery.bandwidth.util; import java.util.Calendar; diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java index 229ab109cf..f020544002 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java @@ -308,8 +308,10 @@ public class BandwidthDaoUtil { subscription, time); } catch (RegistryHandlerException e) { // Error occurred querying the registry. Log and continue on - statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), - e); + statusHandler + .handle(Priority.PROBLEM, + "Unable to retrieve data availability offset, using 0 for the offset.", + e); } Calendar withAvailabilityOffset = TimeUtil.newCalendar(time); From 12c47ea3753a8e66ea3b82f8daa47be4515ef727 Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Fri, 10 Jan 2014 10:57:18 -0600 Subject: [PATCH 25/62] Issue #2642 - Update header comment Former-commit-id: 5d669a97afb88503f9bd2e2daeb03d2039ca8396 [formerly 101d9939d67c23135f4d0d274a5aac250f3f372c] [formerly 28114764a5c476d1743cc2684fadadfa79a16464 [formerly 389426adddf3a78d9859f704ecc2241e453b5dc2]] Former-commit-id: 28114764a5c476d1743cc2684fadadfa79a16464 Former-commit-id: 7d25b33cb62ddca8f56c5dc8f509e5ffa60a469a --- .../uf/viz/datadelivery/subscription/SubscriptionTableComp.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionTableComp.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionTableComp.java index 7d446d14f6..f5b3386dc4 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionTableComp.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionTableComp.java @@ -109,7 +109,7 @@ import com.raytheon.uf.viz.datadelivery.utils.DataDeliveryUtils.TABLE_TYPE; * Jul 29, 2013 2232 mpduff IndexOutOfBoundsException check. * Jul 26, 2031 2232 mpduff Refactored Data Delivery permissions. * Oct 11, 2013 2386 mpduff Refactor DD Front end. - * Jan 08, 2014 2642 mpduff + * Jan 08, 2014 2642 mpduff Enable/disable menus based on site, allow user to add their site to a shared sub. * @version 1.0 */ From b616f34af2fa56ed88a9c6f81e2b5a9be2a5e441 Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Fri, 10 Jan 2014 12:05:30 -0600 Subject: [PATCH 26/62] Issue #2452 - Add label stating all lat/lons will be converted to easting. Former-commit-id: 67f63113546c1aee94ea33545e8dd9136ef5c6c4 [formerly 69ca0dd0d240b3aecdeca9030d69acb056d637c5] [formerly 7081c268239161005ed6a0ca1636508024579fee [formerly 84bff804bc089aefcf126a586539eab590e1d04a]] Former-commit-id: 7081c268239161005ed6a0ca1636508024579fee Former-commit-id: 17d19cc0bb88390ea2af6169e1eecf71538f5991 --- .../raytheon/uf/viz/datadelivery/common/ui/AreaComp.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/common/ui/AreaComp.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/common/ui/AreaComp.java index 7a681df497..7c5ab489d3 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/common/ui/AreaComp.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/common/ui/AreaComp.java @@ -93,6 +93,7 @@ import com.vividsolutions.jts.geom.Coordinate; * Jul 12, 2013 2141 mpduff Valid envelope test happens as needed instead of when changes are made. * Oct 10, 2013 2104 mschenke Switched to use MapScalesManager * Oct 11, 2013 2386 mpduff Refactor DD Front end. + * Jan 10, 2014 2452 mpduff Add label stating all lat/lons will be converted to easting. * * * @@ -396,11 +397,17 @@ public class AreaComp extends Composite implements ISubset { }); gd = new GridData(); - gd.horizontalSpan = 3; + gd.horizontalSpan = 2; manualLbl = new Label(regionComp, SWT.LEFT); manualLbl.setText("Manual Lat/Lon Edit"); manualLbl.setLayoutData(gd); + gd = new GridData(); + gd.horizontalSpan = 1; + Label l = new Label(regionComp, SWT.LEFT); + l.setText("All entries will be converted to Easting (0-360)"); + l.setLayoutData(gd); + /* * Predefined controls. */ From 3274c591bfd4b8a00fbe85c2d57a6b48fdbdda13 Mon Sep 17 00:00:00 2001 From: Mike Duff Date: Fri, 10 Jan 2014 10:30:02 -0600 Subject: [PATCH 27/62] Issue #2684 - BandwidthUtil bean now depends on registerDataDeliveryHandlers bean Change-Id: I6f491e7e14e445b59e93f5896eedde3062246034 Former-commit-id: 26e34bb4d1837a5810634158d6a6cb97ace90e00 [formerly b50ea7b162fcc8eac08397715bcd3548ba5ac666] [formerly 744d7367dc69eee78f6bff716431f5ef05b81f06 [formerly 12500574ade0eced65454ff981b83f8f729cd125]] Former-commit-id: 744d7367dc69eee78f6bff716431f5ef05b81f06 Former-commit-id: 0e5332e8cd1f45e8b1e9a7508798c26768d6776c --- .../res/spring/bandwidth-datadelivery.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery.xml index 2dbdd53ad3..96c2ae68b2 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery.xml @@ -48,7 +48,7 @@ + factory-method="getInstance" depends-on="registerDataDeliveryHandlers"> From d70701cc6e42a35b0d50990202e12e283da02faa Mon Sep 17 00:00:00 2001 From: Ron Anderson Date: Fri, 10 Jan 2014 13:13:29 -0600 Subject: [PATCH 28/62] Issue #2508 Restore DiscreteGridSlice.setKey method used by iscMosaic. Change-Id: I503cf82ce896e8cdf39c238eda0f31453d8510a5 Former-commit-id: 17ed8a6e754035451a0ef7e55f675153130c1000 [formerly 3017260991532642935431f462f64552fcc5934d] [formerly d80ce4a19ec277c701c6fbeb688ca9326f038d02 [formerly 142f68c426c4e2fbeb1e0b97cbb7b47c38e3b90d]] Former-commit-id: d80ce4a19ec277c701c6fbeb688ca9326f038d02 Former-commit-id: 57d3503ed608c271693ea54a06455bae4e287539 --- .../edex_static/base/gfe/isc/ifpnetCDF.py | 6 ++-- .../edex_static/base/gfe/isc/iscMosaic.py | 36 ++++++++++++++++--- .../gfe/slice/DiscreteGridSlice.java | 9 +++++ 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py index 570a424483..05a65635e6 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/ifpnetCDF.py @@ -843,7 +843,7 @@ def storeVectorWE(we, trList, file, timeRange, for i in xrange(len(overlappingTimes) -1, -1, -1): ot = overlappingTimes[i] if not ot in histDict: - del overlappingTime[i] + del overlappingTimes[i] del timeList[i] elif we.getGpi().isRateParm(): durRatio = (float(timeList[i][1]-timeList[i][0]))/float((ot[1]-ot[0])) @@ -996,7 +996,7 @@ def storeWeatherWE(we, trList, file, timeRange, databaseID, invMask, clipArea): for i in xrange(len(overlappingTimes) -1, -1, -1): ot = overlappingTimes[i] if not ot in histDict: - del overlappingTime[i] + del overlappingTimes[i] del timeList[i] # make the variable name @@ -1081,7 +1081,7 @@ def storeDiscreteWE(we, trList, file, timeRange, databaseID, invMask, clipArea): for i in xrange(len(overlappingTimes) -1, -1, -1): ot = overlappingTimes[i] if not ot in histDict: - del overlappingTime[i] + del overlappingTimes[i] del timeList[i] # make the variable name diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py index 19405007dc..9cd47ed306 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/gfe/isc/iscMosaic.py @@ -84,6 +84,7 @@ from com.raytheon.uf.edex.database.cluster import ClusterTask # 10/31/2013 2508 randerso Change to use DiscreteGridSlice.getKeys() # 11/05/13 2517 randerso Restructured logging so it coulde be used by WECache # Changed WECache to limit the number of cached grids kept in memory +# 01/09/14 16952 randerso Fix regression made in #2517 which caused errors with overlapping grids # # @@ -462,6 +463,7 @@ class IscMosaic: self.__mysite = args['siteID'] self.__userID = args['userID'] self.__db = None # ifpServer database object + self.__dbGrid = None self.__parmsToProcess = args['parmsToProcess'] self.__blankOtherPeriods = args['blankOtherPeriods'] self.__altMask = args['altMask'] @@ -823,7 +825,7 @@ class IscMosaic: logger.debug("Merge: %s %s %s", printTR(m[0]), printTR(m[1]), m[2]) - gotGrid = self._wec[m[0]] + gotGrid = self.__getDbGrid(m[0]) if gotGrid is not None: destGrid = gotGrid[0] @@ -888,6 +890,30 @@ class IscMosaic: self._wec[tr] = None self.__dbinv = self._wec.keys() + #--------------------------------------------------------------------- + # get db grid + # Gets the needed database grid + # tr = desired grid, identified by time range + # Returns tuple of (grid, history) (or None if unknown) + #--------------------------------------------------------------------- + def __getDbGrid(self, tr): + if tr is None: + return None + + if self.__dbGrid is None or tr != self.__dbGrid[2]: + self.__dbGrid = None + #grid = self.__dbwe.getGridAndHist(tr) + grid = self._wec[tr] + if grid is not None: + destGrid, history = grid + self.__dbGrid = (destGrid, history, tr) + else: + self.logProblem("Unable to access grid for ", + self.__printTR(tr), "for ", self.__parmName) + return None + + return (self.__dbGrid[0], self.__dbGrid[1]) + #--------------------------------------------------------------------- # calculate file start/end processing times # Returns (startTime, endTime) or None for processing @@ -1107,7 +1133,7 @@ class IscMosaic: for m in mergeInfo: if m[0] != m[1]: #split grid needed if m[0] != oldTR: - oldGrid = self._wec[m[0]] + oldGrid = self.__getDbGrid(m[0]) oldTR = m[0] if oldGrid is not None: if self.__rateParm: @@ -1116,8 +1142,9 @@ class IscMosaic: self.__storeGrid(m[1], (adjGrid, oldGrid[1])) else: self.__storeGrid(m[1], oldGrid) + self.__dbGrid = None - #------------------------------------------------------------------------- + #------------------------------------------------------------------------- # Get Incoming netCDF file grid valid times # netCDFfile, var is the netCDF variable #------------------------------------------------------------------------- @@ -1395,7 +1422,7 @@ class IscMosaic: if m[0] != None and m[2] == 1: if self.__siteInDbGrid(m[0]): try: - (destGrid, oldHist) = self._wec[m[0]] + (destGrid, oldHist) = self.__getDbGrid(m[0]) except: destGrid = None oldHist = None @@ -1611,6 +1638,7 @@ class IscMosaic: #--------------------------------------------------------------------- def __eraseAllGrids(self, processTimePeriod): self.__storeGrid(processTimePeriod, None) + self.__dbGrid = None def convertList(unknownList): diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/slice/DiscreteGridSlice.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/slice/DiscreteGridSlice.java index 4bf375ade1..75adcfaa29 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/slice/DiscreteGridSlice.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/slice/DiscreteGridSlice.java @@ -802,6 +802,15 @@ public class DiscreteGridSlice extends AbstractGridSlice implements Cloneable { this.keys = keys; } + /** + * Used by iscMosaic.py + * + * @param key + */ + public void setKey(List key) { + setKeys(key.toArray(new DiscreteKey[] {})); + } + /** * @param keys * the keys to set From 9df631248df78a9e00088d2a7d8a3a797fc197b8 Mon Sep 17 00:00:00 2001 From: Ron Anderson Date: Fri, 10 Jan 2014 15:01:10 -0600 Subject: [PATCH 29/62] Issue #2044 Fix some error handling in GFE to eliminate exceptions in edex logs. Change-Id: Iad8edf92318d6c9277648396ba450a3fc6eb5c5a Former-commit-id: 7cae1b981d5bf3bf044081d9ad4369c7da2313c4 [formerly 89f07fe932bc958de73f5bac36398985fd9883d0] [formerly 1c520b8cd1c9d623b4ae6ed5194d2a7489282cef [formerly 3f9f254229066cfe12501aacd14e68937764fadb]] Former-commit-id: 1c520b8cd1c9d623b4ae6ed5194d2a7489282cef Former-commit-id: bbac6df77defbe5d30481799b676f9d97a9d9d9c --- .../edex/plugin/gfe/server/GridParmManager.java | 4 +++- .../plugin/gfe/server/database/D2DGridDatabase.java | 10 ++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java index 81aae88798..556f3f14c4 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/GridParmManager.java @@ -1257,7 +1257,9 @@ public class GridParmManager { d2dModelName, desiredVersions)) { D2DGridDatabase db = D2DGridDatabase.getDatabase(config, d2dModelName, refTime); - addDB(db); + if (db != null) { + addDB(db); + } } } catch (Exception e) { statusHandler.error("Error initializing D2D model: " diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/D2DGridDatabase.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/D2DGridDatabase.java index 5dd6f12d44..927e428e08 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/D2DGridDatabase.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/D2DGridDatabase.java @@ -195,9 +195,6 @@ public class D2DGridDatabase extends VGridDatabase { } } - /** - } - /** * Retrieves DatabaseIDs for the n most recent model runs of a given * d2dModelName @@ -229,7 +226,7 @@ public class D2DGridDatabase extends VGridDatabase { // regex to match parmnnhr private static final Pattern parmHrPattern = Pattern - .compile("(\\D+)\\d+hr"); + .compile("(.*\\D)\\d+hr"); private static final String GFE_LEVEL_MAPPING_FILE = "grid/gfeLevelMappingFile.xml"; @@ -1405,6 +1402,11 @@ public class D2DGridDatabase extends VGridDatabase { } TimeRange tr = getTimeRange(parmID, fcstHour); + if (tr == null) { + statusHandler.warn("Unexpected fcst hour (" + fcstHour + ") for " + + parmID); + return null; + } List histList = new ArrayList(); histList.add(new GridDataHistory( GridDataHistory.OriginType.INITIALIZED, parmID, tr, null, From f57529be9b85d292cc7c1b5117d39b2b9701048c Mon Sep 17 00:00:00 2001 From: Brad Gonzales Date: Thu, 9 Jan 2014 11:30:22 -0600 Subject: [PATCH 30/62] Issue #2615 Refactored Subscription valid time period calculation from BandwidthDaoUtil to RecurringSubscription. Add environment configuration files to unit tests setup. Changed the devRegistry debug port to the same port as registry. Amend: Updates from peer review. Change-Id: I4f5a25d4667dc949804b86541a9d9428728b779a Former-commit-id: 8eeb3dc412bf0fb8a4be9910c35cb8991eefec08 [formerly 4537513df7b8d283690b13b00ce7783dba085d4f] [formerly 343a2495e58c47198c8eaa87f6aae4f24ce38cdd [formerly 33a3dead503276926af71d7355f87242f5250e54]] Former-commit-id: 343a2495e58c47198c8eaa87f6aae4f24ce38cdd Former-commit-id: 4049af96301a485c0dd450c41873c7b4d52424aa --- edexOsgi/build.edex/esb/etc/devRegistry.sh | 3 +- .../registry/RecurringSubscription.java | 75 +++++- .../datadelivery/registry/Subscription.java | 24 ++ .../uf/common/time/util/TimeUtil.java | 100 ++++++- .../bandwidth/BandwidthManager.java | 51 +++- .../bandwidth/IBandwidthManager.java | 11 + .../BandwidthUtilizationProcessor.java | 6 +- .../bandwidth/retrieval/RetrievalPlan.java | 12 +- .../bandwidth/util/BandwidthDaoUtil.java | 115 ++------- .../bandwidth/util/BandwidthUtil.java | 35 +-- tests/conf/res/base/attributeNames.xml | 243 ++++++++++++++++++ tests/conf/res/base/environment.xml | 57 ++++ tests/conf/res/config.xml | 43 ++++ tests/conf/res/site/attributeNames.xml | 25 ++ tests/conf/res/site/environment.xml | 29 +++ .../localization/PathManagerFactoryTest.java | 20 +- .../handler/RegistryObjectHandlersUtil.java | 5 +- .../raytheon/uf/common/util/SpringFiles.java | 3 + .../bandwidth/util/BandwidthDaoUtilTest.java | 8 +- 19 files changed, 715 insertions(+), 150 deletions(-) create mode 100644 tests/conf/res/base/attributeNames.xml create mode 100644 tests/conf/res/base/environment.xml create mode 100644 tests/conf/res/config.xml create mode 100644 tests/conf/res/site/attributeNames.xml create mode 100644 tests/conf/res/site/environment.xml diff --git a/edexOsgi/build.edex/esb/etc/devRegistry.sh b/edexOsgi/build.edex/esb/etc/devRegistry.sh index 95338858d8..c00775981d 100644 --- a/edexOsgi/build.edex/esb/etc/devRegistry.sh +++ b/edexOsgi/build.edex/esb/etc/devRegistry.sh @@ -22,7 +22,8 @@ export MAX_MEM=1536 # in Meg export MAX_PERM_SIZE=192m export METADATA_POOL_MIN=10 -export EDEX_DEBUG_PORT=5013 +export EDEX_DEBUG_PORT=5012 export EDEX_JMX_PORT=1620 export LOG_CONF=logback-registry.xml export MGMT_PORT=9605 +export EBXML_REGISTRY_FEDERATION_ENABLED=false diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java index c37787bd7c..5b1453bcc7 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java @@ -60,9 +60,10 @@ import com.raytheon.uf.common.time.util.TimeUtil; * May 15, 2013 1040 mpduff Changed to use Set for office id. * May 21, 2013 2020 mpduff Rename UserSubscription to SiteSubscription. * Sept 30,2013 1797 dhladky Generics - * Oct 23, 2013 2484 dhladky Unique ID for subscriptions updated. - * Oct 30, 2013 2448 dhladky Fixed pulling data before and after activePeriod starting and ending. - * Nov 14, 2013 2548 mpduff Add a subscription type slot. + * Oct 23, 2013 2484 dhladky Unique ID for subscriptions updated. + * Oct 30, 2013 2448 dhladky Fixed pulling data before and after activePeriod starting and ending. + * Nov 14, 2013 2548 mpduff Add a subscription type slot. + * Jan 08, 2014 2615 bgonzale Implement calculate start and calculate end methods. * * * @@ -450,6 +451,58 @@ public abstract class RecurringSubscription this.activePeriodEnd = activePeriodEnd; } + private Calendar getActivePeriodStart(Calendar base) { + // active period values are month and day of month only, use base + // Calendar for active period year + Calendar activePeriodStartCal = TimeUtil + .newCalendar(activePeriodStart); + TimeUtil.minCalendarFields(activePeriodStartCal, Calendar.MILLISECOND, + Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY); + activePeriodStartCal.set(Calendar.YEAR, base.get(Calendar.YEAR)); + return activePeriodStartCal; + } + + private Calendar getActivePeriodEnd(Calendar base) { + // active period values are month and day of month only, use base + // Calendar for active period year + Calendar activePeriodEndCal = TimeUtil.newCalendar(activePeriodEnd); + TimeUtil.maxCalendarFields(activePeriodEndCal, Calendar.MILLISECOND, + Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY); + activePeriodEndCal.set(Calendar.YEAR, base.get(Calendar.YEAR)); + return activePeriodEndCal; + } + + @Override + public Calendar calculateStart(Calendar startConstraint) { + Calendar realStart = null; + boolean hasActivePeriodStart = activePeriodStart != null; + if (hasActivePeriodStart) { + realStart = getActivePeriodStart(startConstraint); + if (realStart.before(startConstraint)) { + realStart = startConstraint; + } + } else { + realStart = startConstraint; + } + return TimeUtil.newCalendar(TimeUtil.max(subscriptionStart, + realStart)); + } + + @Override + public Calendar calculateEnd(Calendar endConstraint) { + Calendar realEnd = null; + boolean hasActivePeriodEnd = activePeriodEnd != null; + if (hasActivePeriodEnd) { + realEnd = getActivePeriodEnd(endConstraint); + if (realEnd.before(endConstraint)) { + realEnd = endConstraint; + } + } else { + realEnd = endConstraint; + } + return TimeUtil.newCalendar(TimeUtil.min(subscriptionEnd, realEnd)); + } + /** * isNotify flag for subscription. * @@ -819,9 +872,19 @@ public abstract class RecurringSubscription @Override public String toString() { - return getName() + "::" + getProvider() + "::" + getDataSetName() - + "::" + getOwner() + "::" + getOriginatingSite() + "::" - + getSubscriptionType().name(); + SubscriptionType subType = getSubscriptionType(); + StringBuilder sb = new StringBuilder(getName()); + sb.append("::"); + sb.append(getProvider()); + sb.append("::"); + sb.append(getDataSetName()); + sb.append("::"); + sb.append(getOwner()); + sb.append("::"); + sb.append(getOriginatingSite()); + sb.append("::"); + sb.append(subType == null ? "null" : subType.name()); + return sb.toString(); } /** diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Subscription.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Subscription.java index 53ed25abd0..4df35239a7 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Subscription.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Subscription.java @@ -19,6 +19,7 @@ **/ package com.raytheon.uf.common.datadelivery.registry; +import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.Set; @@ -42,6 +43,7 @@ import javax.xml.bind.annotation.XmlEnumValue; * Sept 30,2013 1797 dhladky Abstracted and genericized. * Oct 23, 2013 2484 dhladky Unique ID for subscriptions updated. * Nov 14, 2013 2548 mpduff Add a subscription type information. + * Jan 08, 2014 2615 bgonzale Added calculate start and calculate end methods. * * * @@ -297,6 +299,28 @@ public interface Subscription { */ void setActivePeriodEnd(Date activePeriodEnd); + /** + * Calculate the earliest that this subscription is valid based on active + * period and start time. + * + * @param startConstraint + * the earliest valid time. + * + * @return the valid subscription start Date. + */ + Calendar calculateStart(Calendar startConstraint); + + /** + * Calculate the latest that this subscription is valid based on active + * period and end time. + * + * @param endConstraint + * the latest valid time. + * + * @return the valid subscription end Date. + */ + Calendar calculateEnd(Calendar endConstraint); + /** * isNotify flag for subscription. * diff --git a/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/util/TimeUtil.java b/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/util/TimeUtil.java index 9c55491b7f..755cbc657e 100644 --- a/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/util/TimeUtil.java +++ b/edexOsgi/com.raytheon.uf.common.time/src/com/raytheon/uf/common/time/util/TimeUtil.java @@ -54,6 +54,8 @@ import com.raytheon.uf.common.time.domain.api.ITimePoint; * Jun 05, 2013 DR 16279 D. Friedman Add timeOfDayToAbsoluteTime * Oct 30, 2013 2448 dhladky Added current year addition to calendar object. * Nov 05, 2013 2499 rjpeter Added prettyDuration. + * Jan 08, 2014 2615 bgonzale Added Calendar min and max methods. + * Added newGmtCalendar from a date method. * * * @author njensen @@ -325,6 +327,78 @@ public final class TimeUtil { || (laterCal.get(Calendar.YEAR) > earlierCal.get(Calendar.YEAR)); } + /** + * Min comparison of a Date and a Calendar; returns the lesser. + * + * @param lhs + * @param rhs + * @return the lesser of a Data and a Calendar; returns null if either is + * null. + */ + public static Calendar min(Date lhs, Calendar rhs) { + return min(TimeUtil.newCalendar(lhs), rhs); + } + + /** + * Max comparison of a Date and a Calendar; returns the greater. + * + * @param lhs + * @param rhs + * @return the greater of a Data and a Calendar; returns null if either is + * null. + */ + public static Calendar max(Date lhs, Calendar rhs) { + return max(TimeUtil.newCalendar(lhs), rhs); + } + + /** + * Max comparison of two Calendars; returns the greater. + * + * @param lhs + * @param rhs + * @return the greater of two Calendars; returns null if both are null. + */ + public static Calendar max(Calendar lhs, Calendar rhs) { + if (lhs != null && rhs == null) { + return lhs; + } + if (lhs == null && rhs != null) { + return rhs; + } + if (lhs != null && rhs != null) { + if (lhs.equals(rhs)) { + return lhs; + } else { + return lhs.after(rhs) ? lhs : rhs; + } + } + return null; + } + + /** + * Min comparison of two Calendars; returns the lesser. + * + * @param lhs + * @param rhs + * @return the lesser of two Calendars; returns null if both are null. + */ + public static Calendar min(Calendar lhs, Calendar rhs) { + if (lhs != null && rhs == null) { + return lhs; + } + if (lhs == null && rhs != null) { + return rhs; + } + if (lhs != null && rhs != null) { + if (lhs.equals(rhs)) { + return lhs; + } else { + return lhs.before(rhs) ? lhs : rhs; + } + } + return null; + } + /** * Return a new {@link Calendar} instance. This method delegates to the * {@link SimulatedTime} class to determine the currently configured system @@ -525,8 +599,9 @@ public final class TimeUtil { /** * New Calendar from an existing calendar + * * @param calendar - * @return + * @return new calendar */ public static Calendar newCalendar(final Calendar calendar) { Calendar t = null; @@ -538,9 +613,26 @@ public final class TimeUtil { } /** - * Adds the current year to the calendar object that does not already have it set. - * Some calendar objects are only concerned with the day and month. When a - * comparison of years is necessary, you must add the current year to that calendar object. + * New GMT Calendar from a Date + * + * @param date + * @return + */ + public static Calendar newGmtCalendar(final Date date) { + Calendar t = null; + if (date != null) { + t = TimeUtil.newGmtCalendar(); + t.setTime(date); + } + return t; + } + + /** + * Adds the current year to the calendar object that does not already have + * it set. Some calendar objects are only concerned with the day and month. + * When a comparison of years is necessary, you must add the current year to + * that calendar object. + * * @param calendar * @return */ diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java index 56a9538ac0..52431e5275 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java @@ -132,6 +132,8 @@ import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException; * Dec 04, 2013 2566 bgonzale added method to retrieve and parse spring files for a mode. * Dec 11, 2013 2566 bgonzale fix spring resource resolution. * Dec 17, 2013 2636 bgonzale Changed logging to differentiate the output. + * Jan 08, 2014 2615 bgonzale getMostRecent checks subscription time constraints before scheduling. + * handlePoint method now schedules most recent. * * * @@ -484,9 +486,19 @@ public abstract class BandwidthManager @Override public List scheduleAdhoc( AdhocSubscription subscription) { + return scheduleAdhoc(subscription, BandwidthUtil.now()); + } + + /** + * {@inheritDoc} + * + * @return + */ + @Override + public List scheduleAdhoc( + AdhocSubscription subscription, Calendar now) { List subscriptions = new ArrayList(); - Calendar now = BandwidthUtil.now(); // Store the AdhocSubscription with a base time of now.. subscriptions.add(bandwidthDao.newBandwidthSubscription(subscription, now)); @@ -602,8 +614,11 @@ public abstract class BandwidthManager */ private List handlePoint( Subscription subscription) { - return schedule(subscription, - ((PointTime) subscription.getTime()).getInterval()); + List unscheduled = Collections.emptyList(); + unscheduled.addAll(schedule(subscription, + ((PointTime) subscription.getTime()).getInterval())); + unscheduled.addAll(getMostRecent(subscription, false)); + return unscheduled; } /** @@ -628,10 +643,18 @@ public abstract class BandwidthManager unscheduled = schedule(subscription, Sets.newTreeSet(cycles)); } + unscheduled.addAll(getMostRecent(subscription, + useMostRecentDataSetUpdate)); + return unscheduled; + } + + private List getMostRecent( + Subscription subscription, boolean useMostRecentDataSetUpdate) { + List unscheduled = Collections.emptyList(); // Create an adhoc subscription based on the new subscription, // and set it to retrieve the most recent cycle (or most recent // url if a daily product) - if (subscription instanceof SiteSubscription) { + if (subscription instanceof SiteSubscription && subscription.isActive()) { AdhocSubscription adhoc = new AdhocSubscription( (SiteSubscription) subscription); adhoc = bandwidthDaoUtil.setAdhocMostRecentUrlAndTime(adhoc, @@ -644,7 +667,25 @@ public abstract class BandwidthManager + "No adhoc requested.", subscription.getName())); } else { - unscheduled = scheduleAdhoc(adhoc); + RetrievalPlan plan = retrievalManager.getPlan(subscription.getRoute()); + if (plan != null) { + Date subscriptionValidStart = subscription.calculateStart( + plan.getPlanStart()).getTime(); + Date subscriptionValidEnd = subscription.calculateEnd( + plan.getPlanEnd()).getTime(); + Date now = TimeUtil.newDate(); + + if ((now.equals(subscriptionValidStart) || now + .after(subscriptionValidStart)) + && now.before(subscriptionValidEnd)) { + unscheduled = scheduleAdhoc(adhoc); + } else { + statusHandler.info(String.format( + "Time frame outside of subscription active time frame [%s]. " + + "No adhoc requested.", + subscription.getName())); + } + } } } else { statusHandler diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/IBandwidthManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/IBandwidthManager.java index 8224ebac21..187cd77fbe 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/IBandwidthManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/IBandwidthManager.java @@ -19,6 +19,7 @@ **/ package com.raytheon.uf.edex.datadelivery.bandwidth; +import java.util.Calendar; import java.util.List; import com.raytheon.uf.common.datadelivery.registry.AdhocSubscription; @@ -43,6 +44,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.interfaces.ISubscriptionAggre * Jul 10, 2013 2106 djohnson Remove EDEX instance specific methods. * 10/23/2013 2385 bphillip Change schedule method to scheduleAdhoc * Jan 06, 2014 2636 mpduff Update javadoc + * Jan 08, 2014 2615 bgonzale Added scheduleAdoc method. * * * @author djohnson @@ -69,6 +71,15 @@ public interface IBandwidthManager { */ List scheduleAdhoc(AdhocSubscription subscription); + /** + * Schedule AdhocSubscription to run at the given time 'now'. + * + * @param subscription + * @param b + * @return + */ + List scheduleAdhoc( + AdhocSubscription subscription, Calendar now); /** * When a Subscription is updated in the Registry, update the retrieval plan * accordingly to match the updated Subscription. diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/registry/BandwidthUtilizationProcessor.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/registry/BandwidthUtilizationProcessor.java index 8c6cbda098..6cbb858e36 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/registry/BandwidthUtilizationProcessor.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/registry/BandwidthUtilizationProcessor.java @@ -45,6 +45,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.dao.IBandwidthBucketDao; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Nov 27, 2013 1736 dhladky Initial creation + * Jan 08, 2014 2615 bgonzale Change calculation of bytesPerSec to make a divide by zero error less likely. * * * @@ -95,8 +96,9 @@ public class BandwidthUtilizationProcessor implements Job { private int getBytesPerSecondAndReset() { long now = TimeUtil.currentTimeMillis(); - int diffSeconds = (int) (now - lastRun)/1000; - int bytesPerSec = totalBytes.getAndSet(0)/diffSeconds; + int diffMilliSeconds = (int) (now - lastRun); + int bytesPerMillSec = totalBytes.getAndSet(0) / diffMilliSeconds; + int bytesPerSec = bytesPerMillSec / 1000; // reset time map.put("lastRun", now); diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/RetrievalPlan.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/RetrievalPlan.java index b4a5d16182..573367f52a 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/RetrievalPlan.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/RetrievalPlan.java @@ -49,6 +49,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthUtil; * Dec 17, 2013 2636 bgonzale Check for removed buckets when removing BandwidthAllocations or * BandwidthReservations. Add constrained bucket addition method. * Added debug logging. + * Jan 08, 2014 2615 bgonzale Log registry bandwidth calculation errors. * * * @@ -151,8 +152,15 @@ public class RetrievalPlan { // subtract registry traffic from total available bytes/per second for (BandwidthBucket bucket : bucketsDao.getAll(network)) { long startMillis = bucket.getBucketStartTime(); - int registryBytesPerSecond = rbs - .getRegistryBandwidth(startMillis); + int registryBytesPerSecond = 0; + try { + registryBytesPerSecond = rbs + .getRegistryBandwidth(startMillis); + } catch (IllegalArgumentException e) { + statusHandler + .error("Failed to init registry bandwidth calculation. Registry bandwidth will be ignored.", + e); + } bucket.setBucketSize(bucket.getBucketSize() - (registryBytesPerSecond * TimeUtil.SECONDS_PER_MINUTE * bucketMinutes)); } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java index f020544002..0b33325be3 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtil.java @@ -77,6 +77,8 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.retrieval.RetrievalStatus; * Fix for subscription end time set to end of day. * Dec 02, 2013 2545 mpduff Fix for delay starting retrievals, execute adhoc upon subscribing. * Dec 20, 2013 2636 mpduff Fix dataset offset. + * Jan 08, 2014 2615 bgonzale Refactored getRetrievalTimes into RecurringSubscription + * calculateStart and calculateEnd methods. * * * @author djohnson @@ -169,94 +171,33 @@ public class BandwidthDaoUtil { Calendar planEnd = plan.getPlanEnd(); Calendar planStart = plan.getPlanStart(); - Calendar activePeriodStart = null; - Calendar activePeriodEnd = null; - // Make sure the RetrievalPlan's start and end times intersect - // the Subscription's active period. - if (subscription.getActivePeriodEnd() != null - && subscription.getActivePeriodStart() != null) { + // starting time when when subscription is first valid for scheduling + // based on plan start, subscription start, and active period start. + Calendar subscriptionCalculatedStart = subscription + .calculateStart(planStart); + // end time when when subscription is last valid for scheduling based on + // plan end, subscription end, and active period end. + Calendar subscriptionCalculatedEnd = subscription.calculateEnd(planEnd); - activePeriodStart = TimeUtil.newCalendar(subscription - .getActivePeriodStart()); - // Substitute the active periods month and day for the - // plan start month and day. - Calendar start = BandwidthUtil.planToPeriodCompareCalendar( - planStart, activePeriodStart); - // If the active period start is outside the plan bounds, - // there is no intersection - just return an empty set. - if (start.after(planEnd)) { - return subscriptionTimes; - } - - // Do the same for active plan end.. - activePeriodEnd = TimeUtil.newCalendar(subscription - .getActivePeriodEnd()); - // Substitute the active periods month and day for the - // plan ends month and day. - Calendar end = BandwidthUtil.planToPeriodCompareCalendar(planStart, - activePeriodEnd); - // If the active period end is before the start of the plan, - // there is no intersection - just return an empty set. - if (end.before(planStart)) { - return subscriptionTimes; - } - } - - // Now check the Subscription start and end times for intersection - // with the RetrievalPlan... - // Figure out the 'active' period for a subscription.. - Calendar subscriptionEnd = TimeUtil.newCalendar(subscription - .getSubscriptionEnd()); - Calendar subscriptionStart = null; - // Check to see if this is a non-expiring subscription - if (subscriptionEnd == null) { - // If there is no subscription start end dates then the largest - // window that can be scheduled is the RetrievalPlan size.. - subscriptionEnd = TimeUtil.newCalendar(planEnd); - subscriptionStart = TimeUtil.newCalendar(planStart); - } else { - // If there is a start and end time, then modify the start and - // end times to 'fit' within the RetrievalPlan times - subscriptionStart = TimeUtil.newCalendar(BandwidthUtil.max( - subscription.getSubscriptionStart(), planStart)); - subscriptionEnd = TimeUtil.newCalendar(BandwidthUtil.min( - subscription.getSubscriptionEnd(), planEnd)); - } - - // setup active period checks if necessary - if (activePeriodStart != null && activePeriodEnd != null) { - // need to add the current year in order to make the checks relevant - activePeriodStart = TimeUtil - .addCurrentYearCalendar(activePeriodStart); - activePeriodEnd = TimeUtil.addCurrentYearCalendar(activePeriodEnd); - - // Create a Set of Calendars for all the baseReferenceTimes that a - // Subscription can contain... - TimeUtil.minCalendarFields(activePeriodStart, Calendar.MILLISECOND, - Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY); - TimeUtil.maxCalendarFields(activePeriodEnd, Calendar.MILLISECOND, - Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY); - } - - Calendar start = (Calendar) subscriptionStart.clone(); - outerloop: while (!start.after(subscriptionEnd)) { + Calendar start = (Calendar) subscriptionCalculatedStart.clone(); + outerloop: while (!start.after(subscriptionCalculatedEnd)) { for (Integer cycle : hours) { start.set(Calendar.HOUR_OF_DAY, cycle); - // start equal-to-or-after subscriptionStart - if (start.compareTo(subscriptionStart) >= 0) { + // start base equal-to-or-after subscriptionStart + if (start.compareTo(subscriptionCalculatedStart) >= 0) { for (Integer minute : minutes) { start.set(Calendar.MINUTE, minute); - // start equal-to-or-after subscriptionStart - if (start.compareTo(subscriptionStart) >= 0) { + // start minutes equal-to-or-after subscriptionStart + if (start.compareTo(subscriptionCalculatedStart) >= 0) { // Check for nonsense - if (start.after(subscriptionEnd)) { + if (start.after(subscriptionCalculatedEnd)) { break outerloop; } else { - Calendar time = TimeUtil.newGmtCalendar(); + Calendar time = TimeUtil.newCalendar(); time.setTimeInMillis(start.getTimeInMillis()); /** * Fine grain check by hour and minute, for @@ -264,23 +205,11 @@ public class BandwidthDaoUtil { * activePeriod(start/end) **/ // Subscription Start and End time first - if (start != null && subscriptionEnd != null) { - if (time.after(subscriptionEnd) - || time.before(start)) { - // don't schedule this retrieval time, - // outside subscription window - continue; - } - } - // Check Active Period Second - if (activePeriodStart != null - && activePeriodEnd != null) { - if (time.after(activePeriodEnd) - || time.before(activePeriodStart)) { - // don't schedule this retrieval time, - // outside activePeriod window - continue; - } + if (time.after(subscriptionCalculatedEnd) + || time.before(start)) { + // don't schedule this retrieval time, + // outside subscription window + continue; } subscriptionTimes.add(time); diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthUtil.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthUtil.java index eaaa7be9f5..236a5d438d 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthUtil.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthUtil.java @@ -30,8 +30,9 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.dao.BandwidthSubscription; * Jun 13, 2013 2095 djohnson Point subscriptions don't check for dataset updates on aggregation. * Jun 25, 2013 2106 djohnson CheapClone was cheap in ease, not performance. * Jul 11, 2013 2106 djohnson Use SubscriptionPriority enum. - * Oct 30, 2013 2448 dhladky Moved methods to TimeUtil. + * Oct 30, 2013 2448 dhladky Moved methods to TimeUtil. * Dec 20, 2013 2636 mpduff Changed dataset delay to offset. + * Jan 08, 2014 2615 bgonzale Moved Calendar min and max methods to TimeUtil. * * * @@ -67,38 +68,6 @@ public class BandwidthUtil { return instance.subscriptionLatencyCalculator.getLatency(subscription); } - public static Calendar min(Date lhs, Calendar rhs) { - return min(TimeUtil.newCalendar(lhs), rhs); - } - - public static Calendar max(Date lhs, Calendar rhs) { - return max(TimeUtil.newCalendar(lhs), rhs); - } - - public static Calendar max(Calendar lhs, Calendar rhs) { - Calendar calendar = null; - if (lhs != null && rhs != null) { - if (lhs.equals(rhs)) { - return lhs; - } else { - return lhs.after(rhs) ? lhs : rhs; - } - } - return calendar; - } - - public static Calendar min(Calendar lhs, Calendar rhs) { - Calendar calendar = null; - if (lhs != null && rhs != null) { - if (lhs.equals(rhs)) { - return lhs; - } else { - return lhs.before(rhs) ? lhs : rhs; - } - } - return calendar; - } - /** * Seconds and milliseconds on a Calendar are not used in bandwidth * management and can alter some of the time arithmetic that is used diff --git a/tests/conf/res/base/attributeNames.xml b/tests/conf/res/base/attributeNames.xml new file mode 100644 index 0000000000..c6e6cd6568 --- /dev/null +++ b/tests/conf/res/base/attributeNames.xml @@ -0,0 +1,243 @@ + + + + + ATTRIBUTE_NAMES + + + + product_type + datatype + satellite + area_subtype + product + parameter + non_goes_satellite_product + source + creating_entity + locationkey + physical_element + projection + resolution + lambert_scanning_horiz + lambert_scanning_vert + lambert_scanning_axis + + mercator_scanning_horiz + + + mercator_scanning_vert + + + mercator_scanning_axis + + + mercator_intersect_lat + + + navigational_indicator + + projection_center + records + record_size + valid_time + Nx + Ny + Lat1 + Lon1 + Lov + Dx + Dy + Latin1 + image_resolution + data_compression + version_number + + navigational_indicator + + navigational_info + resolution + Lat2 + Lon2 + + longitudinal_increment + + latitudinal_increment + + mercator_intersection_lat + + image_resolution + number_octets + reserved + original_filename + key + plainText</PLAINTEXT> + <DECODEMETHOD>decode_method</DECODEMETHOD> + <INDEXDIR>indexDir</INDEXDIR> + <INDEXTIME>index_time</INDEXTIME> + <PERSISTDIR>persistDir</PERSISTDIR> + <DECODER>Decoder</DECODER> + <PLUGIN>Plugin</PLUGIN> + <PLUGINDIR>pluginDirectory</PLUGINDIR> + <SERVICEDIR>servicesDirectory</SERVICEDIR> + <DEGRIBEXECPATH>degribExecPath</DEGRIBEXECPATH> + <HTTPPROXYSET>httpProxySet</HTTPPROXYSET> + <HTTPPROXYHOST>httpProxyHost</HTTPPROXYHOST> + <HTTPPROXYPORT>httpProxyPort</HTTPPROXYPORT> + <FILENAMEDECODER>FilenameDecoder</FILENAMEDECODER> + <WRITER>Writer</WRITER> + <UENGINEOUTDIR>uengineOutDir</UENGINEOUTDIR> + <DEFAULTDATADIR>defaultDataDir</DEFAULTDATADIR> + <GRIBJARS>gribJars</GRIBJARS> + <BMEXISTS>bms_exists</BMEXISTS> + <GDEXISTS>gds_exists</GDEXISTS> + <BASETIME>base_time</BASETIME> + <CENTERNAME>center_name</CENTERNAME> + <DECIMALSCALE>decimal_scale</DECIMALSCALE> + <DESCRIPTION>description</DESCRIPTION> + <FORECASTTIME>forecast_time</FORECASTTIME> + <GRIDID>grid_id</GRIDID> + <FIRSTFIXEDSURFACE>first_fixed_surface</FIRSTFIXEDSURFACE> + <FIRSTFIXEDVALUE>first_fixed_value</FIRSTFIXEDVALUE> + <FIRSTFIXEDSURFACEUNITS> + first_fixed_surface_units + </FIRSTFIXEDSURFACEUNITS> + <SECONDFIXEDSURFACE>second_fixed_surface</SECONDFIXEDSURFACE> + <SECONDFIXEDVALUE>second_fixed_value</SECONDFIXEDVALUE> + <SECONDFIXEDSURFACEUNITS> + second_fixed_surface_units + </SECONDFIXEDSURFACEUNITS> + <PROCESSID>process_id</PROCESSID> + <PRODUCDEFINITIONNAME>product_definition_name</PRODUCDEFINITIONNAME> + <REFERENCETIME>reference_time</REFERENCETIME> + <SUBCENTERNAME>subcenter_name</SUBCENTERNAME> + <TIMERANGE>time_range</TIMERANGE> + <TIMEUNITS>time_units</TIMEUNITS> + <PARAMETERTYPE>parameter_type</PARAMETERTYPE> + <PARAMETERUNITS>parameter_units</PARAMETERUNITS> + <ANALYSISGENPROCESS>analysis_gen_process</ANALYSISGENPROCESS> + <BACKGENPROCESS>back_gen_process</BACKGENPROCESS> + <COORDINATES>coordinates</COORDINATES> + <HOURSAFTER>hours_after</HOURSAFTER> + <MINUTESAFTER>minutes_after</MINUTESAFTER> + <PARAMETERCATEGORY>parameter_category</PARAMETERCATEGORY> + <PARAMETERNUMBER>parameter_number</PARAMETERNUMBER> + <PRODUCTDEFINITION>product_definition</PRODUCTDEFINITION> + <PRODUCTDEFINITIONNAME> + product_definition_name + </PRODUCTDEFINITIONNAME> + <GENPROCESS>gen_process</GENPROCESS> + <GRIBTYPE>grib_type</GRIBTYPE> + <PROJTYPE>projection</PROJTYPE> + <SPATIAL_DESCRIPTOR>spatial_descriptor</SPATIAL_DESCRIPTOR> + + <RED>red</RED> + <BLUE>blue</BLUE> + <GREEN>green</GREEN> + + <JSLIBRARY>jsLibraryDir</JSLIBRARY> + + <LowLightVis>3</LowLightVis> + <IRDefault>7</IRDefault> + <WVAlternate>10</WVAlternate> + <Linear>57</Linear> + <WindModes>16</WindModes> + <WindSpeed>18</WindSpeed> + <Velocity>19</Velocity> + <Reflectivity>20</Reflectivity> + <LayerMaxRefl>21</LayerMaxRefl> + <VisDefault>25</VisDefault> + <GriddedData>29</GriddedData> + <LowrangeEnhanced>30</LowrangeEnhanced> + <MidrangeEnhanced>31</MidrangeEnhanced> + <HirangeEnhanced>32</HirangeEnhanced> + <WarmToCold>33</WarmToCold> + <CWBZReflectivity>34</CWBZReflectivity> + <StormClearReflectivity>35</StormClearReflectivity> + <IRWV>36</IRWV> + <IRFog>37</IRFog> + <SLCWV>38</SLCWV> + <Lvl8Vel>39</Lvl8Vel> + <Bit8Refl>40</Bit8Refl> + <VADWindProfile>41</VADWindProfile> + <VelocityAzimuthDisplay>42</VelocityAzimuthDisplay> + <Level16Reflectivity>43</Level16Reflectivity> + <Level8Reflectivity>44</Level8Reflectivity> + <Level256Reflectivity>72</Level256Reflectivity> + <Level16Velocity>45</Level16Velocity> + <Level8Velocity>46</Level8Velocity> + <Level256Velocity>73</Level256Velocity> + <Hr1_3PrecipAccumulation>47</Hr1_3PrecipAccumulation> + <SpectrumWidth>48</SpectrumWidth> + <Level16CompositeReflectivity>49</Level16CompositeReflectivity> + <Shear>50</Shear> + <StormClearRefl>74</StormClearRefl> + <SevereWxProb>51</SevereWxProb> + <EchoTops>52</EchoTops> + <CombinedShear>53</CombinedShear> + <VerticallyIntegratedLiquid>54</VerticallyIntegratedLiquid> + <SRMRadialVelocity>55</SRMRadialVelocity> + <ClutterFilterControl>56</ClutterFilterControl> + <GrayScaleWaterVapor>11</GrayScaleWaterVapor> + <CWAThreatIndex>58</CWAThreatIndex> + <LiftedIndex>60</LiftedIndex> + <PrecipWater>61</PrecipWater> + <SkinTemp>62</SkinTemp> + <CloudTopHeight>63</CloudTopHeight> + <QPFBestCategory>68</QPFBestCategory> + <LAMPGriddedData>69</LAMPGriddedData> + <Bit8Vel>70</Bit8Vel> + <km10RadarCodedMessage>71</km10RadarCodedMessage> + <Hr0_3RadarBasedProbabilities>75</Hr0_3RadarBasedProbabilities> + <Hr0_3RadarBasedCategorical>76</Hr0_3RadarBasedCategorical> + <DigitalVIL>77</DigitalVIL> + <OSFDigitalVIL>78</OSFDigitalVIL> + <EnhancedEchoTops>79</EnhancedEchoTops> + <StormTotalPrecip>80</StormTotalPrecip> + <OSFStormTotalPrecip>81</OSFStormTotalPrecip> + <CUSTOM_LIB>customLib</CUSTOM_LIB> + <DATAURI>dataURI</DATAURI> + + <OBJECT>OBJECT</OBJECT> + <METADATA>METADATA</METADATA> + <SEPARATOR>SEPARATOR</SEPARATOR> + <RECORD>Record</RECORD> + + <ADAPTERSRVQUE>adapterServiceQueue</ADAPTERSRVQUE> + <RESFOLDER>resFolder</RESFOLDER> + <HDF5DIR>hdf5Dir</HDF5DIR> + <SHAREDIR>shareDir</SHAREDIR> + <SCRIPTFOLDER>pluginScriptFolder</SCRIPTFOLDER> + + <BINDADDR>bindAddr</BINDADDR> + <UTILITYDIR>utilityDir</UTILITYDIR> + <STATICDIR>staticDir</STATICDIR> + <SITENAME>sitename</SITENAME> + <GFESMARTINIT>gfeSmartInitEnable</GFESMARTINIT> + <LOGDIR>logDir</LOGDIR> + <FXADEBUGSAVEBADTEXTFILES>fxaDebugSaveBadTextFiles</FXADEBUGSAVEBADTEXTFILES> + <ARCHIVEDIR>archiveDir</ARCHIVEDIR> + <SVCBACKUP>svcBackupDir</SVCBACKUP> + <MHS_DATA>mhsData</MHS_DATA> +</properties> + diff --git a/tests/conf/res/base/environment.xml b/tests/conf/res/base/environment.xml new file mode 100644 index 0000000000..f76a4ebefe --- /dev/null +++ b/tests/conf/res/base/environment.xml @@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!-- + 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. + --> + +<properties> + <Name>ENVIRONMENT</Name> + <logDir>${env:edex.home}/logs</logDir> + <pluginDirectory>${env:edex.home}/lib/plugins/</pluginDirectory> + <servicesDirectory>${env:edex.home}/lib/services/</servicesDirectory> + <pluginResDirectory>res/</pluginResDirectory> + <httpProxySet>true</httpProxySet> + <httpProxyHost>proxy.ext.ray.com</httpProxyHost> + <httpProxyPort>80</httpProxyPort> + <gribJars>${env:edex.home}/lib</gribJars> + <uengineOutDir>${env:edex.home}/data/uEngine</uengineOutDir> + <defaultDataDir>${env:edex.home}/data/</defaultDataDir> + <archiveDir>${env:data.archive.root}</archiveDir> + <jsLibraryDir>${env:edex.home}/esb/js/</jsLibraryDir> + <customLib>${env:edex.home}/lib/</customLib> + <bindAddr>bindaddr</bindAddr> + <adapterServiceQueue>edex.AdapterSrv</adapterServiceQueue> + <resFolder>../conf/res</resFolder> + <pluginScriptFolder>${env:edex.home}/conf/db/commonScripts/</pluginScriptFolder> + <!-- + hdf5Dir now refers only to the local hdf5 directory; pypies keeps track + of its own hdf5 directory. The local hdf5 directory will only be used + by plugins that do not store / retrieve their data through pypies + (ex: QC). + --> + <hdf5Dir>${env:edex.home}/data/hdf5</hdf5Dir> + <shareDir>${env:edex.home}/data/share</shareDir> + <utilityDir>${env:edex.home}/data/utility</utilityDir> + <staticDir>${env:edex.home}/data/static</staticDir> + <gfeSmartInitEnable>true</gfeSmartInitEnable> + <fxaDebugSaveBadTextFiles>false</fxaDebugSaveBadTextFiles> + <svcBackupDir>${env:edex.home}/../GFESuite/</svcBackupDir> + <mhsData>/data/fxa/mhs</mhsData> +</properties> + + diff --git a/tests/conf/res/config.xml b/tests/conf/res/config.xml new file mode 100644 index 0000000000..6a054d604c --- /dev/null +++ b/tests/conf/res/config.xml @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!-- + 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. + --> + +<configuration> + <header> + <result> + <nodeCombiner config-class="org.apache.commons.configuration.tree.OverrideCombiner"/> + </result> + </header> + + <!-- Localized Environmental Properties --> + <override> + <xml fileName="site/environment.xml" encoding="UTF-8" validating="false" /> + <xml fileName="base/environment.xml" encoding="UTF-8" validating="false" /> + </override> + + <!-- Localized Attribute Names --> + <override> + <xml fileName="site/attributeNames.xml" encoding="UTF-8" validating="false" /> + <xml fileName="base/attributeNames.xml" encoding="UTF-8" validating="false" /> + </override> + +</configuration> + + diff --git a/tests/conf/res/site/attributeNames.xml b/tests/conf/res/site/attributeNames.xml new file mode 100644 index 0000000000..ed6efd29be --- /dev/null +++ b/tests/conf/res/site/attributeNames.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!-- + 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. + --> + +<properties> + <Name>ATTRIBUTE_NAMES</Name> +</properties> + diff --git a/tests/conf/res/site/environment.xml b/tests/conf/res/site/environment.xml new file mode 100644 index 0000000000..78acd16974 --- /dev/null +++ b/tests/conf/res/site/environment.xml @@ -0,0 +1,29 @@ +<?xml version="1.0" encoding="ISO-8859-1" ?> + <!-- + 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. + --> + +<properties> + <Name>ENVIRONMENT</Name> + <clustered>false</clustered> + <sitename>${env:aw.site.identifier}</sitename> + <!-- httpServer and jmsServer moved to setup.env --> +</properties> + + diff --git a/tests/unit/com/raytheon/uf/common/localization/PathManagerFactoryTest.java b/tests/unit/com/raytheon/uf/common/localization/PathManagerFactoryTest.java index ea5d25f951..0b1438bad3 100644 --- a/tests/unit/com/raytheon/uf/common/localization/PathManagerFactoryTest.java +++ b/tests/unit/com/raytheon/uf/common/localization/PathManagerFactoryTest.java @@ -22,6 +22,7 @@ package com.raytheon.uf.common.localization; import static org.junit.Assert.assertTrue; import java.io.File; +import java.io.IOException; import org.junit.Before; import org.junit.Test; @@ -32,6 +33,7 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; import com.raytheon.uf.common.localization.TestPathManager.TestLocalizationAdapter; +import com.raytheon.uf.common.util.FileUtil; import com.raytheon.uf.common.util.TestUtil; /** @@ -47,6 +49,7 @@ import com.raytheon.uf.common.util.TestUtil; * Jul 18, 2012 740 djohnson Initial creation * Oct 23, 2012 1286 djohnson Handle executing tests in Eclipse/command-line transparently. * Apr 18, 2013 1914 djohnson Allow initializing test localization support from Spring. + * Jan 08, 2014 2615 bgonzale Fixes for PropertiesFactory configuration loading in test. * * </pre> * @@ -74,7 +77,8 @@ public class PathManagerFactoryTest implements BeanFactoryPostProcessor { // Clear known file cache and the directory each time PathManager.fileCache.clear(); File file = TestUtil.setupTestClassDir(PathManagerFactoryTest.class); - savedLocalizationFileDir = new File(file, "utility"); + savedLocalizationFileDir = new File(file, "data"); + savedLocalizationFileDir = new File(savedLocalizationFileDir, "utility"); savedLocalizationFileDir.mkdirs(); // But only install the path manager if the test version is not already @@ -85,6 +89,20 @@ public class PathManagerFactoryTest implements BeanFactoryPostProcessor { : new CommandLineTestLocalizationAdapter(site, savedLocalizationFileDir); PathManagerFactory.pathManager = new TestPathManager(adapter); + + System.setProperty("edex.home", file.getAbsolutePath()); + File confResDataDir = new File(file, "conf/res"); + confResDataDir.mkdirs(); + File confResTestDataDir = new File("conf/res/"); + + try { + FileUtil.copyDirectory(confResTestDataDir, confResDataDir); + } catch (IOException e) { + throw new RuntimeException( + "Failed to setup test configuration directory conf/res", + e); + } + } } diff --git a/tests/unit/com/raytheon/uf/common/registry/handler/RegistryObjectHandlersUtil.java b/tests/unit/com/raytheon/uf/common/registry/handler/RegistryObjectHandlersUtil.java index 48a94b61d6..d163eee15e 100644 --- a/tests/unit/com/raytheon/uf/common/registry/handler/RegistryObjectHandlersUtil.java +++ b/tests/unit/com/raytheon/uf/common/registry/handler/RegistryObjectHandlersUtil.java @@ -37,7 +37,8 @@ import com.raytheon.uf.common.util.TestUtil; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Oct 04, 2012 1241 djohnson Initial creation - * Jul 10, 2013 2106 djohnson Spring file path moved to SpringFiles for reuse. + * Jul 10, 2013 2106 djohnson Spring file path moved to SpringFiles for reuse. + * Jan 09, 2014 2615 bgonzale Added spring files to initialize beans missing in tests. * * </pre> * @@ -78,7 +79,9 @@ public class RegistryObjectHandlersUtil { RegistryObjectHandlers.clear(); new ClassPathXmlApplicationContext( new String[] { + TestUtil.getResResourcePath(SpringFiles.DATADELIVERY_HANDLERS_IMPL_XML), TestUtil.getResResourcePath(SpringFiles.DATADELIVERY_HANDLERS_XML), + TestUtil.getResResourcePath(SpringFiles.DATADELIVERY_STANDALONE_XML), TestUtil.getResResourcePath(resResource) }, RegistryObjectHandlersUtil.class); } diff --git a/tests/unit/com/raytheon/uf/common/util/SpringFiles.java b/tests/unit/com/raytheon/uf/common/util/SpringFiles.java index 7e9e4d466a..4c58a75a2c 100644 --- a/tests/unit/com/raytheon/uf/common/util/SpringFiles.java +++ b/tests/unit/com/raytheon/uf/common/util/SpringFiles.java @@ -36,6 +36,7 @@ import org.junit.Ignore; * May 28, 2013 1650 djohnson Add event bus spring files. * Jun 24, 2013 2106 djohnson Remove spring file. * Jul 10, 2013 2106 djohnson Add MEMORY_DATADELIVERY_HANDLERS_XML. + * Jan 09, 2014 2615 bgonzale Add DATADELIVERY_STANDALONE_XML. * * </pre> * @@ -73,6 +74,8 @@ public class SpringFiles { public static final String DATADELIVERY_HANDLERS_IMPL_XML = "/spring/datadelivery-handlers-impl.xml"; + public static final String DATADELIVERY_STANDALONE_XML = "/spring/datadelivery-standalone.xml"; + public static final String EBXML_XML = "/spring/ebxml.xml"; public static final String EBXML_IMPL_XML = "/spring/ebxml-impl.xml"; diff --git a/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtilTest.java b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtilTest.java index b757a704c3..e06437442c 100644 --- a/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtilTest.java +++ b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/util/BandwidthDaoUtilTest.java @@ -33,6 +33,7 @@ import static org.mockito.Mockito.when; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; +import java.util.Collections; import java.util.Date; import java.util.List; import java.util.Map; @@ -56,6 +57,7 @@ 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.registry.handler.RegistryObjectHandlersUtil; import com.raytheon.uf.common.time.util.TimeUtil; import com.raytheon.uf.common.time.util.TimeUtilTest; import com.raytheon.uf.edex.datadelivery.bandwidth.InMemoryBandwidthBucketDao; @@ -81,8 +83,9 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.retrieval.RetrievalStatus; * Feb 14, 2013 1595 djohnson Fix retrieval plan/subscription time intersections. * Jun 05, 2013 2038 djohnson Use public API for getting retrieval times. * Jun 25, 2013 2106 djohnson RetrievalPlan uses setters instead of constructor injection now. - * Sept 25, 2013 1797 dhladky separated time and gridded time + * Sep 25, 2013 1797 dhladky separated time and gridded time * Jan 07, 2014 2636 mpduff Removed dataset availability offset calculator (not used). + * Jan 08, 2014 2615 bgonzale Updated test. * * </pre> * @@ -107,6 +110,7 @@ public class BandwidthDaoUtilTest { public void setUp() { TimeUtilTest.freezeTime(TimeUtil.MILLIS_PER_DAY * 2); + RegistryObjectHandlersUtil.init(); PathManagerFactoryTest.initLocalization(); IPathManager pm = PathManagerFactory.getPathManager(); @@ -183,7 +187,7 @@ public class BandwidthDaoUtilTest { SortedSet<Calendar> subscriptionTimes = bandwidthDaoUtil .getRetrievalTimes(subscription, cycles); - final List<Integer> daysOfTheYear = Arrays.asList(4); + final List<Integer> daysOfTheYear = Collections.EMPTY_LIST; verifySubscriptionTimesContainsCyclesForSpecifiedDays(daysOfTheYear, cycles, subscriptionTimes); final List<Integer> notScheduledDays = Arrays.asList(3); From 850ee18fd4dc22e1a687001f2636ac14bdc3b48d Mon Sep 17 00:00:00 2001 From: Mike Duff <michael.duff@raytheon.com> Date: Mon, 13 Jan 2014 09:25:34 -0600 Subject: [PATCH 31/62] Issue #2636 - Removed apache Equals and Hashcode builder, using eclipse generated versions. Former-commit-id: 2a1f84b72d180b51763ed8832c09143a8f813550 [formerly 92b404f6ecdd80839b5e32b1d1d598ff33c691e8] [formerly 9e817de4a98ce7869907e5053e293518736a5462 [formerly 605f5a0a496deeb9be0e3aed1a56f6ac816038b4]] Former-commit-id: 9e817de4a98ce7869907e5053e293518736a5462 Former-commit-id: fc3dec0591b9b8348db0e7b7f23dac4eb95ceeb7 --- .../bandwidth/util/NameProviderKey.java | 43 +++++++++++++------ 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/NameProviderKey.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/NameProviderKey.java index b056948a7b..bc2ec66849 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/NameProviderKey.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/util/NameProviderKey.java @@ -19,8 +19,6 @@ **/ package com.raytheon.uf.edex.datadelivery.bandwidth.util; -import org.apache.commons.lang.builder.EqualsBuilder; -import org.apache.commons.lang.builder.HashCodeBuilder; /** * Object holding name and provider Strings to act as a hash key. @@ -31,7 +29,8 @@ import org.apache.commons.lang.builder.HashCodeBuilder; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Dec 20, 2013 2636 mpduff Initial creation + * Dec 20, 2013 2636 mpduff Initial creation. + * Jan 13, 2014 2636 mpduff Removed the apache commons Equals/Hashcode builder. * * </pre> * @@ -89,11 +88,12 @@ public class NameProviderKey { */ @Override public int hashCode() { - HashCodeBuilder builder = new HashCodeBuilder(); - builder.append(name); - builder.append(provider); - - return builder.hashCode(); + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + + ((provider == null) ? 0 : provider.hashCode()); + return result; } /* @@ -103,15 +103,30 @@ public class NameProviderKey { */ @Override public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } if (!(obj instanceof NameProviderKey)) { return false; } NameProviderKey other = (NameProviderKey) obj; - - EqualsBuilder builder = new EqualsBuilder(); - builder.append(this.name, other.getName()); - builder.append(this.provider, other.getProvider()); - - return builder.isEquals(); + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (provider == null) { + if (other.provider != null) { + return false; + } + } else if (!provider.equals(other.provider)) { + return false; + } + return true; } } From ff88e4ab9995d181d5b8061c64c50663e3b84683 Mon Sep 17 00:00:00 2001 From: Nate Jensen <Nathan.Jensen@raytheon.com> Date: Mon, 13 Jan 2014 12:56:24 -0600 Subject: [PATCH 32/62] Issue #2581 improve LSR error handling because there was yet another event type missing Change-Id: I954d408ecfcfda14f3856f4afc7c04e7ef8148be Former-commit-id: 738f97cab1b39644699b105235661c6f483d8d6e [formerly eb96c396c286a3391876573ca7c146f6bfe77acc] [formerly b6a21ccb7c845cc038a7a3737c3b58020fc953e5 [formerly b85ccd6315e5506c67c39f939c71af363d15a45f]] Former-commit-id: b6a21ccb7c845cc038a7a3737c3b58020fc953e5 Former-commit-id: 1b0a722e0219f97ce34e4e5ca30ef060c3e33492 --- .../common/dataplugin/lsr/LSREventType.java | 4 +- .../META-INF/MANIFEST.MF | 1 + .../exception/BadDataException.java | 74 +++++++++++++++++++ .../exception/UnrecognizedDataException.java | 74 +++++++++++++++++++ .../uf/edex/plugin/lsr/decoder/LSRParser.java | 50 ++++++++----- 5 files changed, 184 insertions(+), 19 deletions(-) create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/exception/BadDataException.java create mode 100644 edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/exception/UnrecognizedDataException.java diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java b/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java index fd2fe785cd..7c95421386 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java @@ -35,6 +35,7 @@ import java.util.Map; * Oct 14, 2009 jkorman Initial creation * Dec 09, 2013 2581 njensen Added freezing drizzle * Jan 03, 2014 2581 njensen Added coastal flood + * Jan 13, 2014 2581 njensen Added debris flow * * </pre> * @@ -85,7 +86,8 @@ public enum LSREventType { WATERSPOUT("WATER SPOUT",38,LSRUnits.NOUNITS), WILDFIRE("WILDFIRE",39,LSRUnits.NOUNITS), FREEZINGDRIZZLE("FREEZING DRIZZLE", 40, LSRUnits.NOUNITS), - COASTALFLOOD("COASTAL FLOOD", 41, LSRUnits.NOUNITS); + COASTALFLOOD("COASTAL FLOOD", 41, LSRUnits.NOUNITS), + DEBRISFLOW("DEBRIS FLOW", 42, LSRUnits.NOUNITS); private final String eventName; diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.common.dataplugin/META-INF/MANIFEST.MF index dee4ff2d80..7528d681f3 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin/META-INF/MANIFEST.MF +++ b/edexOsgi/com.raytheon.uf.common.dataplugin/META-INF/MANIFEST.MF @@ -9,6 +9,7 @@ Eclipse-RegisterBuddy: com.raytheon.uf.common.serialization Export-Package: com.raytheon.uf.common.dataplugin, com.raytheon.uf.common.dataplugin.annotations, com.raytheon.uf.common.dataplugin.defaults, + com.raytheon.uf.common.dataplugin.exception, com.raytheon.uf.common.dataplugin.message, com.raytheon.uf.common.dataplugin.persist, com.raytheon.uf.common.dataplugin.request diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/exception/BadDataException.java b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/exception/BadDataException.java new file mode 100644 index 0000000000..53a495ff28 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/exception/BadDataException.java @@ -0,0 +1,74 @@ +/** + * 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.exception; + +/** + * An exception for bad data. Intended primarily to be subclassed but + * potentially used in catch blocks. + * + * <pre> + * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Jan 13, 2014 njensen Initial creation + * + * </pre> + * + * @author njensen + * @version 1.0 + */ + +public abstract class BadDataException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * Default Constructor + * + */ + public BadDataException() { + super(); + } + + /** + * @param message + */ + public BadDataException(String message) { + super(message); + } + + /** + * @param message + * @param cause + */ + public BadDataException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param cause + */ + public BadDataException(Throwable cause) { + super(cause); + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/exception/UnrecognizedDataException.java b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/exception/UnrecognizedDataException.java new file mode 100644 index 0000000000..1d048ecae9 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.dataplugin/src/com/raytheon/uf/common/dataplugin/exception/UnrecognizedDataException.java @@ -0,0 +1,74 @@ +/** + * 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.exception; + +/** + * An exception for when the data may be valid but the code does not recognize + * it and/or doesn't know to handle it. + * + * <pre> + * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Jan 13, 2014 2581 njensen Initial creation + * + * </pre> + * + * @author njensen + * @version 1.0 + */ + +public class UnrecognizedDataException extends BadDataException { + + private static final long serialVersionUID = 1L; + + /** + * Default Constructor + * + */ + public UnrecognizedDataException() { + super(); + } + + /** + * @param message + */ + public UnrecognizedDataException(String message) { + super(message); + } + + /** + * @param message + * @param cause + */ + public UnrecognizedDataException(String message, Throwable cause) { + super(message, cause); + } + + /** + * @param cause + */ + public UnrecognizedDataException(Throwable cause) { + super(cause); + } + +} diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java b/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java index 9e75eac277..b8da362fb3 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.lsr/src/com/raytheon/uf/edex/plugin/lsr/decoder/LSRParser.java @@ -29,6 +29,7 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; import com.raytheon.edex.esb.Headers; +import com.raytheon.uf.common.dataplugin.exception.UnrecognizedDataException; import com.raytheon.uf.common.dataplugin.lsr.LSREventType; import com.raytheon.uf.common.dataplugin.lsr.LocalStormReport; import com.raytheon.uf.common.pointdata.PointDataContainer; @@ -55,6 +56,7 @@ import com.raytheon.uf.edex.wmo.message.WMOHeader; * Dec 09, 2013 2581 njensen Reuse patterns for efficiency * Check entire time line looking for latlon * Jan 07, 2013 2581 njensen Check to end of string for source, not a set length + * Jan 13, 2013 2581 njensen Improved error handling and logging * * </pre> * @@ -315,26 +317,32 @@ public class LSRParser { LocalStormReport rpt = new LocalStormReport(); String s = r.getReportLine(); - if (parseTimeLine(s, rpt)) { - List<InternalReport> rptLines = r.getSubLines(); - if (rptLines != null) { - r = rptLines.get(0); - if (InternalType.DATE.equals(r.getLineType())) { - s = r.getReportLine(); - if (parseDateLine(s, rpt)) { - // Now check the remarks section. - parseRemarks(rptLines, rpt); - rpt.setWmoHeader(wmoHeader - .getWmoHeader()); - rpt.setOfficeid(officeid); - rpt.setTraceId(traceId); + try { + if (parseTimeLine(s, rpt)) { + List<InternalReport> rptLines = r.getSubLines(); + if (rptLines != null) { + r = rptLines.get(0); + if (InternalType.DATE.equals(r + .getLineType())) { + s = r.getReportLine(); + if (parseDateLine(s, rpt)) { + // Now check the remarks section. + parseRemarks(rptLines, rpt); + rpt.setWmoHeader(wmoHeader + .getWmoHeader()); + rpt.setOfficeid(officeid); + rpt.setTraceId(traceId); - reports.add(rpt); + reports.add(rpt); + } + } else { + logger.error("Date Line expected"); } - } else { - logger.error("Date Line expected"); } } + } catch (UnrecognizedDataException e) { + logger.error("Error decoding line " + s + + " - skipping this entry", e); } } } @@ -343,7 +351,8 @@ public class LSRParser { return reports; } - private boolean parseTimeLine(String timeLine, LocalStormReport rpt) { + private boolean parseTimeLine(String timeLine, LocalStormReport rpt) + throws UnrecognizedDataException { boolean timeOk = false; if (timeLine != null) { @@ -366,7 +375,12 @@ public class LSRParser { } } ss = timeLine.substring(EVENT, EVENT + EVENT_LENGTH).trim(); - rpt.setEventType(LSREventType.lookup(ss)); + LSREventType eventType = LSREventType.lookup(ss); + if (eventType == null) { + throw new UnrecognizedDataException( + "LSRParser does not recognize eventType " + ss); + } + rpt.setEventType(eventType); ss = timeLine.substring(LOCATION, LOCATION + LOCATION_LENGTH) .trim(); From 5cf9c5bd1c1f9ec02f21344b861946c75eca78cd Mon Sep 17 00:00:00 2001 From: Dave Hladky <david_j_hladky@raytheon.com> Date: Tue, 14 Jan 2014 15:25:25 -0600 Subject: [PATCH 33/62] Issue #2692 Fixed non-notification of adhoc's due to incorrect lookup of subscription. Former-commit-id: 56b0f4274dc310a976bac06eae50d1e80b10d015 [formerly fee9c183f9ae495f12f7574c73f175154934714f] [formerly 8a6a386410cd2e44202e916bf232a7ebc73f33f6 [formerly 339245a534bf2da5071536e959086d5e4f7b2bf0]] Former-commit-id: 8a6a386410cd2e44202e916bf232a7ebc73f33f6 Former-commit-id: 79e5b19f314cc818010d362c6366fdb1a9afe268 --- .../MonolithicBandwidthManagerCreator.java | 8 +++-- .../ncf/NcfBandwidthManagerCreator.java | 8 +++-- .../bandwidth-datadelivery-edex-impl.xml | 1 + .../bandwidth/BandwidthManager.java | 6 ++-- .../EdexBandwidthContextFactory.java | 12 +++++-- .../bandwidth/EdexBandwidthManager.java | 34 +++++++++++++++---- .../bandwidth/WfoBandwidthManagerCreator.java | 8 +++-- ...ntegrationTestBandwidthContextFactory.java | 7 ++-- .../IntegrationTestWfoBandwidthManager.java | 5 ++- ...grationTestWfoBandwidthManagerCreator.java | 5 ++- .../IntegrationTestNcfBandwidthManager.java | 5 ++- ...grationTestNcfBandwidthManagerCreator.java | 5 ++- 12 files changed, 80 insertions(+), 24 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/src/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/MonolithicBandwidthManagerCreator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/src/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/MonolithicBandwidthManagerCreator.java index 0a9f771c5b..d88467860f 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/src/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/MonolithicBandwidthManagerCreator.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/src/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/MonolithicBandwidthManagerCreator.java @@ -21,6 +21,7 @@ package com.raytheon.uf.edex.datadelivery.bandwidth.ncf; import com.raytheon.uf.common.datadelivery.registry.Coverage; import com.raytheon.uf.common.datadelivery.registry.Time; +import com.raytheon.uf.common.datadelivery.registry.handlers.IAdhocSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; import com.raytheon.uf.common.datadelivery.service.ISubscriptionNotificationService; @@ -49,6 +50,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthDaoUtil; * ------------ ---------- ----------- -------------------------- * Nov 13, 2013 2545 bgonzale Initial creation * Dec 04, 2013 2566 bgonzale use bandwidthmanager method to retrieve spring files. + * Jan 14, 2014 2692 dhladky AdhocSubscription handler * * </pre> * @@ -81,9 +83,10 @@ public class MonolithicBandwidthManagerCreator<T extends Time, C extends Coverag BandwidthDaoUtil<T, C> bandwidthDaoUtil, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService subscriptionNotificationService) { super(dbInit, bandwidthDao, retrievalManager, bandwidthDaoUtil, - dataSetMetaDataHandler, subscriptionHandler, + dataSetMetaDataHandler, subscriptionHandler, adhocSubscriptionHandler, subscriptionNotificationService); } @@ -103,10 +106,11 @@ public class MonolithicBandwidthManagerCreator<T extends Time, C extends Coverag BandwidthDaoUtil bandwidthDaoUtil, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService subscriptionNotificationService) { return new MonolithicBandwidthManager(dbInit, bandwidthDao, retrievalManager, - bandwidthDaoUtil, dataSetMetaDataHandler, subscriptionHandler, + bandwidthDaoUtil, dataSetMetaDataHandler, subscriptionHandler, adhocSubscriptionHandler, subscriptionNotificationService); } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/src/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/NcfBandwidthManagerCreator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/src/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/NcfBandwidthManagerCreator.java index 151229bcb3..2c8e60b0e5 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/src/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/NcfBandwidthManagerCreator.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/src/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/NcfBandwidthManagerCreator.java @@ -29,6 +29,7 @@ import com.raytheon.uf.common.datadelivery.registry.Coverage; import com.raytheon.uf.common.datadelivery.registry.DataDeliveryRegistryObjectTypes; import com.raytheon.uf.common.datadelivery.registry.Subscription; import com.raytheon.uf.common.datadelivery.registry.Time; +import com.raytheon.uf.common.datadelivery.registry.handlers.IAdhocSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; import com.raytheon.uf.common.datadelivery.service.ISubscriptionNotificationService; @@ -62,6 +63,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthDaoUtil; * Nov 19, 2013 2545 bgonzale Added registryEventListener method for update events. * Reschedule updated shared subscriptions. * Dec 04, 2013 2566 bgonzale use bandwidthmanager method to retrieve spring files. + * Jan 14, 2014 2692 dhladky AdhocSubscription handler * * </pre> * @@ -92,9 +94,10 @@ public class NcfBandwidthManagerCreator<T extends Time, C extends Coverage> impl BandwidthDaoUtil<T, C> bandwidthDaoUtil, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService subscriptionNotificationService) { super(dbInit, bandwidthDao, retrievalManager, bandwidthDaoUtil, - dataSetMetaDataHandler, subscriptionHandler, + dataSetMetaDataHandler, subscriptionHandler, adhocSubscriptionHandler, subscriptionNotificationService); } @@ -151,9 +154,10 @@ public class NcfBandwidthManagerCreator<T extends Time, C extends Coverage> impl BandwidthDaoUtil bandwidthDaoUtil, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService subscriptionNotificationService) { return new NcfBandwidthManager(dbInit, bandwidthDao, retrievalManager, - bandwidthDaoUtil, dataSetMetaDataHandler, subscriptionHandler, + bandwidthDaoUtil, dataSetMetaDataHandler, subscriptionHandler, adhocSubscriptionHandler, subscriptionNotificationService); } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl.xml index 2d4d87e504..97313a4dd5 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl.xml @@ -48,6 +48,7 @@ <!-- Registry handlers required for EdexBandwidthManager --> <constructor-arg ref="DataSetMetaDataHandler" /> <constructor-arg ref="SubscriptionHandler" /> + <constructor-arg ref="AdhocSubscriptionHandler" /> <constructor-arg ref="subscriptionNotificationService" /> </bean> </beans> \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java index 52431e5275..bc4e093f69 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java @@ -134,6 +134,7 @@ import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException; * Dec 17, 2013 2636 bgonzale Changed logging to differentiate the output. * Jan 08, 2014 2615 bgonzale getMostRecent checks subscription time constraints before scheduling. * handlePoint method now schedules most recent. + * Jan 14, 2014 2692 dhladky Bad Point scheduling final Empty list. * * </pre> * @@ -614,9 +615,8 @@ public abstract class BandwidthManager<T extends Time, C extends Coverage> */ private List<BandwidthAllocation> handlePoint( Subscription<T, C> subscription) { - List<BandwidthAllocation> unscheduled = Collections.emptyList(); - unscheduled.addAll(schedule(subscription, - ((PointTime) subscription.getTime()).getInterval())); + List<BandwidthAllocation> unscheduled = schedule(subscription, + ((PointTime) subscription.getTime()).getInterval()); unscheduled.addAll(getMostRecent(subscription, false)); return unscheduled; } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthContextFactory.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthContextFactory.java index 2714609c75..6a7725194b 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthContextFactory.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthContextFactory.java @@ -23,6 +23,7 @@ import java.io.File; import com.raytheon.uf.common.datadelivery.registry.Coverage; import com.raytheon.uf.common.datadelivery.registry.Time; +import com.raytheon.uf.common.datadelivery.registry.handlers.IAdhocSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; import com.raytheon.uf.common.datadelivery.service.ISubscriptionNotificationService; @@ -55,6 +56,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthDaoUtil; * Jul 10, 2013 2106 djohnson Dependency inject registry handlers. * Oct 03, 2013 1797 dhladky Some generics * Nov 07, 2013 2506 bgonzale Added notification handler to bandwidth context. + * Jan 14, 2014 2692 dhladky AdhocSubscription handler * * </pre> * @@ -85,6 +87,7 @@ public class EdexBandwidthContextFactory<T extends Time, C extends Coverage> imp BandwidthDaoUtil<T, C> bandwidthDaoUtil, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService notificationService); } @@ -103,6 +106,8 @@ public class EdexBandwidthContextFactory<T extends Time, C extends Coverage> imp private final IDataSetMetaDataHandler dataSetMetaDataHandler; private final ISubscriptionHandler subscriptionHandler; + + private final IAdhocSubscriptionHandler adhocSubscriptionHandler; private final ISubscriptionNotificationService notificationService; @@ -117,6 +122,7 @@ public class EdexBandwidthContextFactory<T extends Time, C extends Coverage> imp * @param dbInit * @param dataSetMetaDataHandler * @param subscriptionHandler + * @param adhocSubscriptionHandler * @param notificationService */ EdexBandwidthContextFactory(IBandwidthDao<T, C> bandwidthDao, @@ -126,6 +132,7 @@ public class EdexBandwidthContextFactory<T extends Time, C extends Coverage> imp IBandwidthDbInit dbInit, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService notificationService) { this.bandwidthDao = bandwidthDao; this.bandwidthBucketDao = bandwidthBucketDao; @@ -134,6 +141,7 @@ public class EdexBandwidthContextFactory<T extends Time, C extends Coverage> imp this.dbInit = dbInit; this.dataSetMetaDataHandler = dataSetMetaDataHandler; this.subscriptionHandler = subscriptionHandler; + this.adhocSubscriptionHandler = adhocSubscriptionHandler; this.notificationService = notificationService; } @@ -147,7 +155,7 @@ public class EdexBandwidthContextFactory<T extends Time, C extends Coverage> imp * the {@link BandwidthManager} instance */ EdexBandwidthContextFactory(EdexBandwidthManager<T, C> instance) { - this(null, null, null, null, null, null, null, null); + this(null, null, null, null, null, null, null, null, null); EdexBandwidthContextFactory.instance = instance; } @@ -239,7 +247,7 @@ public class EdexBandwidthContextFactory<T extends Time, C extends Coverage> imp BandwidthDaoUtil bandwidthDaoUtil) { return bandwidthManagerCreator.getBandwidthManager(dbInit, bandwidthDao, retrievalManager, bandwidthDaoUtil, - dataSetMetaDataHandler, subscriptionHandler, + dataSetMetaDataHandler, subscriptionHandler, adhocSubscriptionHandler, notificationService); } } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java index 0ef41d3a09..6542b1c51c 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java @@ -52,6 +52,7 @@ import com.raytheon.uf.common.datadelivery.registry.PointTime; import com.raytheon.uf.common.datadelivery.registry.SiteSubscription; import com.raytheon.uf.common.datadelivery.registry.Subscription; import com.raytheon.uf.common.datadelivery.registry.Time; +import com.raytheon.uf.common.datadelivery.registry.handlers.IAdhocSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; import com.raytheon.uf.common.datadelivery.service.ISubscriptionNotificationService; @@ -110,6 +111,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthUtil; * Nov 15, 2013 2545 bgonzale Added check for subscription events before sending * notifications. Republish dataset metadata registry * insert and update events as dataset metadata events. + * Jan 14, 2014 2692 dhladky AdhocSubscription handler * * </pre> * @@ -125,6 +127,8 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> private final IDataSetMetaDataHandler dataSetMetaDataHandler; private final ISubscriptionHandler subscriptionHandler; + + private final IAdhocSubscriptionHandler adhocSubscriptionHandler; private final ScheduledExecutorService scheduler; @@ -158,12 +162,14 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> BandwidthDaoUtil<T, C> bandwidthDaoUtil, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService subscriptionNotificationService) { super(dbInit, bandwidthDao, retrievalManager, bandwidthDaoUtil); this.dataSetMetaDataHandler = dataSetMetaDataHandler; this.subscriptionHandler = subscriptionHandler; this.subscriptionNotificationService = subscriptionNotificationService; + this.adhocSubscriptionHandler = adhocSubscriptionHandler; // schedule maintenance tasks scheduler = Executors.newScheduledThreadPool(1); @@ -228,6 +234,7 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> * @param subscription * The completed subscription. */ + @SuppressWarnings("unchecked") @Subscribe public void subscriptionFulfilled( SubscriptionRetrievalFulfilled subscriptionRetrievalFulfilled) { @@ -260,14 +267,23 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> // Schedule the next iteration of the subscription BandwidthSubscription dao = sr.getBandwidthSubscription(); Subscription<T, C> subscription; + try { + // recurring site subscription subscription = subscriptionHandler.getByName(dao.getName()); if (subscription == null) { - StringBuilder sb = new StringBuilder("Subscription: "); - sb.append(dao.getName()); - sb.append(" Not Found in Subscription Handler."); - throw new RegistryHandlerException(sb.toString()); + // not recurring, try an adhoc subscription + subscription = adhocSubscriptionHandler.getByName(dao + .getName()); + // still doesn't work, punt! + if (subscription == null) { + + StringBuilder sb = new StringBuilder("Subscription: "); + sb.append(dao.getName()); + sb.append(" Not Found in Subscription Handler."); + throw new RegistryHandlerException(sb.toString()); + } } } catch (RegistryHandlerException e1) { statusHandler.handle(Priority.PROBLEM, @@ -277,6 +293,8 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> // AdhocSubscriptions are one and done, so don't reschedule. if (subscription instanceof AdhocSubscription) { + statusHandler.info("Adhoc Subscription [" + + subscription.getName() + "] complete."); return; } @@ -321,6 +339,7 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> * * @param event */ + @SuppressWarnings("unchecked") @Subscribe @AllowConcurrentEvents public void subscriptionRemoved(RemoveRegistryEvent event) { @@ -356,6 +375,7 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> * @param re * The <code>InsertRegistryEvent</code> Object to evaluate. */ + @SuppressWarnings("unchecked") @Subscribe @AllowConcurrentEvents public void registryEventListener(InsertRegistryEvent re) { @@ -418,7 +438,7 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> private void publishDataSetMetaDataEvent(RegistryEvent re) { final String id = re.getId(); - DataSetMetaData dsmd = getDataSetMetaData(id); + DataSetMetaData<?> dsmd = getDataSetMetaData(id); if (dsmd != null) { // Repost the Object to the BandwidthEventBus to free @@ -442,6 +462,7 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> } } + @SuppressWarnings("unchecked") private DataSetMetaData<T> getDataSetMetaData(String id) { return getRegistryObjectById(dataSetMetaDataHandler, id); } @@ -739,7 +760,6 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> final SubscriptionRetrievalAttributes<T, C> sra = bandwidthDao .getSubscriptionRetrievalAttributes(retrieval); if (sra != null) { - @SuppressWarnings("unchecked") Subscription<T, C> sub = sra.getSubscription(); if (sub != null) { subscriptions.add(sub); @@ -768,7 +788,7 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> * the datasetmetadata update * @return the subscription */ - @SuppressWarnings("rawtypes") + @SuppressWarnings({ "rawtypes", "unchecked" }) private static Subscription updateSubscriptionWithDataSetMetaData( Subscription sub, DataSetMetaData dataSetMetaData) { // TODO perfect candidate for the factory for time and coverage diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/WfoBandwidthManagerCreator.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/WfoBandwidthManagerCreator.java index 65afbe1a37..dd440c65b8 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/WfoBandwidthManagerCreator.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/WfoBandwidthManagerCreator.java @@ -32,6 +32,7 @@ import com.raytheon.uf.common.datadelivery.registry.Coverage; import com.raytheon.uf.common.datadelivery.registry.DataDeliveryRegistryObjectTypes; import com.raytheon.uf.common.datadelivery.registry.Subscription; import com.raytheon.uf.common.datadelivery.registry.Time; +import com.raytheon.uf.common.datadelivery.registry.handlers.IAdhocSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; import com.raytheon.uf.common.datadelivery.service.ISubscriptionNotificationService; @@ -65,6 +66,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthDaoUtil; * Reschedule updated local subscriptions. * Nov 27, 2013 2545 mpduff Get data by network * Dec 04, 2013 2566 bgonzale use bandwidthmanager method to retrieve spring files. + * Jan 14, 2014 2692 dhladky AdhocSubscription handler * * </pre> * @@ -101,9 +103,10 @@ public class WfoBandwidthManagerCreator<T extends Time, C extends Coverage> BandwidthDaoUtil bandwidthDaoUtil, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService subscriptionNotificationService) { super(dbInit, bandwidthDao, retrievalManager, bandwidthDaoUtil, - dataSetMetaDataHandler, subscriptionHandler, + dataSetMetaDataHandler, subscriptionHandler, adhocSubscriptionHandler, subscriptionNotificationService); } @@ -192,9 +195,10 @@ public class WfoBandwidthManagerCreator<T extends Time, C extends Coverage> BandwidthDaoUtil bandwidthDaoUtil, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService subscriptionNotificationService) { return new WfoBandwidthManager<T, C>(dbInit, bandwidthDao, retrievalManager, bandwidthDaoUtil, dataSetMetaDataHandler, - subscriptionHandler, subscriptionNotificationService); + subscriptionHandler, adhocSubscriptionHandler, subscriptionNotificationService); } } diff --git a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/IntegrationTestBandwidthContextFactory.java b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/IntegrationTestBandwidthContextFactory.java index f678a0588d..9f068f136f 100644 --- a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/IntegrationTestBandwidthContextFactory.java +++ b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/IntegrationTestBandwidthContextFactory.java @@ -21,6 +21,7 @@ package com.raytheon.uf.edex.datadelivery.bandwidth; import java.io.File; +import com.raytheon.uf.common.datadelivery.registry.handlers.IAdhocSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; import com.raytheon.uf.common.datadelivery.service.ISubscriptionNotificationService; @@ -71,11 +72,13 @@ public class IntegrationTestBandwidthContextFactory extends IBandwidthDbInit dbInit, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, + ISubscriptionNotificationService notificationService) { super(bandwidthDao, bandwidthBucketsDao, new IntegrationTestBandwidthInitializer(), bandwidthManagerCreator, dbInit, dataSetMetaDataHandler, - subscriptionHandler, notificationService); + subscriptionHandler, adhocSubscriptionHandler, notificationService); } /** @@ -93,6 +96,6 @@ public class IntegrationTestBandwidthContextFactory extends */ public static File getIntegrationTestBandwidthMapConfigFile() { return new IntegrationTestBandwidthContextFactory(null, null, null, - null, null, null, null).getBandwidthMapConfigFile(); + null, null, null, null, null).getBandwidthMapConfigFile(); } } diff --git a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/IntegrationTestWfoBandwidthManager.java b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/IntegrationTestWfoBandwidthManager.java index 571a6d1949..eb50cc3d26 100644 --- a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/IntegrationTestWfoBandwidthManager.java +++ b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/IntegrationTestWfoBandwidthManager.java @@ -19,6 +19,7 @@ **/ package com.raytheon.uf.edex.datadelivery.bandwidth; +import com.raytheon.uf.common.datadelivery.registry.handlers.IAdhocSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; import com.raytheon.uf.common.datadelivery.service.ISubscriptionNotificationService; @@ -45,6 +46,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthDaoUtil; * May 15, 2013 2000 djohnson Include daos. * Jul 10, 2013 2106 djohnson Dependency inject registry handlers. * Nov 08, 2013 2506 bgonzale Added notification service to bandwidth manager. + * Jan 14, 2014 2692 dhladky AdhocSubscription handler * * </pre> * @@ -74,9 +76,10 @@ public class IntegrationTestWfoBandwidthManager extends WfoBandwidthManager { BandwidthDaoUtil bandwidthDaoUtil, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService subscriptionNotificationService) { super(dbInit, bandwidthDao, retrievalManager, bandwidthDaoUtil, - dataSetMetaDataHandler, subscriptionHandler, + dataSetMetaDataHandler, subscriptionHandler, adhocSubscriptionHandler, subscriptionNotificationService); } diff --git a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/IntegrationTestWfoBandwidthManagerCreator.java b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/IntegrationTestWfoBandwidthManagerCreator.java index 8416d547ec..29049286a7 100644 --- a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/IntegrationTestWfoBandwidthManagerCreator.java +++ b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/IntegrationTestWfoBandwidthManagerCreator.java @@ -19,6 +19,7 @@ **/ package com.raytheon.uf.edex.datadelivery.bandwidth; +import com.raytheon.uf.common.datadelivery.registry.handlers.IAdhocSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; import com.raytheon.uf.common.datadelivery.service.ISubscriptionNotificationService; @@ -40,6 +41,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthDaoUtil; * Feb 20, 2013 1543 djohnson Initial creation * Jul 10, 2013 2106 djohnson Dependency inject registry handlers. * Nov 08, 2013 2506 bgonzale Added notification service to bandwidth manager. + * Jan 14, 2014 2692 dhladky AdhocSubscription handler * * </pre> * @@ -58,9 +60,10 @@ public class IntegrationTestWfoBandwidthManagerCreator implements BandwidthDaoUtil bandwidthDaoUtil, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService subscriptionNotificationService) { return new IntegrationTestWfoBandwidthManager(dbInit, bandwidthDao, retrievalManager, bandwidthDaoUtil, dataSetMetaDataHandler, - subscriptionHandler, subscriptionNotificationService); + subscriptionHandler, adhocSubscriptionHandler, subscriptionNotificationService); } } diff --git a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/IntegrationTestNcfBandwidthManager.java b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/IntegrationTestNcfBandwidthManager.java index e8e4b5d5e7..5390bd5047 100644 --- a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/IntegrationTestNcfBandwidthManager.java +++ b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/IntegrationTestNcfBandwidthManager.java @@ -19,6 +19,7 @@ **/ package com.raytheon.uf.edex.datadelivery.bandwidth.ncf; +import com.raytheon.uf.common.datadelivery.registry.handlers.IAdhocSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; import com.raytheon.uf.common.datadelivery.service.ISubscriptionNotificationService; @@ -45,6 +46,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthDaoUtil; * Feb 27, 2013 1644 djohnson Extend NCF bandwidth manager. * Jul 10, 2013 2106 djohnson Dependency inject registry handlers. * Nov 08, 2013 2506 bgonzale Added notification service to bandwidth manager. + * Jan 14, 2014 2692 dhladky AdhocSubscription handler * * </pre> * @@ -74,9 +76,10 @@ public class IntegrationTestNcfBandwidthManager extends NcfBandwidthManager { BandwidthDaoUtil bandwidthDaoUtil, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService subscriptionNotificationService) { super(dbInit, bandwidthDao, retrievalManager, bandwidthDaoUtil, - dataSetMetaDataHandler, subscriptionHandler, + dataSetMetaDataHandler, subscriptionHandler, adhocSubscriptionHandler, subscriptionNotificationService); } diff --git a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/IntegrationTestNcfBandwidthManagerCreator.java b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/IntegrationTestNcfBandwidthManagerCreator.java index 24a0dd7a63..cad6e53776 100644 --- a/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/IntegrationTestNcfBandwidthManagerCreator.java +++ b/tests/integration/com/raytheon/uf/edex/datadelivery/bandwidth/ncf/IntegrationTestNcfBandwidthManagerCreator.java @@ -19,6 +19,7 @@ **/ package com.raytheon.uf.edex.datadelivery.bandwidth.ncf; +import com.raytheon.uf.common.datadelivery.registry.handlers.IAdhocSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; import com.raytheon.uf.common.datadelivery.service.ISubscriptionNotificationService; @@ -41,6 +42,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthDaoUtil; * Feb 20, 2013 1543 djohnson Initial creation * Jul 10, 2013 2106 djohnson Dependency inject registry handlers. * Nov 08, 2013 2506 bgonzale Added notification service to bandwidth manager. + * Jan 14, 2014 2692 dhladky AdhocSubscription handler * * </pre> * @@ -59,9 +61,10 @@ public class IntegrationTestNcfBandwidthManagerCreator implements BandwidthDaoUtil bandwidthDaoUtil, IDataSetMetaDataHandler dataSetMetaDataHandler, ISubscriptionHandler subscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler, ISubscriptionNotificationService subscriptionNotificationService) { return new IntegrationTestNcfBandwidthManager(dbInit, bandwidthDao, retrievalManager, bandwidthDaoUtil, dataSetMetaDataHandler, - subscriptionHandler, subscriptionNotificationService); + subscriptionHandler, adhocSubscriptionHandler, subscriptionNotificationService); } } From 9a45b95db683808f0b1a3238a07f37a84e7e33c1 Mon Sep 17 00:00:00 2001 From: Mike Duff <michael.duff@raytheon.com> Date: Wed, 15 Jan 2014 09:19:17 -0600 Subject: [PATCH 34/62] Issue #2459 - Refactor the subscription status Former-commit-id: d03c012a549388fa23ced9a8c141f6f3dfc1f7f3 [formerly f94593867edcd4a0465c6a487f22c2725357de68] [formerly 245d76358e8de7e39192b64c930799e86932bde6 [formerly 3ab5b072627d0a8b0eabe12fb700f6a74319b5f9]] Former-commit-id: 245d76358e8de7e39192b64c930799e86932bde6 Former-commit-id: d96a9d2937d8887cdac567f976382382e5103c48 --- ...aDeliveryProductBrowserDataDefinition.java | 4 +- .../subscription/CreateSubscriptionDlg.java | 8 +- .../subscription/SubscriptionManagerDlg.java | 7 +- .../SubscriptionManagerRowData.java | 4 +- .../subscription/subset/SubsetManagerDlg.java | 2 +- .../registry/RecurringSubscription.java | 121 +++++++++++------- .../datadelivery/registry/Subscription.java | 52 +++++--- .../common/datadelivery/registry/Utils.java | 44 ++++--- .../ebxml/SubscriptionFilterableQuery.java | 36 +++--- .../handlers/BaseSubscriptionHandler.java | 12 +- .../bandwidth/BandwidthManager.java | 13 +- .../registry/BaseSubscriptionFixture.java | 2 +- .../registry/SiteSubscriptionTest.java | 65 +++++++++- .../registry/SubscriptionBuilder.java | 13 +- 14 files changed, 250 insertions(+), 133 deletions(-) diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/DataDeliveryProductBrowserDataDefinition.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/DataDeliveryProductBrowserDataDefinition.java index a44b8d1f09..e0d3868526 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/DataDeliveryProductBrowserDataDefinition.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/DataDeliveryProductBrowserDataDefinition.java @@ -33,7 +33,6 @@ import com.raytheon.uf.common.datadelivery.registry.Coverage; import com.raytheon.uf.common.datadelivery.registry.DataType; import com.raytheon.uf.common.datadelivery.registry.Subscription; import com.raytheon.uf.common.datadelivery.registry.Subscription.SubscriptionType; -import com.raytheon.uf.common.datadelivery.registry.Utils.SubscriptionStatus; import com.raytheon.uf.common.datadelivery.registry.handlers.IAdhocSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; import com.raytheon.uf.common.dataquery.requests.RequestConstraint; @@ -74,6 +73,7 @@ import com.raytheon.viz.pointdata.util.PointDataInventory; * Oct 13, 2013 2460 dhladky Added display of Adhoc subscriptions * Nov 19, 2013 2458 mpduff Only pull subscriptions for the local site * Nov 21, 2013 2554 dhladky Restored ADHOC's to working. + * Jan 14, 2014 2459 mpduff Change Subscription status code * * </pre> * @@ -403,7 +403,7 @@ public class DataDeliveryProductBrowserDataDefinition List<Subscription> subList = getSubscriptions(); for (Subscription s : subList) { - if (SubscriptionStatus.ACTIVE.toString().equals(s.getStatus()) + if (s.isActive() || s.getSubscriptionType().equals(SubscriptionType.QUERY)) { if (s.getDataSetType() == dataType) { activeSubList.add(s); diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/CreateSubscriptionDlg.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/CreateSubscriptionDlg.java index 598080bcb4..08c98b6d63 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/CreateSubscriptionDlg.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/CreateSubscriptionDlg.java @@ -72,7 +72,6 @@ import com.raytheon.uf.common.datadelivery.registry.SharedSubscription; import com.raytheon.uf.common.datadelivery.registry.Subscription; import com.raytheon.uf.common.datadelivery.registry.Subscription.SubscriptionPriority; import com.raytheon.uf.common.datadelivery.registry.Time; -import com.raytheon.uf.common.datadelivery.registry.Utils.SubscriptionStatus; import com.raytheon.uf.common.datadelivery.registry.ebxml.DataSetQuery; import com.raytheon.uf.common.datadelivery.registry.handlers.DataDeliveryHandlers; import com.raytheon.uf.common.datadelivery.registry.handlers.IPendingSubscriptionHandler; @@ -144,6 +143,7 @@ import com.raytheon.viz.ui.presenter.components.ComboBoxConf; * Oct 21, 2013 2292 mpduff Close dialog on OK. * Nov 07, 2013 2291 skorolev Used showText() method for "Unable to Create Subscription" message. * Nov 08, 2013 2506 bgonzale Removed send notification when a subscription is updated and created. + * Jan 14, 2014 2459 mpduff Change Subscription status code * * </pre> * @@ -1088,14 +1088,11 @@ public class CreateSubscriptionDlg extends CaveSWTDialog { .parse(endText); subscription.setActivePeriodEnd(endPeriodDate); } - - subscription.setActive(true); } catch (ParseException e) { statusHandler.handle(Priority.PROBLEM, e.getLocalizedMessage(), e); } } else { - subscription.setActive(true); subscription.setActivePeriodStart(null); subscription.setActivePeriodEnd(null); } @@ -1635,8 +1632,7 @@ public class CreateSubscriptionDlg extends CaveSWTDialog { // If currently in the window, assume starting from last year for // the start date - if (subscription.getStatus().equals( - SubscriptionStatus.ACTIVE.toString())) { + if (subscription.isActive()) { calendarYearToUse--; } diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionManagerDlg.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionManagerDlg.java index 0b81c53cd4..5a95043c85 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionManagerDlg.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionManagerDlg.java @@ -147,6 +147,7 @@ import com.raytheon.viz.ui.presenter.IDisplay; * Nov 08, 2013 2506 bgonzale Removed send notification when a subscription is deleted. * Dec 05, 2013 2570 skorolev Show All subscriptions. * Jan 08, 2014 2642 mpduff Update dialog for permissions, adding site to shared + * Jan 14, 2014 2459 mpduff Change Subscription status code * </pre> * * @author mpduff @@ -1161,7 +1162,11 @@ public class SubscriptionManagerDlg extends CaveSWTDialog implements .getSubscriptionData().getDataRow(idx); Subscription sub = rowData.getSubscription(); - sub.setActive(activate); + if (activate) { + sub.activate(); + } else { + sub.deactivate(); + } try { SubscriptionServiceResult response = subscriptionService diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionManagerRowData.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionManagerRowData.java index b5d504ebbc..f92d1d876d 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionManagerRowData.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/SubscriptionManagerRowData.java @@ -50,6 +50,7 @@ import com.raytheon.uf.viz.datadelivery.utils.DataDeliveryUtils.TABLE_TYPE; * Jan 25, 2012 1528 djohnson Priorities no longer need incrementing for display. * Apr 08, 2013 1826 djohnson Remove delivery options. * May 15, 2013 1040 mpduff Change Office IDs to set. + * Jan 14, 2014 2459 mpduff Change Subscription status code * </pre> * * @author mpduff @@ -472,8 +473,7 @@ public class SubscriptionManagerRowData implements this.setPriority(subscription.getPriority().getPriorityValue()); this.setSubscriptionStart(subscription.getSubscriptionStart()); this.setSubscriptionEnd(subscription.getSubscriptionEnd()); - this.setActive(subscription.isActive()); - this.setStatus(subscription.getStatus()); + this.setStatus(subscription.getStatus().toString()); } /** diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/subset/SubsetManagerDlg.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/subset/SubsetManagerDlg.java index 5553e9985e..b0d8986d29 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/subset/SubsetManagerDlg.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/subset/SubsetManagerDlg.java @@ -138,6 +138,7 @@ import com.raytheon.viz.ui.presenter.IDisplay; * Oct 25, 2013 2292 mpduff Move overlap processing to edex. * Nov 14, 2013 2538 mpduff Added check for duplicate subscription. * Nov 14, 2013 2548 mpduff Set the subscription type (QUERY OR RECURRING) + * Jan 14, 2014 2459 mpduff Change Subscription status code * </pre> * * @author mpduff @@ -603,7 +604,6 @@ public abstract class SubsetManagerDlg extends CaveSWTDialog implements sub.setSubscriptionStart(this.subscription.getSubscriptionStart()); sub.setActivePeriodEnd(this.subscription.getActivePeriodEnd()); sub.setActivePeriodStart(this.subscription.getActivePeriodStart()); - sub.setActive(this.subscription.isActive()); sub.setPriority(this.subscription.getPriority()); } diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java index 5b1453bcc7..37f1bd8371 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java @@ -64,6 +64,7 @@ import com.raytheon.uf.common.time.util.TimeUtil; * Oct 30, 2013 2448 dhladky Fixed pulling data before and after activePeriod starting and ending. * Nov 14, 2013 2548 mpduff Add a subscription type slot. * Jan 08, 2014 2615 bgonzale Implement calculate start and calculate end methods. + * Jan 14, 2014 2459 mpduff Add subscription state. * * </pre> * @@ -95,7 +96,6 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> * New subscription name */ public RecurringSubscription(Subscription<T, C> sub, String name) { - this.setActive(sub.isActive()); this.setActivePeriodEnd(sub.getActivePeriodEnd()); this.setActivePeriodStart(sub.getActivePeriodStart()); this.setCoverage(sub.getCoverage()); @@ -209,11 +209,6 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> @SlotAttribute(Subscription.DATA_SET_SLOT) private String dataSetName; - @XmlAttribute - @DynamicSerializeElement - @SlotAttribute - private boolean active; - @XmlAttribute @DynamicSerializeElement @SlotAttribute @@ -267,6 +262,11 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> @SlotAttribute(Subscription.SUBSCRIPTION_TYPE_SLOT) private SubscriptionType subscriptionType; + @XmlAttribute + @DynamicSerializeElement + @SlotAttribute(Subscription.SUBSCRIPTION_STATE_SLOT) + private SubscriptionState subscriptionState; + /** * Get subscription name. * @@ -454,8 +454,7 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> private Calendar getActivePeriodStart(Calendar base) { // active period values are month and day of month only, use base // Calendar for active period year - Calendar activePeriodStartCal = TimeUtil - .newCalendar(activePeriodStart); + Calendar activePeriodStartCal = TimeUtil.newCalendar(activePeriodStart); TimeUtil.minCalendarFields(activePeriodStartCal, Calendar.MILLISECOND, Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY); activePeriodStartCal.set(Calendar.YEAR, base.get(Calendar.YEAR)); @@ -484,8 +483,7 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> } else { realStart = startConstraint; } - return TimeUtil.newCalendar(TimeUtil.max(subscriptionStart, - realStart)); + return TimeUtil.newCalendar(TimeUtil.max(subscriptionStart, realStart)); } @Override @@ -704,18 +702,7 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> */ @Override public boolean isActive() { - return active; - } - - /** - * Set the subscription status to active. - * - * @param active - * subscription active - */ - @Override - public void setActive(boolean active) { - this.active = active; + return getStatus() == SubscriptionStatus.ACTIVE; } /** @@ -727,6 +714,9 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> @Override public void setValid(boolean valid) { this.valid = valid; + if (!valid) { + subscriptionState = SubscriptionState.OFF; + } } /** @@ -892,14 +882,14 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> * * @return true if status is expired */ - @Override - public boolean isExpired() { + private boolean isExpired() { Calendar cal = TimeUtil.newGmtCalendar(); Date today = cal.getTime(); boolean expired = false; if (this.getSubscriptionEnd() != null && today.after(this.getSubscriptionEnd())) { expired = true; + this.subscriptionState = SubscriptionState.OFF; } return expired; @@ -908,32 +898,40 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> /** * Get the current subscription status. * - * @return String value of SUBSCRIPTION_STATUS + * @return SUBSCRIPTION_STATUS */ @Override - public String getStatus() { - SubscriptionStatus status = SubscriptionStatus.INVALID; - - if (isValid()) { - if (isExpired()) { - status = SubscriptionStatus.EXPIRED; - } else if (!isActive()) { - status = SubscriptionStatus.INACTIVE; - } else { - Calendar cal = TimeUtil.newGmtCalendar(); - Date today = cal.getTime(); - - status = (inWindow(today)) ? SubscriptionStatus.ACTIVE - : SubscriptionStatus.INACTIVE; - - if (status == SubscriptionStatus.ACTIVE && isUnscheduled()) { - status = SubscriptionStatus.UNSCHEDULED; - } - } + public SubscriptionStatus getStatus() { + if (!isValid()) { + return SubscriptionStatus.INVALID; + } else if (isExpired()) { + return SubscriptionStatus.EXPIRED; + } else if (subscriptionState == SubscriptionState.OFF) { + return SubscriptionStatus.DEACTIVATED; } - return status.toString(); + // At this point the subscription is in the ON state + Calendar cal = TimeUtil.newGmtCalendar(); + Date today = cal.getTime(); + if (unscheduled) { + return SubscriptionStatus.UNSCHEDULED; + } else if (inWindow(today)) { + return SubscriptionStatus.ACTIVE; + } + + return SubscriptionStatus.INACTIVE; + } + + /** + * Return true if this subscription should be scheduled. Scheduling is based + * on the status of the subscription. Returns false if the subscription is + * expired or deactivated. + * + * @return true if this subscription should be scheduled + */ + public boolean shouldSchedule() { + return subscriptionState == SubscriptionState.ON && !isExpired(); } private boolean inWindow(Date checkDate) { @@ -1046,4 +1044,37 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> public void setSubscriptionType(SubscriptionType subscriptionType) { this.subscriptionType = subscriptionType; } + + /** + * @return the subscriptionState + */ + public SubscriptionState getSubscriptionState() { + return subscriptionState; + } + + /** + * @param subscriptionState + * the subscriptionState to set + */ + public void setSubscriptionState(SubscriptionState subscriptionState) { + this.subscriptionState = subscriptionState; + } + + /** + * {@inheritDoc} + */ + @Override + public void activate() { + if (valid && !isExpired()) { + this.setSubscriptionState(SubscriptionState.ON); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void deactivate() { + this.setSubscriptionState(SubscriptionState.OFF); + } } diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Subscription.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Subscription.java index 4df35239a7..f884ad4b4b 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Subscription.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Subscription.java @@ -27,6 +27,8 @@ import java.util.Set; import javax.xml.bind.annotation.XmlEnum; import javax.xml.bind.annotation.XmlEnumValue; +import com.raytheon.uf.common.datadelivery.registry.Utils.SubscriptionStatus; + /** * Definition of a subscription. * @@ -43,7 +45,8 @@ import javax.xml.bind.annotation.XmlEnumValue; * Sept 30,2013 1797 dhladky Abstracted and genericized. * Oct 23, 2013 2484 dhladky Unique ID for subscriptions updated. * Nov 14, 2013 2548 mpduff Add a subscription type information. - * Jan 08, 2014 2615 bgonzale Added calculate start and calculate end methods. + * Jan 08, 2014 2615 bgonzale Added calculate start and calculate end methods. + * Jan 14, 2014 2459 mpduff Change Subscription status code * * </pre> * @@ -58,6 +61,19 @@ public interface Subscription<T extends Time, C extends Coverage> { QUERY, RECURRING; } + /** + * State of the subscription. + * + * <pre> + * ON for Active, Inactive, Unscheduled status + * OFF for Expired, Deactivated, Invalid status + * </pre> + */ + @XmlEnum + public enum SubscriptionState { + ON, OFF; + } + /** Enumeration to use for subscription priorities */ @XmlEnum public static enum SubscriptionPriority { @@ -157,6 +173,9 @@ public interface Subscription<T extends Time, C extends Coverage> { /** Subscription type slot (query, recurring) */ String SUBSCRIPTION_TYPE_SLOT = "subscriptionType"; + /** Subscription state slot (off or on) */ + String SUBSCRIPTION_STATE_SLOT = "subscriptionState"; + /** * Get subscription name. * @@ -458,20 +477,12 @@ public interface Subscription<T extends Time, C extends Coverage> { void setDataSetName(String dataSetName); /** - * isActive flag for subscription status. + * Check if status is SubscriptionStatus.ACTIVE * * @return boolean true if subscription is Active */ boolean isActive(); - /** - * Set the subscription status to active. - * - * @param active - * subscription active - */ - void setActive(boolean active); - /** * Set subscription valid. * @@ -558,19 +569,12 @@ public interface Subscription<T extends Time, C extends Coverage> { */ void setId(String id); - /** - * Determine if subscription status is expired. - * - * @return true if status is expired - */ - boolean isExpired(); - /** * Get the current subscription status. * - * @return String value of SUBSCRIPTION_STATUS + * @return SubscriptionStatus */ - String getStatus(); + SubscriptionStatus getStatus(); /** * Get the route. @@ -679,4 +683,14 @@ public interface Subscription<T extends Time, C extends Coverage> { * @param subType */ void setSubscriptionType(SubscriptionType subType); + + /** + * Activate the subscription + */ + void activate(); + + /** + * Deactivate the subscription + */ + void deactivate(); } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Utils.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Utils.java index 7d8d7bef26..a1eeb9700e 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Utils.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Utils.java @@ -21,7 +21,8 @@ import com.vividsolutions.jts.geom.Polygon; * ------------ ---------- ----------- -------------------------- * Feb 20, 2011 218 dhladky Initial creation. * Oct 1, 2012 1103 jpiatt Added invalid subscription status. - * Nov 20, 2012 1286 djohnson Add UNSCHEDULED. + * Nov 20, 2012 1286 djohnson Add UNSCHEDULED. + * Jan 14, 2014 2459 mpduff Change Subscription status code * * </pre> * @@ -35,12 +36,11 @@ public class Utils { * Get the geometry for a bounding box * * @param upperLeft - * upper left corner + * upper left corner * @param LowerRight - * lower right corner + * lower right corner * - * @return bounding box - * counding box coordinates + * @return bounding box bounding box coordinates */ public static Geometry getGeometry(Coordinate upperLeft, Coordinate LowerRight) { @@ -65,12 +65,11 @@ public class Utils { * Date conversion. * * @param format - * pass in date format + * pass in date format * @param dateString - * date in string format - * - * @return Date - * converted date + * date in string format + * + * @return Date converted date * @throws ParseException */ public static Date convertDate(String format, String dateString) @@ -82,19 +81,30 @@ public class Utils { /** * Subscription status options. + * + * <pre> + * Expired - Do not schedule + * Deactivated - Do not schedule + * Active - Currently scheduled + * Inactive - Not currently scheduled (outside of active period) + * Unscheduled - Not currently scheduled due to bandwidth limitations + * Invalid - Subscription does not match the available data set + * </pre> */ public static enum SubscriptionStatus { - + /** Active Subscription Status */ - ACTIVE("Active"), + ACTIVE("Active"), /** Inactive Subscription Status */ - INACTIVE("Inactive"), + INACTIVE("Inactive"), /** Expired Subscription Status */ - EXPIRED("Expired"), - /** Invalid Subscription Status */ - INVALID("Invalid"), + EXPIRED("Expired"), /** Unscheduled Subscription Status */ - UNSCHEDULED("Unscheduled"); + UNSCHEDULED("Unscheduled"), + /** Deactivated Subscription Status */ + DEACTIVATED("Deactivated"), + /** Invalid Subscription Status */ + INVALID("Invalid"); private final String status; diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/ebxml/SubscriptionFilterableQuery.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/ebxml/SubscriptionFilterableQuery.java index 1fc00d78e9..7e0bdb9879 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/ebxml/SubscriptionFilterableQuery.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/ebxml/SubscriptionFilterableQuery.java @@ -10,8 +10,8 @@ import javax.xml.bind.annotation.XmlAccessorType; import com.raytheon.uf.common.datadelivery.registry.Network; import com.raytheon.uf.common.datadelivery.registry.Subscription; +import com.raytheon.uf.common.datadelivery.registry.Subscription.SubscriptionState; import com.raytheon.uf.common.registry.ebxml.AdhocRegistryQuery; -import com.raytheon.uf.common.registry.ebxml.BooleanAttribute; import com.raytheon.uf.common.registry.ebxml.CalendarAttribute; import com.raytheon.uf.common.registry.ebxml.StringAttribute; import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; @@ -36,6 +36,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; * Feb 20, 2013 1543 djohnson Add ability to filter on routes. * May 28, 2013 1650 djohnson More information when failing to schedule. * Sep 04, 2013 2330 bgonzale OfficeIds attribute is a collection. + * Jan 14, 2014 2459 mpduff Change to query for ON subscription state. * * </pre> * @@ -48,11 +49,12 @@ public abstract class SubscriptionFilterableQuery<T> extends AdhocRegistryQuery<T> { /** - * A setter for the queryable attribute dataSetName equals a single String value. - * Using this setter will equate to an HQL "equals" query against the specified column name. - * + * A setter for the queryable attribute dataSetName equals a single String + * value. Using this setter will equate to an HQL "equals" query against the + * specified column name. + * * @param collectionName - * The value of the dataSetName attribute to search for. + * The value of the dataSetName attribute to search for. */ public void setDataSetName(String dataSetName) { setAttribute("dataSetName", new StringAttribute(dataSetName)); @@ -60,10 +62,11 @@ public abstract class SubscriptionFilterableQuery<T> extends /** * A setter for the queryable attribute time equals a single String value. - * Using this setter will equate to an HQL "equals" query against the specified column name. - * + * Using this setter will equate to an HQL "equals" query against the + * specified column name. + * * @param collectionName - * The value of the time attribute to search for. + * The value of the time attribute to search for. */ public void setMatureTime(Calendar matureTime) { CalendarAttribute ca = new CalendarAttribute(matureTime); @@ -73,10 +76,11 @@ public abstract class SubscriptionFilterableQuery<T> extends /** * A setter for the queryable attribute name equals a single String value. - * Using this setter will equate to an HQL "equals" query against the specified column name. - * + * Using this setter will equate to an HQL "equals" query against the + * specified column name. + * * @param collectionName - * The value of the name attribute to search for. + * The value of the name attribute to search for. */ public void setName(String name) { setAttribute(Subscription.NAME_SLOT, new StringAttribute(name)); @@ -109,10 +113,11 @@ public abstract class SubscriptionFilterableQuery<T> extends /** * A setter for the queryable attribute owner equals a single String value. - * Using this setter will equate to an HQL "equals" query against the specified column name. - * + * Using this setter will equate to an HQL "equals" query against the + * specified column name. + * * @param collectionName - * The value of the owner attribute to search for. + * The value of the owner attribute to search for. */ public void setOwner(String owner) { setAttribute("owner", new StringAttribute(owner)); @@ -155,7 +160,8 @@ public abstract class SubscriptionFilterableQuery<T> extends * The value of the active attribute to search for. */ public void setActive(boolean active) { - setAttribute("active", new BooleanAttribute(active)); + setAttribute(Subscription.SUBSCRIPTION_STATE_SLOT, new StringAttribute( + SubscriptionState.ON.name())); } /** diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/BaseSubscriptionHandler.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/BaseSubscriptionHandler.java index b385369c26..2f1e4c1fdd 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/BaseSubscriptionHandler.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/BaseSubscriptionHandler.java @@ -19,6 +19,7 @@ **/ package com.raytheon.uf.common.datadelivery.registry.handlers; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; @@ -26,6 +27,7 @@ import java.util.List; import java.util.Set; import com.raytheon.uf.common.datadelivery.registry.Network; +import com.raytheon.uf.common.datadelivery.registry.RecurringSubscription; import com.raytheon.uf.common.datadelivery.registry.Subscription; import com.raytheon.uf.common.datadelivery.registry.ebxml.SubscriptionDataSetNameQuery; import com.raytheon.uf.common.datadelivery.registry.ebxml.SubscriptionFilterableQuery; @@ -50,6 +52,7 @@ import com.raytheon.uf.common.registry.handler.RegistryHandlerException; * Jun 24, 2013 2106 djohnson Now composes a registryHandler. * Jul 18, 2013 2193 mpduff Changes for SubscriptionDataSetNameQuery. * Sep 11, 2013 2352 mpduff Add siteId to getSubscribedToDataSetNames method. + * Jan 14, 2014 2459 mpduff Validate subs should be scheduled before returning them. * * </pre> * @@ -200,7 +203,12 @@ public abstract class BaseSubscriptionHandler<T extends Subscription, QUERY exte checkResponse(response, "getActiveForRoutes"); - return response.getResults(); + List<T> returnList = new ArrayList<T>(); + for (T sub : response.getResults()) { + if (((RecurringSubscription) sub).shouldSchedule()) { + returnList.add(sub); + } + } + return returnList; } - } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java index bc4e093f69..1609f5c1f3 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java @@ -40,6 +40,7 @@ import com.raytheon.uf.common.datadelivery.registry.PointTime; import com.raytheon.uf.common.datadelivery.registry.SiteSubscription; import com.raytheon.uf.common.datadelivery.registry.Subscription; import com.raytheon.uf.common.datadelivery.registry.Time; +import com.raytheon.uf.common.datadelivery.registry.Utils.SubscriptionStatus; import com.raytheon.uf.common.datadelivery.registry.handlers.DataDeliveryHandlers; import com.raytheon.uf.common.event.EventBus; import com.raytheon.uf.common.registry.handler.RegistryHandlerException; @@ -135,6 +136,7 @@ import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException; * Jan 08, 2014 2615 bgonzale getMostRecent checks subscription time constraints before scheduling. * handlePoint method now schedules most recent. * Jan 14, 2014 2692 dhladky Bad Point scheduling final Empty list. + * Jan 14, 2014 2459 mpduff Change to subscription status. * * </pre> * @@ -589,10 +591,10 @@ public abstract class BandwidthManager<T extends Time, C extends Coverage> // If BandwidthManager does not know about the subscription, and // it's active, attempt to add it.. - if (bandwidthSubscriptions.isEmpty() && subscription.isActive() - && !subscription.isUnscheduled()) { + if (bandwidthSubscriptions.isEmpty() && subscription.isActive()) { return schedule(subscription); - } else if (!subscription.isActive() || subscription.isUnscheduled()) { + } else if (subscription.isUnscheduled() + || subscription.getStatus() == SubscriptionStatus.DEACTIVATED) { // See if the subscription was inactivated or unscheduled.. // Need to remove BandwidthReservations for this // subscription. @@ -647,7 +649,7 @@ public abstract class BandwidthManager<T extends Time, C extends Coverage> useMostRecentDataSetUpdate)); return unscheduled; } - + private List<BandwidthAllocation> getMostRecent( Subscription<T, C> subscription, boolean useMostRecentDataSetUpdate) { List<BandwidthAllocation> unscheduled = Collections.emptyList(); @@ -667,7 +669,8 @@ public abstract class BandwidthManager<T extends Time, C extends Coverage> + "No adhoc requested.", subscription.getName())); } else { - RetrievalPlan plan = retrievalManager.getPlan(subscription.getRoute()); + RetrievalPlan plan = retrievalManager.getPlan(subscription + .getRoute()); if (plan != null) { Date subscriptionValidStart = subscription.calculateStart( plan.getPlanStart()).getTime(); diff --git a/tests/unit/com/raytheon/uf/common/datadelivery/registry/BaseSubscriptionFixture.java b/tests/unit/com/raytheon/uf/common/datadelivery/registry/BaseSubscriptionFixture.java index 4644d01ec7..314f04eff1 100644 --- a/tests/unit/com/raytheon/uf/common/datadelivery/registry/BaseSubscriptionFixture.java +++ b/tests/unit/com/raytheon/uf/common/datadelivery/registry/BaseSubscriptionFixture.java @@ -43,6 +43,7 @@ import com.raytheon.uf.common.time.util.TimeUtil; * May 15, 2013 1040 mpduff Office Ids are now a list. * Oct 2 2013 1797 dhladky subscription and time generics * Oct 21, 2013 2292 mpduff Implement multiple data types + * Jan 14, 2014 2459 mpduff Change subscription status code * * </pre> * @@ -77,7 +78,6 @@ public abstract class BaseSubscriptionFixture<M extends Subscription> { public M getInstance(long seedValue, Random random, DataType dataType) { M subscription = getSubscription(); - subscription.setActive(random.nextBoolean()); subscription.setActivePeriodStart(TimeUtil.newDate()); subscription.setActivePeriodEnd(new Date(subscription .getActivePeriodStart().getTime() + seedValue)); diff --git a/tests/unit/com/raytheon/uf/common/datadelivery/registry/SiteSubscriptionTest.java b/tests/unit/com/raytheon/uf/common/datadelivery/registry/SiteSubscriptionTest.java index d276a2d0d1..4789beefaa 100644 --- a/tests/unit/com/raytheon/uf/common/datadelivery/registry/SiteSubscriptionTest.java +++ b/tests/unit/com/raytheon/uf/common/datadelivery/registry/SiteSubscriptionTest.java @@ -55,6 +55,7 @@ import com.raytheon.uf.common.time.util.TimeUtilTest; * Mar 28, 2013 1841 djohnson Subscription is now UserSubscription. * May 15, 2013 1040 mpduff Office Id now a set. * Oct 21, 2013 2292 mpduff Implement multiple data types + * Jan 14, 2014 2459 mpduff Change Subscription status code * * </pre> * @@ -134,7 +135,7 @@ public class SiteSubscriptionTest { .withActivePeriodEnd(fiveDaysFromNow).build(); assertThat(subscription.getStatus(), - is(equalTo(SubscriptionStatus.ACTIVE.toString()))); + is(equalTo(SubscriptionStatus.ACTIVE))); } @Test @@ -149,7 +150,7 @@ public class SiteSubscriptionTest { .withActivePeriodEnd(yesterday).build(); assertThat(subscription.getStatus(), - is(equalTo(SubscriptionStatus.INACTIVE.toString()))); + is(equalTo(SubscriptionStatus.INACTIVE))); } @Test @@ -166,7 +167,7 @@ public class SiteSubscriptionTest { .withActivePeriodEnd(fiveDaysFromNow1970).build(); assertThat(subscription.getStatus(), - is(equalTo(SubscriptionStatus.ACTIVE.toString()))); + is(equalTo(SubscriptionStatus.ACTIVE))); } @Test @@ -184,7 +185,7 @@ public class SiteSubscriptionTest { .withActivePeriodEnd(yesterday1970).build(); assertThat(subscription.getStatus(), - is(equalTo(SubscriptionStatus.INACTIVE.toString()))); + is(equalTo(SubscriptionStatus.INACTIVE))); } @Test @@ -203,7 +204,61 @@ public class SiteSubscriptionTest { .withActivePeriodEnd(januaryFirst).build(); assertThat(subscription.getStatus(), - is(equalTo(SubscriptionStatus.ACTIVE.toString()))); + is(equalTo(SubscriptionStatus.ACTIVE))); + } + + @Test + public void testActivatedSubOutsideActivePeriodReturnsInactive() { + final Date fiveDaysAgo = new Date(TimeUtil.currentTimeMillis() + - (TimeUtil.MILLIS_PER_DAY * 5)); + final Date yesterday = new Date(TimeUtil.currentTimeMillis() + - TimeUtil.MILLIS_PER_DAY); + + Subscription sub = new SubscriptionBuilder() + .withActivePeriodStart(fiveDaysAgo) + .withActivePeriodEnd(yesterday).build(); + + sub.deactivate(); + sub.activate(); + assertThat(sub.getStatus(), is(equalTo(SubscriptionStatus.INACTIVE))); + } + + @Test + public void testGetStatusOfDeactivatedSubReturnsDeactivatedStatus() { + Subscription sub = new SubscriptionBuilder().build(); + sub.deactivate(); + sub.getStatus(); + assertThat(sub.getStatus(), is(equalTo(SubscriptionStatus.DEACTIVATED))); + } + + @Test + public void testGetStatusOfReactivatedSubReturnsActive() { + Subscription sub = new SubscriptionBuilder().build(); + sub.deactivate(); + sub.activate(); + assertThat(sub.getStatus(), is(equalTo(SubscriptionStatus.ACTIVE))); + } + + @Test + public void testActivatingAnExpiredSubIsStillExpired() { + Subscription sub = new SubscriptionBuilder().build(); + Calendar endTime = TimeUtil.newGmtCalendar(); + endTime.add(Calendar.DAY_OF_MONTH, -30); + sub.setSubscriptionEnd(endTime.getTime()); + + // activate it + sub.activate(); + + assertThat(sub.getStatus(), is(equalTo(SubscriptionStatus.EXPIRED))); + } + + @Test + public void testInvalidSubCannotBeActivated() { + SiteSubscription sub = new SubscriptionBuilder().build(); + sub.setValid(false); + sub.activate(); + + assertThat(sub.getStatus(), is(equalTo(SubscriptionStatus.INVALID))); } @Test diff --git a/tests/unit/com/raytheon/uf/common/datadelivery/registry/SubscriptionBuilder.java b/tests/unit/com/raytheon/uf/common/datadelivery/registry/SubscriptionBuilder.java index 0d1691938a..ef3f25a913 100644 --- a/tests/unit/com/raytheon/uf/common/datadelivery/registry/SubscriptionBuilder.java +++ b/tests/unit/com/raytheon/uf/common/datadelivery/registry/SubscriptionBuilder.java @@ -40,6 +40,7 @@ import com.raytheon.uf.common.time.util.TimeUtil; * Apr 08, 2013 1826 djohnson Remove delivery options. * May 15, 2013 1040 mpduff Office Id now a set. * Oct 21, 2013 2292 mpduff Implement multiple data types + * Jan 14, 2014 2459 mpduff Change Subscription status code * * </pre> * @@ -51,8 +52,6 @@ public class SubscriptionBuilder { private int latencyInMinutes = 0; - private boolean active = true; - private Date activePeriodStart; private Date activePeriodEnd; @@ -98,7 +97,6 @@ public class SubscriptionBuilder { public SiteSubscription build() { SiteSubscription subscription = SiteSubscriptionFixture.INSTANCE .get(dataType); - subscription.setActive(active); subscription.setActivePeriodStart(activePeriodStart); subscription.setActivePeriodEnd(activePeriodEnd); subscription.setDataSetName(dataSetName); @@ -132,15 +130,6 @@ public class SubscriptionBuilder { return this; } - /** - * @param active - * the active to set - */ - public SubscriptionBuilder withActive(boolean active) { - this.active = active; - return this; - } - /** * @param activePeriodStart * the activePeriodStart to set From d4236a7fc02f974eac50f3a6aaf0eab8edad6f4a Mon Sep 17 00:00:00 2001 From: Nate Jensen <Nathan.Jensen@raytheon.com> Date: Wed, 15 Jan 2014 09:50:35 -0600 Subject: [PATCH 35/62] Issue #2581 fix local storm report delta script and unique constraint Change-Id: I421aed1572c10c80a592381c849d85eac8d1e809 Former-commit-id: 562e85e45b9d34436823e6c2bc806aff378732cc [formerly e6feb413f73e258df9bd0a50fed1d3b5490a89c7] [formerly 059e057cdb4e2f969021e070ffa7b21f5e8cc194 [formerly 88918268a6d72d35dd2f19be09fbb429851fe46b]] Former-commit-id: 059e057cdb4e2f969021e070ffa7b21f5e8cc194 Former-commit-id: bc2f099cc6268528f1e29181fed7630d8b1e2e91 --- cots/org.apache.camel/.classpath | 10 +++++----- deltaScripts/14.2.1/dropLSRdataURI.sh | 2 +- .../uf/common/dataplugin/lsr/LocalStormReport.java | 3 ++- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/cots/org.apache.camel/.classpath b/cots/org.apache.camel/.classpath index a2c6e537e6..36bda9b9ef 100644 --- a/cots/org.apache.camel/.classpath +++ b/cots/org.apache.camel/.classpath @@ -1,12 +1,12 @@ <?xml version="1.0" encoding="UTF-8"?> <classpath> <classpathentry exported="true" kind="lib" path="camel-core-2.11.2.jar" sourcepath="apache-camel-2.11.2-src.zip"/> - <classpathentry exported="true" kind="lib" path="camel-http-2.11.2.jar"/> - <classpathentry exported="true" kind="lib" path="camel-http4-2.11.2.jar"/> - <classpathentry exported="true" kind="lib" path="camel-jetty-2.11.2.jar"/> + <classpathentry exported="true" kind="lib" path="camel-http-2.11.2.jar" sourcepath="apache-camel-2.11.2-src.zip"/> + <classpathentry exported="true" kind="lib" path="camel-http4-2.11.2.jar" sourcepath="apache-camel-2.11.2-src.zip"/> + <classpathentry exported="true" kind="lib" path="camel-jetty-2.11.2.jar" sourcepath="apache-camel-2.11.2-src.zip"/> <classpathentry exported="true" kind="lib" path="camel-jms-2.11.2.jar" sourcepath="apache-camel-2.11.2-src.zip"/> - <classpathentry exported="true" kind="lib" path="camel-quartz-2.11.2.jar"/> - <classpathentry exported="true" kind="lib" path="camel-spring-2.11.2.jar"/> + <classpathentry exported="true" kind="lib" path="camel-quartz-2.11.2.jar" sourcepath="apache-camel-2.11.2-src.zip"/> + <classpathentry exported="true" kind="lib" path="camel-spring-2.11.2.jar" sourcepath="apache-camel-2.11.2-src.zip"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/> <classpathentry kind="output" path="bin"/> diff --git a/deltaScripts/14.2.1/dropLSRdataURI.sh b/deltaScripts/14.2.1/dropLSRdataURI.sh index fb9bb06d5f..f8a01872db 100644 --- a/deltaScripts/14.2.1/dropLSRdataURI.sh +++ b/deltaScripts/14.2.1/dropLSRdataURI.sh @@ -36,7 +36,7 @@ function dropDatauriAndAddConstraint { echo "INFO: Dropping dataURI columns." -dropDatauriAndAddConstraint lsr lsr_latitude_longitude_stationId_reftime_forecasttime_eventtype_key "(latitude, longitude, stationId, reftime, forecasttime, eventtype)" +dropDatauriAndAddConstraint lsr lsr_latitude_longitude_officeId_reftime_forecasttime_eventtype_key "(latitude, longitude, officeId, reftime, forecasttime, eventtype)" echo "INFO: LSR dataURI column dropped successfully" diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LocalStormReport.java b/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LocalStormReport.java index eb2174a557..a952eafe65 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LocalStormReport.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LocalStormReport.java @@ -69,6 +69,7 @@ import com.vividsolutions.jts.geom.Geometry; * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * Oct 14, 2013 2361 njensen Removed XML annotations and IDecoderGettable * Dec 10, 2013 2581 njensen Removed dataURI column + * Jan 15, 2014 2581 njensen Changed constraint to use officeId instead of stationId * * </pre> * @@ -78,7 +79,7 @@ import com.vividsolutions.jts.geom.Geometry; @Entity @SequenceGenerator(initialValue = 1, name = PluginDataObject.ID_GEN, sequenceName = "lsrseq") @Table(name = "lsr", uniqueConstraints = { @UniqueConstraint(columnNames = { - "latitude", "longitude", "stationId", "refTime", "forecastTime", + "latitude", "longitude", "officeId", "refTime", "forecastTime", "eventType" }) }) /* * Both refTime and forecastTime are included in the refTimeIndex since From 9d136bb7d8e1389a72a4b27803bbae5cb0e651b4 Mon Sep 17 00:00:00 2001 From: Dave Hladky <david_j_hladky@raytheon.com> Date: Mon, 13 Jan 2014 17:15:52 -0600 Subject: [PATCH 36/62] Issue #2679 Multiple regions for a single collector mapped to single WFS source Change-Id: I1e4b1eefe5f507742805886292ba67b24f40f34c Former-commit-id: eddceed7568786258b798002e69febc69f980c0d [formerly 08625addbaa52edb6ff6d80a9ed1ddaf87540c9d] [formerly c57c27c84342d7c214e6ae1bc8f38219b0b8fed2 [formerly b888d311923ba0628fa015018ef2f62fce47fb43]] Former-commit-id: c57c27c84342d7c214e6ae1bc8f38219b0b8fed2 Former-commit-id: 6069bb90c70c7958e03a3a95a4583d36462776ca --- .../harvester/MADIS-harvester.xml | 817 +++++++++++++++++- .../bandwidth/EdexBandwidthManager.java | 6 +- .../retrieval/util/WfsConnectionUtil.java | 15 +- .../edex/ogc/common/db/ICollectorAddon.java | 3 +- .../ogc/registry/RegistryCollectorAddon.java | 27 +- .../registry/RegistryFeatureTypeModifier.java | 17 +- .../registry/WcsRegistryCollectorAddon.java | 57 +- .../registry/WfsRegistryCollectorAddon.java | 341 ++++++-- .../res/spring/madis-ogc-registry.xml | 16 +- .../registry/MadisRegistryCollectorAddon.java | 78 +- .../res/spring/obs-ogc-registry.xml | 1 - .../registry/ObsRegistryCollectorAddon.java | 73 +- 12 files changed, 1208 insertions(+), 243 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.harvester/utility/common_static/base/datadelivery/harvester/MADIS-harvester.xml b/edexOsgi/com.raytheon.uf.common.datadelivery.harvester/utility/common_static/base/datadelivery/harvester/MADIS-harvester.xml index 34e548d512..06fc387809 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.harvester/utility/common_static/base/datadelivery/harvester/MADIS-harvester.xml +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.harvester/utility/common_static/base/datadelivery/harvester/MADIS-harvester.xml @@ -21,14 +21,827 @@ </provider> <agent xsi:type="ogcAgent" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <dateFormat>HHddMMMyyyy</dateFormat> - <layer name="madis" namespace="http://madis.edex.uf.raytheon.com"> + <layer name="madis-conus" namespace="http://madis.edex.uf.raytheon.com"> <!-- Geographic constraint of madis layer data --> <minx>-120.0</minx> <maxx>-70.0</maxx> <miny>20.0</miny> <maxy>50.0</maxy> <crs>crs:84</crs> - <!-- Registry Parameters in madis layer --> + <!-- Registry Parameters in madis conus layer --> + <parameter name="timeObs" providerName="OBSTIME" + definition="Time of observation" dataType="POINT" baseType="String"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="provider" providerName="PVDR" + definition="Provider Network" dataType="POINT" baseType="String"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="sub_provider" providerName="SUBPVDR" + definition="Sub Provider Network" dataType="POINT" baseType="String"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="restriction" providerName="RES" + definition="Restriction Level" dataType="POINT" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dataset" providerName="DS" + definition="Dataset" dataType="POINT" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="obsLocation" providerName="obsLocation" + definition="Location of Observation" dataType="POINT" units="Degrees" + missingValue="-9999" fillValue="-9999" baseType="ObsLocation"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dewpoint" providerName="TD" + definition="Dewpoint Temperature" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="K"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dewpoint_qcd" providerName="TD_QCD" + definition="Dewpoint QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dewpoint_qca" providerName="TD_QCA" + definition="Dewpoint QCD" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dewpoint_qcr" providerName="TD_QCR" + definition="Dewpoint QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="rh" providerName="RH" + definition="Relative Humidity" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Integer" units="%"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="rh_qcd" providerName="RH_QCD" + definition="Relative Humidity QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="rh_qca" providerName="RH_QCA" + definition="Relative Humidity QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="rh_qcr" providerName="RH_QCR" + definition="Relative Humidity QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="altimeter" providerName="ALTSE" + definition="Altimeter Setting" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Integer" units="Pa"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="altimeter_qcd" providerName="ALTSE_QCD" + definition="Altimeter Setting QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="altimeter_qca" providerName="ALTSE_QCA" + definition="Altimeter Setting QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="altimeter_qcr" providerName="ALTSE_QCR" + definition="Altimeter Setting QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="temperature" providerName="T" + definition="Temperature" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="K"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="temperature_qcd" providerName="T_QCD" + definition="Temperature QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="temperature_qca" providerName="T_QCA" + definition="Temperature QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="temperature_qcr" providerName="T_QCR" + definition="Temperature QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windDirection" providerName="DD" + definition="Wind Direction" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Integer" units="degrees"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windDirection_qcd" providerName="DD_QCD" + definition="Wind Direction QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windDirection_qca" providerName="DD_QCA" + definition="Wind Direction QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windDirection_qcr" providerName="DD_QCR" + definition="Wind Direction QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windSpeed" providerName="FF" + definition="Wind Speed" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="degrees"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windSpeed_qcd" providerName="FF_QCD" + definition="Wind Speed QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windSpeed_qca" providerName="FF_QCA" + definition="Wind Speed QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windSpeed_qcr" providerName="FF_QCR" + definition="Wind Speed QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="elevation" providerName="ELEV" + definition="Elevation" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="degrees"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="elevation_qcd" providerName="ELEV_QCD" + definition="Elevation QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="elevation_qca" providerName="ELEV_QCA" + definition="Elevation QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="elevation_qcr" providerName="ELEV_QCR" + definition="Elevation QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lon_qcd" providerName="LON_QCD" + definition="longitude QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lon_qca" providerName="LON_QCA" + definition="Longitude QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lon_qcr" providerName="LON_QCR" + definition="Longitude QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lat_qcd" providerName="LAT_QCD" + definition="Latitude QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lat_qca" providerName="LAT_QCA" + definition="Latitude QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lat_qcr" providerName="LAT_QCR" + definition="Latitude QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipRate" providerName="PCPRATE" + definition="Precipitation Rate" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="in/hr"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipRate_qcd" providerName="PCPRATE_QCD" + definition="Precipitation Rate QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipRate_qca" providerName="PCPRATE_QCA" + definition="Precipitation Rate QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipRate_qcr" providerName="PCPRATE_QCR" + definition="Precipitation Rate QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windGust" providerName="FFGUST" + definition="Wind Gust" dataType="POINT" + missingValue="-9999" fillValue="-9999" baseType="Float" units="kts"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windGust_qcd" providerName="FFGUST_QCD" + definition="Wind Gust QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windGust_qca" providerName="FFGUST_QCA" + definition="Wind Gust QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windGust_qcr" providerName="FFGUST_QCR" + definition="Wind Gust QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipitalWater" providerName="PWV" + definition="Precipital Water Vapor" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="in"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipitalWater_qcd" providerName="PWV_QCD" + definition="Precipital Water Vapor QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipitalWater_qca" providerName="PWV_QCA" + definition="Precipital Water Vapor QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipitalWater_qcr" providerName="PWV_QCR" + definition="Precipital Water Vapor QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="pressure" providerName="P" + definition="Pressure" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="Pa"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="pressure_qcd" providerName="P_QCD" + definition="Pressure QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="pressure_qca" providerName="P_QCA" + definition="Pressure QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="pressure_qcr" providerName="P_QCR" + definition="Pressure QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + </layer> + <layer name="madis-alaska" namespace="http://madis.edex.uf.raytheon.com"> + <!-- Geographic constraint of madis alaska layer data --> + <minx>-180.0</minx> + <maxx>-114.0</maxx> + <miny>55.0</miny> + <maxy>85.0</maxy> + <crs>crs:84</crs> + <!-- Registry Parameters in madis alaska layer --> + <parameter name="timeObs" providerName="OBSTIME" + definition="Time of observation" dataType="POINT" baseType="String"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="provider" providerName="PVDR" + definition="Provider Network" dataType="POINT" baseType="String"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="sub_provider" providerName="SUBPVDR" + definition="Sub Provider Network" dataType="POINT" baseType="String"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="restriction" providerName="RES" + definition="Restriction Level" dataType="POINT" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dataset" providerName="DS" + definition="Dataset" dataType="POINT" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="obsLocation" providerName="obsLocation" + definition="Location of Observation" dataType="POINT" units="Degrees" + missingValue="-9999" fillValue="-9999" baseType="ObsLocation"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dewpoint" providerName="TD" + definition="Dewpoint Temperature" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="K"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dewpoint_qcd" providerName="TD_QCD" + definition="Dewpoint QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dewpoint_qca" providerName="TD_QCA" + definition="Dewpoint QCD" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dewpoint_qcr" providerName="TD_QCR" + definition="Dewpoint QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="rh" providerName="RH" + definition="Relative Humidity" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Integer" units="%"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="rh_qcd" providerName="RH_QCD" + definition="Relative Humidity QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="rh_qca" providerName="RH_QCA" + definition="Relative Humidity QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="rh_qcr" providerName="RH_QCR" + definition="Relative Humidity QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="altimeter" providerName="ALTSE" + definition="Altimeter Setting" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Integer" units="Pa"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="altimeter_qcd" providerName="ALTSE_QCD" + definition="Altimeter Setting QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="altimeter_qca" providerName="ALTSE_QCA" + definition="Altimeter Setting QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="altimeter_qcr" providerName="ALTSE_QCR" + definition="Altimeter Setting QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="temperature" providerName="T" + definition="Temperature" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="K"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="temperature_qcd" providerName="T_QCD" + definition="Temperature QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="temperature_qca" providerName="T_QCA" + definition="Temperature QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="temperature_qcr" providerName="T_QCR" + definition="Temperature QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windDirection" providerName="DD" + definition="Wind Direction" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Integer" units="degrees"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windDirection_qcd" providerName="DD_QCD" + definition="Wind Direction QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windDirection_qca" providerName="DD_QCA" + definition="Wind Direction QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windDirection_qcr" providerName="DD_QCR" + definition="Wind Direction QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windSpeed" providerName="FF" + definition="Wind Speed" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="degrees"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windSpeed_qcd" providerName="FF_QCD" + definition="Wind Speed QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windSpeed_qca" providerName="FF_QCA" + definition="Wind Speed QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windSpeed_qcr" providerName="FF_QCR" + definition="Wind Speed QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="elevation" providerName="ELEV" + definition="Elevation" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="degrees"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="elevation_qcd" providerName="ELEV_QCD" + definition="Elevation QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="elevation_qca" providerName="ELEV_QCA" + definition="Elevation QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="elevation_qcr" providerName="ELEV_QCR" + definition="Elevation QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lon_qcd" providerName="LON_QCD" + definition="longitude QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lon_qca" providerName="LON_QCA" + definition="Longitude QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lon_qcr" providerName="LON_QCR" + definition="Longitude QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lat_qcd" providerName="LAT_QCD" + definition="Latitude QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lat_qca" providerName="LAT_QCA" + definition="Latitude QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lat_qcr" providerName="LAT_QCR" + definition="Latitude QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipRate" providerName="PCPRATE" + definition="Precipitation Rate" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="in/hr"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipRate_qcd" providerName="PCPRATE_QCD" + definition="Precipitation Rate QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipRate_qca" providerName="PCPRATE_QCA" + definition="Precipitation Rate QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipRate_qcr" providerName="PCPRATE_QCR" + definition="Precipitation Rate QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windGust" providerName="FFGUST" + definition="Wind Gust" dataType="POINT" + missingValue="-9999" fillValue="-9999" baseType="Float" units="kts"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windGust_qcd" providerName="FFGUST_QCD" + definition="Wind Gust QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windGust_qca" providerName="FFGUST_QCA" + definition="Wind Gust QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windGust_qcr" providerName="FFGUST_QCR" + definition="Wind Gust QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipitalWater" providerName="PWV" + definition="Precipital Water Vapor" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="in"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipitalWater_qcd" providerName="PWV_QCD" + definition="Precipital Water Vapor QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipitalWater_qca" providerName="PWV_QCA" + definition="Precipital Water Vapor QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipitalWater_qcr" providerName="PWV_QCR" + definition="Precipital Water Vapor QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="pressure" providerName="P" + definition="Pressure" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="Pa"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="pressure_qcd" providerName="P_QCD" + definition="Pressure QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="pressure_qca" providerName="P_QCA" + definition="Pressure QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="pressure_qcr" providerName="P_QCR" + definition="Pressure QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + </layer> + <layer name="madis-hawaii" namespace="http://madis.edex.uf.raytheon.com"> + <!-- Geographic constraint of madis hawaii layer data --> + <minx>-162.0</minx> + <maxx>-152.0</maxx> + <miny>16.0</miny> + <maxy>24.0</maxy> + <crs>crs:84</crs> + <!-- Registry Parameters in madis hawaii layer --> + <parameter name="timeObs" providerName="OBSTIME" + definition="Time of observation" dataType="POINT" baseType="String"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="provider" providerName="PVDR" + definition="Provider Network" dataType="POINT" baseType="String"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="sub_provider" providerName="SUBPVDR" + definition="Sub Provider Network" dataType="POINT" baseType="String"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="restriction" providerName="RES" + definition="Restriction Level" dataType="POINT" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dataset" providerName="DS" + definition="Dataset" dataType="POINT" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="obsLocation" providerName="obsLocation" + definition="Location of Observation" dataType="POINT" units="Degrees" + missingValue="-9999" fillValue="-9999" baseType="ObsLocation"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dewpoint" providerName="TD" + definition="Dewpoint Temperature" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="K"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dewpoint_qcd" providerName="TD_QCD" + definition="Dewpoint QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dewpoint_qca" providerName="TD_QCA" + definition="Dewpoint QCD" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="dewpoint_qcr" providerName="TD_QCR" + definition="Dewpoint QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="rh" providerName="RH" + definition="Relative Humidity" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Integer" units="%"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="rh_qcd" providerName="RH_QCD" + definition="Relative Humidity QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="rh_qca" providerName="RH_QCA" + definition="Relative Humidity QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="rh_qcr" providerName="RH_QCR" + definition="Relative Humidity QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="altimeter" providerName="ALTSE" + definition="Altimeter Setting" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Integer" units="Pa"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="altimeter_qcd" providerName="ALTSE_QCD" + definition="Altimeter Setting QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="altimeter_qca" providerName="ALTSE_QCA" + definition="Altimeter Setting QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="altimeter_qcr" providerName="ALTSE_QCR" + definition="Altimeter Setting QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="temperature" providerName="T" + definition="Temperature" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="K"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="temperature_qcd" providerName="T_QCD" + definition="Temperature QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="temperature_qca" providerName="T_QCA" + definition="Temperature QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="temperature_qcr" providerName="T_QCR" + definition="Temperature QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windDirection" providerName="DD" + definition="Wind Direction" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Integer" units="degrees"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windDirection_qcd" providerName="DD_QCD" + definition="Wind Direction QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windDirection_qca" providerName="DD_QCA" + definition="Wind Direction QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windDirection_qcr" providerName="DD_QCR" + definition="Wind Direction QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windSpeed" providerName="FF" + definition="Wind Speed" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="degrees"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windSpeed_qcd" providerName="FF_QCD" + definition="Wind Speed QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windSpeed_qca" providerName="FF_QCA" + definition="Wind Speed QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windSpeed_qcr" providerName="FF_QCR" + definition="Wind Speed QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="elevation" providerName="ELEV" + definition="Elevation" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="degrees"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="elevation_qcd" providerName="ELEV_QCD" + definition="Elevation QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="elevation_qca" providerName="ELEV_QCA" + definition="Elevation QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="elevation_qcr" providerName="ELEV_QCR" + definition="Elevation QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lon_qcd" providerName="LON_QCD" + definition="longitude QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lon_qca" providerName="LON_QCA" + definition="Longitude QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lon_qcr" providerName="LON_QCR" + definition="Longitude QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lat_qcd" providerName="LAT_QCD" + definition="Latitude QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lat_qca" providerName="LAT_QCA" + definition="Latitude QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="lat_qcr" providerName="LAT_QCR" + definition="Latitude QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipRate" providerName="PCPRATE" + definition="Precipitation Rate" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="in/hr"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipRate_qcd" providerName="PCPRATE_QCD" + definition="Precipitation Rate QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipRate_qca" providerName="PCPRATE_QCA" + definition="Precipitation Rate QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipRate_qcr" providerName="PCPRATE_QCR" + definition="Precipitation Rate QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windGust" providerName="FFGUST" + definition="Wind Gust" dataType="POINT" + missingValue="-9999" fillValue="-9999" baseType="Float" units="kts"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windGust_qcd" providerName="FFGUST_QCD" + definition="Wind Gust QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windGust_qca" providerName="FFGUST_QCA" + definition="Wind Gust QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="windGust_qcr" providerName="FFGUST_QCR" + definition="Wind Gust QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipitalWater" providerName="PWV" + definition="Precipital Water Vapor" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="in"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipitalWater_qcd" providerName="PWV_QCD" + definition="Precipital Water Vapor QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipitalWater_qca" providerName="PWV_QCA" + definition="Precipital Water Vapor QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="precipitalWater_qcr" providerName="PWV_QCR" + definition="Precipital Water Vapor QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="pressure" providerName="P" + definition="Pressure" dataType="POINT" missingValue="-9999" + fillValue="-9999" baseType="Float" units="Pa"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="pressure_qcd" providerName="P_QCD" + definition="Pressure QCD" dataType="POINT" baseType="QCD"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="pressure_qca" providerName="P_QCA" + definition="Pressure QCA" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + <parameter name="pressure_qcr" providerName="P_QCR" + definition="Pressure QCR" dataType="POINT" missingValue="0" + fillValue="0" baseType="Integer"> + <levelType levelType="SFC" /> + </parameter> + </layer> + <layer name="madis-puertorico" namespace="http://madis.edex.uf.raytheon.com"> + <!-- Geographic constraint of madis puerto rico layer data --> + <minx>-63.8</minx> + <maxx>-68.5</maxx> + <miny>16.5</miny> + <maxy>19.8</maxy> + <crs>crs:84</crs> + <!-- Registry Parameters in madis puerto rico layer --> <parameter name="timeObs" providerName="OBSTIME" definition="Time of observation" dataType="POINT" baseType="String"> <levelType levelType="SFC" /> diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java index 6542b1c51c..3d28404308 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java @@ -111,7 +111,8 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthUtil; * Nov 15, 2013 2545 bgonzale Added check for subscription events before sending * notifications. Republish dataset metadata registry * insert and update events as dataset metadata events. - * Jan 14, 2014 2692 dhladky AdhocSubscription handler + * Jan 13, 2014 2679 dhladky Small Point data updates. + * Jan 14, 2014 2692 dhladky AdhocSubscription handler * * </pre> * @@ -437,8 +438,9 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> } private void publishDataSetMetaDataEvent(RegistryEvent re) { + final String id = re.getId(); - DataSetMetaData<?> dsmd = getDataSetMetaData(id); + DataSetMetaData<T> dsmd = getDataSetMetaData(id); if (dsmd != null) { // Repost the Object to the BandwidthEventBus to free diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/util/WfsConnectionUtil.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/util/WfsConnectionUtil.java index 0fc5e88bd2..c3c6878915 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/util/WfsConnectionUtil.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/util/WfsConnectionUtil.java @@ -2,6 +2,7 @@ package com.raytheon.uf.edex.datadelivery.retrieval.util; import java.net.URI; import java.net.URISyntaxException; +import java.util.regex.Pattern; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.StringEntity; @@ -34,6 +35,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * Aug 23, 2013 2180 mpduff Implement changes to ProviderCredentialsUtil * Aug 06, 2013 2097 dhladky WFS 2.0 compliance upgrade and switched to POST * Nov 20, 2013 2554 dhladky Added GZIP capability to WFS requests. + * Jan 13, 2014 2697 dhladky Added util to strip unique Id field from URL. * * </pre> * @@ -45,6 +47,8 @@ public class WfsConnectionUtil { private static final IUFStatusHandler statusHandler = UFStatus .getHandler(WfsConnectionUtil.class); + + private static final Pattern COMMA_PATTERN = Pattern.compile(","); /** * Connect to the provided URL and return the xml response. @@ -66,7 +70,7 @@ public class WfsConnectionUtil { try { - rootUrl = providerConn.getUrl(); + rootUrl = getCleanUrl(providerConn.getUrl()); http = HttpClient.getInstance(); // accept gzipped data for WFS http.setGzipResponseHandling(true); @@ -192,4 +196,13 @@ public class WfsConnectionUtil { return httpPort; } } + + /** + * Removes un-needed unique Identifier from PointDataSetMetaData derived URL's + * @param rootUrl + * @return + */ + private static String getCleanUrl(String providerUrl) { + return COMMA_PATTERN.split(providerUrl)[0]; + } } diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/ICollectorAddon.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/ICollectorAddon.java index c9eb501a84..f5b46ba3da 100644 --- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/ICollectorAddon.java +++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/ICollectorAddon.java @@ -13,6 +13,7 @@ import java.util.Date; import java.util.Set; import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.dataplugin.persist.PersistableDataObject; /** * Interface for extending layer collectors to perform additional tasks @@ -30,7 +31,7 @@ import com.raytheon.uf.common.dataplugin.PluginDataObject; * @author bclement * @version 1.0 */ -public interface ICollectorAddon<D extends SimpleDimension, L extends SimpleLayer<D>, R extends PluginDataObject> { +public interface ICollectorAddon<D extends SimpleDimension, L extends SimpleLayer<D>, R extends PersistableDataObject> { /** * Called after record is added to layer. Both should be treated as diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/RegistryCollectorAddon.java b/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/RegistryCollectorAddon.java index ba9b554e36..94a5693956 100644 --- a/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/RegistryCollectorAddon.java +++ b/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/RegistryCollectorAddon.java @@ -35,10 +35,12 @@ import com.raytheon.uf.common.datadelivery.registry.DataType; import com.raytheon.uf.common.datadelivery.registry.Levels; import com.raytheon.uf.common.datadelivery.registry.Parameter; import com.raytheon.uf.common.datadelivery.registry.Provider; +import com.raytheon.uf.common.datadelivery.registry.Time; import com.raytheon.uf.common.datadelivery.registry.handlers.DataDeliveryHandlers; import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.IDataSetMetaDataHandler; import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.geospatial.ISpatialObject; import com.raytheon.uf.common.registry.handler.RegistryHandlerException; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; @@ -48,7 +50,7 @@ import com.raytheon.uf.edex.ogc.common.db.SimpleDimension; import com.raytheon.uf.edex.ogc.common.db.SimpleLayer; /** - * TODO Add Description + * Collector Used to gather data with DPA, used for AWIPS registry data feeds from providers. * * <pre> * @@ -58,6 +60,7 @@ import com.raytheon.uf.edex.ogc.common.db.SimpleLayer; * ------------ ---------- ----------- -------------------------- * Jul 23, 2013 bclement Initial creation * Aug 08, 2013 dhladky Made operational + * Jan 13, 2014 #2679 dhladky multiple layers * * </pre> * @@ -108,7 +111,7 @@ public abstract class RegistryCollectorAddon<D extends SimpleDimension, L extend * @param metaDatas * @param dataSet */ - public void storeMetaData(final DataSetMetaData metaData) { + public void storeMetaData(final DataSetMetaData<?> metaData) { IDataSetMetaDataHandler handler = DataDeliveryHandlers .getDataSetMetaDataHandler(); @@ -132,7 +135,7 @@ public abstract class RegistryCollectorAddon<D extends SimpleDimension, L extend * * @param dataSetToStore */ - protected void storeDataSetName(DataSet dataSetToStore) { + protected void storeDataSetName(DataSet<?, ?> dataSetToStore) { DataSetName dsn = new DataSetName(); // Set the RegistryObject Id keys for this Object @@ -158,9 +161,9 @@ public abstract class RegistryCollectorAddon<D extends SimpleDimension, L extend /** * @param dataSet */ - protected void storeDataSet(final DataSet dataSet) { + protected void storeDataSet(final DataSet<?, ?> dataSet) { - DataSet dataSetToStore = getDataSetToStore(dataSet); + DataSet<?, ?> dataSetToStore = getDataSetToStore(dataSet); final String dataSetName = dataSetToStore.getDataSetName(); IDataSetHandler handler = DataDeliveryHandlers.getDataSetHandler(); @@ -200,9 +203,11 @@ public abstract class RegistryCollectorAddon<D extends SimpleDimension, L extend * the dataSet * @return the dataSet instance that should be stored to the registry */ + + @SuppressWarnings({ "rawtypes", "unchecked" }) protected DataSet getDataSetToStore(DataSet dataSet) { try { - DataSet result = DataDeliveryHandlers.getDataSetHandler() + DataSet<Time, Coverage> result = DataDeliveryHandlers.getDataSetHandler() .getByNameAndProvider(dataSet.getDataSetName(), dataSet.getProviderName()); if (result != null) { @@ -244,7 +249,7 @@ public abstract class RegistryCollectorAddon<D extends SimpleDimension, L extend protected abstract void setCoverage(L layer); - protected abstract Coverage getCoverage(); + protected abstract Coverage getCoverage(String layerName); public void setParameters(L layer) { synchronized (layer) { @@ -266,11 +271,11 @@ public abstract class RegistryCollectorAddon<D extends SimpleDimension, L extend protected abstract void setDataSet(L layer); - protected abstract DataSet getDataSet(); + protected abstract DataSet<?, ?> getDataSet(String layerName); protected abstract void setDataSetMetaData(L layer); - protected abstract DataSetMetaData getDataSetMetaData(); + protected abstract DataSetMetaData<?> getDataSetMetaData(String layerName); protected abstract DataType getDataType(); @@ -283,5 +288,9 @@ public abstract class RegistryCollectorAddon<D extends SimpleDimension, L extend public void setAgent(OGCAgent agent) { this.agent = agent; } + + public abstract String isWithinLayer(R record); + + public abstract ISpatialObject getSpatial(R record); } diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/RegistryFeatureTypeModifier.java b/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/RegistryFeatureTypeModifier.java index 3e60c370c7..6ee3fdb9a9 100644 --- a/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/RegistryFeatureTypeModifier.java +++ b/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/RegistryFeatureTypeModifier.java @@ -31,6 +31,7 @@ import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.edex.ogc.common.OgcGeoBoundingBox; import com.raytheon.uf.edex.wfs.WfsFeatureType; +import com.raytheon.uf.edex.wfs.reg.AbstractWfsSource; import com.raytheon.uf.edex.wfs.reg.IFeatureTypeModifier; /** @@ -44,6 +45,7 @@ import com.raytheon.uf.edex.wfs.reg.IFeatureTypeModifier; * ------------ ---------- ----------- -------------------------- * Jul 26, 2013 bclement Initial creation * Aug 18, 2013 #2097 dhladky Adapted to AWIPS + * Jan 13, 2014 #2679 dhladky multiple layers mapping to single request window * * </pre> * @@ -115,13 +117,10 @@ public class RegistryFeatureTypeModifier implements IFeatureTypeModifier { OgcGeoBoundingBox bbox = null; try { - ConfigLayer layer = getConfigLayer(name); - double upperLeftLon = layer.getMinx(); - double lowerRightLon = layer.getMaxx(); - double upperLeftLat = layer.getMaxy(); - double lowerRightLat = layer.getMiny(); - bbox = new OgcGeoBoundingBox(lowerRightLon, upperLeftLon, - upperLeftLat, lowerRightLat); + // we default to whole earth now. + // We don't really care about the DataSet specific areas for the feature + // They are added together and treated as a whole for requests from the DPA + bbox = AbstractWfsSource.fullBbox; } catch (Exception e) { statusHandler.handle(Priority.ERROR, @@ -142,8 +141,8 @@ public class RegistryFeatureTypeModifier implements IFeatureTypeModifier { String crs = null; try { - ConfigLayer layer = getConfigLayer(name); - crs = layer.getCrs(); + // Default to WGS:84 + crs = AbstractWfsSource.defaultCRS; } catch (Exception e) { statusHandler.handle(Priority.ERROR, "Couldn't retrieve CRS for feature: " + name diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/WcsRegistryCollectorAddon.java b/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/WcsRegistryCollectorAddon.java index fe40bb57fb..a4e978197b 100644 --- a/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/WcsRegistryCollectorAddon.java +++ b/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/WcsRegistryCollectorAddon.java @@ -28,6 +28,8 @@ import java.util.Set; import com.raytheon.uf.common.datadelivery.registry.Coverage; import com.raytheon.uf.common.datadelivery.registry.DataLevelType; import com.raytheon.uf.common.datadelivery.registry.DataLevelType.LevelType; +import com.raytheon.uf.common.datadelivery.registry.DataSet; +import com.raytheon.uf.common.datadelivery.registry.DataSetMetaData; import com.raytheon.uf.common.datadelivery.registry.DataType; import com.raytheon.uf.common.datadelivery.registry.GriddedDataSet; import com.raytheon.uf.common.datadelivery.registry.GriddedDataSetMetaData; @@ -35,6 +37,7 @@ import com.raytheon.uf.common.datadelivery.registry.Levels; import com.raytheon.uf.common.datadelivery.registry.Time; import com.raytheon.uf.common.datadelivery.retrieval.util.LookupManager; import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.geospatial.ISpatialObject; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.edex.ogc.common.db.SimpleDimension; @@ -52,6 +55,7 @@ import com.raytheon.uf.edex.ogc.common.interfaces.IWCSMetaData; * ------------ ---------- ----------- -------------------------- * Jul 25, 2013 bclement Initial creation * Aug 18, 2013 #2097 dhladky Adapted to AWIPS + * Jan 13, 2014 #2679 dhladky Multiple layers * * </pre> * @@ -69,18 +73,16 @@ public class WcsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp protected GriddedDataSetMetaData gdsmd = null; protected Time time = null; + + public WcsRegistryCollectorAddon() { + super(); + } @Override protected void setCoverage(L layer) { // TODO: NOt yet implemented } - @Override - protected Coverage getCoverage() { - // TODO Auto-generated method stub - return null; - } - @Override protected void setDataSet(L layer) { // TODO Auto-generated method stub @@ -96,16 +98,6 @@ public class WcsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp return DataType.GRID; } - @Override - public GriddedDataSet getDataSet() { - return gds; - } - - @Override - public GriddedDataSetMetaData getDataSetMetaData() { - return gdsmd; - } - // TODO implement this when we do WCS @Override public Levels getLevels(DataLevelType type, String collectionName) { @@ -136,8 +128,7 @@ public class WcsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp levels.setDz(dz); } catch (Exception e) { - statusHandler.error("Level info" + collectionName + " url: " - + getDataSetMetaData().getUrl(), e); + statusHandler.error("Level info" + collectionName + ":", e); } return levels; @@ -205,4 +196,34 @@ public class WcsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp } + @Override + protected Coverage getCoverage(String layerName) { + // TODO Auto-generated method stub + return null; + } + + @Override + protected DataSet<?, ?> getDataSet(String layerName) { + // TODO Auto-generated method stub + return null; + } + + @Override + protected DataSetMetaData<?> getDataSetMetaData(String layerName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public String isWithinLayer(R record) { + // TODO Auto-generated method stub + return null; + } + + @Override + public ISpatialObject getSpatial(R record) { + // TODO Auto-generated method stub + return null; + } + } diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/WfsRegistryCollectorAddon.java b/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/WfsRegistryCollectorAddon.java index da4d9f2702..d9d5146234 100644 --- a/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/WfsRegistryCollectorAddon.java +++ b/edexOsgi/com.raytheon.uf.edex.ogc.registry/src/com/raytheon/uf/edex/ogc/registry/WfsRegistryCollectorAddon.java @@ -23,8 +23,12 @@ import java.lang.reflect.Constructor; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; import java.util.Set; import java.util.TimeZone; import java.util.TreeSet; @@ -42,6 +46,7 @@ import com.raytheon.uf.common.datadelivery.registry.PointDataSetMetaData; import com.raytheon.uf.common.datadelivery.registry.PointTime; import com.raytheon.uf.common.datadelivery.registry.WFSPointDataSet; import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.geospatial.ISpatialObject; import com.raytheon.uf.common.geospatial.MapUtil; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; @@ -70,39 +75,39 @@ import com.vividsolutions.jts.geom.Envelope; * Sept 30, 2013 1797 dhladky Generics * Oct 10, 2013 1797 bgonzale Refactored registry Time objects. * Nov 6, 2013 2525 dhladky Stop appending "/wfs" + * Jan 13, 2014 2679 dhladky Multiple ingest layer windows for a single request window. * * </pre> * * @author bclement * @version 1.0 */ -public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends SimpleLayer<D>, R extends PluginDataObject> +public abstract class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends SimpleLayer<D>, R extends PluginDataObject> extends RegistryCollectorAddon<D, L, R> implements IWFSMetaData<L> { protected final IUFStatusHandler statusHandler = UFStatus.getHandler(this .getClass()); - protected WFSPointDataSet wpds = new WFSPointDataSet(); + protected final Map<String, WFSPointDataSet> wpds = new HashMap<String, WFSPointDataSet>(1); - protected PointDataSetMetaData pdsmd = new PointDataSetMetaData(); + protected final Map<String, PointDataSetMetaData> pdsmds = new HashMap<String, PointDataSetMetaData>(1); - protected PointTime time = new PointTime(); + protected final Map<String, PointTime> times = new HashMap<String, PointTime>(1); - protected Coverage coverage = new Coverage(); + protected final Map<String, Coverage> coverages = new HashMap<String, Coverage>(1); - protected volatile L _layer = null; - - protected int roundCutoff = 45; - - protected final String layerName; + protected final Map<String, L> layers = new HashMap<String, L>(1); + + protected final Map<String, Date> previousTimes = new HashMap<String, Date>(1); - protected Date previousTime = null; + protected int roundCutoff = 45; + + /** Used to identify breaking character for URL and unique naming key **/ + public static final String UNIQUE_ID_SEPARATOR = ","; - /** - * @param layerName - */ - public WfsRegistryCollectorAddon(String layerName) { - this.layerName = layerName; + public WfsRegistryCollectorAddon() { + + super(); } /* @@ -116,8 +121,12 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp @Override public void onCollect(L layer, R record) { ensureLayer(layer); - synchronized (_layer) { - Date time = record.getDataTime().getRefTime(); + synchronized (layers) { + // find enclosing layer to assign to + String layerName = isWithinLayer(record); + L _layer = layers.get(layerName); + copy(_layer); + Date time = getTime(record); _layer.getTimes().add(time); } } @@ -139,21 +148,24 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp * @param layer */ private void ensureLayer(L layer) { - if (_layer == null) { - synchronized (layerName) { - if (_layer != null) { - // another thread got here first - return; + + /** + * this interfaces with the WfsSource, in registry collectors there + * exists a one to many relationship for featureType to layers. In this + * case we just re-init if they are null, not caring what got passed in; + */ + + synchronized (layers) { + for (Entry<String, L> entry : layers.entrySet()) { + + L _layer = entry.getValue(); + + if (_layer == null) { + synchronized (_layer) { + initializeLayer(_layer); + layers.put(layer.getName(), _layer); + } } - L copy = copy(layer); - copy.getTimes().clear(); - initializeLayer(copy); - _layer = copy; - } - } else { - if (!layer.getName().equals(layerName)) { - statusHandler - .warn("WFS Registry collector used with multiple layers, unexpected behavior may occur"); } } } @@ -188,11 +200,10 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp */ protected void initializeLayer(L layer) { synchronized (layer) { - // create the main point data set - layer.setName(layerName); - setDataSet(layer); - Coordinate lowerRight = getCoverage().getLowerRight(); - Coordinate upperLeft = getCoverage().getUpperLeft(); + + Coverage coverage = getCoverage(layer.getName()); + Coordinate lowerRight = coverage.getLowerRight(); + Coordinate upperLeft = coverage.getUpperLeft(); ReferencedEnvelope env = new ReferencedEnvelope(upperLeft.x, lowerRight.x, lowerRight.y, upperLeft.y, MapUtil.LATLON_PROJECTION); @@ -204,9 +215,12 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp layer.setTargetMinx(configLayer.getMinx()); layer.setTargetMiny(configLayer.getMiny()); layer.setTimes(new TreeSet<Date>()); - // install main dataset name on registry - storeDataSet(getDataSet()); + // create the main point data set + setDataSet(layer); + // install main dataset name on registry + WFSPointDataSet pds = getDataSet(layer.getName()); + storeDataSet(pds); } } @@ -221,8 +235,16 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp } @Override - public WFSPointDataSet getDataSet() { - return wpds; + public WFSPointDataSet getDataSet(String layerName) { + + WFSPointDataSet wpd = wpds.get(layerName); + + if (wpd == null) { + wpd = new WFSPointDataSet(); + wpds.put(layerName, wpd); + } + + return wpd; } /** @@ -233,24 +255,28 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp protected void setTime(L layer) { synchronized (layer) { // always creating a new time object for transfer - List<Date> times = new ArrayList<Date>(); + List<Date> timeList = new ArrayList<Date>(); // for dataset we just create a place holder object // DataSetMetaData gets the actual times if (layer.getTimes() != null) { for (Date time : layer.getTimes()) { - times.add(time); + timeList.add(time); } - time.setTimes(times); - time.setNumTimes(times.size()); + PointTime time = getTime(layer.getName()); + time.setTimes(timeList); + time.setNumTimes(timeList.size()); // apply date format SimpleDateFormat dateFormat = new SimpleDateFormat( getConfiguration().getAgent().getDateFormat()); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT")); time.setFormat(dateFormat.toPattern()); - if (!times.isEmpty()) { + if (!timeList.isEmpty()) { + + Date previousTime = previousTimes.get(layer.getName()); + if (previousTime == null) { - time.setStart(times.get(0)); + time.setStart(timeList.get(0)); } else { try { time.setStartDate(dateFormat.format(previousTime)); @@ -259,20 +285,34 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp "Failed to parse date.", e); } } - Date lastTime = times.get(times.size() - 1); + Date lastTime = timeList.get(timeList.size() - 1); try { time.setEndDate(dateFormat.format(lastTime)); } catch (ParseException e) { statusHandler.handle(Priority.PROBLEM, "Failed to parse date.", e); } - setPreviousTime(lastTime); + setPreviousTime(layer.getName(), lastTime); } } } } - protected PointTime getTime() { + /** + * Get a point time + * + * @param layerName + * @return PointTime + */ + protected PointTime getTime(String layerName) { + + PointTime time = times.get(layerName); + + if (time == null) { + time = new PointTime(); + times.put(layerName, time); + } + return time; } @@ -282,21 +322,31 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp synchronized (layer) { // set coverage if not set setCoverage(layer); - wpds.setCoverage(getCoverage()); - wpds.setDataSetName(layer.getName()); - wpds.setProviderName(getConfiguration().getProvider().getName()); - wpds.setCollectionName(layer.getName()); + WFSPointDataSet wpd = getDataSet(layer.getName()); + Coverage coverage = getCoverage(layer.getName()); + wpd.setCoverage(coverage); + wpd.setDataSetName(layer.getName()); + wpd.setProviderName(getConfiguration().getProvider().getName()); + wpd.setCollectionName(layer.getName()); // set parameters if not already setParameters(layer); - wpds.setParameters(getParameters()); + wpd.setParameters(getParameters()); // set time if not already setTime(layer); - wpds.setTime(getTime()); + wpd.setTime(getTime(layer.getName())); } } @Override - public PointDataSetMetaData getDataSetMetaData() { + public PointDataSetMetaData getDataSetMetaData(String layerName) { + + PointDataSetMetaData pdsmd = pdsmds.get(layerName); + + if (pdsmd == null) { + pdsmd = new PointDataSetMetaData(); + pdsmds.put(layerName, pdsmd); + } + return pdsmd; } @@ -311,12 +361,22 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp sb.append(layer.getTargetMiny()).append(" : "); sb.append(layer.getTargetMinx()).append(", "); sb.append(layer.getTargetMaxy()); + + PointDataSetMetaData pdsmd = getDataSetMetaData(layer.getName()); pdsmd.setDataSetDescription(sb.toString()); pdsmd.setDataSetName(layer.getName()); pdsmd.setProviderName(getConfiguration().getProvider().getName()); StringBuilder sb2 = new StringBuilder(); sb2.append(getConfiguration().getProvider().getConnection() .getUrl()); + /** + * this is added to the URL because the URL is what the registry + * uses as it's unique identifier. All WFS/WCS requests use the same + * URL, we have to add the dataset name to ensure uniqueness of the + * key in the registry. This is stripped off and discarded in retrieval. + **/ + sb2.append(UNIQUE_ID_SEPARATOR); + sb2.append(layer.getName()); pdsmd.setUrl(sb2.toString()); } } @@ -327,14 +387,19 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp @Override protected void setCoverage(L layer) { synchronized (layer) { - setCoverage(layer.getName()); + getCoverage(layer.getName()); } } /** + * Make me a new coverage + * * @param layerName + * @return Coverage */ - private void setCoverage(String layerName) { + private Coverage getNewCoverage(String layerName) { + + Coverage coverage = new Coverage(); ConfigLayer configLayer = getAgent().getLayer(layerName); Coordinate lowerRight = new Coordinate(configLayer.getMaxx(), configLayer.getMiny()); @@ -343,16 +408,28 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp ReferencedEnvelope re = EnvelopeUtils.createLatLonEnvelope(lowerRight, upperLeft); coverage.setEnvelope(re); + + return coverage; } /** * Gets the coverage * * @param layer + * @param layername * @return */ @Override - protected Coverage getCoverage() { + protected Coverage getCoverage(String layerName) { + + Coverage coverage = coverages.get(layerName); + + if (coverage == null) { + + coverage = getNewCoverage(layerName); + coverages.put(layerName, coverage); + } + return coverage; } @@ -374,40 +451,43 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp // place into a WFS metadata object. synchronized (layer) { // creates a new PointTime object - time = new PointTime(); + times.put(layer.getName(), new PointTime()); // harvests the times from the layer setTime(layer); // make sure you populate the metadata setDataSetMetaData(layer); - getDataSetMetaData().setTime(getTime()); + getDataSetMetaData(layer.getName()).setTime(getTime(layer.getName())); ImmutableDate date = null; - date = new ImmutableDate(getTime().getEnd()); - getDataSetMetaData().setDate(date); - storeMetaData(getDataSetMetaData()); + date = new ImmutableDate(getTime(layer.getName()).getEnd()); + getDataSetMetaData(layer.getName()).setDate(date); + storeMetaData(getDataSetMetaData(layer.getName())); } } /** - * Adds the new times to the layer, transmit meta data + * Adds the new times to the layers, transmit meta data objects */ public void buildLayerUpdate() { - if (_layer == null) { - return; - } - synchronized (_layer) { - try { - if (!_layer.getTimes().isEmpty()) { - sendMetaData(_layer); - statusHandler.info("MetaData update " + _layer.getName() - + ": times: " + _layer.getTimes().size()); - _layer.getTimes().clear(); - } else { - statusHandler.info("No new metadata to update " - + _layer.getName()); + + synchronized (layers) { + for (String name : layers.keySet()) { + // grab each layer to evaluate + L layer = layers.get(name); + + try { + if (!layer.getTimes().isEmpty()) { + sendMetaData(layer); + statusHandler.info("MetaData update " + layer.getName() + + ": times: " + layer.getTimes().size()); + layer.getTimes().clear(); + } else { + statusHandler.info("No new metadata to update " + + layer.getName()); + } + } catch (Exception e) { + statusHandler.error("problem updating " + layer.getName() + + " layer. " + e); } - } catch (Exception e) { - statusHandler.error("problem updating " + _layer.getName() - + " layer. " + e); } } } @@ -445,16 +525,105 @@ public class WfsRegistryCollectorAddon<D extends SimpleDimension, L extends Simp * From this date to last will be the next query * @return */ - public Date getPreviousTime() { - return previousTime; + public Date getPreviousTime(String layerName) { + + Date previous = previousTimes.get(layerName); + return previous; } /** * Sets the marker time for previousDate + * @param layername * @param previousTime */ - public void setPreviousTime(Date previousTime) { - this.previousTime = previousTime; + public void setPreviousTime(String layerName, Date previousTime) { + previousTimes.put(layerName, previousTime); + } + + /** + * Filter geographically + * @param pdos + */ + public PluginDataObject[] filter(PluginDataObject[] pdos) { + + Collection<PluginDataObject> withInGeoConstraint = new ArrayList<PluginDataObject>(); + PluginDataObject[] pdor = null; + + for (PluginDataObject record : pdos) { + + if (record != null) { + + @SuppressWarnings("unchecked") + ISpatialObject spatial = getSpatial((R) record); + Coordinate c = spatial.getGeometry().getCoordinate(); + + // Have to loop over the layers in order to separate them. + for (String name : layers.keySet()) { + + Coverage coverage = getCoverage(name); + + if (coverage != null) { + + Envelope e = coverage.getEnvelope(); + + if (c != null) { + + if (e.contains(c)) { + withInGeoConstraint.add(record); + // once it is found to be within one, you are done. + break; + } else { + statusHandler.handle( + Priority.DEBUG, + "Record discarded: outside of range: " + + c.x + " " + + c.y); + } + } + } + } + } + } + + if (!withInGeoConstraint.isEmpty()) { + int size = withInGeoConstraint.size(); + pdor = withInGeoConstraint.toArray(new PluginDataObject[size]); + } + + return pdor; + } + + @Override + public String isWithinLayer(R record) { + + String layerName = null; + + if (record != null) { + + ISpatialObject spatial = getSpatial(record); + Coordinate c = spatial.getGeometry().getCoordinate(); + + // Figure out which layer to tally this record too. + for (String name : layers.keySet()) { + + Coverage coverage = getCoverage(name); + + if (coverage != null) { + + Envelope e = coverage.getEnvelope(); + + if (c != null) { + + if (e.contains(c)) { + layerName = name; + break; + } + } + } + } + } + + return layerName; } } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.madis.registry/res/spring/madis-ogc-registry.xml b/edexOsgi/com.raytheon.uf.edex.plugin.madis.registry/res/spring/madis-ogc-registry.xml index 1811a66f72..4250cd20c2 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.madis.registry/res/spring/madis-ogc-registry.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.madis.registry/res/spring/madis-ogc-registry.xml @@ -49,16 +49,18 @@ <bean id="madisRegistryAddon" class="com.raytheon.uf.edex.plugin.madis.registry.MadisRegistryCollectorAddon" depends-on="registerDataDeliveryHandlers, registerRequestRegistryRouter, registerMadisPlugin"> - <constructor-arg value="madis" /> </bean> - - <bean id="madisRegistryAddonProvider" class="com.raytheon.uf.edex.ogc.registry.RegistryCollectorAddonProvider"> - <constructor-arg ref="madisRegistryAddon"/> + + <bean id="madisRegistryAddonProvider" + class="com.raytheon.uf.edex.ogc.registry.RegistryCollectorAddonProvider" + depends-on="madisRegistryAddon"> + <constructor-arg ref="madisRegistryAddon" /> </bean> + + <bean id="madisWfsTypeModifier" + class="com.raytheon.uf.edex.ogc.registry.RegistryFeatureTypeModifier" /> - <bean id="madisWfsTypeModifier" class="com.raytheon.uf.edex.ogc.registry.RegistryFeatureTypeModifier" /> - - <bean class="com.raytheon.uf.edex.ogc.common.util.AddonPropsPostProcessor"> + <bean class="com.raytheon.uf.edex.ogc.common.util.AddonPropsPostProcessor" depends-on="madisRegistryAddonProvider, madisRegistryAddon"> <constructor-arg> <map> <entry key="madisIngestFilter"> diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.madis.registry/src/com/raytheon/uf/edex/plugin/madis/registry/MadisRegistryCollectorAddon.java b/edexOsgi/com.raytheon.uf.edex.plugin.madis.registry/src/com/raytheon/uf/edex/plugin/madis/registry/MadisRegistryCollectorAddon.java index 5bfce9e07e..237523dc73 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.madis.registry/src/com/raytheon/uf/edex/plugin/madis/registry/MadisRegistryCollectorAddon.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.madis.registry/src/com/raytheon/uf/edex/plugin/madis/registry/MadisRegistryCollectorAddon.java @@ -19,19 +19,16 @@ **/ package com.raytheon.uf.edex.plugin.madis.registry; -import java.util.ArrayList; -import java.util.Collection; import java.util.Date; -import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.datadelivery.harvester.ConfigLayer; +import com.raytheon.uf.common.datadelivery.harvester.OGCAgent; import com.raytheon.uf.common.dataplugin.madis.MadisRecord; -import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; import com.raytheon.uf.edex.ogc.common.util.PluginIngestFilter; import com.raytheon.uf.edex.ogc.registry.WfsRegistryCollectorAddon; import com.raytheon.uf.edex.plugin.madis.ogc.MadisDimension; import com.raytheon.uf.edex.plugin.madis.ogc.MadisLayer; -import com.vividsolutions.jts.geom.Coordinate; -import com.vividsolutions.jts.geom.Envelope; /** * @@ -46,6 +43,7 @@ import com.vividsolutions.jts.geom.Envelope; * Aug 30, 2013 #2098 dhladky Incorrect time returned * Sept 2, 2013 #2098 dhladky Improved time management. * Sept 9, 2013 #2351 dhladky Speed improvements + * Jan 13, 2014 #2679 dhladky multiple ingest layers for a single request window. * * </pre> * @@ -57,12 +55,19 @@ public class MadisRegistryCollectorAddon extends implements PluginIngestFilter { /** - * @param layerName + * @param layerNames */ - public MadisRegistryCollectorAddon(String layerName) { - super(layerName); - this._layer = new MadisLayer(); - initializeLayer(_layer); + public MadisRegistryCollectorAddon() { + + super(); + OGCAgent agent = getAgent(); + + for (ConfigLayer clayer: agent.getLayers()) { + MadisLayer layer = new MadisLayer(); + layer.setName(clayer.getName()); + layers.put(clayer.getName(), layer); + initializeLayer(layer); + } } /* @@ -90,50 +95,15 @@ public class MadisRegistryCollectorAddon extends return new MadisLayer(layer); } - /** - * Filter geographically - */ - public PluginDataObject[] filter(PluginDataObject[] pdos) { - - Collection<MadisRecord> withInGeoConstraint = new ArrayList<MadisRecord>(); - PluginDataObject[] pdor = null; - Envelope e = null; - - if (getCoverage() != null) { - - e = getCoverage().getEnvelope(); - - for (PluginDataObject record : pdos) { - - MadisRecord rec = (MadisRecord) record; - - if (rec != null && rec.getLocation() != null) { - - Coordinate c = rec.getLocation().getLocation() - .getCoordinate(); - - if (c != null) { - - if (e.contains(c)) { - withInGeoConstraint.add(rec); - } else { - statusHandler.handle( - Priority.DEBUG, - "Madis record discarded: outside of range: " - + rec.getLatitude() + " " - + rec.getLongitude()); - } - } - } - } + @Override + public SurfaceObsLocation getSpatial(MadisRecord record) { + + if (record.getLocation() != null) { + return record.getLocation(); } + return null; + } - if (!withInGeoConstraint.isEmpty()) { - int size = withInGeoConstraint.size(); - pdor = withInGeoConstraint.toArray(new PluginDataObject[size]); - } - - return pdor; - } + } diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.obs.registry/res/spring/obs-ogc-registry.xml b/edexOsgi/com.raytheon.uf.edex.plugin.obs.registry/res/spring/obs-ogc-registry.xml index 2f6d8d9a5f..9853a10fed 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.obs.registry/res/spring/obs-ogc-registry.xml +++ b/edexOsgi/com.raytheon.uf.edex.plugin.obs.registry/res/spring/obs-ogc-registry.xml @@ -4,7 +4,6 @@ http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd"> <bean id="obsRegistryAddon" class="com.raytheon.uf.edex.plugin.obs.registry.ObsRegirstyCollectorAddon"> - <constructor-arg value="metar"/> </bean> <bean id="obsRegistryAddonProvider" class="com.raytheon.uf.edex.ogc.registry.RegistryCollectorAddonProvider"> diff --git a/edexOsgi/com.raytheon.uf.edex.plugin.obs.registry/src/com/raytheon/uf/edex/plugin/obs/registry/ObsRegistryCollectorAddon.java b/edexOsgi/com.raytheon.uf.edex.plugin.obs.registry/src/com/raytheon/uf/edex/plugin/obs/registry/ObsRegistryCollectorAddon.java index a132741b5b..b37a36123c 100644 --- a/edexOsgi/com.raytheon.uf.edex.plugin.obs.registry/src/com/raytheon/uf/edex/plugin/obs/registry/ObsRegistryCollectorAddon.java +++ b/edexOsgi/com.raytheon.uf.edex.plugin.obs.registry/src/com/raytheon/uf/edex/plugin/obs/registry/ObsRegistryCollectorAddon.java @@ -9,21 +9,18 @@ */ package com.raytheon.uf.edex.plugin.obs.registry; -import java.util.ArrayList; import java.util.Calendar; -import java.util.Collection; import java.util.Date; -import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.datadelivery.harvester.ConfigLayer; +import com.raytheon.uf.common.datadelivery.harvester.OGCAgent; import com.raytheon.uf.common.dataplugin.obs.metar.MetarRecord; -import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.common.pointdata.spatial.SurfaceObsLocation; import com.raytheon.uf.edex.ogc.common.db.DefaultPointDataDimension; import com.raytheon.uf.edex.ogc.common.db.LayerCollector; import com.raytheon.uf.edex.ogc.common.util.PluginIngestFilter; import com.raytheon.uf.edex.ogc.registry.WfsRegistryCollectorAddon; import com.raytheon.uf.edex.plugin.obs.ogc.metar.MetarLayer; -import com.vividsolutions.jts.geom.Coordinate; -import com.vividsolutions.jts.geom.Envelope; /** * Registry Collector for Observations @@ -35,6 +32,7 @@ import com.vividsolutions.jts.geom.Envelope; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jul 26, 2013 bclement Initial creation + * Jan 13, 2014 #2679 dhladky multiple layers * * </pre> * @@ -46,11 +44,16 @@ public class ObsRegistryCollectorAddon WfsRegistryCollectorAddon<DefaultPointDataDimension, MetarLayer, MetarRecord> implements PluginIngestFilter { - /** - * @param layerName - */ - public ObsRegistryCollectorAddon(String layerName) { - super(layerName); + public ObsRegistryCollectorAddon() { + + super(); + OGCAgent agent = getAgent(); + + for (ConfigLayer clayer: agent.getLayers()) { + MetarLayer layer = new MetarLayer(); + layers.put(clayer.getName(), layer); + initializeLayer(layer); + } } /* @@ -78,49 +81,13 @@ public class ObsRegistryCollectorAddon return new MetarLayer(layer); } - /** - * Filter geographically - */ - public PluginDataObject[] filter(PluginDataObject[] pdos) { - - Collection<MetarRecord> withInGeoConstraint = new ArrayList<MetarRecord>(); - PluginDataObject[] pdor = null; - - for (PluginDataObject record : pdos) { - - MetarRecord rec = (MetarRecord) record; - - if (rec != null) { - - Envelope e = getCoverage().getEnvelope(); - - if (rec.getLocation() != null) { - - Coordinate c = rec.getLocation().getLocation() - .getCoordinate(); - - if (c != null) { - - if (e.contains(c)) { - withInGeoConstraint.add(rec); - } else { - statusHandler.handle( - Priority.DEBUG, - "Obs record discarded: outside of range: " - + rec.getLatitude() + " " - + rec.getLongitude()); - } - } - } - } + @Override + public SurfaceObsLocation getSpatial(MetarRecord record) { + + if (record.getLocation() != null) { + return record.getLocation(); } - - if (!withInGeoConstraint.isEmpty()) { - int size = withInGeoConstraint.size(); - pdor = withInGeoConstraint.toArray(new PluginDataObject[size]); - } - - return pdor; + return null; } } From 4533642f26ac14d42758d1cebeb0a3bd54dfe9ba Mon Sep 17 00:00:00 2001 From: Nate Jensen <Nathan.Jensen@raytheon.com> Date: Wed, 15 Jan 2014 13:29:06 -0600 Subject: [PATCH 37/62] Issue #2359 printout connection exceptions to aid in diagnosing connectivity problems Change-Id: I957abb82cd3a736485f289a266b00cdbd89a578c Former-commit-id: ccaa9dbde143b169170727d95d7f52952641b02e [formerly fc6b31c1c0e96d87ec400314fbde8319279ca998] [formerly 5f39322d593ecdb3fcc6ccd01a7d231e5b60479b [formerly 8d7445a4ba4b76335166569de32c00bac1a2a84b]] Former-commit-id: 5f39322d593ecdb3fcc6ccd01a7d231e5b60479b Former-commit-id: deb57e3b35cf4c34785197931c098781faf1e517 --- .../uf/viz/core/comm/ConnectivityManager.java | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/comm/ConnectivityManager.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/comm/ConnectivityManager.java index 2935809090..cca57dcbd6 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/comm/ConnectivityManager.java +++ b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/comm/ConnectivityManager.java @@ -20,7 +20,9 @@ package com.raytheon.uf.viz.core.comm; import java.net.URI; +import java.text.SimpleDateFormat; import java.util.Collections; +import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -53,6 +55,7 @@ import com.raytheon.uf.viz.core.requests.ThriftClient; * Mar 22, 2013 1786 mpduff Changed to use HttpClient for * connectivity. * Aug 02, 2013 2202 bsteffen Add edex specific connectivity checking. + * Jan 15, 2013 njensen Added printConnectivityProblems() * * </pre> * @@ -88,7 +91,8 @@ public class ConnectivityManager { * @return whether quit was selected. TODO: need to return two booleans, one * for quit and one for connectivity */ - public static void checkHttpServer(String server, IConnectivityCallback callback) { + public static void checkHttpServer(String server, + IConnectivityCallback callback) { boolean good = false; try { HttpClient client = HttpClient.getInstance(); @@ -97,7 +101,7 @@ public class ConnectivityManager { client.executeRequest(request); good = true; } catch (Exception e) { - // ignore + printConnectivityProblem(server, "http", e); } callback.connectionChecked(new ConnectivityResult(good, server)); } @@ -108,12 +112,13 @@ public class ConnectivityManager { * @param server * server to check */ - public static void checkLocalizationServer(String server, IConnectivityCallback callback) { + public static void checkLocalizationServer(String server, + IConnectivityCallback callback) { boolean good = false; try { good = checkLocalizationServer(server, true) != null; } catch (Exception e) { - // ignore + printConnectivityProblem(server, "localization", e); } callback.connectionChecked(new ConnectivityResult(good, server)); } @@ -124,8 +129,8 @@ public class ConnectivityManager { * result is returned, otherwise the localization server is contacted to get * the response. */ - public static GetServersResponse checkLocalizationServer(String server, boolean force) - throws VizException { + public static GetServersResponse checkLocalizationServer(String server, + boolean force) throws VizException { if (!force) { GetServersResponse resp = getServersResponseCache.get(server); if (resp != null) { @@ -133,7 +138,8 @@ public class ConnectivityManager { } } GetServersRequest req = new GetServersRequest(); - GetServersResponse resp = (GetServersResponse) ThriftClient.sendRequest(req, server); + GetServersResponse resp = (GetServersResponse) ThriftClient + .sendRequest(req, server); getServersResponseCache.put(server, resp); return resp; @@ -154,8 +160,29 @@ public class ConnectivityManager { ActiveMQConnectionFactory f = new ActiveMQConnectionFactory(server); f.createConnection().close(); } catch (JMSException e) { + printConnectivityProblem(server, "JMS", e); good = false; } callback.connectionChecked(new ConnectivityResult(good, server)); } + + /** + * Prints the connectivity exception to the console, to help with diagnosing + * connection issues + * + * @param server + * the server address it attempted to connect to + * @param serverType + * the type of server it attempted to connect to + * @param e + * the exception that occurred + */ + private static void printConnectivityProblem(String server, + String serverType, Exception e) { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + System.out.println(sdf.format(new Date()) + " MAY NOT BE AN ERROR:"); + System.out.println("Couldn't connect to " + serverType + " server at " + + server); + e.printStackTrace(System.out); + } } From 70446e302ed50db9630416db2766c69f54012059 Mon Sep 17 00:00:00 2001 From: Benjamin Phillippe <Benjamin_D_Phillippe@raytheon.com> Date: Wed, 15 Jan 2014 15:06:05 -0600 Subject: [PATCH 38/62] Issue #2613 Registry peformance enhancements -- Added indexes to registry tables -- Better cleanup when a registry leaves the federation -- Batching of queries in notification handler to reduce number of web service calls -- Added Hibernate flushes and clears to better manage memory Change-Id: I88ec580694d2104458391a798667748c88f16dd0 Former-commit-id: c3e9724e7ee4437ba815094408ea2a2aae8e7a1f [formerly fd30caddb0f06dadf5845ce9ea4e1aa624fc877d] [formerly 83bec75737a080c6a79d0ab0b3afe569d892eafc [formerly 4344ffec77286a531b9be29e9ef94acd9c6ce342]] Former-commit-id: 83bec75737a080c6a79d0ab0b3afe569d892eafc Former-commit-id: 59d5644742566530721c27f368de0a0fb86afa81 --- .../services/RegistryRESTServices.java | 35 +-- .../services/RegistrySOAPServices.java | 36 +-- .../xsd/rim/v4/ExtensibleObjectType.java | 3 + .../tc/ebxml/regrep/xsd/rim/v4/SlotType.java | 5 +- .../federation/RegistryFederationManager.java | 192 +++++++++---- .../res/scripts/RegistryIndices.sql | 259 ++++++++++++++++-- ...raytheon.uf.edex.registry.ebxml.properties | 2 +- .../services/RegistryGarbageCollector.java | 2 + .../NotificationListenerImpl.java | 112 ++++---- .../RegistrySubscriptionManager.java | 3 + 10 files changed, 471 insertions(+), 178 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/services/RegistryRESTServices.java b/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/services/RegistryRESTServices.java index 69e1202c6b..b22ad3da3b 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/services/RegistryRESTServices.java +++ b/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/services/RegistryRESTServices.java @@ -21,11 +21,7 @@ package com.raytheon.uf.common.registry.services; import java.lang.reflect.Proxy; import java.net.URL; -import java.nio.charset.Charset; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; +import java.nio.charset.StandardCharsets; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; @@ -40,9 +36,6 @@ import org.apache.cxf.transport.http.HTTPConduit; import org.apache.cxf.transports.http.configuration.ConnectionType; import org.apache.cxf.transports.http.configuration.HTTPClientPolicy; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; import com.google.common.io.Resources; import com.raytheon.uf.common.comm.ProxyConfiguration; import com.raytheon.uf.common.registry.RegistryJaxbManager; @@ -68,6 +61,7 @@ import com.raytheon.uf.common.registry.services.rest.IRepositoryItemsRestService * 10/30/2013 1538 bphillip Moved data delivery services out of registry plugin * 11/20/2013 2534 bphillip Added HTTPClient policy for rest connections. Eliminated service caching. * 12/2/2013 1829 bphillip Removed expectedType argument on getRegistryObject method + * 1/15/2014 2613 bphillip Removed Service cache due to unexpected behavior * </pre> * * @author bphillip @@ -99,8 +93,6 @@ public class RegistryRESTServices { } } - private Map<Class<?>, LoadingCache<String, ?>> serviceCache = new HashMap<Class<?>, LoadingCache<String, ?>>(); - public RegistryRESTServices() throws JAXBException { jaxbManager = new RegistryJaxbManager(new RegistryNamespaceMapper()); } @@ -179,8 +171,8 @@ public class RegistryRESTServices { public Object accessXMLRestService(String url) { String response = null; try { - response = Resources - .toString(new URL(url), Charset.forName("UTF8")); + ; + response = Resources.toString(new URL(url), StandardCharsets.UTF_8); } catch (Exception e) { throw new RegistryServiceException( "Error accessing REST service at URL: [" + url + "]", e); @@ -194,26 +186,9 @@ public class RegistryRESTServices { } } - @SuppressWarnings("unchecked") protected <T extends Object> T getPort(String serviceUrl, final Class<T> serviceInterface) { - LoadingCache<String, ?> cache = serviceCache.get(serviceInterface); - if (cache == null) { - cache = CacheBuilder.newBuilder() - .expireAfterAccess(1, TimeUnit.MINUTES) - .build(new CacheLoader<String, T>() { - public T load(String key) { - return createService(key, serviceInterface); - } - }); - serviceCache.put(serviceInterface, cache); - } - try { - return (T) cache.get(serviceUrl); - } catch (ExecutionException e) { - throw new RuntimeException("Error getting service at [" - + serviceUrl + "]", e); - } + return createService(serviceUrl, serviceInterface); } protected <T extends Object> T createService(String url, diff --git a/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/services/RegistrySOAPServices.java b/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/services/RegistrySOAPServices.java index 56b629b934..bf82d70bc6 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/services/RegistrySOAPServices.java +++ b/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/services/RegistrySOAPServices.java @@ -27,8 +27,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; import javax.xml.ws.wsaddressing.W3CEndpointReference; import javax.xml.ws.wsaddressing.W3CEndpointReferenceBuilder; @@ -51,9 +49,6 @@ import org.apache.cxf.transport.http.HTTPConduit; import org.apache.cxf.transports.http.configuration.ConnectionType; import org.apache.cxf.transports.http.configuration.HTTPClientPolicy; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; import com.raytheon.uf.common.comm.ProxyConfiguration; import com.raytheon.uf.common.comm.ProxyUtil; import com.raytheon.uf.common.localization.PathManagerFactory; @@ -77,6 +72,7 @@ import com.raytheon.uf.common.status.UFStatus; * 9/5/2013 1538 bphillip Add HTTP header information * 10/30/2013 1538 bphillip Made methods in this class non-static * 11/20/2013 2534 bphillip Eliminated service caching + * 1/15/2014 2613 bphillip Eliminated service caching...again * </pre> * * @author bphillip @@ -118,13 +114,18 @@ public class RegistrySOAPServices { private static final ProxyConfiguration proxyConfig; protected static final HTTPClientPolicy httpClientPolicy; + + protected static final String HTTP_RECEIVE_TIMEOUT_PROPERTY = "ebxml-http-receive-timeout"; + + protected static final String HTTP_CONNECTION_TIMEOUT_PROPERTY = "ebxml-http-connection-timeout"; + static { proxyConfig = getProxyConfiguration(); httpClientPolicy = new HTTPClientPolicy(); try { httpClientPolicy.setReceiveTimeout(Long.parseLong(System - .getProperty("ebxml-http-receive-timeout"))); + .getProperty(HTTP_RECEIVE_TIMEOUT_PROPERTY))); } catch (NumberFormatException e) { statusHandler .error("ebxml-http-receive-timeout not specified. Using default value of 1 minute", @@ -133,7 +134,7 @@ public class RegistrySOAPServices { } try { httpClientPolicy.setConnectionTimeout(Long.parseLong(System - .getProperty("ebxml-http-connection-timeout"))); + .getProperty(HTTP_CONNECTION_TIMEOUT_PROPERTY))); } catch (NumberFormatException e) { statusHandler .error("ebxml-http-connection-timeout not specified. Using default value of 10 seconds", @@ -149,8 +150,6 @@ public class RegistrySOAPServices { } } - private Map<Class<?>, LoadingCache<String, ?>> serviceCache = new HashMap<Class<?>, LoadingCache<String, ?>>(); - /** * Gets the notification listener service URL for the given host * @@ -355,26 +354,9 @@ public class RegistrySOAPServices { return port; } - @SuppressWarnings("unchecked") private <T extends Object> T getPort(String serviceUrl, final Class<T> serviceInterface) { - LoadingCache<String, ?> cache = serviceCache.get(serviceInterface); - if (cache == null) { - cache = CacheBuilder.newBuilder() - .expireAfterAccess(1, TimeUnit.MINUTES) - .build(new CacheLoader<String, T>() { - public T load(String key) { - return createService(key, serviceInterface); - } - }); - serviceCache.put(serviceInterface, cache); - } - try { - return (T) cache.get(serviceUrl); - } catch (ExecutionException e) { - throw new RuntimeException("Error getting service at [" - + serviceUrl + "]", e); - } + return createService(serviceUrl, serviceInterface); } /** diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/ExtensibleObjectType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/ExtensibleObjectType.java index fe4989348c..5d8f2006a0 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/ExtensibleObjectType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/ExtensibleObjectType.java @@ -50,6 +50,7 @@ import oasis.names.tc.ebxml.regrep.xsd.rs.v4.RegistryExceptionType; import oasis.names.tc.ebxml.regrep.xsd.rs.v4.RegistryRequestType; import oasis.names.tc.ebxml.regrep.xsd.rs.v4.RegistryResponseType; +import org.hibernate.annotations.BatchSize; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @@ -91,6 +92,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 2012 bphillip Initial implementation * 10/17/2013 1682 bphillip Added software history * 12/2/2013 1829 bphillip Made ExtensibleObjectType persistable, modified persistence annotations, added hashCode and equals + * 1/15/2014 2613 bphillip Added batch size Slot field * </pre> * * @author bphillip @@ -124,6 +126,7 @@ public abstract class ExtensibleObjectType implements Serializable, @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "parent_id", nullable = false, referencedColumnName = "id") @XmlElement(name = "Slot") + @BatchSize(size = 50) @DynamicSerializeElement protected List<SlotType> slot; diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/SlotType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/SlotType.java index 9c900b22de..6c23308767 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/SlotType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/SlotType.java @@ -84,6 +84,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Made ExtensibleObjectType persistable, * modified persistence annotations, added * constructors, hashCode, toString and equals + * 1/15/2014 2613 bphillip Removed automatically created index * </pre> * * @author bphillip @@ -96,9 +97,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @Entity @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL, include = "all") @Table(schema = RegrepUtil.EBXML_SCHEMA, name = "Slot") -@org.hibernate.annotations.Table(appliesTo = "Slot", indexes = { - @Index(name = "slot_idx", columnNames = { "parent_id" }), - @Index(name = "value_idx", columnNames = { "value_id" }) }) +@org.hibernate.annotations.Table(appliesTo = "Slot", indexes = { @Index(name = "value_idx", columnNames = { "value_id" }) }) public class SlotType extends ExtensibleObjectType implements IPersistableDataObject<String> { diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/src/com/raytheon/uf/edex/datadelivery/registry/federation/RegistryFederationManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/src/com/raytheon/uf/edex/datadelivery/registry/federation/RegistryFederationManager.java index f26202856d..07f8f7125a 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/src/com/raytheon/uf/edex/datadelivery/registry/federation/RegistryFederationManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.registry/src/com/raytheon/uf/edex/datadelivery/registry/federation/RegistryFederationManager.java @@ -45,6 +45,7 @@ import oasis.names.tc.ebxml.regrep.wsdl.registry.services.v4.LifecycleManager; import oasis.names.tc.ebxml.regrep.wsdl.registry.services.v4.MsgRegistryException; import oasis.names.tc.ebxml.regrep.wsdl.registry.services.v4.QueryManager; import oasis.names.tc.ebxml.regrep.xsd.lcm.v4.Mode; +import oasis.names.tc.ebxml.regrep.xsd.lcm.v4.RemoveObjectsRequest; import oasis.names.tc.ebxml.regrep.xsd.lcm.v4.SubmitObjectsRequest; import oasis.names.tc.ebxml.regrep.xsd.query.v4.QueryRequest; import oasis.names.tc.ebxml.regrep.xsd.query.v4.QueryResponse; @@ -52,6 +53,7 @@ import oasis.names.tc.ebxml.regrep.xsd.query.v4.ResponseOptionType; import oasis.names.tc.ebxml.regrep.xsd.rim.v4.AssociationType; import oasis.names.tc.ebxml.regrep.xsd.rim.v4.DeliveryInfoType; import oasis.names.tc.ebxml.regrep.xsd.rim.v4.FederationType; +import oasis.names.tc.ebxml.regrep.xsd.rim.v4.ObjectRefListType; import oasis.names.tc.ebxml.regrep.xsd.rim.v4.ObjectRefType; import oasis.names.tc.ebxml.regrep.xsd.rim.v4.OrganizationType; import oasis.names.tc.ebxml.regrep.xsd.rim.v4.PersonType; @@ -65,7 +67,9 @@ import oasis.names.tc.ebxml.regrep.xsd.rim.v4.SubscriptionType; import oasis.names.tc.ebxml.regrep.xsd.rim.v4.VersionInfoType; import org.springframework.stereotype.Service; +import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionCallbackWithoutResult; import org.springframework.transaction.support.TransactionTemplate; import org.w3c.dom.Attr; import org.w3c.dom.Document; @@ -151,6 +155,7 @@ import com.raytheon.uf.edex.registry.ebxml.util.EbxmlObjectUtil; * 11/20/2013 2534 bphillip Consolidated RegistryReplicationManager into this class and added reciprocal subscriptions. Added remote subscription monitor. * 12/2/2013 1829 bphillip Modified to use correct getters for slot values * 12/9/2013 2613 bphillip Optimized registry sync function + * 1/15/2014 2613 bphillip Added leaveFederation method to prevent inactive registries from participating in the federation unintentionally. * </pre> * * @author bphillip @@ -203,7 +208,10 @@ public class RegistryFederationManager implements RegistryInitializedListener { protected String ncfAddress = System.getenv("NCF_ADDRESS"); /** The mode that EDEX was started in */ - private String registryMode = System.getProperty("edex.run.mode"); + public static final boolean centralRegistry = System.getProperty( + "edex.run.mode").equals(CENTRAL_REGISTRY_MODE); + + private static final String FEDERATION_SYNC_THREADS_PROPERTY = "ebxml-federation-sync-threads"; /** * When a federation sync is necessary, this is the number of threads that @@ -307,9 +315,9 @@ public class RegistryFederationManager implements RegistryInitializedListener { "Error initializing JAXB Manager!", e); } - if (System.getProperty("ebxml-federation-sync-threads") != null) { + if (System.getProperty(FEDERATION_SYNC_THREADS_PROPERTY) != null) { registrySyncThreads = Integer.valueOf(System - .getProperty("ebxml-federation-sync-threads")); + .getProperty(FEDERATION_SYNC_THREADS_PROPERTY)); } /* @@ -400,7 +408,7 @@ public class RegistryFederationManager implements RegistryInitializedListener { RegistryServiceException, JAXBException { FederationType federation = null; - if (isCentralRegistry()) { + if (centralRegistry) { statusHandler.info("Creating Federation object..."); federation = new FederationType(); federation.setId(FEDERATION_ID); @@ -502,7 +510,7 @@ public class RegistryFederationManager implements RegistryInitializedListener { "Error submitting federation objects to registry", e); } - if (!isCentralRegistry()) { + if (!centralRegistry) { statusHandler .info("Submitting federation registration objects to NCF..."); try { @@ -1124,14 +1132,24 @@ public class RegistryFederationManager implements RegistryInitializedListener { statusHandler .info("Registry shutting down. Removing subscriptions from: [" + remoteRegistryBaseURL + "]"); - dataDeliveryRestClient - .getRegistryDataAccessService( - remoteRegistryBaseURL) - .removeSubscriptionsForSite( - federationProperties - .getSiteIdentifier()); - statusHandler.info("Subscriptions removed from: [" - + remoteRegistryBaseURL + "]"); + if (dataDeliveryRestClient + .isRegistryAvailable(remoteRegistryBaseURL)) { + dataDeliveryRestClient + .getRegistryDataAccessService( + remoteRegistryBaseURL) + .removeSubscriptionsForSite( + federationProperties + .getSiteIdentifier()); + statusHandler + .info("Subscriptions removed from: [" + + remoteRegistryBaseURL + "]"); + } else { + statusHandler + .warn("Registry at [" + + remoteRegistryBaseURL + + "] is not available. Unable to remove subscriptions."); + } + } }); return true; @@ -1240,7 +1258,17 @@ public class RegistryFederationManager implements RegistryInitializedListener { .warn("Registry at [" + remoteRegistryUrl + "] is unavailable. Unable to verify subscriptions"); - return; + continue; + } + + if (!Boolean.parseBoolean(dataDeliveryRestClient + .getFederationService(remoteRegistryUrl) + .isFederated())) { + statusHandler + .warn("Registry at [" + + remoteRegistryUrl + + "] is currently not participating in the federation. Skipping subscription verification"); + continue; } int resubmissions = 0; QueryManager remoteQueryManager = registrySoapServices @@ -1335,39 +1363,36 @@ public class RegistryFederationManager implements RegistryInitializedListener { scheduler.schedule(this, 10, TimeUnit.SECONDS); } } + } - private boolean joinFederation() { + public boolean joinFederation() { + try { try { - try { - if (!isCentralRegistry()) { - if (dataDeliveryRestClient - .isRegistryAvailable(ncfAddress)) { - statusHandler - .info("NCF Registry is available. Attempting to join federation..."); - } else { - statusHandler - .error("Unable to join federation. NCF is currently unreachable."); - return false; - } - } - List<RegistryObjectType> objects = new ArrayList<RegistryObjectType>( - 5); - RegistryType registry = federationProperties - .createRegistryObject(); - OrganizationType org = federationProperties - .createOrganization(); - PersonType primaryContact = federationProperties - .createPrimaryContactPerson(); - FederationType federation = getFederation(); - AssociationType federationAssociation = null; - if (federation == null) { + if (!centralRegistry) { + if (dataDeliveryRestClient.isRegistryAvailable(ncfAddress)) { statusHandler - .error("Unable to join federation. Federation Object not found."); + .info("NCF Registry is available. Attempting to join federation..."); } else { - federationAssociation = getFederationAssociation( - registry, federation); + statusHandler + .error("Unable to join federation. NCF is currently unreachable."); + return false; } - if (isCentralRegistry()) { + } + List<RegistryObjectType> objects = new ArrayList<RegistryObjectType>( + 5); + final RegistryType registry = federationProperties + .createRegistryObject(); + final OrganizationType org = federationProperties + .createOrganization(); + final PersonType primaryContact = federationProperties + .createPrimaryContactPerson(); + FederationType federation = getFederation(); + + if (federation != null) { + final AssociationType federationAssociation = getFederationAssociation( + registry, federation); + + if (centralRegistry) { objects.add(federation); } objects.add(registry); @@ -1381,20 +1406,82 @@ public class RegistryFederationManager implements RegistryInitializedListener { statusHandler .warn("No replication servers have been specified!"); } - return true; - } catch (EbxmlRegistryException e) { - statusHandler.error("Error registering with federation", e); - return false; + + Runtime.getRuntime().addShutdownHook(new Thread() { + + public void run() { + txTemplate + .execute(new TransactionCallbackWithoutResult() { + + @Override + protected void doInTransactionWithoutResult( + TransactionStatus status) { + leaveFederation(); + + } + }); + + } + }); } - } catch (Throwable e) { - statusHandler.error("Error initializing EBXML database!", e); + return true; + } catch (EbxmlRegistryException e) { + statusHandler.error("Error registering with federation", e); return false; } + } catch (Throwable e) { + statusHandler.error("Error initializing EBXML database!", e); + return false; } } - private boolean isCentralRegistry() { - return registryMode.equals(CENTRAL_REGISTRY_MODE); + public boolean leaveFederation() { + try { + final RegistryType registry = federationProperties + .createRegistryObject(); + final OrganizationType org = federationProperties + .createOrganization(); + final PersonType primaryContact = federationProperties + .createPrimaryContactPerson(); + FederationType federation = getFederation(); + + if (federation != null) { + final AssociationType federationAssociation = getFederationAssociation( + registry, federation); + ObjectRefListType refList = new ObjectRefListType(); + refList.getObjectRef().add(new ObjectRefType(registry.getId())); + refList.getObjectRef().add(new ObjectRefType(org.getId())); + refList.getObjectRef().add( + new ObjectRefType(primaryContact.getId())); + refList.getObjectRef().add( + new ObjectRefType(federationAssociation.getId())); + RemoveObjectsRequest req = new RemoveObjectsRequest(); + req.setId("Removing [" + registry.getId() + + "] from the federation..."); + req.setComment("Remove request to remove federation related objects"); + req.setDeleteChildren(true); + req.setObjectRefList(refList); + statusHandler.info("Disconnecting from federation..."); + try { + if (RegistryFederationManager.centralRegistry) { + lcm.removeObjects(req); + } else { + registrySoapServices.getLifecycleManagerServiceForHost( + ncfAddress).removeObjects(req); + } + statusHandler + .info("Registry disconnected from federation."); + } catch (MsgRegistryException e) { + statusHandler.error( + "Error while disconnecting from federation!", e); + } + } + } catch (Throwable e) { + statusHandler.error("Error leaving federation", e); + return false; + } + return true; + } public static Set<String> getObjectTypes() { @@ -1422,4 +1509,9 @@ public class RegistryFederationManager implements RegistryInitializedListener { DataDeliveryRESTServices dataDeliveryRestClient) { this.dataDeliveryRestClient = dataDeliveryRestClient; } + + public static FederationProperties getFederationProperties() { + return federationProperties; + } + } diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/res/scripts/RegistryIndices.sql b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/res/scripts/RegistryIndices.sql index 6945423a5d..a79e00c797 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/res/scripts/RegistryIndices.sql +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/res/scripts/RegistryIndices.sql @@ -1,11 +1,11 @@ CREATE INDEX event_id_idx ON ebxml.auditableevent_action - USING btree + USING hash (auditableevent_id); CREATE INDEX notification_id_idx ON ebxml.notification_auditableevent - USING btree + USING hash (notification_id); CREATE INDEX objectreflist_id_idx @@ -15,57 +15,57 @@ CREATE INDEX objectreflist_id_idx CREATE INDEX organization_id_email_idx ON ebxml.organization_emailaddress - USING btree + USING hash (organization_id); CREATE INDEX organization_id_org_idx ON ebxml.organization_organization - USING btree + USING hash (org_id); CREATE INDEX organization_id_address_idx ON ebxml.organization_postaladdress - USING btree + USING hash (organization_id); CREATE INDEX organization_id_telephone_idx ON ebxml.organization_telephonenumber - USING btree + USING hash (organization_id); CREATE INDEX person_id_email_idx ON ebxml.person_emailaddress - USING btree + USING hash (person_id); CREATE INDEX person_id_address_idx ON ebxml.person_postaladdress - USING btree + USING hash (person_id); CREATE INDEX person_id_telephone_idx ON ebxml.person_telephonenumber - USING btree + USING hash (person_id); CREATE INDEX querydefinition_id_idx ON ebxml.querydefinition_parameter - USING btree + USING hash (querydefinition_id); CREATE INDEX registryobject_id_classification_idx ON ebxml.registryobject_classification - USING btree + USING hash (registryobject_id); CREATE INDEX registryobject_id_externalid_idx ON ebxml.registryobject_externalidentifier - USING btree + USING hash (registryobject_id); CREATE INDEX registryobject_id_externallink_idx ON ebxml.registryobject_externallink - USING btree + USING hash (registryobject_id); CREATE INDEX registryobjectlist_id_idx @@ -75,20 +75,245 @@ CREATE INDEX registryobjectlist_id_idx CREATE INDEX service_id_idx ON ebxml.service_serviceendpoint - USING btree + USING hash (service_id); CREATE INDEX subscription_id_idx ON ebxml.subscription_deliveryinfo - USING btree + USING hash (subscription_id); CREATE INDEX taxonomyelement_id_idx ON ebxml.taxonomyelementtype_classificationnode - USING btree + USING hash (taxonomyelementtype_id); CREATE INDEX value_id_idx ON ebxml.value_value USING btree - (value_id); \ No newline at end of file + (value_id); + +CREATE INDEX collectionvalue_id_idx + ON ebxml.value_value + USING btree + (collectionvalue_id); + +CREATE INDEX objectref_id_idx + ON ebxml.objectref + USING hash + (id COLLATE pg_catalog."default"); + +CREATE INDEX objectref_key_idx + ON ebxml.objectref + USING hash + (key COLLATE pg_catalog."default"); + +CREATE INDEX objectreflist_key_idx + ON ebxml.objectreflist_objectref + USING hash + (objectref_key COLLATE pg_catalog."default"); + +CREATE INDEX slot_parent_id_idx + ON ebxml.slot + USING hash + (parent_id COLLATE pg_catalog."default"); + +CREATE INDEX action_eventtype_idx + ON ebxml.action + USING hash + (eventtype COLLATE pg_catalog."default"); + +CREATE INDEX auditableevent_timestamp_idx + ON ebxml.auditableevent + USING btree + ("timestamp"); + +CREATE INDEX action_id_hash_idx + ON ebxml.action + USING hash + (id); + +CREATE INDEX deliveryinfo_id_hash_idx + ON ebxml.deliveryinfo + USING hash + (id); + +CREATE INDEX emailaddress_id_hash_idx + ON ebxml.emailaddress + USING hash + (id); + +CREATE INDEX registryobject_id_hash_idx + ON ebxml.registryobject + USING hash + (id); + +CREATE INDEX association_id_hash_idx + ON ebxml.association + USING hash + (id); + +CREATE INDEX auditableevent_id_hash_idx + ON ebxml.auditableevent + USING hash + (id); + +CREATE INDEX classification_id_hash_idx + ON ebxml.classification + USING hash + (id); + +CREATE INDEX externalidentifier_id_hash_idx + ON ebxml.externalidentifier + USING hash + (id); + + +CREATE INDEX externallink_id_hash_idx + ON ebxml.externallink + USING hash + (id); + +CREATE INDEX extrinsicobject_id_hash_idx + ON ebxml.extrinsicobject + USING hash + (id); + +CREATE INDEX comment_id_hash_idx + ON ebxml.comment + USING hash + (id); + +CREATE INDEX federation_id_hash_idx + ON ebxml.federation + USING hash + (id); + + +CREATE INDEX notification_id_hash_idx + ON ebxml.notification + USING hash + (id); + +CREATE INDEX organization_id_hash_idx + ON ebxml.organization + USING hash + (id); + +CREATE INDEX person_id_hash_idx + ON ebxml.person + USING hash + (id); + +CREATE INDEX querydefinition_id_hash_idx + ON ebxml.querydefinition + USING hash + (id); + + +CREATE INDEX registrypackage_id_hash_idx + ON ebxml.registrypackage + USING hash + (id); + +CREATE INDEX registry_id_hash_idx + ON ebxml.registry + USING hash + (id); + +CREATE INDEX role_id_hash_idx + ON ebxml.role + USING hash + (id); + +CREATE INDEX servicebinding_id_hash_idx + ON ebxml.servicebinding + USING hash + (id); + + +CREATE INDEX serviceendpoint_id_hash_idx + ON ebxml.serviceendpoint + USING hash + (id); + +CREATE INDEX serviceinterface_id_hash_idx + ON ebxml.serviceinterface + USING hash + (id); + +CREATE INDEX service_id_hash_idx + ON ebxml.service + USING hash + (id); + +CREATE INDEX subscription_id_hash_idx + ON ebxml.subscription + USING hash + (id); + + +CREATE INDEX classificationnode_id_hash_idx + ON ebxml.classificationnode + USING hash + (id); + +CREATE INDEX classificationscheme_id_hash_idx + ON ebxml.classificationscheme + USING hash + (id); + +CREATE INDEX workflowaction_id_hash_idx + ON ebxml.workflowaction + USING hash + (id); + +CREATE INDEX parameter_id_hash_idx + ON ebxml.parameter + USING hash + (id); + + +CREATE INDEX personname_id_hash_idx + ON ebxml.personname + USING hash + (id); + +CREATE INDEX postaladdress_id_hash_idx + ON ebxml.postaladdress + USING hash + (id); + +CREATE INDEX queryexpression_id_hash_idx + ON ebxml.queryexpression + USING hash + (id); + +CREATE INDEX stringqueryexpression_id_hash_idx + ON ebxml.stringqueryexpression + USING hash + (id); + + +CREATE INDEX xmlqueryexpression_id_hash_idx + ON ebxml.xmlqueryexpression + USING hash + (id); + +CREATE INDEX query_id_hash_idx + ON ebxml.query + USING hash + (id); + +CREATE INDEX slot_id_hash_idx + ON ebxml.slot + USING hash + (id); + +CREATE INDEX telephonenumber_id_hash_idx + ON ebxml.telephonenumber + USING hash + (id); + + + \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/resources/com.raytheon.uf.edex.registry.ebxml.properties b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/resources/com.raytheon.uf.edex.registry.ebxml.properties index cd34de3a89..1443109d82 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/resources/com.raytheon.uf.edex.registry.ebxml.properties +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/resources/com.raytheon.uf.edex.registry.ebxml.properties @@ -1,7 +1,7 @@ # The period which registry subscriptions are processed ebxml-subscription-process.cron=0/20+*+*+*+*+? # The period which the registry runs the garbage collection -ebxml-garbage-collect-process.cron=0/10+*+*+*+*+? +ebxml-garbage-collect-process.cron=*+0/5+*+*+*+? # The period which adhoc subscriptions are cleaned, every 20 mins adhocsubscription-process.cron=0+0/20+*+*+*+? # When a federation synchonization is necessary, this is the number of threads diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/RegistryGarbageCollector.java b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/RegistryGarbageCollector.java index cadb068159..2311f42187 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/RegistryGarbageCollector.java +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/RegistryGarbageCollector.java @@ -52,6 +52,7 @@ import com.raytheon.uf.edex.registry.ebxml.exception.EbxmlRegistryException; * ------------ ---------- ----------- -------------------------- * 7/11/2013 1707 bphillip Initial implementation * 7/29/2013 2191 bphillip Added executors to remove orphaned slots and expired events + * 1/15/2014 2613 bphillip Added Hibernate flush() call * </pre> * * @author bphillip @@ -162,6 +163,7 @@ public class RegistryGarbageCollector { @Override public void runWithTransaction() { eventDao.delete(event); + eventDao.flushAndClearSession(); } } } diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/NotificationListenerImpl.java b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/NotificationListenerImpl.java index ee50b8c799..edd3cbd274 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/NotificationListenerImpl.java +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/NotificationListenerImpl.java @@ -90,6 +90,7 @@ import com.raytheon.uf.edex.registry.ebxml.util.EbxmlObjectUtil; * 10/23/2013 1538 bphillip Added log message denoting when processing is complete and time duration * 10/30/2013 1538 bphillip Changed to use non-static registry soap service client * 12/2/2013 1829 bphillip Added getIdsFrom action method and changed how slots are added to objects + * 1/15/2014 2613 bphillip Added batching of notification update queries to reduce number of web service calls * * </pre> * @@ -143,64 +144,75 @@ public class NotificationListenerImpl implements NotificationListener { List<AuditableEventType> events = notification.getEvent(); - // Process the received auditable events and add them to the - // appropriate - // list based on the action performed + List<String> actionList = new ArrayList<String>(events.size()); + List<String> objIdList = new ArrayList<String>(events.size()); + for (AuditableEventType event : events) { List<ActionType> actions = event.getAction(); for (ActionType action : actions) { String eventType = action.getEventType(); List<String> objectIds = getIdsFromAction(action); - - if (objectIds.isEmpty()) { - statusHandler.info("Event " + event.getId() - + " contains 0 affected objects "); - continue; - } - - if (eventType.equals(ActionTypes.create) - || eventType.equals(ActionTypes.update)) { - try { - SubmitObjectsRequest submitRequest = createSubmitObjectsRequest( - clientBaseURL, notification.getId(), objectIds, - Mode.CREATE_OR_REPLACE); - lcm.submitObjects(submitRequest); - } catch (MsgRegistryException e) { - throw new RuntimeException( - "Error creating objects in registry!", e); - } catch (EbxmlRegistryException e) { - throw new RuntimeException( - "Error creating submit objects request!", e); - } - } else if (eventType.equals(ActionTypes.delete)) { - ObjectRefListType refList = new ObjectRefListType(); - for (String id : objectIds) { - RegistryObjectType object = registryObjectDao - .getById(id); - if (object != null) { - refList.getObjectRef().add(new ObjectRefType(id)); - } - } - if (!CollectionUtil.isNullOrEmpty(refList.getObjectRef())) { - RemoveObjectsRequest request = new RemoveObjectsRequest( - "Remove Objects for notification [" - + notification.getId() + "]", - "Notification delete object submission", null, - null, refList, false, true, - DeletionScope.DELETE_ALL); - try { - lcm.removeObjects(request); - } catch (MsgRegistryException e) { - throw new RuntimeException( - "Error creating remove objects request!", e); - } - } - } else { - statusHandler.info("Unknown event type [" + eventType - + "] received in notification"); + objIdList.addAll(objectIds); + for (int i = 0; i < objectIds.size(); i++) { + actionList.add(eventType); } } } + + int listSize = objIdList.size(); + for (int i = 0; i < listSize;) { + List<String> insertIds = new ArrayList<String>(); + while (i < listSize + && (actionList.get(i).equals(ActionTypes.create) || actionList + .get(i).equals(ActionTypes.update))) { + insertIds.add(objIdList.get(i)); + i++; + } + if (!insertIds.isEmpty()) { + try { + SubmitObjectsRequest submitRequest = createSubmitObjectsRequest( + clientBaseURL, notification.getId(), insertIds, + Mode.CREATE_OR_REPLACE); + lcm.submitObjects(submitRequest); + } catch (MsgRegistryException e) { + throw new RuntimeException( + "Error creating objects in registry!", e); + } catch (EbxmlRegistryException e) { + throw new RuntimeException( + "Error creating submit objects request!", e); + } + } + List<String> deleteIds = new ArrayList<String>(); + while (i < listSize && actionList.get(i).equals(ActionTypes.delete)) { + deleteIds.add(objIdList.get(i)); + i++; + } + if (!deleteIds.isEmpty()) { + ObjectRefListType refList = new ObjectRefListType(); + for (String id : deleteIds) { + RegistryObjectType object = registryObjectDao.getById(id); + if (object != null) { + refList.getObjectRef().add(new ObjectRefType(id)); + } + } + if (!CollectionUtil.isNullOrEmpty(refList.getObjectRef())) { + RemoveObjectsRequest request = new RemoveObjectsRequest( + "Remove Objects for notification [" + + notification.getId() + "]", + "Notification delete object submission", null, + null, refList, false, true, + DeletionScope.DELETE_ALL); + try { + lcm.removeObjects(request); + } catch (MsgRegistryException e) { + throw new RuntimeException( + "Error creating remove objects request!", e); + } + } + } + } + + registryDao.flushAndClearSession(); statusHandler.info("Processing notification id [" + notification.getId() + "] completed in " + (TimeUtil.currentTimeMillis() - startTime) + " ms"); diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/RegistrySubscriptionManager.java b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/RegistrySubscriptionManager.java index c0ff92f16a..52074c75ac 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/RegistrySubscriptionManager.java +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/RegistrySubscriptionManager.java @@ -80,6 +80,7 @@ import com.raytheon.uf.edex.registry.ebxml.util.EbxmlObjectUtil; * to not create duplicate slots on objects * 11/20/2013 2534 bphillip Moved method to get notification destinations to utility * 12/9/2013 2613 bphillip Setting last run time of subscription now occurs before notification is sent + * 1/15/2014 2613 bphillip Added Hibernate flush and clear after subscription processing * </pre> * * @author bphillip @@ -394,6 +395,8 @@ public class RegistrySubscriptionManager implements statusHandler.error( "Errors occurred while processing subscription [" + subscriptionName + "]", e); + } finally { + subscriptionDao.flushAndClearSession(); } } From 4f4f4996be3610ec9ed0f7ecab37dafff59a34ce Mon Sep 17 00:00:00 2001 From: Ron Anderson <ron.anderson@raytheon.com> Date: Wed, 15 Jan 2014 16:16:44 -0600 Subject: [PATCH 39/62] Issue #1571 Fix bug in GFE where DbId in ParmId did not match the Database. Change-Id: I08b5ec1dbbf95d269c9f1ad7fb5e02a8a471b7ec Former-commit-id: a656439fb2c39ae3116ace4a8fe74a6871f98b76 [formerly 46f00786edeadff2f51ded0b962d0b27a8f10af7] [formerly fae5283358711eb9b156b1636c04ff21e575de0d [formerly c03aacd100a73d84d96bfcd3db447597f478fcb7]] Former-commit-id: fae5283358711eb9b156b1636c04ff21e575de0d Former-commit-id: 151cb21153a646dd02be01b5ef25ab26521468bf --- .../edex/plugin/gfe/config/GridDbConfig.java | 6 +++-- .../gfe/server/database/IFPGridDatabase.java | 8 ------ .../gfe/db/objects/ParmStorageInfo.java | 26 ++++++++++++++++++- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GridDbConfig.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GridDbConfig.java index 46c80ba889..308d9c6cfa 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GridDbConfig.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/config/GridDbConfig.java @@ -48,6 +48,8 @@ import com.raytheon.uf.common.dataplugin.gfe.weather.WxDefinition; * 03/14/08 #1030 randerso Initial port * 04/8/08 #875 bphillip Added getter for Grid Parm Info dictionary * 08/05/2013 #1571 randerso Made GridParmInfo a field in ParmStorageInfo + * Cloned ParmStorageInfo when requested so we have + * a unique instance per database. * * </pre> * @@ -345,12 +347,12 @@ public class GridDbConfig { * * @param parmName * @param level - * @return + * @return the ParmStorageInfo */ public ParmStorageInfo getParmStorageInfo(final String parmName, final String level) { String composite = parmName + "_" + level; - return _parmInfoDict.get(composite); + return _parmInfoDict.get(composite).clone(); } @Override diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java index 605990fe45..8e6f286e0e 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/server/database/IFPGridDatabase.java @@ -578,7 +578,6 @@ public class IFPGridDatabase extends GridDatabase { try { // Remove the entire data structure for the parm dao.removeParm(parmStorageInfo.get(item).getParmID()); - // parmIdMap.remove(item); this.parmStorageInfo.remove(item); } catch (DataAccessLayerException e) { statusHandler.handle(Priority.PROBLEM, "Error removing: " @@ -589,7 +588,6 @@ public class IFPGridDatabase extends GridDatabase { @Override public ServerResponse<List<ParmID>> getParmList() { - // List<ParmID> parmIds = new ArrayList<ParmID>(parmIdMap.values()); List<ParmID> parmIds = new ArrayList<ParmID>(parmStorageInfo.size()); for (ParmStorageInfo psi : parmStorageInfo.values()) { parmIds.add(psi.getParmID()); @@ -1273,18 +1271,14 @@ public class IFPGridDatabase extends GridDatabase { List<ParmStorageInfo> parmInfoList = dao.getParmStorageInfo(dbId); parmStorageInfo = new HashMap<String, ParmStorageInfo>( parmInfoList.size(), 1.0f); - // parmIdMap = new HashMap<String, ParmID>(parmInfoList.size(), - // 1.0f); for (ParmStorageInfo psi : parmInfoList) { ParmID pid = psi.getParmID(); String compositeName = pid.getCompositeName(); - // parmIdMap.put(compositeName, pid); parmStorageInfo.put(compositeName, psi); } } catch (DataAccessLayerException e) { parmStorageInfo = Collections.emptyMap(); - // parmIdMap = Collections.emptyMap(); String msg = "Error retrieving parm info from Database: " + e.getLocalizedMessage(); statusHandler.error(msg, e); @@ -2152,7 +2146,6 @@ public class IFPGridDatabase extends GridDatabase { */ public ParmID getCachedParmID(String parmNameAndLevel) throws UnknownParmIdException { - // ParmID rval = parmIdMap.get(parmNameAndLevel); ParmID rval = this.parmStorageInfo.get(parmNameAndLevel).getParmID(); if (rval == null) { @@ -2165,7 +2158,6 @@ public class IFPGridDatabase extends GridDatabase { @Override public ParmID getCachedParmID(ParmID parmId) throws UnknownParmIdException { - // ParmID rval = parmIdMap.get(parmId.getCompositeName()); ParmID rval = this.parmStorageInfo.get(parmId.getCompositeName()) .getParmID(); diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/ParmStorageInfo.java b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/ParmStorageInfo.java index 8fc4a079f9..55b08fe3d9 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/ParmStorageInfo.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.gfe/src/com/raytheon/uf/common/dataplugin/gfe/db/objects/ParmStorageInfo.java @@ -43,6 +43,7 @@ import javax.persistence.UniqueConstraint; * Added GridParmInfo as a field. * Added hibernate annotations * 10/22/2013 #2361 njensen Remove ISerializableObject + * 01/15/2014 #1571 randerso Added clone method and copy constructor * * </pre> * @@ -52,7 +53,7 @@ import javax.persistence.UniqueConstraint; @Entity @Table(name = "gfe_parminfo", uniqueConstraints = { @UniqueConstraint(columnNames = { "parmId_id" }) }) -public class ParmStorageInfo { +public class ParmStorageInfo implements Cloneable { /** * Auto-generated surrogate key @@ -103,6 +104,29 @@ public class ParmStorageInfo { this.gridParmInfo = gridParmInfo; } + /** + * Copy constructor + * + * @param orig + */ + public ParmStorageInfo(final ParmStorageInfo orig) { + this.storageType = orig.storageType; + this.dataOffset = orig.dataOffset; + this.dataMultiplier = orig.dataMultiplier; + this.dataType = orig.dataType; + this.gridParmInfo = orig.gridParmInfo.clone(); + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#clone() + */ + @Override + public ParmStorageInfo clone() { + return new ParmStorageInfo(this); + } + /** * @return the id */ From c05cbb533758c1f4be8fa5089ba777274948850a Mon Sep 17 00:00:00 2001 From: Dave Hladky <david_j_hladky@raytheon.com> Date: Wed, 15 Jan 2014 13:29:18 -0600 Subject: [PATCH 40/62] Issue #2693 Data set information infrastructure for availability offset calculations Change-Id: I0f8d90a753ce37d37c682ff17613eb9a44554a3b Former-commit-id: ef8eb701daf180ea49a5c32f36155dba2ba21ba6 [formerly 129163bf87c00a5c0eba9bc635731f53f65a2529] [formerly b64df5806afba5482ea2cf22fb9a968701bf8bd5 [formerly 48fad391deb95616556628424b1a1799c2929f89]] Former-commit-id: b64df5806afba5482ea2cf22fb9a968701bf8bd5 Former-commit-id: 682b06c89d09a0c901e4eac59ad58ebf88c5291b --- .../lookups/DataSetInformationLookup.xml | 1435 +++++++++++++++++ .../util/DataSetInformationXmlWriter.java | 54 + .../retrieval/util/LookupManager.java | 201 ++- .../retrieval/xml/DataSetInformation.java | 118 ++ .../xml/DataSetInformationLookup.java | 74 + .../datadelivery/OPENDAPServiceConfig.xml | 3 + .../opendap/OpenDAPMetaDataParser.java | 60 +- 7 files changed, 1925 insertions(+), 20 deletions(-) create mode 100644 edexOsgi/com.raytheon.uf.common.datadelivery.harvester/utility/common_static/base/datadelivery/lookups/DataSetInformationLookup.xml create mode 100644 edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/util/DataSetInformationXmlWriter.java create mode 100644 edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/xml/DataSetInformation.java create mode 100644 edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/xml/DataSetInformationLookup.java diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.harvester/utility/common_static/base/datadelivery/lookups/DataSetInformationLookup.xml b/edexOsgi/com.raytheon.uf.common.datadelivery.harvester/utility/common_static/base/datadelivery/lookups/DataSetInformationLookup.xml new file mode 100644 index 0000000000..8fdf1af782 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.harvester/utility/common_static/base/datadelivery/lookups/DataSetInformationLookup.xml @@ -0,0 +1,1435 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<!-- + This file is intended for use by the NCF to tweak Data Set availability offsets + for given dataset groups, be careful what you do here, these are semi-default in nature. +--> +<DataSetInformationLookup> + <dataSetInformation> + <modelName>wave_mww3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rap32</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>70</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_048_gma</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>naefs_bc_gemode</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>375</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmm_p1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_000_gma</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>210</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_nowcast_6hrly_reg1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_nowcast_6hrly_reg2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_nowcast_6hrly_reg3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmb_ctl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_bc_gep_all</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>360</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_em_p2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_em_p3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_em_p1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_ndgd_ge10pt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>420</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>naefs_ndgd_gemode</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>555</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_144_atl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>420</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>nam_alaskanest</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>180</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmm_p2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmm_p3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hiresw_eastarw</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>330</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_nowcast_daily_uvel</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_forecast_hires_std_atl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>720</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>fens_all</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>450</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmb_ctl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>fnlflx</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>405</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>nam_conusnest</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>180</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtma2p5_err</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>60</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>wave_nph</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>315</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_120_gs</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>390</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_ndgd_ge50pt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>420</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_em_n2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>wave_enp</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>285</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_em_n3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_120_gm</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>390</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_em_n1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hirtma_ges</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_2ds_nowcast_3hrly_diag</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gurtma_err</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmm_ctl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hiresw_westarw</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>330</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gfs2p5</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>300</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmm_n2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmm_n3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmm_n1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_2ds_forecast_3hrly_prog</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>naefs_ndgd_gespr</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>555</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_2ds_forecast_3hrly_diag</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmb_p3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gfs</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>285</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_2ds_forecast_daily_prog</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmm_n3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmm_n2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmm_n1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>wave_nww3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_024_gma</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>akrtma_anl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_forecast_daily_vvel</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>naefs_bc_ge50pt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>naefs_ndgd_geavg</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>555</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_em_n1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_bc_geavg</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_em_n2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>nam_na</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>180</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_em_n3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_nowcast_daily_salt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>prrtma_ges</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_bc_ge90pt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmb_n3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_048_atl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>ncom_amseas</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>900</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmb_n2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmb_n1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_bc_ge10pt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>wave_wna</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmb_p2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmb_p1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>narre_130_mean</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>150</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_em_ctl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>estofs_conus</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>360</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmb_n1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmb_n2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmb_n3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>nam</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>180</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>naefs_ndgd_ge90pt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>555</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmm_p3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rap</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>70</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmm_p2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>wave_nah</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>315</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmm_p1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_024_atl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>300</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmb_ctl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>ncom_socal</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>750</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>ice</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>420</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hiresw_guamnmm</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>300</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_em_p3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_forecast_6hrly_reg1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hiresw_hiarw</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_em_p1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_forecast_6hrly_reg3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_em_p2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_forecast_6hrly_reg2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_em_n1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_em_n3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_em_n2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>ncom_useast</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>810</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmb_p3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmb_p2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_096_gma</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>360</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmb_p1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_ndgd_gespr</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>420</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>nam_crb</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>180</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_2ds_forecast_daily_diag</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>naefs_ndgd_ge10pt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>555</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>narre_242_spread</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>150</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>nam_priconest</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>180</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_ndgd_geavg</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>420</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>wave_akw</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>285</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmb_p3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmb_p2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmb_p1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gurtma_anl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_forecast_daily_salt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_2ds_nowcast_daily_diag</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_ndgd_ge90pt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>420</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_120_atl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>390</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hiresw_guamarw</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>285</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_2ds_nowcast_daily_prog</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtma2p5_anl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>600</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_em_p3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_em_p2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_096_gm</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>360</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_em_p1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_em_ctl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_gep_all</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>360</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_bc_gespr</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>naefs_ndgd_ge50pt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>555</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_048_gm</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>prrtma_err</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_048_gs</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>cmcens_all</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>540</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_bc_gemode</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_forecast_atl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>400</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_120_gma</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>390</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_em_p1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_000_gm</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>210</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hiresw_westnmm</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_000_gs</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>210</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>nam_ak</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>180</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmm_n1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmm_n2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmm_n3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>akrtma_err</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtma2p5_ges</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>60</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_em_p2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_bc_gens_bc</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtma_ges</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_em_p3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtma_err</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_ndgd_gemode</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>420</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmb_n3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmb_n2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_nmb_n1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>aqm_dailymax_1hro3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>210</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_em_n1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_144_gma</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>420</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hirtma_anl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_em_n3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>wave_nfcens</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>390</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_em_n2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_nowcast_daily_vvel</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_bc_gegfs</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>narre_130_spread</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>105</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>cmcensspr</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>495</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_000_atl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>210</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmm_n3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_096_gs</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>360</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>naefs_bc_ge90pt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>naefs_bc_geavg</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>375</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmm_n1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmm_n2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gfs_anl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>285</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmm_p1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmm_p2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmm_ctl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na132_nmm_p3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_forecast_daily_temp</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmm_ctl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_072_gma</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>300</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hiresw_prarw</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>300</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_em_ctl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>wave_glw</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>180</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmm_ctl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>prrtma_anl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_latlon</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmm_p2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmm_p1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>srefbc_nmm_p3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_024_gs</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_072_gs</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>300</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hirtma_err</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_024_gm</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>narre_242_mean</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>150</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hiresw_eastnmm</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>330</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gfs_hd</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>285</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>akrtma_ges</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmb_p3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmb_p1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmb_p2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmb_ctl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_096_atl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>345</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmb_n3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_nowcast_atl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>300</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gurtma_ges</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_nowcast_daily_temp</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>naefs_bc_ge10pt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>nam_hawaiinest</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>180</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_072_atl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>300</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>nam1hr</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>180</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_2ds_nowcast_3hrly_prog</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>ncom_hawaii</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>720</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_072_gm</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>300</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>naefs_bc_gespr</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>375</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>gens_bc_ge50pt</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>270</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hiresw_hinmm</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>300</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>aqm_dailymax_8hro3</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>210</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_glo_3dz_forecast_daily_uvel</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>1440</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtma_anl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>45</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_144_gm</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>400</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_na_em_ctl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>nam_pac</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>180</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmb_n1</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>sref_nmb_n2</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>240</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_nowcast_hires_std_atl</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>480</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>cmcensavg</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>495</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>estofs_pr</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>360</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>rtofs_native_144_gs</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>400</defaultOffset> + </dataSetInformation> + <dataSetInformation> + <modelName>hiresw_prnmm</modelName> + <multiplier>1.5</multiplier> + <modelRunIncrement>6</modelRunIncrement> + <defaultOffset>300</defaultOffset> + </dataSetInformation> +</DataSetInformationLookup> \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/util/DataSetInformationXmlWriter.java b/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/util/DataSetInformationXmlWriter.java new file mode 100644 index 0000000000..fd14f54f41 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/util/DataSetInformationXmlWriter.java @@ -0,0 +1,54 @@ +package com.raytheon.uf.common.datadelivery.retrieval.util; + +/** + * 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. + **/ + +import com.raytheon.uf.common.datadelivery.retrieval.xml.DataSetInformationLookup; + +/** + * Writes out DataSet Information data to xml. + * + * <pre> + * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Jan 14, 2014 dhladky Initial creation + * + * </pre> + * + * @author dhladky + * @version 1.0 + */ + +public interface DataSetInformationXmlWriter { + + /** + * Writes the DataSetInformation lookup to XML + * + * @param aol + * @param modelName + * @throws Exception + */ + void writeDataSetInformationXml(DataSetInformationLookup dsi) + throws Exception; + +} diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/util/LookupManager.java b/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/util/LookupManager.java index 84c9aa1bdc..eff7cd452d 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/util/LookupManager.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/util/LookupManager.java @@ -26,10 +26,13 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import javax.xml.bind.JAXBException; import com.raytheon.uf.common.datadelivery.registry.Parameter; +import com.raytheon.uf.common.datadelivery.retrieval.xml.DataSetInformation; +import com.raytheon.uf.common.datadelivery.retrieval.xml.DataSetInformationLookup; import com.raytheon.uf.common.datadelivery.retrieval.xml.LevelLookup; import com.raytheon.uf.common.datadelivery.retrieval.xml.ParameterConfig; import com.raytheon.uf.common.datadelivery.retrieval.xml.ParameterLookup; @@ -60,6 +63,7 @@ import com.raytheon.uf.common.util.ServiceLoaderUtil; * Jan 18, 2013 1513 dhladky Level lookup refit. * Mar 21, 2013 1794 djohnson ServiceLoaderUtil now requires the requesting class. * Nov 07, 2013 2361 njensen Use JAXBManager for XML + * Jam 14, 2014 dhladky AvailabilityOffset calculations * * </pre> * @@ -72,7 +76,7 @@ public class LookupManager { * Implementation of the xml writers that writes to localization files. */ private class LocalizationXmlWriter implements LevelXmlWriter, - ParameterXmlWriter { + ParameterXmlWriter, DataSetInformationXmlWriter { /** * {@inheritDoc} */ @@ -107,6 +111,23 @@ public class LookupManager { getJaxbManager().marshalToXmlFile(pl, file.getAbsolutePath()); } + + + @Override + public void writeDataSetInformationXml(DataSetInformationLookup dsi) + throws Exception { + + IPathManager pm = PathManagerFactory.getPathManager(); + LocalizationContext lc = pm.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.SITE); + String fileName = getDataSetInformationFileName(); + LocalizationFile lf = pm.getLocalizationFile(lc, fileName); + File file = lf.getFile(); + + getJaxbManager().marshalToXmlFile(dsi, file.getAbsolutePath()); + + } + } private static final IUFStatusHandler statusHandler = UFStatus @@ -120,6 +141,8 @@ public class LookupManager { + File.separatorChar + "lookups" + File.separatorChar; private static final String CONFIG_FILE_PARAM = "ParameterLookup.xml"; + + private static final String CONFIG_FILE_DATASETINFO = "DataSetInformationLookup.xml"; private static final String CONFIG_FILE_LEVEL = "LevelLookup.xml"; @@ -135,9 +158,11 @@ public class LookupManager { return instance; } - private final Map<String, ParameterLookup> parameters = new HashMap<String, ParameterLookup>(); + private final Map<String, ParameterLookup> parameters = new HashMap<String, ParameterLookup>(1); - private final Map<String, LevelLookup> levels = new HashMap<String, LevelLookup>(); + private final Map<String, LevelLookup> levels = new HashMap<String, LevelLookup>(1); + + private final Map<String, DataSetInformation> dataSetInformations = new HashMap<String, DataSetInformation>(1); private UnitLookup unitLookup = null; @@ -148,13 +173,17 @@ public class LookupManager { private final ParameterXmlWriter parameterXmlWriter = ServiceLoaderUtil .load(LookupManager.class, ParameterXmlWriter.class, new LocalizationXmlWriter()); + + private final DataSetInformationXmlWriter dataSetInformationXmlWriter = ServiceLoaderUtil + .load(LookupManager.class, DataSetInformationXmlWriter.class, + new LocalizationXmlWriter()); private static JAXBManager jaxb; - private static JAXBManager getJaxbManager() - throws JAXBException { + private static JAXBManager getJaxbManager() throws JAXBException { if (jaxb == null) { jaxb = new JAXBManager(LevelLookup.class, ParameterLookup.class, + DataSetInformationLookup.class, DataSetInformation.class, UnitLookup.class); } @@ -295,6 +324,168 @@ public class LookupManager { return paramLoookup; } + + /** + * Gets the Data Set Information + * + * @param modelName + * @return + */ + public DataSetInformation getDataSetInformation(String modelName) { + + DataSetInformation dsi = null; + + if (dataSetInformations.isEmpty()) { + + DataSetInformationLookup dataSetInformationLookup = getDataSetInformationLookupFromFile(); + + if (dataSetInformationLookup == null) { + dataSetInformationLookup = new DataSetInformationLookup(); + } + + for (DataSetInformation dataSetinfo: dataSetInformationLookup.getDataSetInformations()){ + dataSetInformations.put(dataSetinfo.getModelName(), dataSetinfo); + } + } + + if (dataSetInformations.containsKey(modelName)) { + dsi = dataSetInformations.get(modelName); + } + + return dsi; + } + + private DataSetInformationLookup getDataSetInformationLookupFromFile() { + + DataSetInformationLookup dataSetInformationLookup = null; + LocalizationFile file = null; + String fileName = getDataSetInformationFileName(); + + try { + file = getLocalizationFile(fileName); + } catch (Exception e) { + statusHandler + .error(" Failed to read Data Set Information Lookup: " + fileName, e); + } + + if (file != null) { + try { + dataSetInformationLookup = readDataSetInformationXml(file.getFile()); + } catch (Exception e) { + statusHandler.handle( + Priority.PROBLEM, + "Failed to Read Data Set Information Lookup from file: " + + file.getName(), e); + } + } + + return dataSetInformationLookup; + } + + /** + * Availability Offset file name + * + * @param modelName + * @return + */ + private String getDataSetInformationFileName() { + return CONFIG_FILE_ROOT + CONFIG_FILE_DATASETINFO; + } + + /** + * Read Data Set Information lookup + * + * @param file + * @return + * @throws Exception + */ + private DataSetInformationLookup readDataSetInformationXml(File file) throws Exception { + + DataSetInformationLookup dsi = null; + + if (file != null && file.exists()) { + dsi = getJaxbManager().unmarshalFromXmlFile( + DataSetInformationLookup.class, file); + } + + return dsi; + } + + /** + * Modify or create a data set information lookup + * + * @param modelName + */ + public void modifyDataSetInformationLookup(DataSetInformation dsi) { + + try { + DataSetInformationLookup dataSetInformationLookup = null; + // update map and write out file + synchronized (dataSetInformations) { + + dataSetInformations.put(dsi.getModelName(), dsi); + dataSetInformationLookup = getDataSetInformationLookupFromFile(); + + if (dataSetInformationLookup == null) { + dataSetInformationLookup = new DataSetInformationLookup(); + } + + if (dataSetInformationLookup.getDataSetInformations().contains( + dsi)) { + // no changes + return; + } else { + // clear the hash and rebuild it with what is set in current + dataSetInformationLookup.getDataSetInformations().clear(); + + for (Entry<String, DataSetInformation> entry : dataSetInformations + .entrySet()) { + dataSetInformationLookup.getDataSetInformations().add( + entry.getValue()); + } + } + } + + if (dataSetInformationLookup != null) { + dataSetInformationXmlWriter + .writeDataSetInformationXml(dataSetInformationLookup); + + statusHandler + .info("Updated/Created Data Set Information lookup! " + + dsi.getModelName()); + } + + } catch (Exception e) { + statusHandler.error( + "Couldn't create/update Data Set Information lookup! ", e); + } + } + + /** + * Does a availability offset lookup exist? + * + * @param modelName + * @return + */ + public boolean dataSetInformationLookupExists() { + + LocalizationFile file = null; + String fileName = getDataSetInformationFileName(); + try { + file = getLocalizationFile(fileName); + } catch (Exception fnfe) { + statusHandler.error( + "Failed to lookup Data Set Information localization file: " + + fileName, fnfe); + } + if (file != null) { + return file.exists(); + } + + return false; + } + + /** * param file name diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/xml/DataSetInformation.java b/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/xml/DataSetInformation.java new file mode 100644 index 0000000000..2c64949b57 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/xml/DataSetInformation.java @@ -0,0 +1,118 @@ +package com.raytheon.uf.common.datadelivery.retrieval.xml; + +/** + * 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. + **/ + + +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.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + +/** + * Data Set Info XML Object. + * + * <pre> + * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Jan 14, 2014 dhladky Initial creation. + * + * </pre> + * + * @author dhladky + * @version 1.0 + */ + +@XmlRootElement(name = "DataSetInformation") +@XmlAccessorType(XmlAccessType.NONE) +@DynamicSerialize +public class DataSetInformation { + + @XmlElement(name = "modelName", type = String.class) + @DynamicSerializeElement + protected String modelName; + + @XmlElement(name = "multiplier", type = Double.class) + @DynamicSerializeElement + protected Double multiplier; + + @XmlElement(name = "modelRunIncrement", type = Integer.class) + @DynamicSerializeElement + protected Integer modelRunIncrement; + + @XmlElement(name = "defaultOffset", type = Integer.class) + @DynamicSerializeElement + protected Integer defaultOffset; + + public DataSetInformation() { + + } + + public DataSetInformation(String modelName, Double multiplier, int modelRunIncrement, int defaultOffset) { + + this.modelName = modelName; + this.multiplier = multiplier; + this.modelRunIncrement = modelRunIncrement; + this.defaultOffset = defaultOffset; + } + + public String getModelName() { + return modelName; + } + + public void setModelName(String modelName) { + this.modelName = modelName; + } + + public Double getMultiplier() { + return multiplier; + } + + public void setMultiplier(Double multiplier) { + this.multiplier = multiplier; + } + + public Integer getModelRunIncrement() { + return modelRunIncrement; + } + + public void setModelRunIncrement(Integer modelRunIncrement) { + this.modelRunIncrement = modelRunIncrement; + } + + public Integer getDefaultOffset() { + return defaultOffset; + } + + public void setDefaultOffset(Integer defaultOffset) { + this.defaultOffset = defaultOffset; + } + + public int getRange() { + return (int) (getMultiplier() * getModelRunIncrement()); + } + +} diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/xml/DataSetInformationLookup.java b/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/xml/DataSetInformationLookup.java new file mode 100644 index 0000000000..e2042bccd0 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.retrieval/src/com/raytheon/uf/common/datadelivery/retrieval/xml/DataSetInformationLookup.java @@ -0,0 +1,74 @@ +package com.raytheon.uf.common.datadelivery.retrieval.xml; + +/** + * 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. + **/ + + +import java.util.ArrayList; +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.XmlElements; +import javax.xml.bind.annotation.XmlRootElement; + +import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; +import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; + +/** + * Data Set Lookup XML Object. + * + * <pre> + * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Jan 14, 2014 dhladky Initial creation. + * + * </pre> + * + * @author dhladky + * @version 1.0 + */ + +@XmlRootElement(name = "DataSetInformationLookup") +@XmlAccessorType(XmlAccessType.NONE) +@DynamicSerialize +public class DataSetInformationLookup { + + public DataSetInformationLookup() { + dataSetInformations = new ArrayList<DataSetInformation>(1); + } + + @XmlElements({ @XmlElement(name = "dataSetInformation", type = DataSetInformation.class) }) + @DynamicSerializeElement + private List<DataSetInformation> dataSetInformations; + + public List<DataSetInformation> getDataSetInformations() { + return dataSetInformations; + } + + public void setDataSetInformations(List<DataSetInformation> dataSetInformations) { + this.dataSetInformations = dataSetInformations; + } + +} diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.harvester/utility/common_static/base/datadelivery/OPENDAPServiceConfig.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.harvester/utility/common_static/base/datadelivery/OPENDAPServiceConfig.xml index 1c895b1050..a652faedb8 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.harvester/utility/common_static/base/datadelivery/OPENDAPServiceConfig.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.harvester/utility/common_static/base/datadelivery/OPENDAPServiceConfig.xml @@ -86,5 +86,8 @@ <constant name="UNIT_PATTERN" value=".*(\[(.*?)\])\s*"/> <constant name="TWOM" value="2m"/> <constant name="TENM" value="10m"/> + <constant name="DEFAULT_MULTIPLIER" value="1.5"/> + <constant name="DEFAULT_RUN_INCREMENT" value="6"/> + <constant name="DEFAULT_OFFSET" value="270"/> </serviceConfig> \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java index f1bd4d778e..6e6fefe754 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/opendap/OpenDAPMetaDataParser.java @@ -47,6 +47,7 @@ import com.raytheon.uf.common.datadelivery.registry.Provider.ServiceType; import com.raytheon.uf.common.datadelivery.registry.Time; import com.raytheon.uf.common.datadelivery.retrieval.util.HarvesterServiceManager; import com.raytheon.uf.common.datadelivery.retrieval.util.LookupManager; +import com.raytheon.uf.common.datadelivery.retrieval.xml.DataSetInformation; import com.raytheon.uf.common.datadelivery.retrieval.xml.ParameterConfig; import com.raytheon.uf.common.datadelivery.retrieval.xml.ParameterLookup; import com.raytheon.uf.common.gridcoverage.Corner; @@ -95,6 +96,7 @@ import dods.dap.DAS; * Sept 25, 2013 1797 dhladky separated time from gridded time * Oct 10, 2013 1797 bgonzale Refactored registry Time objects. * Dec 18, 2013 2636 mpduff Calculate a data availability delay for the dataset and dataset meta data. + * Jan 14, 2014 dhladky Data set info used for availability delay calculations. * * </pre> * @@ -261,21 +263,7 @@ class OpenDAPMetaDataParser extends MetaDataParser { time.setStepUnit(Time.findStepUnit(step.get(1)) .getDurationUnit()); gdsmd.setTime(time); - - // Calculate dataset availability delay - long startMillis = time.getStart().getTime(); - long now = TimeUtil.newGmtCalendar().getTimeInMillis(); - long offset = (now - startMillis) / TimeUtil.MILLIS_PER_MINUTE; - dataSet.setAvailabilityOffset((int) offset); - gdsmd.setAvailabilityOffset((int) offset); - - if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { - statusHandler.debug("Dataset Name: " - + dataSet.getDataSetName()); - statusHandler.debug("StartTime: " + time.getStart()); - statusHandler.debug("Offset: " - + dataSet.getAvailabilityOffset()); - } + } catch (Exception le) { logParsingException(timecon, "Time", collectionName, url); } @@ -756,12 +744,54 @@ class OpenDAPMetaDataParser extends MetaDataParser { throw new IllegalStateException( "The time cannot be null for a DataSet object!"); } + + // Calculate dataset availability delay + DataSetInformation dsi = LookupManager.getInstance().getDataSetInformation(gdsmd.getDataSetName()); + long offset = 0l; + long startMillis = gdsmd.getTime().getStart().getTime(); + long endMillis = TimeUtil.newGmtCalendar().getTimeInMillis(); + + /** + * This is here for if no one has configured this particular model + * They are gross defaults and will not guarantee this model working + */ + if (dsi == null) { + Double multi = Double.parseDouble(serviceConfig + .getConstantValue("DEFAULT_MULTIPLIER")); + Integer runIncrement = Integer.parseInt(serviceConfig + .getConstantValue("DEFAULT_RUN_INCREMENT")); + Integer defaultOffest = Integer.parseInt(serviceConfig + .getConstantValue("DEFAULT_OFFSET")); + dsi = new DataSetInformation(gdsmd.getDataSetName(), multi, + runIncrement, defaultOffest); + // writes out a place holder DataSetInformation object in the file + LookupManager.getInstance().modifyDataSetInformationLookup(dsi); + } + + offset = (endMillis - startMillis) / TimeUtil.MILLIS_PER_MINUTE; + // this is the actually ranging check + if (dsi.getRange() < offset) { + offset = dsi.getDefaultOffset(); + } + dataSet.setAvailabilityOffset((int) offset); + gdsmd.setAvailabilityOffset((int) offset); + + if (statusHandler.isPriorityEnabled(Priority.DEBUG)) { + statusHandler.debug("Dataset Name: " + + dataSet.getDataSetName()); + statusHandler.debug("StartTime: " + gdsmd.getTime()); + statusHandler.debug("Offset: " + + dataSet.getAvailabilityOffset()); + } + List<DataSetMetaData<?>> toStore = metaDatas.get(dataSet); + if (toStore == null) { toStore = new ArrayList<DataSetMetaData<?>>(); metaDatas.put(dataSet, toStore); } + toStore.add(gdsmd); } From 7e608842b293c65ab8a1256ec9eb36939eeeeb68 Mon Sep 17 00:00:00 2001 From: Brad Gonzales <bradley_l_gonzales@raytheon.com> Date: Wed, 15 Jan 2014 15:17:25 -0600 Subject: [PATCH 41/62] Issue #2678 Fix for multiple threads grabbing a retrieval for processing. Change-Id: I1e982d4db4d4f68531b8b9c65e7070bff3825c28 Former-commit-id: a2fbcecef66d3182e9b319a00939edf64e77d67e [formerly 3e3fcfa9af588c28ab9f5e199562ba16c2f0b47e] [formerly 46a2a5f70f51e3a156334d1e9e6a44dea729a901 [formerly 3d396223b93631f0ea561a4df8ae9a3d71dde767]] Former-commit-id: 46a2a5f70f51e3a156334d1e9e6a44dea729a901 Former-commit-id: a1429a3911be4c583f63588b253f3838d9ad2c2a --- .../datadelivery/registry/Coverage.java | 6 ++++-- ...idth-datadelivery-edex-impl-monolithic.xml | 2 ++ .../bandwidth-datadelivery-edex-impl-ncf.xml | 1 + .../bandwidth-datadelivery-edex-impl-wfo.xml | 4 ++++ .../retrieval/SubscriptionRetrievalAgent.java | 16 +++++++++++---- .../res/spring/retrieval-datadelivery-ncf.xml | 2 +- .../res/spring/retrieval-datadelivery-wfo.xml | 2 +- .../res/spring/retrieval-datadelivery.xml | 2 ++ .../PerformRetrievalsThenReturnFinder.java | 20 ++++++++++++------- .../SubscriptionRetrievalAgentTest.java | 8 +++++++- ...mRetrievalPluginDataObjectsFinderTest.java | 8 ++++++-- .../retrieval/handlers/RetrievalTaskTest.java | 10 ++++++++-- 12 files changed, 61 insertions(+), 20 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Coverage.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Coverage.java index fb5aa2667e..b9dfb47382 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Coverage.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Coverage.java @@ -25,6 +25,7 @@ import java.io.Serializable; 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 javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @@ -45,14 +46,15 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jan 17, 2011 191 dhladky Initial creation - * Dec 10, 2012 1259 bsteffen Switch Data Delivery from LatLon to referenced envelopes. - * + * Dec 10, 2012 1259 bsteffen Switch Data Delivery from LatLon to referenced envelopes. + * Jan 15, 2014 2678 bgonzale Added XmlRootElement annotation. * </pre> * * @author dhladky * @version 1.0 */ +@XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @XmlSeeAlso({ GriddedCoverage.class, LatLonGridCoverage.class }) diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/res/spring/bandwidth-datadelivery-edex-impl-monolithic.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/res/spring/bandwidth-datadelivery-edex-impl-monolithic.xml index 539ee0f834..3558bc5adc 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/res/spring/bandwidth-datadelivery-edex-impl-monolithic.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/res/spring/bandwidth-datadelivery-edex-impl-monolithic.xml @@ -33,6 +33,7 @@ <constructor-arg ref="bandwidthDao" /> <constructor-arg ref="retrievalDao" /> <constructor-arg ref="ProviderHandler" /> + <constructor-arg ref="retrievalQueue" /> </bean> <bean id="sbnSubscriptionRetrievalAgentPrototype" @@ -46,6 +47,7 @@ <constructor-arg ref="bandwidthDao" /> <constructor-arg ref="retrievalDao" /> <constructor-arg ref="ProviderHandler" /> + <constructor-arg ref="retrievalQueue" /> </bean> <util:map id="retrievalAgents"> diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/res/spring/bandwidth-datadelivery-edex-impl-ncf.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/res/spring/bandwidth-datadelivery-edex-impl-ncf.xml index 0677664a36..3a4059d6a9 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/res/spring/bandwidth-datadelivery-edex-impl-ncf.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/res/spring/bandwidth-datadelivery-edex-impl-ncf.xml @@ -47,6 +47,7 @@ <constructor-arg ref="bandwidthDao" /> <constructor-arg ref="retrievalDao" /> <constructor-arg ref="ProviderHandler" /> + <constructor-arg ref="retrievalQueue" /> </bean> <util:map id="retrievalAgents"> diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml index 74ca849916..ea8e7fcf3b 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml @@ -47,6 +47,7 @@ <constructor-arg ref="bandwidthDao" /> <constructor-arg ref="retrievalDao" /> <constructor-arg ref="ProviderHandler" /> + <constructor-arg ref="retrievalQueue" /> </bean> <bean id="sbnSubscriptionRetrievalAgentPrototype" @@ -60,6 +61,9 @@ <constructor-arg ref="bandwidthDao" /> <constructor-arg ref="retrievalDao" /> <constructor-arg ref="ProviderHandler" /> + <constructor-arg name="retrievalQueue" > + <null/> + </constructor-arg> </bean> <util:map id="retrievalAgents"> diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgent.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgent.java index db6d65a79a..5d6975d35f 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgent.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgent.java @@ -6,6 +6,7 @@ package com.raytheon.uf.edex.datadelivery.bandwidth.retrieval; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; import com.google.common.annotations.VisibleForTesting; import com.raytheon.uf.common.datadelivery.registry.Network; @@ -34,6 +35,7 @@ import com.raytheon.uf.edex.datadelivery.retrieval.RetrievalManagerNotifyEvent; import com.raytheon.uf.edex.datadelivery.retrieval.ServiceTypeFactory; import com.raytheon.uf.edex.datadelivery.retrieval.db.IRetrievalDao; import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecord; +import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecordPK; /** * Class used to process SubscriptionRetrieval BandwidthAllocations. @@ -51,6 +53,8 @@ import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecord; * Jun 24, 2013 2106 djohnson Set actual start time when sending to retrieval rather than overwrite scheduled start. * Jul 09, 2013 2106 djohnson Dependency inject registry handlers. * Jul 11, 2013 2106 djohnson Use SubscriptionPriority enum. + * Jan 15, 2014 2678 bgonzale Use Queue for passing RetrievalRequestRecords to the + * RetrievalTasks (PerformRetrievalsThenReturnFinder). * * </pre> * @@ -72,15 +76,19 @@ public class SubscriptionRetrievalAgent extends private final IProviderHandler providerHandler; + private final ConcurrentLinkedQueue<RetrievalRequestRecordPK> retrievalQueue; + public SubscriptionRetrievalAgent(Network network, String destinationUri, final Object notifier, int defaultPriority, RetrievalManager retrievalManager, IBandwidthDao bandwidthDao, - IRetrievalDao retrievalDao, IProviderHandler providerHandler) { + IRetrievalDao retrievalDao, IProviderHandler providerHandler, + ConcurrentLinkedQueue<RetrievalRequestRecordPK> retrievalQueue) { super(network, destinationUri, notifier, retrievalManager); this.defaultPriority = defaultPriority; this.bandwidthDao = bandwidthDao; this.retrievalDao = retrievalDao; this.providerHandler = providerHandler; + this.retrievalQueue = retrievalQueue; } @Override @@ -134,9 +142,6 @@ public class SubscriptionRetrievalAgent extends @VisibleForTesting void wakeRetrievalTasks() throws EdexException { EDEXUtil.getMessageProducer().sendAsync(destinationUri, null); - EDEXUtil.getMessageProducer().sendAsync(destinationUri, null); - EDEXUtil.getMessageProducer().sendAsync(destinationUri, null); - EDEXUtil.getMessageProducer().sendAsync(destinationUri, null); } @Override @@ -211,6 +216,9 @@ public class SubscriptionRetrievalAgent extends rec.setRetrieval(SerializationUtil .transformToThrift(retrieval)); rec.setState(RetrievalRequestRecord.State.PENDING); + if (retrievalQueue != null) { + retrievalQueue.add(rec.getId()); + } } catch (Exception e) { statusHandler.error("Subscription: " + subscriptionName + " Failed to serialize request [" + retrieval diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery-ncf.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery-ncf.xml index 13bf3fbd9a..38e3bc0f9d 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery-ncf.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery-ncf.xml @@ -14,7 +14,7 @@ <constructor-arg> <bean class="com.raytheon.uf.edex.datadelivery.retrieval.handlers.PerformRetrievalsThenReturnFinder"> - <constructor-arg value="SBN" /> + <constructor-arg ref="retrievalQueue" /> <constructor-arg ref="retrievalDao" /> </bean> </constructor-arg> diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery-wfo.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery-wfo.xml index ee956e01a0..40145e5743 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery-wfo.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery-wfo.xml @@ -14,7 +14,7 @@ <constructor-arg> <bean class="com.raytheon.uf.edex.datadelivery.retrieval.handlers.PerformRetrievalsThenReturnFinder"> - <constructor-arg value="OPSNET" /> + <constructor-arg ref="retrievalQueue" /> <constructor-arg ref="retrievalDao" /> </bean> </constructor-arg> diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery.xml index e3909ac819..5d2f29ccf7 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/res/spring/retrieval-datadelivery.xml @@ -76,6 +76,8 @@ </bean> </constructor-arg> </bean> + + <bean id="retrievalQueue" class="java.util.concurrent.ConcurrentLinkedQueue" /> <camelContext id="dataDeliveryNotify-camel" xmlns="http://camel.apache.org/schema/spring" errorHandlerRef="errorHandler"> diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/handlers/PerformRetrievalsThenReturnFinder.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/handlers/PerformRetrievalsThenReturnFinder.java index a598aea51f..49edc92dfc 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/handlers/PerformRetrievalsThenReturnFinder.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval/src/com/raytheon/uf/edex/datadelivery/retrieval/handlers/PerformRetrievalsThenReturnFinder.java @@ -21,11 +21,11 @@ package com.raytheon.uf.edex.datadelivery.retrieval.handlers; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; import com.google.common.annotations.VisibleForTesting; import com.raytheon.uf.common.datadelivery.event.status.DataDeliverySystemStatusDefinition; import com.raytheon.uf.common.datadelivery.event.status.SystemStatusEvent; -import com.raytheon.uf.common.datadelivery.registry.Network; import com.raytheon.uf.common.datadelivery.registry.Provider.ServiceType; import com.raytheon.uf.common.datadelivery.retrieval.xml.Retrieval; import com.raytheon.uf.common.datadelivery.retrieval.xml.RetrievalAttribute; @@ -40,6 +40,7 @@ import com.raytheon.uf.edex.datadelivery.retrieval.adapters.RetrievalAdapter; import com.raytheon.uf.edex.datadelivery.retrieval.db.IRetrievalDao; import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecord; import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecord.State; +import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecordPK; import com.raytheon.uf.edex.datadelivery.retrieval.interfaces.IRetrievalRequestBuilder; import com.raytheon.uf.edex.datadelivery.retrieval.interfaces.IRetrievalResponse; @@ -58,6 +59,7 @@ import com.raytheon.uf.edex.datadelivery.retrieval.interfaces.IRetrievalResponse * Feb 12, 2013 1543 djohnson Retrieval responses are now passed further down the chain. * Feb 15, 2013 1543 djohnson Retrieval responses are now xml. * Jul 16, 2013 1655 mpduff Send a system status event based on the response from the provider. + * Jan 15, 2014 2678 bgonzale Retrieve RetrievalRequestRecords from a Queue for processing. * * </pre> * @@ -70,18 +72,19 @@ public class PerformRetrievalsThenReturnFinder implements IRetrievalsFinder { private static final IUFStatusHandler statusHandler = UFStatus .getHandler(PerformRetrievalsThenReturnFinder.class); - private final Network network; - private final IRetrievalDao retrievalDao; + private final ConcurrentLinkedQueue<RetrievalRequestRecordPK> retrievalQueue; + /** * Constructor. * * @param network */ - public PerformRetrievalsThenReturnFinder(Network network, + public PerformRetrievalsThenReturnFinder( + ConcurrentLinkedQueue<RetrievalRequestRecordPK> retrievalQueue, IRetrievalDao retrievalDao) { - this.network = network; + this.retrievalQueue = retrievalQueue; this.retrievalDao = retrievalDao; } @@ -95,9 +98,12 @@ public class PerformRetrievalsThenReturnFinder implements IRetrievalsFinder { ITimer timer = TimeUtil.getTimer(); try { timer.start(); - RetrievalRequestRecord request = retrievalDao - .activateNextRetrievalRequest(network); + RetrievalRequestRecordPK id = retrievalQueue.poll(); + if (id == null) { + return null; + } + RetrievalRequestRecord request = retrievalDao.getById(id); if (request == null) { return null; } diff --git a/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgentTest.java b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgentTest.java index 6b88a53998..7f658cfaba 100644 --- a/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgentTest.java +++ b/tests/unit/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgentTest.java @@ -28,6 +28,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.List; +import java.util.concurrent.ConcurrentLinkedQueue; import org.junit.Before; import org.junit.Test; @@ -56,6 +57,7 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.dao.SubscriptionRetrievalAttr import com.raytheon.uf.edex.datadelivery.retrieval.db.IRetrievalDao; import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecord; import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecord.State; +import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecordPK; /** * Test {@link SubscriptionRetrievalAgent}. @@ -68,6 +70,7 @@ import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecord.Sta * ------------ ---------- ----------- -------------------------- * Jan 30, 2013 1543 djohnson Initial creation * Jul 10, 2013 2106 djohnson Inject providerHandler. + * Jan 15, 2014 2678 bgonzale Added Queue. * * </pre> * @@ -84,6 +87,8 @@ public class SubscriptionRetrievalAgentTest { @Qualifier(value = "retrievalDao") private IRetrievalDao retrievalDao; + private final ConcurrentLinkedQueue<RetrievalRequestRecordPK> retrievalQueue = new ConcurrentLinkedQueue<RetrievalRequestRecordPK>(); + @Before public void setUp() throws RegistryHandlerException { PathManagerFactoryTest.initLocalization(); @@ -128,7 +133,8 @@ public class SubscriptionRetrievalAgentTest { SubscriptionRetrievalAgent agent = new SubscriptionRetrievalAgent( route, "someUri", new Object(), 1, null, bandwidthDao, - retrievalDao, DataDeliveryHandlers.getProviderHandler()) { + retrievalDao, DataDeliveryHandlers.getProviderHandler(), + retrievalQueue) { @Override void wakeRetrievalTasks() throws EdexException { // Do nothing diff --git a/tests/unit/com/raytheon/uf/edex/datadelivery/retrieval/handlers/PerformRetrievalPluginDataObjectsFinderTest.java b/tests/unit/com/raytheon/uf/edex/datadelivery/retrieval/handlers/PerformRetrievalPluginDataObjectsFinderTest.java index a007e1a79c..98382b25a5 100644 --- a/tests/unit/com/raytheon/uf/edex/datadelivery/retrieval/handlers/PerformRetrievalPluginDataObjectsFinderTest.java +++ b/tests/unit/com/raytheon/uf/edex/datadelivery/retrieval/handlers/PerformRetrievalPluginDataObjectsFinderTest.java @@ -26,11 +26,11 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.ArrayList; +import java.util.concurrent.ConcurrentLinkedQueue; import org.junit.Before; import org.junit.Test; -import com.raytheon.uf.common.datadelivery.registry.Network; import com.raytheon.uf.common.datadelivery.registry.Provider.ServiceType; import com.raytheon.uf.common.datadelivery.retrieval.xml.Retrieval; import com.raytheon.uf.common.datadelivery.retrieval.xml.RetrievalAttribute; @@ -39,6 +39,7 @@ import com.raytheon.uf.common.serialization.SerializationException; import com.raytheon.uf.edex.datadelivery.retrieval.db.IRetrievalDao; import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecord; import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecord.State; +import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecordPK; import com.raytheon.uf.edex.datadelivery.retrieval.interfaces.IRetrievalResponse; /** @@ -51,6 +52,7 @@ import com.raytheon.uf.edex.datadelivery.retrieval.interfaces.IRetrievalResponse * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Feb 06, 2013 1543 djohnson Initial creation + * Jan 15, 2014 2678 bgonzale Added Queue. * * </pre> * @@ -61,6 +63,8 @@ public class PerformRetrievalPluginDataObjectsFinderTest { private static final String EXCEPTION_MESSAGE = "thrown on purpose"; + private final ConcurrentLinkedQueue<RetrievalRequestRecordPK> retrievalQueue = new ConcurrentLinkedQueue<RetrievalRequestRecordPK>(); + private static final IRetrievalDao MOCK_DAO = mock(IRetrievalDao.class); private final Retrieval retrievalThatThrowsException = new Retrieval() { @@ -132,7 +136,7 @@ public class PerformRetrievalPluginDataObjectsFinderTest { private void processRetrieval(RetrievalRequestRecord retrieval) { final PerformRetrievalsThenReturnFinder pluginDataObjectsFinder = new PerformRetrievalsThenReturnFinder( - Network.OPSNET, MOCK_DAO); + retrievalQueue, MOCK_DAO); pluginDataObjectsFinder.process(retrieval); } } diff --git a/tests/unit/com/raytheon/uf/edex/datadelivery/retrieval/handlers/RetrievalTaskTest.java b/tests/unit/com/raytheon/uf/edex/datadelivery/retrieval/handlers/RetrievalTaskTest.java index c7b72d1bdc..853f530be7 100644 --- a/tests/unit/com/raytheon/uf/edex/datadelivery/retrieval/handlers/RetrievalTaskTest.java +++ b/tests/unit/com/raytheon/uf/edex/datadelivery/retrieval/handlers/RetrievalTaskTest.java @@ -68,6 +68,7 @@ import com.raytheon.uf.edex.datadelivery.retrieval.adapters.RetrievalAdapter.Tra import com.raytheon.uf.edex.datadelivery.retrieval.db.IRetrievalDao; import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecord; import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecord.State; +import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecordPK; import com.raytheon.uf.edex.datadelivery.retrieval.interfaces.IRetrievalResponse; /** @@ -89,6 +90,7 @@ import com.raytheon.uf.edex.datadelivery.retrieval.interfaces.IRetrievalResponse * Aug 09, 2013 1822 bgonzale Added parameters to processRetrievedPluginDataObjects. * Oct 01, 2013 2267 bgonzale Pass request parameter instead of components of request. * Nov 04, 2013 2506 bgonzale removed IRetrievalDao parameter. + * Jan 15, 2014 2678 bgonzale Added Queue. * * </pre> * @@ -157,6 +159,8 @@ public class RetrievalTaskTest { @Qualifier(value = "retrievalDao") private IRetrievalDao dao; + private final ConcurrentLinkedQueue<RetrievalRequestRecordPK> retrievalQueue = new ConcurrentLinkedQueue<RetrievalRequestRecordPK>(); + private final PlaceInCollectionProcessor retrievedDataProcessor = new PlaceInCollectionProcessor(); private final List<DataRetrievalEvent> eventsReceived = new ArrayList<DataRetrievalEvent>(); @@ -239,7 +243,7 @@ public class RetrievalTaskTest { dao.create(RetrievalRequestRecordFixture.INSTANCE.get()); IRetrievalsFinder retrievalDataFinder = new PerformRetrievalsThenReturnFinder( - Network.OPSNET, dao); + retrievalQueue, dao); final ConcurrentLinkedQueue<String> retrievalQueue = new ConcurrentLinkedQueue<String>(); final File testDirectory = TestUtil @@ -287,7 +291,9 @@ public class RetrievalTaskTest { private void stageRetrievals() { dao.create(opsnetRetrieval); + retrievalQueue.add(opsnetRetrieval.getId()); dao.create(sbnRetrieval); + retrievalQueue.add(sbnRetrieval.getId()); } /** @@ -297,7 +303,7 @@ public class RetrievalTaskTest { // Create required strategies for finding, processing, and completing // retrievals final IRetrievalsFinder retrievalDataFinder = new PerformRetrievalsThenReturnFinder( - Network.OPSNET, dao); + retrievalQueue, dao); final IRetrievalResponseCompleter retrievalCompleter = new RetrievalResponseCompleter( mock(SubscriptionNotifyTask.class), dao); From b7ca6eca3052f7d6f9a3104cec490cf5574c6189 Mon Sep 17 00:00:00 2001 From: Ron Anderson <ron.anderson@raytheon.com> Date: Thu, 16 Jan 2014 09:04:15 -0600 Subject: [PATCH 42/62] Issue #2660 Improved error logging in GetBrokerConnections.py Change-Id: Icf39a847106c13785e16aaef12283f44f4791cd1 Former-commit-id: 8531b2157697bd885330c4ad396388782ef1ec14 [formerly f47313690a73bb10c0718751ec0e68a4cd7229d9] [formerly 2db1ae7b2ddc8e3788b84d0eccf6c690cf5e7bd5 [formerly b078a4fa3dc8df69903fa07e172b5de6313bb17a]] Former-commit-id: 2db1ae7b2ddc8e3788b84d0eccf6c690cf5e7bd5 Former-commit-id: 7ae517c5d24c48ecac0e7ca6adc0d6e363af2c18 --- .../utility/common_static/base/GetBrokerConnections.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/GetBrokerConnections.py b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/GetBrokerConnections.py index 8dea21ba5d..62354a9ffa 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/GetBrokerConnections.py +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/GetBrokerConnections.py @@ -26,6 +26,7 @@ # Date Ticket# Engineer Description # ------------ ---------- ----------- -------------------------- # 03/21/13 1814 rjpeter Updated to use rest API for java broker +# 01/15/14 2660 randerso Log status and reason if request fails ## import httplib import json @@ -45,7 +46,8 @@ def getConnections(brokerHost, port=8180): response = httpConn.getresponse() if (response.status != 200): - raise Exception("Unable to post request to server") + msg = "Broker %s returned %d %s" % (brokerHost, response.status, response.reason) + raise Exception(msg) jsonStr = response.read() jsonObjArray = json.loads(jsonStr) From ae3293f0651d0df3e51208f1cffbb664388f6a3c Mon Sep 17 00:00:00 2001 From: Dave Hladky <david_j_hladky@raytheon.com> Date: Thu, 16 Jan 2014 08:59:19 -0600 Subject: [PATCH 43/62] Issue #2613 StandardCharsets NIO dependency removed. Change-Id: I7ba841e1f1e480561d3c7302e8b00ecfaab41f24 Former-commit-id: 0429acfb81f4459123109cabbe499c1660c22001 [formerly c342681a0b14226effab88372047b8d0ce3a26a5] [formerly 33aeec0cb46ab11c5a216a5877b70552bbbabe6c [formerly a9e1fbf4f19beecc2935cb992380f27cb2298ddb]] Former-commit-id: 33aeec0cb46ab11c5a216a5877b70552bbbabe6c Former-commit-id: f7b5ce629a591d9cc7cdffd0dbd0f87beac2afb8 --- .../uf/common/registry/services/RegistryRESTServices.java | 5 ++--- .../services/notification/NotificationListenerImpl.java | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/services/RegistryRESTServices.java b/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/services/RegistryRESTServices.java index b22ad3da3b..685acdcdc4 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/services/RegistryRESTServices.java +++ b/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/services/RegistryRESTServices.java @@ -21,7 +21,7 @@ package com.raytheon.uf.common.registry.services; import java.lang.reflect.Proxy; import java.net.URL; -import java.nio.charset.StandardCharsets; +import java.nio.charset.Charset; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; @@ -171,8 +171,7 @@ public class RegistryRESTServices { public Object accessXMLRestService(String url) { String response = null; try { - ; - response = Resources.toString(new URL(url), StandardCharsets.UTF_8); + response = Resources.toString(new URL(url), Charset.forName("UTF8")); } catch (Exception e) { throw new RegistryServiceException( "Error accessing REST service at URL: [" + url + "]", e); diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/NotificationListenerImpl.java b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/NotificationListenerImpl.java index edd3cbd274..03caf07c38 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/NotificationListenerImpl.java +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/NotificationListenerImpl.java @@ -123,6 +123,8 @@ public class NotificationListenerImpl implements NotificationListener { /** Registry soap service client */ private RegistrySOAPServices registrySoapClient; + // @FIXME This method is pretty scary in it's implementation as Richard + // pointed out. Please fix Ben. @Override public void onNotification(NotificationType notification) { long startTime = TimeUtil.currentTimeMillis(); From 7fe25d02f0603bd13eb23eac03a3259abb648968 Mon Sep 17 00:00:00 2001 From: Mike Duff <michael.duff@raytheon.com> Date: Thu, 16 Jan 2014 10:06:17 -0600 Subject: [PATCH 44/62] Issue #2459 - Add unscheduled as a slot attribute Former-commit-id: 292ef2c068f1c6164546d0061c14dbfed6675eac [formerly 0f655c96e34f6ec137b7a1a7f35fb3464b8bd139] [formerly 47069bd7a42175885abeaaa03b9fe04dad68aa65 [formerly 4cd670bc12e09f1acc778e8760615e92561e3ce3]] Former-commit-id: 47069bd7a42175885abeaaa03b9fe04dad68aa65 Former-commit-id: fe012ebbd17b1ce87ea5beb9b1e81a662b4d3005 --- .../registry/RecurringSubscription.java | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java index 37f1bd8371..e309a2be7b 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java @@ -216,6 +216,7 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> @XmlAttribute @DynamicSerializeElement + @SlotAttribute private boolean unscheduled; @XmlAttribute @@ -267,6 +268,9 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> @SlotAttribute(Subscription.SUBSCRIPTION_STATE_SLOT) private SubscriptionState subscriptionState; + /** Flag stating if the object should be updated */ + private boolean shouldUpdate = false; + /** * Get subscription name. * @@ -878,18 +882,18 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> } /** - * Determine if subscription status is expired. + * Determine if subscription status is expired and set subscription to off + * if it is expired. * * @return true if status is expired */ - private boolean isExpired() { + private boolean checkAndSetExpiration() { Calendar cal = TimeUtil.newGmtCalendar(); - Date today = cal.getTime(); boolean expired = false; - if (this.getSubscriptionEnd() != null - && today.after(this.getSubscriptionEnd())) { + if (subscriptionEnd != null && cal.getTime().after(subscriptionEnd)) { expired = true; this.subscriptionState = SubscriptionState.OFF; + this.shouldUpdate = true; } return expired; @@ -904,7 +908,7 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> public SubscriptionStatus getStatus() { if (!isValid()) { return SubscriptionStatus.INVALID; - } else if (isExpired()) { + } else if (checkAndSetExpiration()) { return SubscriptionStatus.EXPIRED; } else if (subscriptionState == SubscriptionState.OFF) { return SubscriptionStatus.DEACTIVATED; @@ -931,7 +935,8 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> * @return true if this subscription should be scheduled */ public boolean shouldSchedule() { - return subscriptionState == SubscriptionState.ON && !isExpired(); + return subscriptionState == SubscriptionState.ON + && !checkAndSetExpiration(); } private boolean inWindow(Date checkDate) { @@ -1065,7 +1070,7 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> */ @Override public void activate() { - if (valid && !isExpired()) { + if (valid && !checkAndSetExpiration()) { this.setSubscriptionState(SubscriptionState.ON); } } @@ -1077,4 +1082,11 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> public void deactivate() { this.setSubscriptionState(SubscriptionState.OFF); } + + /** + * @return the shouldUpdate + */ + public boolean shouldUpdate() { + return shouldUpdate; + } } From 3f4785f4505d42d29c7132e8a3e181812457cfcf Mon Sep 17 00:00:00 2001 From: Brad Gonzales <bradley_l_gonzales@raytheon.com> Date: Thu, 16 Jan 2014 14:07:18 -0600 Subject: [PATCH 45/62] Issue #2678 fix for sbn retrieval agent subscription queue. init it as null because sbn ingest is from ingest messages. Amend: Because of the files used specifically for InMemoryBandwidthManagerManager, added the SBN RetrievalPlan back to WFO. Change-Id: Ibebd89a2dd0236c47e8060489eb67bec9fc8d583 Former-commit-id: b3f9678dbaf48149d4b66bdba405b845e30c54b5 [formerly e308f2a6eead7bf166dc75265e99fc15738b9c45] [formerly ee4dc7068b4caa1f4599624c5eb93b28df1623b2 [formerly b0c2fcb5e802815b886f669b633e516b022b55a3]] Former-commit-id: ee4dc7068b4caa1f4599624c5eb93b28df1623b2 Former-commit-id: 31705fddf589765aefc630d88c2cffc74ba8c9a8 --- .../bandwidth-datadelivery-edex-impl-wfo.xml | 4 +--- .../res/spring/bandwidth-datadelivery-wfo.xml | 19 +++++++++++++++++++ .../retrieval/SubscriptionRetrievalAgent.java | 7 ++++++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml index ea8e7fcf3b..58ff2f556f 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml @@ -61,9 +61,7 @@ <constructor-arg ref="bandwidthDao" /> <constructor-arg ref="retrievalDao" /> <constructor-arg ref="ProviderHandler" /> - <constructor-arg name="retrievalQueue" > - <null/> - </constructor-arg> + <constructor-arg ref="retrievalQueue" /> </bean> <util:map id="retrievalAgents"> diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-wfo.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-wfo.xml index b41008d270..3806f83eb6 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-wfo.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-wfo.xml @@ -16,10 +16,29 @@ </property> </bean> + <!-- SBN Retrival Plans are defined in the wfo configuration because it is used by the + InMemoryBandwidthManager in the centralRegistry and client registries. They are not + scheduled in the client registries though --> + <bean id="SBNRetrievalPlan" + class="com.raytheon.uf.edex.datadelivery.bandwidth.retrieval.RetrievalPlan"> + <property name="network" value="SBN" /> + <property name="map" ref="BandwidthMap" /> + <property name="bandwidthDao" ref="bandwidthDao" /> + <property name="bucketsDao" ref="bandwidthBucketDao" /> + <property name="associator" ref="bandwidthBucketAllocationAssociator" /> + <property name="scheduler"> + <bean + class="com.raytheon.uf.edex.datadelivery.bandwidth.retrieval.PriorityRetrievalScheduler" /> + </property> + </bean> + <util:map id="retrievalPlans"> <entry key="OPSNET"> <ref local="OPSNETRetrievalPlan" /> </entry> + <entry key="SBN"> + <ref local="SBNRetrievalPlan" /> + </entry> </util:map> </beans> \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgent.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgent.java index 5d6975d35f..d4ad081e90 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgent.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgent.java @@ -88,7 +88,12 @@ public class SubscriptionRetrievalAgent extends this.bandwidthDao = bandwidthDao; this.retrievalDao = retrievalDao; this.providerHandler = providerHandler; - this.retrievalQueue = retrievalQueue; + // SBN retrievals come from ingest processing + if (network.equals(Network.SBN)) { + this.retrievalQueue = null; + } else { + this.retrievalQueue = retrievalQueue; + } } @Override From 84f9abdeaf6a77eb5bcb5a98222900036e4817a6 Mon Sep 17 00:00:00 2001 From: Richard Peter <richard.peter@raytheon.com> Date: Thu, 16 Jan 2014 20:29:50 -0600 Subject: [PATCH 46/62] Issue #2357: Close JmsSession when it has no producers or consumers Change-Id: Icd0d29c0e6a43109ac26a1d1ad1bbeef9d7aca5f Former-commit-id: fe249a9fc20906dea60118b10525e3872cee5324 [formerly 953ddccdb04beff75e7cc4a094ee0584a7df0b1d] [formerly c3529a17697f83537b42d1c3d9432ad872b3938a [formerly 2a152d5ef2b0e3f54948f3679be74ecd717c02f9]] Former-commit-id: c3529a17697f83537b42d1c3d9432ad872b3938a Former-commit-id: 31e2bd3555e0bc16f10836a6c5ec07ed78476726 --- .../src/com/raytheon/uf/common/jms/JmsPooledSession.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/JmsPooledSession.java b/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/JmsPooledSession.java index d3ad93562e..241b6c73e3 100644 --- a/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/JmsPooledSession.java +++ b/edexOsgi/com.raytheon.uf.common.jms/src/com/raytheon/uf/common/jms/JmsPooledSession.java @@ -60,6 +60,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * Apr 15, 2011 rjpeter Initial creation * Mar 08, 2012 194 njensen Improved logging * Feb 21, 2013 1642 rjpeter Fix deadlock scenario + * Jan 26, 2014 2357 rjpeter Close a session when it has no producers or consumers. * </pre> * * @author rjpeter @@ -627,7 +628,7 @@ public class JmsPooledSession { } } - boolean valid = isValid(); + boolean valid = isValid() && hasProducersOrConsumers(); if (valid && returnToPool) { valid = conn.returnSessionToPool(this); } @@ -654,4 +655,10 @@ public class JmsPooledSession { public Object getStateLock() { return stateLock; } + + public boolean hasProducersOrConsumers() { + return !inUseConsumers.isEmpty() || !inUseProducers.isEmpty() + || !availableConsumers.isEmpty() + || !availableProducers.isEmpty(); + } } From 5fded8bd27151d964866d63b3dc3ac8f8f275951 Mon Sep 17 00:00:00 2001 From: Nate Jensen <Nathan.Jensen@raytheon.com> Date: Fri, 17 Jan 2014 09:46:26 -0600 Subject: [PATCH 47/62] Issue #2581 fix yet another missing LSR event type Change-Id: Ia71aa67038f7f9adc17f7d11e4d38990220e3916 Former-commit-id: 60652fe5a701ba836f1f47b8721f5269dffda90f [formerly 7cbfaf7d7d9347ec996dd639025f5125b641a5c5] [formerly 9c5a95e814c6ab6cb4bec38c9b1a311c5ee74ded [formerly 6aac0862eb647a50b9f60cd290c3bb6f96807b3d]] Former-commit-id: 9c5a95e814c6ab6cb4bec38c9b1a311c5ee74ded Former-commit-id: 451d340bf1a2c6dcfec8fc5b11eaaf2fe07783a3 --- .../com/raytheon/uf/common/dataplugin/lsr/LSREventType.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java b/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java index 7c95421386..bb38201db2 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.lsr/src/com/raytheon/uf/common/dataplugin/lsr/LSREventType.java @@ -36,6 +36,7 @@ import java.util.Map; * Dec 09, 2013 2581 njensen Added freezing drizzle * Jan 03, 2014 2581 njensen Added coastal flood * Jan 13, 2014 2581 njensen Added debris flow + * Jan 17, 2014 2581 njensen Added blowing snow * * </pre> * @@ -87,7 +88,10 @@ public enum LSREventType { WILDFIRE("WILDFIRE",39,LSRUnits.NOUNITS), FREEZINGDRIZZLE("FREEZING DRIZZLE", 40, LSRUnits.NOUNITS), COASTALFLOOD("COASTAL FLOOD", 41, LSRUnits.NOUNITS), - DEBRISFLOW("DEBRIS FLOW", 42, LSRUnits.NOUNITS); + DEBRISFLOW("DEBRIS FLOW", 42, LSRUnits.NOUNITS), + BLOWINGSNOW("BLOWING SNOW", 43, LSRUnits.NOUNITS); + + // TODO contemplate storing the event type as a string in the database instead of an enum/integer private final String eventName; From 09bc3382d671123e456b5af652f66ff7418187a9 Mon Sep 17 00:00:00 2001 From: Nate Jensen <Nathan.Jensen@raytheon.com> Date: Fri, 17 Jan 2014 10:24:10 -0600 Subject: [PATCH 48/62] Issue #2359 fix annoying ncep null pointer Change-Id: I5d606f42bfe4060f8874d2cfaf01a48b548ce25e Former-commit-id: f46b6e0a8fd73b4ff4bd68ca117e50ef4d56d8ac [formerly c7addfbdbf5482c29ba8d64682c2c7859bbb36d0] [formerly fa79f2aa14845da97378c70a2d696dff19b47ef1 [formerly 0cb0975786aa578e93fe06227c666feb759e0433]] Former-commit-id: fa79f2aa14845da97378c70a2d696dff19b47ef1 Former-commit-id: 012ee681e5aaf96d391f9817fba2f4f8e44271d2 --- .../nonconvsigmet/util/NonConvSigmetParser.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/ncep/gov.noaa.nws.ncep.edex.plugin.nonconvsigmet/src/gov/noaa/nws/ncep/edex/plugin/nonconvsigmet/util/NonConvSigmetParser.java b/ncep/gov.noaa.nws.ncep.edex.plugin.nonconvsigmet/src/gov/noaa/nws/ncep/edex/plugin/nonconvsigmet/util/NonConvSigmetParser.java index d0cf71c3ae..1c5ea21e4a 100644 --- a/ncep/gov.noaa.nws.ncep.edex.plugin.nonconvsigmet/src/gov/noaa/nws/ncep/edex/plugin/nonconvsigmet/util/NonConvSigmetParser.java +++ b/ncep/gov.noaa.nws.ncep.edex.plugin.nonconvsigmet/src/gov/noaa/nws/ncep/edex/plugin/nonconvsigmet/util/NonConvSigmetParser.java @@ -11,6 +11,7 @@ * 07/2011 F. J. Yen Fix for RTN TTR 9973--ConvSigment Decoder Ignoring * time range (NonConvsigmet, too). Set the rangeEnd * time to the endTime + * Jan 17, 2014 njensen Handle if one or more locations not found in LatLonLocTbl * * This code has been developed by the SIB for use in the AWIPS2 system. */ @@ -344,14 +345,17 @@ public class NonConvSigmetParser { currentLocation.setLocationLine(lines); currentLocation.setLocation(location); point = LatLonLocTbl.getLatLonPoint(location, "vors"); - currentLocation.setIndex(idxLocation + 1); - idxLocation++; - currentLocation.setLatitude(point + if(point != null) { + currentLocation.setIndex(idxLocation + 1); + idxLocation++; + currentLocation.setLatitude(point .getLatitude(LatLonPoint.INDEGREES)); - currentLocation.setLongitude(point + currentLocation.setLongitude(point .getLongitude(LatLonPoint.INDEGREES)); - recordTable.addNonConvSigmetLocation(currentLocation); + recordTable.addNonConvSigmetLocation(currentLocation); + } } + hasLocationLine = (idxLocation > 0); } else { hasLocationLine = false; } @@ -406,4 +410,4 @@ public class NonConvSigmetParser { return currentRecord; } -} \ No newline at end of file +} From 760fb70dde2931894e202c805c5b316ada99f2d9 Mon Sep 17 00:00:00 2001 From: Benjamin Phillippe <Benjamin_D_Phillippe@raytheon.com> Date: Thu, 16 Jan 2014 15:06:41 -0600 Subject: [PATCH 49/62] Issue #2613 Rewrote poorly written section of code in NotificationListenerImpl Change-Id: Ibcdd415667f379a20799a4166b12cc8cc5e05ed4 Former-commit-id: d81f8ddf89e7f356948619407f3d8a303e224d1f [formerly 6b0d25cf5c126038655e9a73d83b136a8ca47bed] [formerly 7516310ab1cddd471b47de1b58203965a41aa509 [formerly 4d4c7837ad1084b8c6007c660c59e3bd29f757cc]] Former-commit-id: 7516310ab1cddd471b47de1b58203965a41aa509 Former-commit-id: 407687aeb3ec3c0087db9e957a21a9baf2330a5d --- ...raytheon.uf.edex.registry.ebxml.properties | 2 +- .../NotificationListenerImpl.java | 207 +++++++++++++----- 2 files changed, 155 insertions(+), 54 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/resources/com.raytheon.uf.edex.registry.ebxml.properties b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/resources/com.raytheon.uf.edex.registry.ebxml.properties index 1443109d82..b11e318764 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/resources/com.raytheon.uf.edex.registry.ebxml.properties +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/resources/com.raytheon.uf.edex.registry.ebxml.properties @@ -1,7 +1,7 @@ # The period which registry subscriptions are processed ebxml-subscription-process.cron=0/20+*+*+*+*+? # The period which the registry runs the garbage collection -ebxml-garbage-collect-process.cron=*+0/5+*+*+*+? +ebxml-garbage-collect-process.cron=0+0/5+*+*+*+? # The period which adhoc subscriptions are cleaned, every 20 mins adhocsubscription-process.cron=0+0/20+*+*+*+? # When a federation synchonization is necessary, this is the number of threads diff --git a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/NotificationListenerImpl.java b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/NotificationListenerImpl.java index 03caf07c38..d2016cb718 100644 --- a/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/NotificationListenerImpl.java +++ b/edexOsgi/com.raytheon.uf.edex.registry.ebxml/src/com/raytheon/uf/edex/registry/ebxml/services/notification/NotificationListenerImpl.java @@ -21,6 +21,7 @@ package com.raytheon.uf.edex.registry.ebxml.services.notification; import java.util.ArrayList; import java.util.Collection; +import java.util.LinkedList; import java.util.List; import javax.annotation.Resource; @@ -123,8 +124,6 @@ public class NotificationListenerImpl implements NotificationListener { /** Registry soap service client */ private RegistrySOAPServices registrySoapClient; - // @FIXME This method is pretty scary in it's implementation as Richard - // pointed out. Please fix Ben. @Override public void onNotification(NotificationType notification) { long startTime = TimeUtil.currentTimeMillis(); @@ -144,37 +143,28 @@ public class NotificationListenerImpl implements NotificationListener { + ")]"); } - List<AuditableEventType> events = notification.getEvent(); + // Creates a new action list from the received events + ProcessActionList actionList = new ProcessActionList( + notification.getEvent()); - List<String> actionList = new ArrayList<String>(events.size()); - List<String> objIdList = new ArrayList<String>(events.size()); + /* + * Iterate through each action and process them in the order in which + * the were received. Notification types currently supported are create, + * update and delete. All other action types will be ignored and a + * warning message is output into the log + */ + for (ProcessAction action : actionList.getActions()) { + String actionType = action.getActionType(); - for (AuditableEventType event : events) { - List<ActionType> actions = event.getAction(); - for (ActionType action : actions) { - String eventType = action.getEventType(); - List<String> objectIds = getIdsFromAction(action); - objIdList.addAll(objectIds); - for (int i = 0; i < objectIds.size(); i++) { - actionList.add(eventType); - } - } - } - - int listSize = objIdList.size(); - for (int i = 0; i < listSize;) { - List<String> insertIds = new ArrayList<String>(); - while (i < listSize - && (actionList.get(i).equals(ActionTypes.create) || actionList - .get(i).equals(ActionTypes.update))) { - insertIds.add(objIdList.get(i)); - i++; - } - if (!insertIds.isEmpty()) { + /* + * Process creates and updates + */ + if (ActionTypes.create.equals(actionType) + || ActionTypes.update.equals(actionType)) { try { SubmitObjectsRequest submitRequest = createSubmitObjectsRequest( - clientBaseURL, notification.getId(), insertIds, - Mode.CREATE_OR_REPLACE); + clientBaseURL, notification.getId(), + action.getIdList(), Mode.CREATE_OR_REPLACE); lcm.submitObjects(submitRequest); } catch (MsgRegistryException e) { throw new RuntimeException( @@ -184,14 +174,12 @@ public class NotificationListenerImpl implements NotificationListener { "Error creating submit objects request!", e); } } - List<String> deleteIds = new ArrayList<String>(); - while (i < listSize && actionList.get(i).equals(ActionTypes.delete)) { - deleteIds.add(objIdList.get(i)); - i++; - } - if (!deleteIds.isEmpty()) { + /* + * Process deletes + */ + else if (ActionTypes.delete.equals(actionType)) { ObjectRefListType refList = new ObjectRefListType(); - for (String id : deleteIds) { + for (String id : action.getIdList()) { RegistryObjectType object = registryObjectDao.getById(id); if (object != null) { refList.getObjectRef().add(new ObjectRefType(id)); @@ -212,30 +200,22 @@ public class NotificationListenerImpl implements NotificationListener { } } } - } + /* + * Output warning in log that an unsupported action type was + * received + */ + else { + statusHandler.warn("Unsupported action type received [" + + actionType + "]"); + } + } registryDao.flushAndClearSession(); statusHandler.info("Processing notification id [" + notification.getId() + "] completed in " + (TimeUtil.currentTimeMillis() - startTime) + " ms"); } - private List<String> getIdsFromAction(ActionType action) { - List<String> objectIds = new ArrayList<String>(); - if (action.getAffectedObjectRefs() != null) { - for (ObjectRefType ref : action.getAffectedObjectRefs() - .getObjectRef()) { - objectIds.add(ref.getId()); - } - } else if (action.getAffectedObjects() != null) { - for (RegistryObjectType regObj : action.getAffectedObjects() - .getRegistryObject()) { - objectIds.add(regObj.getId()); - } - } - return objectIds; - } - @Override @WebMethod(action = "SynchronousNotification") @WebResult(name = "RegistryResponse", targetNamespace = EbxmlNamespaces.RS_URI, partName = "partRegistryResponse") @@ -371,6 +351,127 @@ public class NotificationListenerImpl implements NotificationListener { return request; } + /** + * This class organizes actions from the received list of auditable events. + * The purpose of this class is to batch together consecutive events having + * the same action type in order to minimize queries to the remote server + * during notification processing. The actions must be processed in the + * order in which the appear in the original auditable event list in order + * to maintain the integrity of the registry across federation members. + * + * @author bphillip + * + */ + private class ProcessActionList { + + /** The list of actions contained in the received auditable events */ + private List<ProcessAction> actions = new ArrayList<NotificationListenerImpl.ProcessAction>(); + + /** + * Creates a new ProcessActionList from the provided list of events + * + * @param events + * The events from which to generate the ProcessActionList + */ + public ProcessActionList(List<AuditableEventType> events) { + if (!CollectionUtil.isNullOrEmpty(events)) { + for (AuditableEventType event : events) { + List<ActionType> actions = event.getAction(); + for (ActionType action : actions) { + addAction(action.getEventType(), + getIdsFromAction(action)); + } + } + } + } + + /** + * Adds an action to the list to be processed + * + * @param actionType + * The type of action + * @param ids + * The ids of the objects on which the action was executed + */ + private void addAction(String actionType, List<String> ids) { + if (actions.isEmpty()) { + actions.add(new ProcessAction(actionType, ids)); + } else { + ProcessAction lastAction = actions.get(actions.size() - 1); + if (lastAction.getActionType().equals(actionType)) { + lastAction.addIds(ids); + } else { + actions.add(new ProcessAction(actionType, ids)); + } + } + + } + + /** + * Extracts the affected object ids from the action + * + * @param action + * The action to get the ids from + * @return The list of ids from the action object + */ + private List<String> getIdsFromAction(ActionType action) { + List<String> objectIds = new ArrayList<String>(); + if (action.getAffectedObjectRefs() != null) { + for (ObjectRefType ref : action.getAffectedObjectRefs() + .getObjectRef()) { + objectIds.add(ref.getId()); + } + } else if (action.getAffectedObjects() != null) { + for (RegistryObjectType regObj : action.getAffectedObjects() + .getRegistryObject()) { + objectIds.add(regObj.getId()); + } + } + return objectIds; + } + + public List<ProcessAction> getActions() { + return actions; + } + + } + + /** + * Private class encapsulating the list of object ids and the action that + * was executed on them. + * + * @author bphillip + * + */ + private class ProcessAction { + + /** The type of action executed */ + private String actionType; + + /** The list of objects that the action was executed on */ + private List<String> idList; + + public ProcessAction(String actionType, List<String> ids) { + this.actionType = actionType; + addIds(ids); + } + + public String getActionType() { + return actionType; + } + + public List<String> getIdList() { + if (idList == null) { + idList = new LinkedList<String>(); + } + return idList; + } + + public void addIds(List<String> ids) { + getIdList().addAll(ids); + } + } + public void setLcm(LifecycleManagerImpl lcm) { this.lcm = lcm; } From caa06ce1e12c89d9f683fde211c389a43893f2b7 Mon Sep 17 00:00:00 2001 From: Richard Peter <richard.peter@raytheon.com> Date: Fri, 17 Jan 2014 14:12:34 -0600 Subject: [PATCH 50/62] Issue #2125: Clean up hibernate warnings Change-Id: Ieb78e7e518a90f09c8db6d72213d5bffa357414e Former-commit-id: f30181d73030e2d28dfa00da5ad1a733d4cff46a [formerly e2d20753e158ca59163f238ad23790a5d20b3e42] [formerly 0c058f461c5d96bed2914453d46726befc1183b6 [formerly 4a99614b887fe02e1ad9831fc9414ceb6808ba7b]] Former-commit-id: 0c058f461c5d96bed2914453d46726befc1183b6 Former-commit-id: 7054a06acbbd4b9a98002a9268cae3e2ce49ab22 --- .../damCatalog/hibernate.cfg.xml | 14 ++--- .../db/hibernateConfig/fxa/hibernate.cfg.xml | 14 ++--- .../db/hibernateConfig/hmdb/hibernate.cfg.xml | 14 ++--- .../db/hibernateConfig/ihfs/hibernate.cfg.xml | 14 ++--- .../db/hibernateConfig/maps/hibernate.cfg.xml | 14 ++--- .../db/hibernateConfig/ncep/hibernate.cfg.xml | 14 ++--- .../status/DataDeliverySystemStatusId.java | 44 +++++++++++++- .../dataplugin/text/db/AutoFaxRecordPK.java | 44 +++++++++++++- .../LambertConformalGridCoverage.java | 29 ++++++---- .../gridcoverage/LatLonGridCoverage.java | 10 ++-- .../gridcoverage/MercatorGridCoverage.java | 41 +++++++------ .../gridcoverage/PolarStereoGridCoverage.java | 57 ++++++++++++------- .../ebxml/regrep/xsd/rim/v4/AnyValueType.java | 20 ++++--- .../regrep/xsd/rim/v4/BooleanValueType.java | 20 ++++--- .../xsd/rim/v4/CollectionValueType.java | 28 +++++---- .../regrep/xsd/rim/v4/DateTimeValueType.java | 20 ++++--- .../regrep/xsd/rim/v4/DurationValueType.java | 20 ++++--- .../regrep/xsd/rim/v4/FloatValueType.java | 20 ++++--- .../regrep/xsd/rim/v4/IntegerValueType.java | 20 ++++--- .../rim/v4/InternationalStringValueType.java | 21 ++++--- .../ebxml/regrep/xsd/rim/v4/MapValueType.java | 20 ++++--- .../regrep/xsd/rim/v4/SlotValueType.java | 20 ++++--- .../regrep/xsd/rim/v4/StringValueType.java | 20 ++++--- .../xsd/rim/v4/VocabularyTermValueType.java | 21 ++++--- .../edex/database/cluster/ClusterTaskPK.java | 43 +++++++++++++- 25 files changed, 398 insertions(+), 204 deletions(-) diff --git a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/damCatalog/hibernate.cfg.xml b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/damCatalog/hibernate.cfg.xml index cae1498b2a..153b4e7837 100644 --- a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/damCatalog/hibernate.cfg.xml +++ b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/damCatalog/hibernate.cfg.xml @@ -59,17 +59,17 @@ <!-- c3p0 Connection Pool Properties --> <!-- Additional properties may be added to c3p0.properties --> - <property name="c3p0.acquire_increment">1</property> - <property name="c3p0.idle_test_period">60</property> - <property name="c3p0.timeout">300</property> - <property name="c3p0.max_size">10</property> - <property name="c3p0.max_statements">10</property> - <property name="c3p0.min_size">1</property> + <property name="hibernate.c3p0.acquire_increment">1</property> + <property name="hibernate.c3p0.idle_test_period">60</property> + <property name="hibernate.c3p0.timeout">300</property> + <property name="hibernate.c3p0.max_size">10</property> + <property name="hibernate.c3p0.max_statements">10</property> + <property name="hibernate.c3p0.min_size">1</property> <!-- Cache Properties --> <property name="hibernate.cache.use_second_level_cache">false</property> - <property name="cache.use_query_cache">false</property> + <property name="hibernate.cache.use_query_cache">false</property> </session-factory> </hibernate-configuration> \ No newline at end of file diff --git a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/fxa/hibernate.cfg.xml b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/fxa/hibernate.cfg.xml index a253267a65..429b285373 100644 --- a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/fxa/hibernate.cfg.xml +++ b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/fxa/hibernate.cfg.xml @@ -59,17 +59,17 @@ <!-- c3p0 Connection Pool Properties --> <!-- Additional properties may be added to c3p0.properties --> - <property name="c3p0.acquire_increment">1</property> - <property name="c3p0.idle_test_period">60</property> - <property name="c3p0.timeout">300</property> - <property name="c3p0.max_size">25</property> - <property name="c3p0.max_statements">10</property> - <property name="c3p0.min_size">1</property> + <property name="hibernate.c3p0.acquire_increment">1</property> + <property name="hibernate.c3p0.idle_test_period">60</property> + <property name="hibernate.c3p0.timeout">300</property> + <property name="hibernate.c3p0.max_size">25</property> + <property name="hibernate.c3p0.max_statements">10</property> + <property name="hibernate.c3p0.min_size">1</property> <!-- Cache Properties --> <property name="hibernate.cache.use_second_level_cache">false</property> - <property name="cache.use_query_cache">false</property> + <property name="hibernate.cache.use_query_cache">false</property> </session-factory> </hibernate-configuration> \ No newline at end of file diff --git a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/hmdb/hibernate.cfg.xml b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/hmdb/hibernate.cfg.xml index 5d96161116..ff103aff47 100644 --- a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/hmdb/hibernate.cfg.xml +++ b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/hmdb/hibernate.cfg.xml @@ -59,17 +59,17 @@ <!-- c3p0 Connection Pool Properties --> <!-- Additional properties may be added to c3p0.properties --> - <property name="c3p0.acquire_increment">1</property> - <property name="c3p0.idle_test_period">60</property> - <property name="c3p0.timeout">300</property> - <property name="c3p0.max_size">10</property> - <property name="c3p0.max_statements">10</property> - <property name="c3p0.min_size">1</property> + <property name="hibernate.c3p0.acquire_increment">1</property> + <property name="hibernate.c3p0.idle_test_period">60</property> + <property name="hibernate.c3p0.timeout">300</property> + <property name="hibernate.c3p0.max_size">10</property> + <property name="hibernate.c3p0.max_statements">10</property> + <property name="hibernate.c3p0.min_size">1</property> <!-- Cache Properties --> <property name="hibernate.cache.use_second_level_cache">false</property> - <property name="cache.use_query_cache">false</property> + <property name="hibernate.cache.use_query_cache">false</property> </session-factory> </hibernate-configuration> \ No newline at end of file diff --git a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/ihfs/hibernate.cfg.xml b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/ihfs/hibernate.cfg.xml index c6849892d2..12b9182cff 100644 --- a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/ihfs/hibernate.cfg.xml +++ b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/ihfs/hibernate.cfg.xml @@ -59,16 +59,16 @@ <!-- c3p0 Connection Pool Properties --> <!-- Additional properties may be added to c3p0.properties --> - <property name="c3p0.acquire_increment">1</property> - <property name="c3p0.idle_test_period">60</property> - <property name="c3p0.timeout">300</property> - <property name="c3p0.max_size">10</property> - <property name="c3p0.max_statements">10</property> - <property name="c3p0.min_size">1</property> + <property name="hibernate.c3p0.acquire_increment">1</property> + <property name="hibernate.c3p0.idle_test_period">60</property> + <property name="hibernate.c3p0.timeout">300</property> + <property name="hibernate.c3p0.max_size">10</property> + <property name="hibernate.c3p0.max_statements">10</property> + <property name="hibernate.c3p0.min_size">1</property> <!-- Cache Properties --> - <property name="cache.use_query_cache">false</property> + <property name="hibernate.cache.use_query_cache">false</property> <property name="hibernate.cache.use_second_level_cache">false</property> </session-factory> diff --git a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/maps/hibernate.cfg.xml b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/maps/hibernate.cfg.xml index 038d89f378..ba4088c582 100644 --- a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/maps/hibernate.cfg.xml +++ b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/maps/hibernate.cfg.xml @@ -59,17 +59,17 @@ <!-- c3p0 Connection Pool Properties --> <!-- Additional properties may be added to c3p0.properties --> - <property name="c3p0.acquire_increment">1</property> - <property name="c3p0.idle_test_period">60</property> - <property name="c3p0.timeout">300</property> - <property name="c3p0.min_size">1</property> - <property name="c3p0.max_size">20</property> - <property name="c3p0.max_statements">20</property> + <property name="hibernate.c3p0.acquire_increment">1</property> + <property name="hibernate.c3p0.idle_test_period">60</property> + <property name="hibernate.c3p0.timeout">300</property> + <property name="hibernate.c3p0.min_size">1</property> + <property name="hibernate.c3p0.max_size">20</property> + <property name="hibernate.c3p0.max_statements">20</property> <!-- Cache Properties --> <property name="hibernate.cache.use_second_level_cache">false</property> - <property name="cache.use_query_cache">false</property> + <property name="hibernate.cache.use_query_cache">false</property> </session-factory> </hibernate-configuration> \ No newline at end of file diff --git a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/ncep/hibernate.cfg.xml b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/ncep/hibernate.cfg.xml index c438fb1368..6b2a5bc64d 100644 --- a/edexOsgi/build.edex/esb/conf/db/hibernateConfig/ncep/hibernate.cfg.xml +++ b/edexOsgi/build.edex/esb/conf/db/hibernateConfig/ncep/hibernate.cfg.xml @@ -56,17 +56,17 @@ <!-- c3p0 Connection Pool Properties --> <!-- Additional properties may be added to c3p0.properties --> - <property name="c3p0.acquire_increment">1</property> - <property name="c3p0.idle_test_period">60</property> - <property name="c3p0.timeout">60</property> - <property name="c3p0.max_size">10</property> - <property name="c3p0.max_statements">1000</property> - <property name="c3p0.min_size">1</property> + <property name="hibernate.c3p0.acquire_increment">1</property> + <property name="hibernate.c3p0.idle_test_period">60</property> + <property name="hibernate.c3p0.timeout">60</property> + <property name="hibernate.c3p0.max_size">10</property> + <property name="hibernate.c3p0.max_statements">1000</property> + <property name="hibernate.c3p0.min_size">1</property> <!-- Cache Properties --> <property name="hibernate.cache.use_second_level_cache">false</property> - <property name="cache.use_query_cache">false</property> + <property name="hibernate.cache.use_query_cache">false</property> </session-factory> </hibernate-configuration> diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/status/DataDeliverySystemStatusId.java b/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/status/DataDeliverySystemStatusId.java index 6baa2a243f..ee54538fb7 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/status/DataDeliverySystemStatusId.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.event/src/com/raytheon/uf/common/datadelivery/event/status/DataDeliverySystemStatusId.java @@ -41,8 +41,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Jul 3, 2013 1655 mpduff Initial creation. - * + * Jul 3, 2013 1655 mpduff Initial creation. + * Jan 17, 2014 2125 rjpeter EmbeddedId classes need hashCode/equals. * </pre> * * @author mpduff @@ -54,6 +54,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @XmlAccessorType(XmlAccessType.NONE) public class DataDeliverySystemStatusId implements Serializable, ISerializableObject { + private static final long serialVersionUID = -6970802086185781078L; @XmlElement @@ -95,4 +96,43 @@ public class DataDeliverySystemStatusId implements Serializable, public void setName(String name) { this.name = name; } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + ((name == null) ? 0 : name.hashCode()); + result = (prime * result) + + ((systemType == null) ? 0 : systemType.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + DataDeliverySystemStatusId other = (DataDeliverySystemStatusId) obj; + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + if (systemType == null) { + if (other.systemType != null) { + return false; + } + } else if (!systemType.equals(other.systemType)) { + return false; + } + return true; + } } diff --git a/edexOsgi/com.raytheon.uf.common.dataplugin.text/src/com/raytheon/uf/common/dataplugin/text/db/AutoFaxRecordPK.java b/edexOsgi/com.raytheon.uf.common.dataplugin.text/src/com/raytheon/uf/common/dataplugin/text/db/AutoFaxRecordPK.java index 4bea64c543..e316ebdee1 100644 --- a/edexOsgi/com.raytheon.uf.common.dataplugin.text/src/com/raytheon/uf/common/dataplugin/text/db/AutoFaxRecordPK.java +++ b/edexOsgi/com.raytheon.uf.common.dataplugin.text/src/com/raytheon/uf/common/dataplugin/text/db/AutoFaxRecordPK.java @@ -29,7 +29,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; /** - * TODO Add Description + * Primary key for an AutoFaxRecord. * * <pre> * @@ -38,7 +38,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Oct 28, 2010 bfarmer Initial creation - * + * Jan 17, 2014 2125 rjpeter EmbeddedId should implement hashCode/equals * </pre> * * @author bfarmer @@ -96,4 +96,44 @@ public class AutoFaxRecordPK implements ISerializableObject, Serializable { this.faxNumber = faxNumber; } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + + ((afosPil == null) ? 0 : afosPil.hashCode()); + result = (prime * result) + + ((faxNumber == null) ? 0 : faxNumber.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + AutoFaxRecordPK other = (AutoFaxRecordPK) obj; + if (afosPil == null) { + if (other.afosPil != null) { + return false; + } + } else if (!afosPil.equals(other.afosPil)) { + return false; + } + if (faxNumber == null) { + if (other.faxNumber != null) { + return false; + } + } else if (!faxNumber.equals(other.faxNumber)) { + return false; + } + return true; + } + } diff --git a/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/LambertConformalGridCoverage.java b/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/LambertConformalGridCoverage.java index af0cfd2255..f547efa10f 100644 --- a/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/LambertConformalGridCoverage.java +++ b/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/LambertConformalGridCoverage.java @@ -25,7 +25,6 @@ import javax.measure.unit.SI; import javax.measure.unit.Unit; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -57,14 +56,13 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * ------------ ---------- ----------- -------------------------- * 4/7/09 1994 bphillip Initial Creation * 09/10/2012 DR 15270 D. Friedman Fix subgrid model name handling. - * + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip * @version 1 */ @Entity -@Table(name = "grib_lambertconformal_coverages") @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -287,33 +285,42 @@ public class LambertConformalGridCoverage extends GridCoverage { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } if (!super.equals(obj)) { return false; } LambertConformalGridCoverage other = (LambertConformalGridCoverage) obj; if (Double.doubleToLongBits(latin1) != Double - .doubleToLongBits(other.latin1)) + .doubleToLongBits(other.latin1)) { return false; + } if (Double.doubleToLongBits(latin2) != Double - .doubleToLongBits(other.latin2)) + .doubleToLongBits(other.latin2)) { return false; - if (Double.doubleToLongBits(lov) != Double.doubleToLongBits(other.lov)) + } + if (Double.doubleToLongBits(lov) != Double.doubleToLongBits(other.lov)) { return false; + } if (Double.doubleToLongBits(majorAxis) != Double - .doubleToLongBits(other.majorAxis)) + .doubleToLongBits(other.majorAxis)) { return false; + } if (Double.doubleToLongBits(minorAxis) != Double - .doubleToLongBits(other.minorAxis)) + .doubleToLongBits(other.minorAxis)) { return false; + } return true; } + @Override public boolean spatialEquals(GridCoverage other) { if (super.spatialEquals(other)) { LambertConformalGridCoverage otherLambert = (LambertConformalGridCoverage) other; diff --git a/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/LatLonGridCoverage.java b/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/LatLonGridCoverage.java index 4c8576a1e6..9348bb5939 100644 --- a/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/LatLonGridCoverage.java +++ b/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/LatLonGridCoverage.java @@ -21,7 +21,6 @@ package com.raytheon.uf.common.gridcoverage; import javax.persistence.Entity; -import javax.persistence.Table; import javax.persistence.Transient; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; @@ -49,14 +48,13 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * ------------ ---------- ----------- -------------------------- * 4/7/09 1994 bphillip Initial Creation * 09/10/2012 DR 15270 D. Friedman Fix subgrid model name handling. - * + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip * @version 1 */ @Entity -@Table(name = "grib_latlon_coverages") @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -92,11 +90,11 @@ public class LatLonGridCoverage extends GridCoverage { @Override public void initialize() throws GridCoverageException { // lower left is cell center, we want cell corners. - double minLon = getLowerLeftLon() - dx / 2; - double maxLon = minLon + dx * nx; + double minLon = getLowerLeftLon() - (dx / 2); + double maxLon = minLon + (dx * nx); double centralMeridian = (minLon + maxLon) / 2.0; - if (dx * nx <= 360) { + if ((dx * nx) <= 360) { centralMeridian = MapUtil.correctLon(centralMeridian); } else { // For almost all map projections geotools will clip all math diff --git a/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/MercatorGridCoverage.java b/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/MercatorGridCoverage.java index afc8cd36f9..cee7f82504 100644 --- a/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/MercatorGridCoverage.java +++ b/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/MercatorGridCoverage.java @@ -25,7 +25,6 @@ import javax.measure.unit.SI; import javax.measure.unit.Unit; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -59,14 +58,13 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * ------------ ---------- ----------- -------------------------- * 4/7/09 1994 bphillip Initial Creation * 09/10/2012 DR 15270 D. Friedman Fix subgrid model name handling. - * + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip * @version 1 */ @Entity -@Table(name = "grib_mercator_coverages") @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -123,7 +121,7 @@ public class MercatorGridCoverage extends GridCoverage { @Override public void initialize() throws GridCoverageException { double meridian = 0; - if (la2 == null || lo2 == null) { + if ((la2 == null) || (lo2 == null)) { initializeSecondCorner(); } @@ -185,20 +183,20 @@ public class MercatorGridCoverage extends GridCoverage { DirectPosition2D position = null; switch (firstGridPointCorner) { case LowerLeft: - position = new DirectPosition2D(firstPosition.x + dx * 1000 - * nx, firstPosition.y + dy * 1000 * ny); + position = new DirectPosition2D(firstPosition.x + + (dx * 1000 * nx), firstPosition.y + (dy * 1000 * ny)); break; case UpperLeft: - position = new DirectPosition2D(firstPosition.x + dx * 1000 - * nx, firstPosition.y - dy * 1000 * ny); + position = new DirectPosition2D(firstPosition.x + + (dx * 1000 * nx), firstPosition.y - (dy * 1000 * ny)); break; case LowerRight: - position = new DirectPosition2D(firstPosition.x - dx * 1000 - * nx, firstPosition.y - dy * 1000 * ny); + position = new DirectPosition2D(firstPosition.x + - (dx * 1000 * nx), firstPosition.y - (dy * 1000 * ny)); break; case UpperRight: - position = new DirectPosition2D(firstPosition.x - dx * 1000 - * nx, firstPosition.y - dy * 1000 * ny); + position = new DirectPosition2D(firstPosition.x + - (dx * 1000 * nx), firstPosition.y - (dy * 1000 * ny)); break; default: throw new GridCoverageException( @@ -352,28 +350,35 @@ public class MercatorGridCoverage extends GridCoverage { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } if (!super.equals(obj)) { return false; } MercatorGridCoverage other = (MercatorGridCoverage) obj; if (Double.doubleToLongBits(latin) != Double - .doubleToLongBits(other.latin)) + .doubleToLongBits(other.latin)) { return false; + } if (Double.doubleToLongBits(majorAxis) != Double - .doubleToLongBits(other.majorAxis)) + .doubleToLongBits(other.majorAxis)) { return false; + } if (Double.doubleToLongBits(minorAxis) != Double - .doubleToLongBits(other.minorAxis)) + .doubleToLongBits(other.minorAxis)) { return false; + } return true; } + @Override public boolean spatialEquals(GridCoverage other) { if (super.spatialEquals(other)) { MercatorGridCoverage otherMercator = (MercatorGridCoverage) other; diff --git a/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/PolarStereoGridCoverage.java b/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/PolarStereoGridCoverage.java index e7d61ca83d..c6d4d9b1da 100644 --- a/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/PolarStereoGridCoverage.java +++ b/edexOsgi/com.raytheon.uf.common.gridcoverage/src/com/raytheon/uf/common/gridcoverage/PolarStereoGridCoverage.java @@ -25,7 +25,6 @@ import javax.measure.unit.SI; import javax.measure.unit.Unit; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -57,14 +56,13 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * ------------ ---------- ----------- -------------------------- * 4/7/09 1994 bphillip Initial Creation * 09/10/2012 DR 15270 D. Friedman Fix subgrid model name handling. - * + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip * @version 1 */ @Entity -@Table(name = "grib_polarstereo_coverages") @XmlRootElement @XmlAccessorType(XmlAccessType.NONE) @DynamicSerialize @@ -171,6 +169,7 @@ public class PolarStereoGridCoverage extends GridCoverage { return rval; } + @Override public String getProjectionType() { return PROJECTION_TYPE; } @@ -249,49 +248,67 @@ public class PolarStereoGridCoverage extends GridCoverage { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (obj == null) + } + if (obj == null) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } PolarStereoGridCoverage other = (PolarStereoGridCoverage) obj; - if (Double.doubleToLongBits(dx) != Double.doubleToLongBits(other.dx)) + if (Double.doubleToLongBits(dx) != Double.doubleToLongBits(other.dx)) { return false; - if (Double.doubleToLongBits(dy) != Double.doubleToLongBits(other.dy)) + } + if (Double.doubleToLongBits(dy) != Double.doubleToLongBits(other.dy)) { return false; - if (Double.doubleToLongBits(la1) != Double.doubleToLongBits(other.la1)) + } + if (Double.doubleToLongBits(la1) != Double.doubleToLongBits(other.la1)) { return false; - if (Double.doubleToLongBits(lo1) != Double.doubleToLongBits(other.lo1)) + } + if (Double.doubleToLongBits(lo1) != Double.doubleToLongBits(other.lo1)) { return false; - if (Double.doubleToLongBits(lov) != Double.doubleToLongBits(other.lov)) + } + if (Double.doubleToLongBits(lov) != Double.doubleToLongBits(other.lov)) { return false; - if (Double.doubleToLongBits(lad) != Double.doubleToLongBits(other.lad)) + } + if (Double.doubleToLongBits(lad) != Double.doubleToLongBits(other.lad)) { return false; + } if (Double.doubleToLongBits(majorAxis) != Double - .doubleToLongBits(other.majorAxis)) + .doubleToLongBits(other.majorAxis)) { return false; + } if (Double.doubleToLongBits(minorAxis) != Double - .doubleToLongBits(other.minorAxis)) + .doubleToLongBits(other.minorAxis)) { return false; + } if (nx == null) { - if (other.nx != null) + if (other.nx != null) { return false; - } else if (!nx.equals(other.nx)) + } + } else if (!nx.equals(other.nx)) { return false; + } if (ny == null) { - if (other.ny != null) + if (other.ny != null) { return false; - } else if (!ny.equals(other.ny)) + } + } else if (!ny.equals(other.ny)) { return false; + } if (spacingUnit == null) { - if (other.spacingUnit != null) + if (other.spacingUnit != null) { return false; - } else if (!spacingUnit.equals(other.spacingUnit)) + } + } else if (!spacingUnit.equals(other.spacingUnit)) { return false; + } return true; } + @Override public boolean spatialEquals(GridCoverage other) { if (super.spatialEquals(other)) { PolarStereoGridCoverage otherPolar = (PolarStereoGridCoverage) other; diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/AnyValueType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/AnyValueType.java index 5717042048..633d67357b 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/AnyValueType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/AnyValueType.java @@ -22,7 +22,6 @@ package oasis.names.tc.ebxml.regrep.xsd.rim.v4; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAnyElement; @@ -74,6 +73,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Removed generic methods, * modified persistence annotations, added * constructors, hashCode, toString and equals + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip @@ -82,7 +82,6 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; */ @Entity @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL) -@Table(schema = RegrepUtil.EBXML_SCHEMA, name = "AnyValue") @XmlRootElement(name = "AnyValue") @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "AnyValueType", propOrder = { "anyValue" }) @@ -131,25 +130,30 @@ public class AnyValueType extends ValueType { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + result = (prime * result) + ((anyValue == null) ? 0 : anyValue.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } AnyValueType other = (AnyValueType) obj; if (anyValue == null) { - if (other.anyValue != null) + if (other.anyValue != null) { return false; - } else if (!anyValue.equals(other.anyValue)) + } + } else if (!anyValue.equals(other.anyValue)) { return false; + } return true; } diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/BooleanValueType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/BooleanValueType.java index 21c03d64da..f1020fd526 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/BooleanValueType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/BooleanValueType.java @@ -22,7 +22,6 @@ package oasis.names.tc.ebxml.regrep.xsd.rim.v4; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -71,6 +70,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Removed generic methods, * modified persistence annotations, added * constructors, hashCode, toString and equals + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip @@ -82,7 +82,6 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @DynamicSerialize @Entity @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL) -@Table(schema = RegrepUtil.EBXML_SCHEMA, name = "BooleanValue") public class BooleanValueType extends ValueType { @Column @@ -126,25 +125,30 @@ public class BooleanValueType extends ValueType { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + result = (prime * result) + ((booleanValue == null) ? 0 : booleanValue.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } BooleanValueType other = (BooleanValueType) obj; if (booleanValue == null) { - if (other.booleanValue != null) + if (other.booleanValue != null) { return false; - } else if (!booleanValue.equals(other.booleanValue)) + } + } else if (!booleanValue.equals(other.booleanValue)) { return false; + } return true; } diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/CollectionValueType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/CollectionValueType.java index 0da053c960..6935b7caf9 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/CollectionValueType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/CollectionValueType.java @@ -28,7 +28,6 @@ import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.JoinTable; import javax.persistence.ManyToMany; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; @@ -80,6 +79,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Removed generic methods, * modified persistence annotations, added * constructors, hashCode, toString and equals + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip @@ -91,7 +91,6 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @DynamicSerialize @Entity @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL) -@Table(schema = RegrepUtil.EBXML_SCHEMA, name = "CollectionValue") public class CollectionValueType extends ValueType { @XmlElement(name = "Element") @@ -192,32 +191,39 @@ public class CollectionValueType extends ValueType { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + result = (prime * result) + ((collectionType == null) ? 0 : collectionType.hashCode()); - result = prime * result + result = (prime * result) + ((collectionValue == null) ? 0 : collectionValue.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } CollectionValueType other = (CollectionValueType) obj; if (collectionType == null) { - if (other.collectionType != null) + if (other.collectionType != null) { return false; - } else if (!collectionType.equals(other.collectionType)) + } + } else if (!collectionType.equals(other.collectionType)) { return false; + } if (collectionValue == null) { - if (other.collectionValue != null) + if (other.collectionValue != null) { return false; - } else if (!collectionValue.equals(other.collectionValue)) + } + } else if (!collectionValue.equals(other.collectionValue)) { return false; + } return true; } diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/DateTimeValueType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/DateTimeValueType.java index 60b7b2961a..f93b54f9b0 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/DateTimeValueType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/DateTimeValueType.java @@ -24,7 +24,6 @@ import java.util.GregorianCalendar; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -79,6 +78,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Removed generic methods, * modified persistence annotations, added * constructors, hashCode, toString and equals + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip @@ -90,7 +90,6 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @DynamicSerialize @Entity @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL) -@Table(schema = RegrepUtil.EBXML_SCHEMA, name = "DateTimeValue") public class DateTimeValueType extends ValueType { @Column @@ -152,25 +151,30 @@ public class DateTimeValueType extends ValueType { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + result = (prime * result) + ((dateTimeValue == null) ? 0 : dateTimeValue.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } DateTimeValueType other = (DateTimeValueType) obj; if (dateTimeValue == null) { - if (other.dateTimeValue != null) + if (other.dateTimeValue != null) { return false; - } else if (!dateTimeValue.equals(other.dateTimeValue)) + } + } else if (!dateTimeValue.equals(other.dateTimeValue)) { return false; + } return true; } diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/DurationValueType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/DurationValueType.java index af3b9c712b..0889e991be 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/DurationValueType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/DurationValueType.java @@ -22,7 +22,6 @@ package oasis.names.tc.ebxml.regrep.xsd.rim.v4; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -73,6 +72,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Removed generic methods, * modified persistence annotations, added * constructors, hashCode, toString and equals + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip @@ -84,7 +84,6 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @DynamicSerialize @Entity @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL) -@Table(schema = RegrepUtil.EBXML_SCHEMA, name = "DurationValue") public class DurationValueType extends ValueType { @XmlElement(name = "Value") @@ -129,25 +128,30 @@ public class DurationValueType extends ValueType { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + result = (prime * result) + ((durationValue == null) ? 0 : durationValue.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } DurationValueType other = (DurationValueType) obj; if (durationValue == null) { - if (other.durationValue != null) + if (other.durationValue != null) { return false; - } else if (!durationValue.equals(other.durationValue)) + } + } else if (!durationValue.equals(other.durationValue)) { return false; + } return true; } diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/FloatValueType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/FloatValueType.java index 872eade720..27b0a1de23 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/FloatValueType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/FloatValueType.java @@ -22,7 +22,6 @@ package oasis.names.tc.ebxml.regrep.xsd.rim.v4; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -71,6 +70,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Removed generic methods, * modified persistence annotations, added * constructors, hashCode, toString and equals + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip @@ -82,7 +82,6 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @DynamicSerialize @Entity @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL) -@Table(schema = RegrepUtil.EBXML_SCHEMA, name = "FloatValue") public class FloatValueType extends ValueType { @Column @@ -126,25 +125,30 @@ public class FloatValueType extends ValueType { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + result = (prime * result) + ((floatValue == null) ? 0 : floatValue.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } FloatValueType other = (FloatValueType) obj; if (floatValue == null) { - if (other.floatValue != null) + if (other.floatValue != null) { return false; - } else if (!floatValue.equals(other.floatValue)) + } + } else if (!floatValue.equals(other.floatValue)) { return false; + } return true; } diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/IntegerValueType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/IntegerValueType.java index d44a3f48fe..6619474b51 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/IntegerValueType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/IntegerValueType.java @@ -24,7 +24,6 @@ import java.math.BigInteger; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -73,6 +72,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Removed generic methods, * modified persistence annotations, added * constructors, hashCode, toString and equals + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip @@ -84,7 +84,6 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @DynamicSerialize @Entity @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL) -@Table(schema = RegrepUtil.EBXML_SCHEMA, name = "IntegerValue") public class IntegerValueType extends ValueType { @Column @@ -132,25 +131,30 @@ public class IntegerValueType extends ValueType { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + result = (prime * result) + ((integerValue == null) ? 0 : integerValue.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } IntegerValueType other = (IntegerValueType) obj; if (integerValue == null) { - if (other.integerValue != null) + if (other.integerValue != null) { return false; - } else if (!integerValue.equals(other.integerValue)) + } + } else if (!integerValue.equals(other.integerValue)) { return false; + } return true; } diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/InternationalStringValueType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/InternationalStringValueType.java index a1e392c58b..1f4a708aa0 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/InternationalStringValueType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/InternationalStringValueType.java @@ -24,7 +24,6 @@ import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -74,6 +73,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Removed generic methods, * modified persistence annotations, added * constructors, hashCode, toString and equals + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip @@ -85,7 +85,6 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @DynamicSerialize @Entity @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL) -@Table(schema = RegrepUtil.EBXML_SCHEMA, name = "InternationalStringValue") public class InternationalStringValueType extends ValueType { @XmlElement(name = "Value") @@ -133,8 +132,7 @@ public class InternationalStringValueType extends ValueType { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime - * result + result = (prime * result) + ((internationalStringValue == null) ? 0 : internationalStringValue.hashCode()); return result; @@ -142,19 +140,24 @@ public class InternationalStringValueType extends ValueType { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } InternationalStringValueType other = (InternationalStringValueType) obj; if (internationalStringValue == null) { - if (other.internationalStringValue != null) + if (other.internationalStringValue != null) { return false; + } } else if (!internationalStringValue - .equals(other.internationalStringValue)) + .equals(other.internationalStringValue)) { return false; + } return true; } diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/MapValueType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/MapValueType.java index edbb6cceff..7f2d5a1245 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/MapValueType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/MapValueType.java @@ -24,7 +24,6 @@ import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -73,6 +72,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Removed generic methods, * modified persistence annotations, added * constructors, hashCode, toString and equals + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip @@ -80,7 +80,6 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; */ @Entity(name = "MapValue") @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL) -@Table(schema = RegrepUtil.EBXML_SCHEMA, name = "MapValue") @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "MapValueType", propOrder = { "mapValue" }) @@ -129,25 +128,30 @@ public class MapValueType extends ValueType { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + result = (prime * result) + ((mapValue == null) ? 0 : mapValue.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } MapValueType other = (MapValueType) obj; if (mapValue == null) { - if (other.mapValue != null) + if (other.mapValue != null) { return false; - } else if (!mapValue.equals(other.mapValue)) + } + } else if (!mapValue.equals(other.mapValue)) { return false; + } return true; } diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/SlotValueType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/SlotValueType.java index 28fe6c12c1..0f80e387bc 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/SlotValueType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/SlotValueType.java @@ -24,7 +24,6 @@ import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.OneToOne; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -73,6 +72,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Removed generic methods, * modified persistence annotations, added * constructors, hashCode, toString and equals + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip @@ -84,7 +84,6 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @DynamicSerialize @Entity @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL) -@Table(schema = RegrepUtil.EBXML_SCHEMA, name = "SlotValue") public class SlotValueType extends ValueType { @XmlElement(name = "Slot") @@ -129,25 +128,30 @@ public class SlotValueType extends ValueType { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + result = (prime * result) + ((slotValue == null) ? 0 : slotValue.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } SlotValueType other = (SlotValueType) obj; if (slotValue == null) { - if (other.slotValue != null) + if (other.slotValue != null) { return false; - } else if (!slotValue.equals(other.slotValue)) + } + } else if (!slotValue.equals(other.slotValue)) { return false; + } return true; } diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/StringValueType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/StringValueType.java index 243f4fb775..09989b8f91 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/StringValueType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/StringValueType.java @@ -22,7 +22,6 @@ package oasis.names.tc.ebxml.regrep.xsd.rim.v4; import javax.persistence.Column; import javax.persistence.Entity; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -72,6 +71,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Removed generic methods, * modified persistence annotations, added * constructors, hashCode, toString and equals + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip @@ -83,7 +83,6 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @DynamicSerialize @Entity @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL) -@Table(schema = RegrepUtil.EBXML_SCHEMA, name = "StringValue") public class StringValueType extends ValueType { @Column(columnDefinition = "text") @@ -127,25 +126,30 @@ public class StringValueType extends ValueType { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime * result + result = (prime * result) + ((stringValue == null) ? 0 : stringValue.hashCode()); return result; } @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } StringValueType other = (StringValueType) obj; if (stringValue == null) { - if (other.stringValue != null) + if (other.stringValue != null) { return false; - } else if (!stringValue.equals(other.stringValue)) + } + } else if (!stringValue.equals(other.stringValue)) { return false; + } return true; } diff --git a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/VocabularyTermValueType.java b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/VocabularyTermValueType.java index 08f98e6ce7..69178b5831 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/VocabularyTermValueType.java +++ b/edexOsgi/com.raytheon.uf.common.registry.schemas.ebxml/src/oasis/names/tc/ebxml/regrep/xsd/rim/v4/VocabularyTermValueType.java @@ -23,7 +23,6 @@ package oasis.names.tc.ebxml.regrep.xsd.rim.v4; import javax.persistence.CascadeType; import javax.persistence.Entity; import javax.persistence.OneToOne; -import javax.persistence.Table; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; @@ -73,6 +72,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * 12/2/2013 1829 bphillip Removed generic methods, * modified persistence annotations, added * constructors, hashCode, toString and equals + * Jan 17, 2014 2125 rjpeter Removed invalid @Table annotation. * </pre> * * @author bphillip @@ -84,7 +84,6 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; @DynamicSerialize @Entity @Cache(region = RegrepUtil.DB_CACHE_REGION, usage = CacheConcurrencyStrategy.TRANSACTIONAL) -@Table(schema = RegrepUtil.EBXML_SCHEMA, name = "VocabularyTermValue") public class VocabularyTermValueType extends ValueType { @XmlElement(name = "Value") @@ -129,8 +128,7 @@ public class VocabularyTermValueType extends ValueType { public int hashCode() { final int prime = 31; int result = super.hashCode(); - result = prime - * result + result = (prime * result) + ((vocabularyTermValue == null) ? 0 : vocabularyTermValue .hashCode()); return result; @@ -138,18 +136,23 @@ public class VocabularyTermValueType extends ValueType { @Override public boolean equals(Object obj) { - if (this == obj) + if (this == obj) { return true; - if (!super.equals(obj)) + } + if (!super.equals(obj)) { return false; - if (getClass() != obj.getClass()) + } + if (getClass() != obj.getClass()) { return false; + } VocabularyTermValueType other = (VocabularyTermValueType) obj; if (vocabularyTermValue == null) { - if (other.vocabularyTermValue != null) + if (other.vocabularyTermValue != null) { return false; - } else if (!vocabularyTermValue.equals(other.vocabularyTermValue)) + } + } else if (!vocabularyTermValue.equals(other.vocabularyTermValue)) { return false; + } return true; } diff --git a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/cluster/ClusterTaskPK.java b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/cluster/ClusterTaskPK.java index 1905e879e4..8443e3e818 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/cluster/ClusterTaskPK.java +++ b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/cluster/ClusterTaskPK.java @@ -27,7 +27,7 @@ import javax.persistence.Embeddable; import com.raytheon.uf.common.serialization.ISerializableObject; /** - * TODO Add Description + * Primary key for a ClusterTask. * * <pre> * @@ -35,7 +35,7 @@ import com.raytheon.uf.common.serialization.ISerializableObject; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Feb 22, 2010 chammack Initial creation - * + * Jan 17, 2014 2125 rjpeter EmbeddedId should implement hashCode/equals. * </pre> * * @author chammack @@ -82,4 +82,43 @@ public class ClusterTaskPK implements ISerializableObject, Serializable { this.name = name; } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = (prime * result) + + ((details == null) ? 0 : details.hashCode()); + result = (prime * result) + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ClusterTaskPK other = (ClusterTaskPK) obj; + if (details == null) { + if (other.details != null) { + return false; + } + } else if (!details.equals(other.details)) { + return false; + } + if (name == null) { + if (other.name != null) { + return false; + } + } else if (!name.equals(other.name)) { + return false; + } + return true; + } + } From a492ec6a4d182b650379bc8bc6ae07b3968fad49 Mon Sep 17 00:00:00 2001 From: Mike Duff <michael.duff@raytheon.com> Date: Fri, 17 Jan 2014 15:34:48 -0600 Subject: [PATCH 51/62] Issue #2459 - Remove unscheduled status from UI Former-commit-id: 0cfa9ee36c13bccddb26d885f5a646a30c3ca384 [formerly 93cb80cfc7d5bb61e99108597064ecd803f809db] [formerly 25d1d39fc2abe6d9c7e592388901b7ae906a4811 [formerly ddbef8fd122a6be6c32ff9a58659e712c2912a07]] Former-commit-id: 25d1d39fc2abe6d9c7e592388901b7ae906a4811 Former-commit-id: a04430e33498f1b562368094268448e33691d84f --- ...rceApplyAndIncreaseLatencyDisplayText.java | 3 +- .../registry/RecurringSubscription.java | 7 +--- .../common/datadelivery/registry/Utils.java | 6 +-- .../handlers/BaseSubscriptionHandler.java | 41 +++++++++++++++++++ .../edex/database/dao/SessionManagedDao.java | 7 +++- .../bandwidth/BandwidthManager.java | 11 +++-- 6 files changed, 59 insertions(+), 16 deletions(-) diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/CancelForceApplyAndIncreaseLatencyDisplayText.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/CancelForceApplyAndIncreaseLatencyDisplayText.java index 4df123b53d..a2360cfb8f 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/CancelForceApplyAndIncreaseLatencyDisplayText.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/CancelForceApplyAndIncreaseLatencyDisplayText.java @@ -39,6 +39,7 @@ import com.raytheon.uf.viz.datadelivery.subscription.SubscriptionService.IForceA * ------------ ---------- ----------- -------------------------- * Dec 4, 2012 1286 djohnson Initial creation * May 28, 2013 1650 djohnson More information when failing to schedule subscriptions. + * Jan 17, 2014 2459 mpduff Change gui usage of unscheduled to deactivated. * * </pre> * @@ -88,7 +89,7 @@ public class CancelForceApplyAndIncreaseLatencyDisplayText implements if (singleSubscription && wouldBeUnscheduledSubscriptions.contains(name)) { return titleCaseActionText + " " + name - + " and leave in an unscheduled status"; + + " and leave in a Deactivated status"; } return titleCaseActionText + " " + name + " and unschedule the others"; diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java index e309a2be7b..62e2fb2dfb 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java @@ -216,7 +216,6 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> @XmlAttribute @DynamicSerializeElement - @SlotAttribute private boolean unscheduled; @XmlAttribute @@ -266,7 +265,7 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> @XmlAttribute @DynamicSerializeElement @SlotAttribute(Subscription.SUBSCRIPTION_STATE_SLOT) - private SubscriptionState subscriptionState; + private SubscriptionState subscriptionState = SubscriptionState.ON; /** Flag stating if the object should be updated */ private boolean shouldUpdate = false; @@ -918,9 +917,7 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> Calendar cal = TimeUtil.newGmtCalendar(); Date today = cal.getTime(); - if (unscheduled) { - return SubscriptionStatus.UNSCHEDULED; - } else if (inWindow(today)) { + if (inWindow(today)) { return SubscriptionStatus.ACTIVE; } diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Utils.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Utils.java index a1eeb9700e..703941af80 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Utils.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/Utils.java @@ -22,7 +22,8 @@ import com.vividsolutions.jts.geom.Polygon; * Feb 20, 2011 218 dhladky Initial creation. * Oct 1, 2012 1103 jpiatt Added invalid subscription status. * Nov 20, 2012 1286 djohnson Add UNSCHEDULED. - * Jan 14, 2014 2459 mpduff Change Subscription status code + * Jan 14, 2014 2459 mpduff Change Subscription status code. + * Jan 17, 2014 2459 mpduff Remove unscheduled status, not just deactivated. * * </pre> * @@ -87,7 +88,6 @@ public class Utils { * Deactivated - Do not schedule * Active - Currently scheduled * Inactive - Not currently scheduled (outside of active period) - * Unscheduled - Not currently scheduled due to bandwidth limitations * Invalid - Subscription does not match the available data set * </pre> */ @@ -99,8 +99,6 @@ public class Utils { INACTIVE("Inactive"), /** Expired Subscription Status */ EXPIRED("Expired"), - /** Unscheduled Subscription Status */ - UNSCHEDULED("Unscheduled"), /** Deactivated Subscription Status */ DEACTIVATED("Deactivated"), /** Invalid Subscription Status */ diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/BaseSubscriptionHandler.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/BaseSubscriptionHandler.java index 2f1e4c1fdd..3fec6a4621 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/BaseSubscriptionHandler.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/BaseSubscriptionHandler.java @@ -25,6 +25,8 @@ import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import com.raytheon.uf.common.datadelivery.registry.Network; import com.raytheon.uf.common.datadelivery.registry.RecurringSubscription; @@ -34,6 +36,10 @@ import com.raytheon.uf.common.datadelivery.registry.ebxml.SubscriptionFilterable import com.raytheon.uf.common.registry.RegistryQueryResponse; import com.raytheon.uf.common.registry.handler.BaseRegistryObjectHandler; import com.raytheon.uf.common.registry.handler.RegistryHandlerException; +import com.raytheon.uf.common.registry.handler.RegistryObjectHandlers; +import com.raytheon.uf.common.status.IUFStatusHandler; +import com.raytheon.uf.common.status.UFStatus; +import com.raytheon.uf.common.status.UFStatus.Priority; /** * Base subscription handler. @@ -53,6 +59,7 @@ import com.raytheon.uf.common.registry.handler.RegistryHandlerException; * Jul 18, 2013 2193 mpduff Changes for SubscriptionDataSetNameQuery. * Sep 11, 2013 2352 mpduff Add siteId to getSubscribedToDataSetNames method. * Jan 14, 2014 2459 mpduff Validate subs should be scheduled before returning them. + * Jan 17, 2014 2459 mpduff Persist the state of the expired subs. * * </pre> * @@ -63,6 +70,11 @@ import com.raytheon.uf.common.registry.handler.RegistryHandlerException; public abstract class BaseSubscriptionHandler<T extends Subscription, QUERY extends SubscriptionFilterableQuery<T>> extends BaseRegistryObjectHandler<T, QUERY> implements IBaseSubscriptionHandler<T> { + private static final IUFStatusHandler statusHandler = UFStatus + .getHandler(BaseSubscriptionHandler.class); + + private final List<T> updateList = new ArrayList<T>(); + /** * {@inheritDoc} * @@ -207,8 +219,37 @@ public abstract class BaseSubscriptionHandler<T extends Subscription, QUERY exte for (T sub : response.getResults()) { if (((RecurringSubscription) sub).shouldSchedule()) { returnList.add(sub); + } else if (((RecurringSubscription) sub).shouldUpdate()) { + updateList.add(sub); } } + + // Save updated objects back to registry + if (!updateList.isEmpty()) { + ExecutorService executor = Executors.newFixedThreadPool(1); + executor.execute(new Runnable() { + @Override + public void run() { + synchronized (updateList) { + ISubscriptionHandler sh = RegistryObjectHandlers + .get(ISubscriptionHandler.class); + for (T s : updateList) { + try { + sh.update(s); + statusHandler.info("Subscription " + + s.getName() + " is expired."); + } catch (RegistryHandlerException e) { + statusHandler.handle(Priority.WARN, + "Unable to set subscription to expired [" + + s.getName() + "]", e); + } + } + updateList.clear(); + } + } + }); + } + return returnList; } } diff --git a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/dao/SessionManagedDao.java b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/dao/SessionManagedDao.java index 5f40b56bb7..4e1aed008b 100644 --- a/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/dao/SessionManagedDao.java +++ b/edexOsgi/com.raytheon.uf.edex.database/src/com/raytheon/uf/edex/database/dao/SessionManagedDao.java @@ -63,6 +63,7 @@ import com.raytheon.uf.edex.database.DataAccessLayerException; * Jun 24, 2013 2106 djohnson Use IDENTIFIER generic for method signature. * 10/8/2013 1682 bphillip Added the createCriteria method * 12/9/2013 2613 bphillip Added flushAndClearSession method + * Jan 17, 2014 2459 mpduff Added null check to prevent NPE. * * </pre> * @@ -127,8 +128,10 @@ public abstract class SessionManagedDao<IDENTIFIER extends Serializable, ENTITY */ @Override public void delete(final ENTITY obj) { - Object toDelete = template.merge(obj); - template.delete(toDelete); + if (obj != null) { + Object toDelete = template.merge(obj); + template.delete(toDelete); + } } /** diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java index 1609f5c1f3..0dc59bd340 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/BandwidthManager.java @@ -37,6 +37,7 @@ import com.raytheon.uf.common.datadelivery.registry.DataType; import com.raytheon.uf.common.datadelivery.registry.GriddedTime; import com.raytheon.uf.common.datadelivery.registry.Network; import com.raytheon.uf.common.datadelivery.registry.PointTime; +import com.raytheon.uf.common.datadelivery.registry.RecurringSubscription; import com.raytheon.uf.common.datadelivery.registry.SiteSubscription; import com.raytheon.uf.common.datadelivery.registry.Subscription; import com.raytheon.uf.common.datadelivery.registry.Time; @@ -591,11 +592,13 @@ public abstract class BandwidthManager<T extends Time, C extends Coverage> // If BandwidthManager does not know about the subscription, and // it's active, attempt to add it.. - if (bandwidthSubscriptions.isEmpty() && subscription.isActive()) { + if (bandwidthSubscriptions.isEmpty() + && ((RecurringSubscription) subscription).shouldSchedule() + && !subscription.isUnscheduled()) { return schedule(subscription); - } else if (subscription.isUnscheduled() - || subscription.getStatus() == SubscriptionStatus.DEACTIVATED) { - // See if the subscription was inactivated or unscheduled.. + } else if (subscription.getStatus() == SubscriptionStatus.DEACTIVATED + || subscription.isUnscheduled()) { + // See if the subscription was deactivated or unscheduled.. // Need to remove BandwidthReservations for this // subscription. return remove(bandwidthSubscriptions); From b225690c65dda2ab89559c3ed7db0194473d4818 Mon Sep 17 00:00:00 2001 From: Dave Hladky <david_j_hladky@raytheon.com> Date: Mon, 20 Jan 2014 12:04:08 -0600 Subject: [PATCH 52/62] Issue #2710 Made MADIS window larger. Former-commit-id: 37ccd1d80d173aaf277e0b55cc5354415e6dfdb3 [formerly edb07269a97c951f819cea856d335664a7d6ac41] [formerly 0094857d34e2dc41b4f4fadfb4cd80e9902787f2 [formerly eddd50a0575d140eb05999889940a632f319438c]] Former-commit-id: 0094857d34e2dc41b4f4fadfb4cd80e9902787f2 Former-commit-id: 78e3974527f4cdedf7a1b43ea76967ae84d1c286 --- .../base/datadelivery/harvester/MADIS-harvester.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.harvester/utility/common_static/base/datadelivery/harvester/MADIS-harvester.xml b/edexOsgi/com.raytheon.uf.common.datadelivery.harvester/utility/common_static/base/datadelivery/harvester/MADIS-harvester.xml index 06fc387809..9e035084fc 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.harvester/utility/common_static/base/datadelivery/harvester/MADIS-harvester.xml +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.harvester/utility/common_static/base/datadelivery/harvester/MADIS-harvester.xml @@ -23,8 +23,8 @@ <dateFormat>HHddMMMyyyy</dateFormat> <layer name="madis-conus" namespace="http://madis.edex.uf.raytheon.com"> <!-- Geographic constraint of madis layer data --> - <minx>-120.0</minx> - <maxx>-70.0</maxx> + <minx>-130.0</minx> + <maxx>-65.0</maxx> <miny>20.0</miny> <maxy>50.0</maxy> <crs>crs:84</crs> From a10034c5eef5a1e8b10d351708480f0cb072e5be Mon Sep 17 00:00:00 2001 From: Nate Jensen <Nathan.Jensen@raytheon.com> Date: Mon, 20 Jan 2014 12:36:04 -0600 Subject: [PATCH 53/62] Issue #2359 better error messages in satellite decoder Change-Id: I81961ca49a18cf3c5b246216f9a48ea7ad67fd49 Former-commit-id: 13e18d40123c7fcc5de953191a6e80c94c606844 [formerly 36fd148cca9f6f5365f3d87f1d2434663dd5e956] [formerly 831d960ca682d69e729c96dd1ceda5160a873611 [formerly 9caeee451d284887660d1290eaa5331cbaa11eec]] Former-commit-id: 831d960ca682d69e729c96dd1ceda5160a873611 Former-commit-id: 99797a2816e2ad815f934897a1f34baf9d6b5e9e --- .../plugin/satellite/SatelliteDecoder.java | 47 +++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/plugin/satellite/SatelliteDecoder.java b/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/plugin/satellite/SatelliteDecoder.java index f43ec80e11..b2013cb29c 100644 --- a/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/plugin/satellite/SatelliteDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/plugin/satellite/SatelliteDecoder.java @@ -33,10 +33,15 @@ import java.util.zip.Inflater; import com.raytheon.edex.exception.DecoderException; import com.raytheon.edex.plugin.satellite.dao.SatelliteDao; +import com.raytheon.edex.plugin.satellite.gini.SatelliteCreatingEntity; +import com.raytheon.edex.plugin.satellite.gini.SatellitePhysicalElement; import com.raytheon.edex.plugin.satellite.gini.SatellitePosition; +import com.raytheon.edex.plugin.satellite.gini.SatelliteSectorId; +import com.raytheon.edex.plugin.satellite.gini.SatelliteSource; import com.raytheon.edex.plugin.satellite.gini.SatelliteUnit; import com.raytheon.edex.util.satellite.SatSpatialFactory; import com.raytheon.uf.common.dataplugin.PluginDataObject; +import com.raytheon.uf.common.dataplugin.exception.UnrecognizedDataException; import com.raytheon.uf.common.dataplugin.satellite.SatMapCoverage; import com.raytheon.uf.common.dataplugin.satellite.SatelliteMessageData; import com.raytheon.uf.common.dataplugin.satellite.SatelliteRecord; @@ -81,6 +86,7 @@ import com.raytheon.uf.common.util.header.WMOHeaderFinder; * * Mar 19, 2013 1785 bgonzale Added performance status handler and added status * to decode. + * Jan 20, 2014 njensen Better error handling when fields are not recognized * * </pre> * @@ -170,20 +176,43 @@ public class SatelliteDecoder { int scanMode = byteBuffer.get(37); // read the source - record.setSource(dao.getSource(byteBuffer.get(0)) - .getSourceName()); + byte sourceByte = byteBuffer.get(0); + SatelliteSource source = dao.getSource(sourceByte); + if (source == null) { + throw new UnrecognizedDataException( + "Unknown satellite source id: " + sourceByte); + } + record.setSource(source.getSourceName()); // read the creating entity - record.setCreatingEntity(dao.getCreatingEntity( - byteBuffer.get(1)).getEntityName()); + byte entityByte = byteBuffer.get(1); + SatelliteCreatingEntity entity = dao + .getCreatingEntity(entityByte); + if (entity == null) { + throw new UnrecognizedDataException( + "Unknown satellite entity id: " + entityByte); + } + record.setCreatingEntity(entity.getEntityName()); // read the sector ID - record.setSectorID(dao.getSectorId(byteBuffer.get(2)) - .getSectorName()); + byte sectorByte = byteBuffer.get(2); + SatelliteSectorId sector = dao.getSectorId(sectorByte); + if (sector == null) { + throw new UnrecognizedDataException( + "Unknown satellite sector id: " + sectorByte); + } + record.setSectorID(sector.getSectorName()); // read the physical element - record.setPhysicalElement(dao.getPhysicalElement( - (byteBuffer.get(3))).getElementName()); + byte physByte = byteBuffer.get(3); + SatellitePhysicalElement physElem = dao + .getPhysicalElement(physByte); + if (physElem == null) { + throw new UnrecognizedDataException( + "Unknown satellite physical element id: " + + physByte); + } + record.setPhysicalElement(physElem.getElementName()); // read the units SatelliteUnit unit = dao.getUnit(byteBuffer.get(3)); @@ -431,6 +460,8 @@ public class SatelliteDecoder { } timer.stop(); perfLog.logDuration("Time to Decode", timer.getElapsedTime()); + } catch (Exception e) { + statusHandler.error("Error decoding satellite", e); } finally { try { f.close(); From f7e01e3083618baf34f60d0350af58ecbd4fc349 Mon Sep 17 00:00:00 2001 From: Brad Gonzales <bradley_l_gonzales@raytheon.com> Date: Fri, 17 Jan 2014 16:25:46 -0600 Subject: [PATCH 54/62] Issue #2678 Better fix for sbn retrieval queue init to null in wfo. Fix for bandwith graph data retrieve of sbn data. Amend: updated commit comment in BandwidthGraphData. Change-Id: Ic77130425e495330fe670086e5bbfad35e7b9287 Former-commit-id: 061884910d4163e87baee853e5641c20535bb491 [formerly 0635a368c67d28d9e1866484a534e1429461c701] [formerly 6b8da117e471922c57dca21aa844da7d01c95345 [formerly 253b19d5cd1c7950209521a708b5ad9abbf000f6]] Former-commit-id: 6b8da117e471922c57dca21aa844da7d01c95345 Former-commit-id: 8e307a22e68ec1b5aeaf618f0768eac410d9b74e --- .../bandwidth/data/BandwidthGraphData.java | 12 +++++------- .../bandwidth-datadelivery-edex-impl-wfo.xml | 1 - .../retrieval/SubscriptionRetrievalAgent.java | 17 +++++++++++------ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/BandwidthGraphData.java b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/BandwidthGraphData.java index 1caa1651dc..40590cc5cd 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/BandwidthGraphData.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.bandwidth/src/com/raytheon/uf/common/datadelivery/bandwidth/data/BandwidthGraphData.java @@ -52,6 +52,8 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerializeElement; * Nov 19, 2013 2545 bgonzale Added 'add' method stub. Still work to do. * Nov 25, 2013 2545 mpduff Finished implementing 2545. * Dec 11, 2013 2625 mpduff Add error handling for no data conditions. + * Jan 17, 2014 2678 bgonzale Changed merge to not check for existing network + * mapping since SBN will be in the OPSNET mapping * * </pre> * @@ -345,7 +347,7 @@ public class BandwidthGraphData { } /** - * Merge another Bandwidth graph data into this object. + * Merge another Bandwidth graph data over the data in this object. * * @param data2 * The other data set to merge @@ -355,18 +357,14 @@ public class BandwidthGraphData { .getNetworkBucketMap(); for (Network network : nbm.keySet()) { - if (!networkBucketMap.containsKey(network)) { - networkBucketMap.put(network, nbm.get(network)); - } + networkBucketMap.put(network, nbm.get(network)); } Map<Network, List<SubscriptionWindowData>> ndm = data2 .getNetworkDataMap(); for (Network network : ndm.keySet()) { - if (!networkDataMap.containsKey(network)) { - networkDataMap.put(network, ndm.get(network)); - } + networkDataMap.put(network, ndm.get(network)); } } } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml index 58ff2f556f..567a3a5471 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml @@ -61,7 +61,6 @@ <constructor-arg ref="bandwidthDao" /> <constructor-arg ref="retrievalDao" /> <constructor-arg ref="ProviderHandler" /> - <constructor-arg ref="retrievalQueue" /> </bean> <util:map id="retrievalAgents"> diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgent.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgent.java index d4ad081e90..bd56dbe5ab 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgent.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/retrieval/SubscriptionRetrievalAgent.java @@ -55,6 +55,7 @@ import com.raytheon.uf.edex.datadelivery.retrieval.db.RetrievalRequestRecordPK; * Jul 11, 2013 2106 djohnson Use SubscriptionPriority enum. * Jan 15, 2014 2678 bgonzale Use Queue for passing RetrievalRequestRecords to the * RetrievalTasks (PerformRetrievalsThenReturnFinder). + * Added constructor that sets the retrievalQueue to null. * * </pre> * @@ -78,6 +79,15 @@ public class SubscriptionRetrievalAgent extends private final ConcurrentLinkedQueue<RetrievalRequestRecordPK> retrievalQueue; + public SubscriptionRetrievalAgent(Network network, String destinationUri, + final Object notifier, int defaultPriority, + RetrievalManager retrievalManager, IBandwidthDao bandwidthDao, + IRetrievalDao retrievalDao, IProviderHandler providerHandler) { + this(network, destinationUri, notifier, defaultPriority, + retrievalManager, bandwidthDao, retrievalDao, providerHandler, + null); + } + public SubscriptionRetrievalAgent(Network network, String destinationUri, final Object notifier, int defaultPriority, RetrievalManager retrievalManager, IBandwidthDao bandwidthDao, @@ -88,12 +98,7 @@ public class SubscriptionRetrievalAgent extends this.bandwidthDao = bandwidthDao; this.retrievalDao = retrievalDao; this.providerHandler = providerHandler; - // SBN retrievals come from ingest processing - if (network.equals(Network.SBN)) { - this.retrievalQueue = null; - } else { - this.retrievalQueue = retrievalQueue; - } + this.retrievalQueue = retrievalQueue; } @Override From 4b570ada3369d3b7c9d80ac9257f64dc5605355f Mon Sep 17 00:00:00 2001 From: Nate Jensen <Nathan.Jensen@raytheon.com> Date: Mon, 20 Jan 2014 13:11:36 -0600 Subject: [PATCH 55/62] Issue #2359 fix ncep pirep decoding null pointer Change-Id: Id255abcda2d8c661ce8d7d0b022addc69f7635ea Former-commit-id: 7961052b41b82b613b333725360e37cd684de8f1 [formerly 7f7f05b8ba4fb6378c0eb4e1fb5d24ed6d790a48] [formerly 5a860252adabaffa09229c868522bee74189b659 [formerly 5f554ec21fcedc7f8ef5b3b00fc951527bb424bb]] Former-commit-id: 5a860252adabaffa09229c868522bee74189b659 Former-commit-id: c0d49c4b2477f4b4a76135f8173695a6bd4d910e --- .../ncep/common/dataplugin/pirep/PirepPointDataTransform.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.pirep/src/gov/noaa/nws/ncep/common/dataplugin/pirep/PirepPointDataTransform.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.pirep/src/gov/noaa/nws/ncep/common/dataplugin/pirep/PirepPointDataTransform.java index eab9616058..23633feccf 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.pirep/src/gov/noaa/nws/ncep/common/dataplugin/pirep/PirepPointDataTransform.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.pirep/src/gov/noaa/nws/ncep/common/dataplugin/pirep/PirepPointDataTransform.java @@ -54,6 +54,7 @@ import com.raytheon.uf.common.time.DataTime; * 09/27/2011 286 qzhou Make TB, IC, SK records all start from 0 in the arrays. * Fixed visibility . * Sep 05, 2013 2316 bsteffen Unify pirep and ncpirep. + * Jan 20, 2014 njensen Fix storage of turbulence top height * </pre> * * @author qzhou @@ -277,7 +278,7 @@ public class PirepPointDataTransform { pdv.setInt(TURB_BASE_HEIGHT, pld.getTurbBaseHeight(), iTb); } if (pld.getTurbTopHeight() != null) { - pdv.setInt(TURB_TOP_HEIGHT, pld.getTurbBaseHeight(), iTb); + pdv.setInt(TURB_TOP_HEIGHT, pld.getTurbTopHeight(), iTb); } if (pld.getIceBaseHeight() != null) { pdv.setInt(ICE_BASE_HEIGHT, pld.getIceBaseHeight(), iIc); From f2bc6abb8024ba2e2ea7190ca406fee4de7c83e3 Mon Sep 17 00:00:00 2001 From: David Gillingham <David.Gillingham@raytheon.com> Date: Mon, 20 Jan 2014 15:37:52 -0600 Subject: [PATCH 56/62] Issue #2418: Fix PHISH parameter name case issues discovered in test. Former-commit-id: 11790804341fc0a96ec7d5e30167d3bc067689dd [formerly c0065ec2a96d9e2597824d8e92f3342d20422551] [formerly 5401124a1fb2ec83a06971460ec4fa244455cb5c [formerly a33e5eb63fe0ad7b9d79e878a9877500065a05a8]] Former-commit-id: 5401124a1fb2ec83a06971460ec4fa244455cb5c Former-commit-id: cc9f2dcd277434ccf40fccb62e6507d1bd9eeb11 --- .../base/parameter/alias/gfeParamName.xml | 2 + .../base/grid/parameterInfo/PHISH.xml | 52 +++++++++---------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/parameter/alias/gfeParamName.xml b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/parameter/alias/gfeParamName.xml index 45191dd1d7..7597df9015 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/parameter/alias/gfeParamName.xml +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/common_static/base/parameter/alias/gfeParamName.xml @@ -308,6 +308,8 @@ <alias base="tp6c8">tp6c8</alias> <alias base="TP6mean">tpmean6</alias> <alias base="TP6sprd">tpsprd6</alias> + <alias base="PSurge0ftRun">PSurge0Ft</alias> + <alias base="PSurge1ftRun">PSurge1Ft</alias> <alias base="PSurge4ftRun">PSurge4Ft</alias> <alias base="PSurge5ftRun">PSurge5Ft</alias> <alias base="PSurge6ftRun">PSurge6Ft</alias> diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/grid/parameterInfo/PHISH.xml b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/grid/parameterInfo/PHISH.xml index 76cdbdf07d..1e8de1ba1f 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/grid/parameterInfo/PHISH.xml +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/utility/edex_static/base/grid/parameterInfo/PHISH.xml @@ -19,7 +19,7 @@ <fcst>280800</fcst> </valtimeMINUSreftime> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>Surge10pct</short_name> + <short_name>Surge10Pct</short_name> <long_name>10% Exceedance Height</long_name> <units>feet</units> <udunits>feet</udunits> @@ -34,7 +34,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>Surge20pct</short_name> + <short_name>Surge20Pct</short_name> <long_name>20% Exceedance Height</long_name> <units>feet</units> <udunits>feet</udunits> @@ -49,7 +49,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>Surge30pct</short_name> + <short_name>Surge30Pct</short_name> <long_name>30% Exceedance Height</long_name> <units>feet</units> <udunits>feet</udunits> @@ -64,7 +64,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>Surge40pct</short_name> + <short_name>Surge40Pct</short_name> <long_name>40% Exceedance Height</long_name> <units>feet</units> <udunits>feet</udunits> @@ -79,7 +79,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>Surge50pct</short_name> + <short_name>Surge50Pct</short_name> <long_name>50% Exceedance Height</long_name> <units>feet</units> <udunits>feet</udunits> @@ -94,7 +94,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge0ft</short_name> + <short_name>PSurge0Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 0 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -109,7 +109,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge1ft</short_name> + <short_name>PSurge1Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 1 foot</long_name> <units>%</units> <udunits>percent</udunits> @@ -124,7 +124,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge2ft</short_name> + <short_name>PSurge2Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 2 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -139,7 +139,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge3ft</short_name> + <short_name>PSurge3Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 3 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -154,7 +154,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge4ft</short_name> + <short_name>PSurge4Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 4 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -169,7 +169,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge5ft</short_name> + <short_name>PSurge5Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 5 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -184,7 +184,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge6ft</short_name> + <short_name>PSurge6Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 6 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -199,7 +199,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge7ft</short_name> + <short_name>PSurge7Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 7 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -214,7 +214,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge8ft</short_name> + <short_name>PSurge8Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 8 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -229,7 +229,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge9ft</short_name> + <short_name>PSurge9Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 9 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -244,7 +244,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge10ft</short_name> + <short_name>PSurge10Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 10 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -259,7 +259,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge11ft</short_name> + <short_name>PSurge11Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 11 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -274,7 +274,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge12ft</short_name> + <short_name>PSurge12Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 12 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -289,7 +289,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge13ft</short_name> + <short_name>PSurge13Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 13 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -304,7 +304,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge14ft</short_name> + <short_name>PSurge14Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 14 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -319,7 +319,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge15ft</short_name> + <short_name>PSurge15Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 15 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -334,7 +334,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge16ft</short_name> + <short_name>PSurge16Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 16 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -349,7 +349,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge17ft</short_name> + <short_name>PSurge17Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 17 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -364,7 +364,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge18ft</short_name> + <short_name>PSurge18Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 18 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -379,7 +379,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge19ft</short_name> + <short_name>PSurge19Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 19 feet</long_name> <units>%</units> <udunits>percent</udunits> @@ -394,7 +394,7 @@ </levels> </gridParameterInfo> <gridParameterInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="parameterInfo"> - <short_name>PSurge20ft</short_name> + <short_name>PSurge20Ft</short_name> <long_name>Prob of Hurricane Storm Surge &gt; 20 feet</long_name> <units>%</units> <udunits>percent</udunits> From 0048ef6a9694933220620000dbcbaecbab215ba2 Mon Sep 17 00:00:00 2001 From: Ron Anderson <ron.anderson@raytheon.com> Date: Mon, 20 Jan 2014 17:22:26 -0600 Subject: [PATCH 57/62] Issue #2717 Force use of legacy merge sort Change-Id: Ic37aa4af53f18cc1cbe9bd23420cb692dfa300d7 Former-commit-id: 34d1b95a79e9dc77633217bbbfaa21039e37d973 [formerly de97ec032fe99ea00991b87ede1e94b9004d3848] [formerly 66bbc997849bdd843c4e36de1d1b7de5e519d6a5 [formerly df2af35f3c54b30915cdb6ccebaa30c0e05c7725]] Former-commit-id: 66bbc997849bdd843c4e36de1d1b7de5e519d6a5 Former-commit-id: 61d8aec23c0545cf0f5750f7b973e254f82c4a05 --- cave/com.raytheon.viz.product.awips/awips.product | 3 ++- edexOsgi/build.edex/esb/conf/wrapper.conf | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/cave/com.raytheon.viz.product.awips/awips.product b/cave/com.raytheon.viz.product.awips/awips.product index 4c76cd21a1..39924ee234 100644 --- a/cave/com.raytheon.viz.product.awips/awips.product +++ b/cave/com.raytheon.viz.product.awips/awips.product @@ -30,7 +30,8 @@ -XX:OnOutOfMemoryError=&quot;capture -t no -p $pid &amp;&quot; -Dlogback.configurationFile=logback-viz-core.xml -Dlogback.statusListenerClass=com.raytheon.uf.common.status.logback.UFLogbackInternalStatusListener --Dthrift.stream.maxsize=200</vmArgs> +-Dthrift.stream.maxsize=200 +-Djava.util.Arrays.useLegacyMergeSort=true</vmArgs> <vmArgsLin>-Xmx1280M</vmArgsLin> <vmArgsWin>-Dfile.encoding=UTF-8 -Xmx768M</vmArgsWin> </launcherArgs> diff --git a/edexOsgi/build.edex/esb/conf/wrapper.conf b/edexOsgi/build.edex/esb/conf/wrapper.conf index 4fd3dc3e13..7d96702b5a 100644 --- a/edexOsgi/build.edex/esb/conf/wrapper.conf +++ b/edexOsgi/build.edex/esb/conf/wrapper.conf @@ -93,6 +93,9 @@ wrapper.java.additional.4=-Dorg.apache.camel.jmx.disabled=true # Enforces GMT to be used as the timezone wrapper.java.additional.5=-Duser.timezone=GMT +# Force Java 7 to use earlier sort algorithm +wrapper.java.additional.6=-Djava.util.Arrays.useLegacyMergeSort=true + # garbage collection settings wrapper.java.additional.gc.1=-XX:+UseConcMarkSweepGC wrapper.java.additional.gc.2=-XX:+CMSIncrementalMode From dad11aca887c8b2cadeb58deb895d8348cab6031 Mon Sep 17 00:00:00 2001 From: Lee Venable <Lee_R_Venable@raytheon.com> Date: Mon, 20 Jan 2014 17:24:38 -0600 Subject: [PATCH 58/62] Issue #2291 - Fixed resizing of components. Former-commit-id: 39e8124ef7b454d470d88ba00244c1da05596a68 [formerly 1927ba49ea292fa8a118d0b309ffc1e40e0b9f45] [formerly d3eb6c16ec93fce9ed851b09e8df3a48fba70c2a [formerly 9956936125611cd67aaaf6ba6e617e01b004a738]] Former-commit-id: d3eb6c16ec93fce9ed851b09e8df3a48fba70c2a Former-commit-id: b8520d1e12616f8cb5541349e9ca0508873424be --- .../uf/viz/datadelivery/utils/TextMessageDlg.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/utils/TextMessageDlg.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/utils/TextMessageDlg.java index 3ba0b13cc6..182c3d119d 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/utils/TextMessageDlg.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/utils/TextMessageDlg.java @@ -21,7 +21,8 @@ import com.raytheon.viz.ui.dialogs.CaveSWTDialog; * * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- - * Nov 7, 2013 skorolev Initial creation + * Nov 7, 2013 skorolev Initial creation + * Jan 20, 2013 #2291 lvenable Fixed resizing of components. * * </pre> * @@ -41,23 +42,26 @@ public class TextMessageDlg extends CaveSWTDialog { @Override protected void initializeComponents(Shell shell) { - GridData gd = new GridData(SWT.FILL, SWT.DEFAULT, false, false); + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); GridLayout gl = new GridLayout(1, false); Composite mainComp = new Composite(shell, SWT.NONE); mainComp.setLayout(gl); mainComp.setLayoutData(gd); - gd = new GridData(); - gd.widthHint = 350; + gd = new GridData(SWT.FILL, SWT.FILL, true, true); + gd.widthHint = 400; gd.heightHint = 350; StyledText text = new StyledText(mainComp, SWT.MULTI | SWT.WRAP | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); text.setLayoutData(gd); text.setText(messageText); + gd = new GridData(SWT.CENTER, SWT.DEFAULT, true, false); + gd.widthHint = 60; Button okBtn = new Button(mainComp, SWT.PUSH); okBtn.setText("OK"); - okBtn.setLayoutData(new GridData(SWT.CENTER, SWT.DEFAULT, true, true)); + okBtn.setLayoutData(gd); + okBtn.setLayoutData(gd); okBtn.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -65,5 +69,4 @@ public class TextMessageDlg extends CaveSWTDialog { } }); } - } From 02d357c803cb59965ac9a16c9075377e9d6518ca Mon Sep 17 00:00:00 2001 From: Dave Hladky <david_j_hladky@raytheon.com> Date: Mon, 20 Jan 2014 16:48:58 -0600 Subject: [PATCH 59/62] Issue #2398 Fixed scheduling outside of active period/ expired window Change-Id: I6a07a597e84351d02cb1a0da29f796d86af28107 Former-commit-id: 470ce5269ee9f82a159e2fd24d24e5959ce06540 [formerly ae45dee8614b4bc1d17079a45865f6a3a227b57e] [formerly dfc0d6d9f5f8313c8f8b9fb2c45cfa3bcb21b5ba [formerly d5e3fdf7bd51177d24312d9daa6af7a2a4920f06]] Former-commit-id: dfc0d6d9f5f8313c8f8b9fb2c45cfa3bcb21b5ba Former-commit-id: 986e0d7dbebd95bf59cf083f76ed228551c10d2b --- .../registry/RecurringSubscription.java | 27 +++++++++ .../bandwidth/EdexBandwidthManager.java | 56 ++++++++++++------- 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java index 62e2fb2dfb..5283c360fd 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/RecurringSubscription.java @@ -65,6 +65,7 @@ import com.raytheon.uf.common.time.util.TimeUtil; * Nov 14, 2013 2548 mpduff Add a subscription type slot. * Jan 08, 2014 2615 bgonzale Implement calculate start and calculate end methods. * Jan 14, 2014 2459 mpduff Add subscription state. + * Jan 20, 2013 2398 dhladky Fixed rescheduling beyond active period/expired window. * * </pre> * @@ -897,6 +898,19 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> return expired; } + + /** + * Check for expiration on date + * @param date + * @return + */ + private boolean isExpired(Date date) { + boolean expired = false; + if (subscriptionEnd != null && date.after(subscriptionEnd)) { + expired = true; + } + return expired; + } /** * Get the current subscription status. @@ -935,6 +949,19 @@ public abstract class RecurringSubscription<T extends Time, C extends Coverage> return subscriptionState == SubscriptionState.ON && !checkAndSetExpiration(); } + + /** + * Should this be scheduled for this time. + * @param checkDate + * @return + */ + public boolean shouldScheduleForTime(Date checkDate) { + if (!isExpired(checkDate) && inWindow(checkDate)) { + return true; + } + + return false; + } private boolean inWindow(Date checkDate) { if (activePeriodStart == null && activePeriodEnd == null) { diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java index 3d28404308..c2f6bca0ef 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/src/com/raytheon/uf/edex/datadelivery/bandwidth/EdexBandwidthManager.java @@ -49,6 +49,7 @@ import com.raytheon.uf.common.datadelivery.registry.DataSetMetaData; import com.raytheon.uf.common.datadelivery.registry.GriddedDataSetMetaData; import com.raytheon.uf.common.datadelivery.registry.PointDataSetMetaData; import com.raytheon.uf.common.datadelivery.registry.PointTime; +import com.raytheon.uf.common.datadelivery.registry.RecurringSubscription; import com.raytheon.uf.common.datadelivery.registry.SiteSubscription; import com.raytheon.uf.common.datadelivery.registry.Subscription; import com.raytheon.uf.common.datadelivery.registry.Time; @@ -112,7 +113,8 @@ import com.raytheon.uf.edex.datadelivery.bandwidth.util.BandwidthUtil; * notifications. Republish dataset metadata registry * insert and update events as dataset metadata events. * Jan 13, 2014 2679 dhladky Small Point data updates. - * Jan 14, 2014 2692 dhladky AdhocSubscription handler + * Jan 14, 2014 2692 dhladky AdhocSubscription handler + * Jan 20, 2013 2398 dhladky Fixed rescheduling beyond active period/expired window. * * </pre> * @@ -306,28 +308,40 @@ public abstract class EdexBandwidthManager<T extends Time, C extends Coverage> for (int day = 1; day <= days; day++) { next.add(Calendar.DAY_OF_YEAR, 1); - // Since subscriptions are based on cycles in a day, add one day - // to the - // completed BandwidthSubscription to get the next days - // retrieval. - // Now check if that BandwidthSubscription has already been - // scheduled. - BandwidthSubscription a = bandwidthDao - .getBandwidthSubscription(dao.getRegistryId(), next); - if (a == null) { - // Create the new BandwidthSubscription record with the next - // time.. - a = bandwidthDao.newBandwidthSubscription(subscription, - next); + // TODO Check if we need to set sub to "OFF" state and save to + // registry + if (((RecurringSubscription<T, C>) subscription) + .shouldScheduleForTime(next.getTime())) { - schedule(subscription, a); - } else { - statusHandler - .info("Subscription [" - + subscription.getName() - + "] has already been scheduled for baseReferenceTime [" - + BandwidthUtil.format(next) + "]"); + // Since subscriptions are based on cycles in a day, add + // one + // day + // to the + // completed BandwidthSubscription to get the next days + // retrieval. + + // Now check if that BandwidthSubscription has already + // been + // scheduled. + BandwidthSubscription a = bandwidthDao + .getBandwidthSubscription(dao.getRegistryId(), next); + if (a == null) { + // Create the new BandwidthSubscription record with + // the + // next + // time.. + a = bandwidthDao.newBandwidthSubscription(subscription, + next); + + schedule(subscription, a); + } else { + statusHandler + .info("Subscription [" + + subscription.getName() + + "] has already been scheduled for baseReferenceTime [" + + BandwidthUtil.format(next) + "]"); + } } } } From e929abf7d74629298dd79f6a0e541982ed1a7757 Mon Sep 17 00:00:00 2001 From: Mike Duff <michael.duff@raytheon.com> Date: Mon, 20 Jan 2014 16:52:00 -0600 Subject: [PATCH 60/62] Issue #2538 - Add AdhocSubscripionHander to SubscriptionHandler. Fix problem querying for adhoc subs. Former-commit-id: 9bd8e84b9f6eb6a7ba346b1ba98ee0d1b88831ac [formerly bdf6a002f6b1efa876f06ecb0a8fa4930e7a888f] [formerly 9a2d2af4a9e93476b743c6c389d67a199431911e [formerly 5fc6b9fcc55b6e93c9837c7b99347df8f28fc90a]] Former-commit-id: 9a2d2af4a9e93476b743c6c389d67a199431911e Former-commit-id: 9112366cae5d3b8b469c96b5ba8c761bc84bf06f --- .../res/spring/datadelivery-handlers.xml | 6 + .../handlers/VizSubscriptionHandler.java | 49 ++++- .../subscription/subset/SubsetManagerDlg.java | 10 +- .../EmptyAdhocSubscriptionHandler.java | 175 ++++++++++++++++++ .../handlers/SubscriptionHandler.java | 28 ++- .../registry/ebxml/StringAttribute.java | 50 +++-- .../bandwidth-datadelivery-edex-impl-ncf.xml | 6 + .../bandwidth-datadelivery-edex-impl-wfo.xml | 5 + .../res/spring/datadelivery-handlers-impl.xml | 6 + 9 files changed, 309 insertions(+), 26 deletions(-) create mode 100644 edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/EmptyAdhocSubscriptionHandler.java diff --git a/cave/com.raytheon.uf.viz.datadelivery/res/spring/datadelivery-handlers.xml b/cave/com.raytheon.uf.viz.datadelivery/res/spring/datadelivery-handlers.xml index 8438f4d560..2305aa664a 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/res/spring/datadelivery-handlers.xml +++ b/cave/com.raytheon.uf.viz.datadelivery/res/spring/datadelivery-handlers.xml @@ -18,6 +18,12 @@ <property name="registryHandler" ref="registryHandler" /> </bean> </constructor-arg> + <constructor-arg> + <bean + class="com.raytheon.uf.common.datadelivery.registry.handlers.AdhocSubscriptionHandler"> + <property name="registryHandler" ref="registryHandler" /> + </bean> + </constructor-arg> </bean> <bean name="PendingSubscriptionHandler" diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/handlers/VizSubscriptionHandler.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/handlers/VizSubscriptionHandler.java index f9284e7be4..8b504ac47c 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/handlers/VizSubscriptionHandler.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/handlers/VizSubscriptionHandler.java @@ -21,7 +21,11 @@ package com.raytheon.uf.viz.datadelivery.handlers; import java.util.List; +import com.raytheon.uf.common.datadelivery.registry.AdhocSubscription; +import com.raytheon.uf.common.datadelivery.registry.SharedSubscription; +import com.raytheon.uf.common.datadelivery.registry.SiteSubscription; import com.raytheon.uf.common.datadelivery.registry.SubscriptionDeleteRequest; +import com.raytheon.uf.common.datadelivery.registry.handlers.IAdhocSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISharedSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISiteSubscriptionHandler; import com.raytheon.uf.common.datadelivery.registry.handlers.ISubscriptionHandler; @@ -46,6 +50,7 @@ import com.raytheon.uf.common.serialization.comm.RequestRouter; * Mar 29, 2013 1841 djohnson Composes a userSubscriptionsHandler. * Apr 05, 2013 1841 djohnson Add shared subscription support. * May 21, 2013 2020 mpduff Rename UserSubscription to SiteSubscription. + * Jan 20, 2014 2538 mpduff Added the doesNameExist method. * * </pre> * @@ -62,8 +67,10 @@ public class VizSubscriptionHandler extends SubscriptionHandler { */ public VizSubscriptionHandler( ISiteSubscriptionHandler siteSubscriptionHandler, - ISharedSubscriptionHandler sharedSubscriptionHandler) { - super(siteSubscriptionHandler, sharedSubscriptionHandler); + ISharedSubscriptionHandler sharedSubscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler) { + super(siteSubscriptionHandler, sharedSubscriptionHandler, + adhocSubscriptionHandler); } /** @@ -72,7 +79,7 @@ public class VizSubscriptionHandler extends SubscriptionHandler { @Override public void deleteByIds(String username, List<String> ids) throws RegistryHandlerException { - + SubscriptionDeleteRequest request = new SubscriptionDeleteRequest(ids, ISubscriptionHandler.class, username); @@ -85,4 +92,40 @@ public class VizSubscriptionHandler extends SubscriptionHandler { } } + /** + * Does the name exist for the provided type of subscription? + * + * @param name + * The subscription name to check + * @param clazzes + * List of subscription types + * @return true if the name exists for any of the provided types + * @throws RegistryHandlerException + */ + public boolean doesNameExist(String name, Class... clazzes) + throws RegistryHandlerException { + boolean found = false; + + for (Class<?> clazz : clazzes) { + if (found) { + return true; + } + if (clazz == SiteSubscription.class) { + found = getSiteSubscriptionHandler().getByName(name) != null; + continue; + } + + if (!found && clazz == SharedSubscription.class) { + found = getSharedSubscriptionHandler().getByName(name) != null; + continue; + } + + if (!found && clazz == AdhocSubscription.class) { + found = getAdhocSubscriptionHandler().getByName(name) != null; + continue; + } + } + + return found; + } } diff --git a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/subset/SubsetManagerDlg.java b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/subset/SubsetManagerDlg.java index b0d8986d29..a228cf51cd 100644 --- a/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/subset/SubsetManagerDlg.java +++ b/cave/com.raytheon.uf.viz.datadelivery/src/com/raytheon/uf/viz/datadelivery/subscription/subset/SubsetManagerDlg.java @@ -51,6 +51,7 @@ import com.raytheon.uf.common.datadelivery.registry.DataType; import com.raytheon.uf.common.datadelivery.registry.GriddedDataSet; import com.raytheon.uf.common.datadelivery.registry.Network; import com.raytheon.uf.common.datadelivery.registry.PointDataSet; +import com.raytheon.uf.common.datadelivery.registry.SharedSubscription; import com.raytheon.uf.common.datadelivery.registry.SiteSubscription; import com.raytheon.uf.common.datadelivery.registry.Subscription; import com.raytheon.uf.common.datadelivery.registry.Subscription.SubscriptionType; @@ -68,6 +69,7 @@ import com.raytheon.uf.viz.core.VizAppTaskExecutor; import com.raytheon.uf.viz.core.localization.LocalizationManager; import com.raytheon.uf.viz.datadelivery.common.xml.AreaXML; import com.raytheon.uf.viz.datadelivery.filter.MetaDataManager; +import com.raytheon.uf.viz.datadelivery.handlers.VizSubscriptionHandler; import com.raytheon.uf.viz.datadelivery.services.DataDeliveryServices; import com.raytheon.uf.viz.datadelivery.subscription.CreateSubscriptionDlg; import com.raytheon.uf.viz.datadelivery.subscription.ISubscriptionService; @@ -139,6 +141,7 @@ import com.raytheon.viz.ui.presenter.IDisplay; * Nov 14, 2013 2538 mpduff Added check for duplicate subscription. * Nov 14, 2013 2548 mpduff Set the subscription type (QUERY OR RECURRING) * Jan 14, 2014 2459 mpduff Change Subscription status code + * Jan 20, 2014 2538 mpduff Call doesNameExist method to check for dupes * </pre> * * @author mpduff @@ -505,10 +508,13 @@ public abstract class SubsetManagerDlg extends CaveSWTDialog implements if (valid) { // Check for existing subscription - ISubscriptionHandler handler = RegistryObjectHandlers + VizSubscriptionHandler handler = (VizSubscriptionHandler) RegistryObjectHandlers .get(ISubscriptionHandler.class); + String name = nameText.getText(); + try { - if (handler.getByName(nameText.getText()) != null) { + if (handler.doesNameExist(name, SiteSubscription.class, + SharedSubscription.class, AdhocSubscription.class)) { String message = "A query with this name already exists.\n\nPlease enter a different query name."; DataDeliveryUtils.showMessage(getShell(), SWT.ERROR, "Duplicate Query Name", message); diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/EmptyAdhocSubscriptionHandler.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/EmptyAdhocSubscriptionHandler.java new file mode 100644 index 0000000000..615567fa90 --- /dev/null +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/EmptyAdhocSubscriptionHandler.java @@ -0,0 +1,175 @@ +/** + * 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.registry.handlers; + +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import com.raytheon.uf.common.datadelivery.registry.AdhocSubscription; +import com.raytheon.uf.common.datadelivery.registry.Network; +import com.raytheon.uf.common.registry.handler.RegistryHandlerException; + +/** + * Empty implementation for adhoc subscriptions. + * + * <pre> + * + * SOFTWARE HISTORY + * + * Date Ticket# Engineer Description + * ------------ ---------- ----------- -------------------------- + * Jan 20, 2014 2538 mpduff Initial creation + * + * </pre> + * + * @author mpduff + * @version 1.0 + */ + +public class EmptyAdhocSubscriptionHandler implements IAdhocSubscriptionHandler { + + @Override + public AdhocSubscription getByName(String name) + throws RegistryHandlerException { + // TODO Auto-generated method stub + return null; + } + + @Override + public List<AdhocSubscription> getByNames(Collection<String> names) + throws RegistryHandlerException { + // TODO Auto-generated method stub + return null; + } + + @Override + public List<AdhocSubscription> getByOwner(String owner) + throws RegistryHandlerException { + // TODO Auto-generated method stub + return null; + } + + @Override + public List<AdhocSubscription> getByGroupName(String group) + throws RegistryHandlerException { + // TODO Auto-generated method stub + return null; + } + + @Override + public List<AdhocSubscription> getByFilters(String group, String officeId) + throws RegistryHandlerException { + // TODO Auto-generated method stub + return null; + } + + @Override + public Set<String> getSubscribedToDataSetNames(String siteId) + throws RegistryHandlerException { + // TODO Auto-generated method stub + return null; + } + + @Override + public List<AdhocSubscription> getActive() throws RegistryHandlerException { + // TODO Auto-generated method stub + return null; + } + + @Override + public List<AdhocSubscription> getActiveForRoute(Network route) + throws RegistryHandlerException { + // TODO Auto-generated method stub + return null; + } + + @Override + public List<AdhocSubscription> getActiveForRoutes(Network... routes) + throws RegistryHandlerException { + // TODO Auto-generated method stub + return null; + } + + @Override + public AdhocSubscription getById(String id) throws RegistryHandlerException { + // TODO Auto-generated method stub + return null; + } + + @Override + public List<AdhocSubscription> getAll() throws RegistryHandlerException { + // TODO Auto-generated method stub + return null; + } + + @Override + public void store(AdhocSubscription obj) throws RegistryHandlerException { + // TODO Auto-generated method stub + + } + + @Override + public void update(AdhocSubscription obj) throws RegistryHandlerException { + // TODO Auto-generated method stub + + } + + @Override + public void delete(AdhocSubscription obj) throws RegistryHandlerException { + // TODO Auto-generated method stub + + } + + @Override + public void deleteById(String username, String registryId) + throws RegistryHandlerException { + // TODO Auto-generated method stub + + } + + @Override + public void deleteByIds(String username, List<String> registryIds) + throws RegistryHandlerException { + // TODO Auto-generated method stub + + } + + @Override + public void delete(String username, AdhocSubscription obj) + throws RegistryHandlerException { + // TODO Auto-generated method stub + + } + + @Override + public void delete(Collection<AdhocSubscription> objects) + throws RegistryHandlerException { + // TODO Auto-generated method stub + + } + + @Override + public void delete(String username, Collection<AdhocSubscription> objects) + throws RegistryHandlerException { + // TODO Auto-generated method stub + + } +} diff --git a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/SubscriptionHandler.java b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/SubscriptionHandler.java index 4e8edc2642..9329495aab 100644 --- a/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/SubscriptionHandler.java +++ b/edexOsgi/com.raytheon.uf.common.datadelivery.registry/src/com/raytheon/uf/common/datadelivery/registry/handlers/SubscriptionHandler.java @@ -58,6 +58,7 @@ import com.raytheon.uf.common.util.CollectionUtil; * May 29, 2013 1650 djohnson Fix ability to delete multiple types of subscriptions at once. * May 31, 2013 1650 djohnson Fix ability to get shared subscriptions by id. * Sep 11, 2013 2352 mpduff Add siteId to getSubscribedToDataSetNames method. + * Jan 20, 2014 2538 mpduff Added AdhocSubscriptionHandler. * * </pre> * @@ -73,6 +74,8 @@ public class SubscriptionHandler implements ISubscriptionHandler { private final ISharedSubscriptionHandler sharedSubscriptionHandler; + private final IAdhocSubscriptionHandler adhocSubscriptionHandler; + /** * Constructor. * @@ -83,9 +86,11 @@ public class SubscriptionHandler implements ISubscriptionHandler { */ public SubscriptionHandler( ISiteSubscriptionHandler siteSubscriptionHandler, - ISharedSubscriptionHandler sharedSubscriptionHandler) { + ISharedSubscriptionHandler sharedSubscriptionHandler, + IAdhocSubscriptionHandler adhocSubscriptionHandler) { this.siteSubscriptionHandler = siteSubscriptionHandler; this.sharedSubscriptionHandler = sharedSubscriptionHandler; + this.adhocSubscriptionHandler = adhocSubscriptionHandler; } /** @@ -421,4 +426,25 @@ public class SubscriptionHandler implements ISubscriptionHandler { } } } + + /** + * @return the siteSubscriptionHandler + */ + public ISiteSubscriptionHandler getSiteSubscriptionHandler() { + return siteSubscriptionHandler; + } + + /** + * @return the sharedSubscriptionHandler + */ + public ISharedSubscriptionHandler getSharedSubscriptionHandler() { + return sharedSubscriptionHandler; + } + + /** + * @return the adhocSubscriptionHandler + */ + public IAdhocSubscriptionHandler getAdhocSubscriptionHandler() { + return adhocSubscriptionHandler; + } } diff --git a/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/ebxml/StringAttribute.java b/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/ebxml/StringAttribute.java index 7b2edc72d3..73ad70cfb1 100644 --- a/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/ebxml/StringAttribute.java +++ b/edexOsgi/com.raytheon.uf.common.registry.ebxml/src/com/raytheon/uf/common/registry/ebxml/StringAttribute.java @@ -17,6 +17,7 @@ import com.raytheon.uf.common.serialization.annotations.DynamicSerialize; * ------------ ---------- ----------- -------------------------- * Mar 28, 2012 jspinks Initial creation * Jun 21, 2012 736 djohnson Add thrift serialization annotations. + * Jan 20, 2014 2538 mpduff Override toString * * </pre> * @@ -36,7 +37,7 @@ public class StringAttribute extends QueryableAttribute<String> { * Create an StringAttribute with an 'in list' relation. * * @param values - * The values to query for. + * The values to query for. */ public StringAttribute(List<String> values) { super(values); @@ -46,53 +47,53 @@ public class StringAttribute extends QueryableAttribute<String> { * Create a StringAttribute with an equals relation. * * @param value - * The value to query for. + * The value to query for. */ public StringAttribute(String value) { super(value); } - + /** * Create a StringAttribute with a 'like' relation. * * @param value - * The value to query for. - * + * The value to query for. + * * @param isLike - * Specify whether or not comparison should be like. + * Specify whether or not comparison should be like. */ public StringAttribute(String value, boolean isLike) { super(value, isLike); } /** - * Return the formatted text of this StringAttribute including - * the processing of a List and like values. + * Return the formatted text of this StringAttribute including the + * processing of a List and like values. * * @return The formatted value for this StringAttribute. */ @Override public String getQueryValue() { if (this.like) { - return "'%"+this.value+"%'"; - } - else if (this.values != null) { - StringBuilder sb = new StringBuilder(); - for (String t : this.values) { - sb.append("'"+t+"',"); + return "'%" + this.value + "%'"; + } else if (this.values != null) { + StringBuilder sb = new StringBuilder(); + for (String t : this.values) { + sb.append("'" + t + "',"); } String items = sb.toString(); - return items.substring(0,items.length()-1); + return items.substring(0, items.length() - 1); } else { - return "'"+this.value+"'"; + return "'" + this.value + "'"; } - } + } /** - * Return the type of slot used to contain the value. For - * StringAttribute that is "stringValue". + * Return the type of slot used to contain the value. For StringAttribute + * that is "stringValue". * - * @return The type of value attribute the slot for this StringAttribute contains. + * @return The type of value attribute the slot for this StringAttribute + * contains. * * @see StringValueType */ @@ -101,4 +102,13 @@ public class StringAttribute extends QueryableAttribute<String> { return "stringValue"; } + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return this.value; + } } diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/res/spring/bandwidth-datadelivery-edex-impl-ncf.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/res/spring/bandwidth-datadelivery-edex-impl-ncf.xml index 3a4059d6a9..ff7f87b06b 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/res/spring/bandwidth-datadelivery-edex-impl-ncf.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth.ncf/res/spring/bandwidth-datadelivery-edex-impl-ncf.xml @@ -19,6 +19,12 @@ <property name="registryHandler" ref="registryHandler" /> </bean> </constructor-arg> + <constructor-arg> + <bean + class="com.raytheon.uf.common.datadelivery.registry.handlers.EmptyAdhocSubscriptionHandler"> + <property name="registryHandler" ref="registryHandler" /> + </bean> + </constructor-arg> </bean> <util:list id="subscriptionRoutesToSchedule"> diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml index 567a3a5471..44094ada6b 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.bandwidth/res/spring/bandwidth-datadelivery-edex-impl-wfo.xml @@ -19,6 +19,11 @@ class="com.raytheon.uf.common.datadelivery.registry.handlers.EmptySharedSubscriptionHandler"> </bean> </constructor-arg> + <constructor-arg> + <bean + class="com.raytheon.uf.common.datadelivery.registry.handlers.EmptyAdhocSubscriptionHandler"> + </bean> + </constructor-arg> </bean> <util:list id="subscriptionRoutesToSchedule"> diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.service/res/spring/datadelivery-handlers-impl.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.service/res/spring/datadelivery-handlers-impl.xml index 30332c4efd..4a1f07d57b 100644 --- a/edexOsgi/com.raytheon.uf.edex.datadelivery.service/res/spring/datadelivery-handlers-impl.xml +++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.service/res/spring/datadelivery-handlers-impl.xml @@ -19,6 +19,12 @@ <property name="registryHandler" ref="registryHandler" /> </bean> </constructor-arg> + <constructor-arg> + <bean + class="com.raytheon.uf.common.datadelivery.registry.handlers.AdhocSubscriptionHandler"> + <property name="registryHandler" ref="registryHandler" /> + </bean> + </constructor-arg> </bean> <bean name="PendingSubscriptionHandler" From 1e35ce4acb46f1279a7d4b93b3e17b59d09b4476 Mon Sep 17 00:00:00 2001 From: Nate Jensen <Nathan.Jensen@raytheon.com> Date: Tue, 21 Jan 2014 09:06:22 -0600 Subject: [PATCH 61/62] Issue #2359 if satellite decode exception occurs, don't store half record Change-Id: Ia6cbf2513d3d3ec8f4c0a38b90ab5a8d30474ad8 Former-commit-id: aa70dfec918ef119230dfb169c7d5fc455af4d89 [formerly 0a72df52a60b96275124fa26b7d98ab80c98dee4] [formerly 79d94e87cf26eca4e85450f54eec3786b0fee39b [formerly 2cfa53b34097e0f1745fa2af85c30d1bb351eea0]] Former-commit-id: 79d94e87cf26eca4e85450f54eec3786b0fee39b Former-commit-id: 70d980543490ced29a6a6dd0f8808f1df5852963 --- .../com/raytheon/edex/plugin/satellite/SatelliteDecoder.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/plugin/satellite/SatelliteDecoder.java b/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/plugin/satellite/SatelliteDecoder.java index b2013cb29c..812167c011 100644 --- a/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/plugin/satellite/SatelliteDecoder.java +++ b/edexOsgi/com.raytheon.edex.plugin.satellite/src/com/raytheon/edex/plugin/satellite/SatelliteDecoder.java @@ -460,8 +460,9 @@ public class SatelliteDecoder { } timer.stop(); perfLog.logDuration("Time to Decode", timer.getElapsedTime()); - } catch (Exception e) { + } catch (Throwable e) { statusHandler.error("Error decoding satellite", e); + record = null; } finally { try { f.close(); From ee5fce8be6555b06182abc7578f0b2b39663498b Mon Sep 17 00:00:00 2001 From: Richard Peter <richard.peter@raytheon.com> Date: Tue, 21 Jan 2014 11:18:06 -0600 Subject: [PATCH 62/62] Issue #2724: Fix Airep/Pirep Autoboxing NPE Change-Id: Ieb2823dc220daf4d77a071ba8baaf3831957bd38 Former-commit-id: d831e8c692addaf8babaceada4550903e38be369 [formerly c6206fd6a87d0dfd817b850bb50720db0b1d0dc2] [formerly 57f60968331677a4ce7b7cd86df1d1b70d200f82 [formerly cbdaaf4d6e28d7001df205ffb7d8d2d56bacd35f]] Former-commit-id: 57f60968331677a4ce7b7cd86df1d1b70d200f82 Former-commit-id: d372cf80f9aef4644f1da7bbc96552257543916c --- .../ncep/common/dataplugin/airep/AirepRecord.java | 15 +++++++++------ .../ncep/common/dataplugin/pirep/PirepRecord.java | 15 +++++++++------ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.airep/src/gov/noaa/nws/ncep/common/dataplugin/airep/AirepRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.airep/src/gov/noaa/nws/ncep/common/dataplugin/airep/AirepRecord.java index f09569e5e0..27b3979b78 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.airep/src/gov/noaa/nws/ncep/common/dataplugin/airep/AirepRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.airep/src/gov/noaa/nws/ncep/common/dataplugin/airep/AirepRecord.java @@ -75,6 +75,9 @@ import com.vividsolutions.jts.geom.Geometry; * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * Sep 05, 2013 2316 bsteffen Unify airep and ncairep. * Dec 03, 2013 2551 rjpeter Extend PersistablePluginDataObject + * Jan 21, 2013 2724 rjpeter Update getter/setter to use same Object as + * internal variable to prevent auto unboxing + * NPE on serialization. * </pre> * * @author jkorman @@ -454,7 +457,7 @@ public class AirepRecord extends PersistablePluginDataObject implements /** * @return the temp */ - public float getTemp() { + public Float getTemp() { return temp; } @@ -462,14 +465,14 @@ public class AirepRecord extends PersistablePluginDataObject implements * @param temp * the temp to set */ - public void setTemp(float temp) { + public void setTemp(Float temp) { this.temp = temp; } /** * @return the windDirection */ - public float getWindDirection() { + public Float getWindDirection() { return windDirection; } @@ -477,14 +480,14 @@ public class AirepRecord extends PersistablePluginDataObject implements * @param windDirection * the windDirection to set */ - public void setWindDirection(float windDirection) { + public void setWindDirection(Float windDirection) { this.windDirection = windDirection; } /** * @return the windspeed */ - public float getWindSpeed() { + public Float getWindSpeed() { return windSpeed; } @@ -492,7 +495,7 @@ public class AirepRecord extends PersistablePluginDataObject implements * @param windspeed * the windspeed to set */ - public void setWindSpeed(float windSpeed) { + public void setWindSpeed(Float windSpeed) { this.windSpeed = windSpeed; } diff --git a/ncep/gov.noaa.nws.ncep.common.dataplugin.pirep/src/gov/noaa/nws/ncep/common/dataplugin/pirep/PirepRecord.java b/ncep/gov.noaa.nws.ncep.common.dataplugin.pirep/src/gov/noaa/nws/ncep/common/dataplugin/pirep/PirepRecord.java index cde4508c04..95a1c0285d 100644 --- a/ncep/gov.noaa.nws.ncep.common.dataplugin.pirep/src/gov/noaa/nws/ncep/common/dataplugin/pirep/PirepRecord.java +++ b/ncep/gov.noaa.nws.ncep.common.dataplugin.pirep/src/gov/noaa/nws/ncep/common/dataplugin/pirep/PirepRecord.java @@ -73,6 +73,9 @@ import com.vividsolutions.jts.geom.Geometry; * Aug 30, 2013 2298 rjpeter Make getPluginName abstract * Sep 05, 2013 2316 bsteffen Unify pirep and ncpirep. * Dec 03, 2013 2551 rjpeter Extend PersistablePluginDataObject. + * Jan 21, 2013 2724 rjpeter Update getter/setter to use same Object as + * internal variable to prevent auto unboxing + * NPE on serialization. * </pre> * * @author jkorman @@ -433,7 +436,7 @@ public class PirepRecord extends PersistablePluginDataObject implements * @return the temp */ // public Double getTemp() { - public float getTemp() { + public Float getTemp() { return temp; } @@ -442,7 +445,7 @@ public class PirepRecord extends PersistablePluginDataObject implements * the temp to set */ // public void setTemp(Double temp) { - public void setTemp(float temp) { + public void setTemp(Float temp) { this.temp = temp; } @@ -450,7 +453,7 @@ public class PirepRecord extends PersistablePluginDataObject implements * @return the windDirection */ // public Integer getWindDirection() { - public float getWindDirection() { + public Float getWindDirection() { return windDirection; } @@ -459,7 +462,7 @@ public class PirepRecord extends PersistablePluginDataObject implements * the windDirection to set */ // public void setWindDirection(Integer windDirection) { - public void setWindDirection(float windDirection) { + public void setWindDirection(Float windDirection) { this.windDirection = windDirection; } @@ -467,7 +470,7 @@ public class PirepRecord extends PersistablePluginDataObject implements * @return the windspeed */ // public Double getWindSpeed() { - public float getWindSpeed() { + public Float getWindSpeed() { return windSpeed; } @@ -476,7 +479,7 @@ public class PirepRecord extends PersistablePluginDataObject implements * the windspeed to set */ // public void setWindSpeed(Double windSpeed) { - public void setWindSpeed(float windSpeed) { + public void setWindSpeed(Float windSpeed) { this.windSpeed = windSpeed; }