varClass) throws NetcdfException {
+ try {
+ return NcFactory.createVar(fileId, name, dims, varClass);
+ } catch (Exception e) {
+ throw new NetcdfException("Unable to create variable", e);
+ }
+ }
+
+ /**
+ * End definition stage of file creation and start data writing stage. After
+ * this method is called, return values of
+ * {@link #defineDim(String, int, Class)} and
+ * {@link #defineVar(String, NcDimension[], Class)} can be used to write
+ * data to file.
+ *
+ * @throws NetcdfException
+ */
+ public void endFileDefinition() throws NetcdfException {
+ try {
+ ncfile.endFileDefinition(fileId);
+ } catch (LLNetcdfException e) {
+ throw new NetcdfException(e);
+ }
+ }
+
+ /**
+ * Called after all data has been written to file.
+ *
+ * @throws NetcdfException
+ */
+ public void close() throws NetcdfException {
+ try {
+ ncfile.closeFile(fileId);
+ } catch (LLNetcdfException e) {
+ throw new NetcdfException(e);
+ }
+ }
+
+ /**
+ * @return the ncid
+ */
+ public int getFileId() {
+ return fileId;
+ }
+
+}
diff --git a/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/NetcdfException.java b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/NetcdfException.java
new file mode 100644
index 0000000000..51399e51dc
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/NetcdfException.java
@@ -0,0 +1,84 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.common.nc4;
+
+import edu.mit.ll.netcdf.LLNetcdfException;
+
+/**
+ * Exception used in Netcdf interface
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Mar 5, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public class NetcdfException extends Exception{
+
+ private static final long serialVersionUID = -508018999572379516L;
+
+ protected int errorCode;
+
+ /**
+ *
+ */
+ public NetcdfException(LLNetcdfException llex) {
+ this(llex.getError());
+ }
+
+ public NetcdfException(int errorCode) {
+ super(NcConstants.ERROR_MAP.get(errorCode));
+ }
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public NetcdfException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * @param message
+ */
+ public NetcdfException(String message) {
+ super(message);
+ }
+
+ /**
+ * @param cause
+ */
+ public NetcdfException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * @return the errorCode
+ */
+ public int getErrorCode() {
+ return errorCode;
+ }
+
+ /**
+ * @param errorCode
+ * the errorCode to set
+ */
+ public void setErrorCode(int errorCode) {
+ this.errorCode = errorCode;
+ }
+
+}
diff --git a/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CFConventions.java b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CFConventions.java
new file mode 100644
index 0000000000..446658006a
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CFConventions.java
@@ -0,0 +1,53 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.common.nc4.cf;
+
+/**
+ * CF Conventions as described for NetCDF library 1.6
+ * Place holder for convention descriptions and names
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Apr 29, 2013 ekladstrup Initial creation
+ *
+ *
+ *
+ * @author ekladstrup
+ * @version 1.0
+ */
+
+public enum CFConventions {
+
+ CF16("CF-1.6");
+
+ /**
+ * @param value
+ */
+ private CFConventions(final String value) {
+ this.value = value;
+ }
+
+ private final String value;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Enum#toString()
+ */
+ @Override
+ public String toString() {
+ return value;
+ }
+
+}
diff --git a/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfConstants.java b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfConstants.java
new file mode 100644
index 0000000000..77fb2cf2da
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfConstants.java
@@ -0,0 +1,170 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.common.nc4.cf;
+
+/**
+ * CF Constants as described for NetCDF library 1.6
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Mar 7, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public class CfConstants {
+
+ /**
+ * Global attribute {@link #CONVENTIONS_ATTR} value for version 1.6
+ */
+ public static final String CONVENTIONS1_6 = "CF-1.6";
+
+ /**
+ * Global attribute for conventions version
+ */
+ public static final String CONVENTIONS_ATTR = "Conventions";
+
+ /**
+ * Variable attribute for standard name
+ */
+ public static final String STANDARD_NAME_ATTR = "standard_name";
+
+ /**
+ * Variable attribute for long name
+ */
+ public static final String LONG_NAME_ATTR = "long_name";
+
+ /**
+ * Variable attribute for units
+ */
+ public static final String UNITS_ATTR = "units";
+
+ /**
+ * Variable attribute for cell methods
+ */
+ public static final String CELL_METHODS_ATTR = "cell_methods";
+
+ /**
+ * Dimension attribute for axis label (x, y, z...)
+ */
+ public static final String AXIS_ATTR = "axis";
+
+ /**
+ * Attribute value for {@link #AXIS_ATTR} for x axis
+ */
+ public static final String X_AXIS = "X";
+
+ /**
+ * Attribute value for {@link #AXIS_ATTR} for y axis
+ */
+ public static final String Y_AXIS = "Y";
+
+ /**
+ * Attribute value for {@link #AXIS_ATTR} for vertical axis
+ */
+ public static final String Z_AXIS = "Z";
+
+ /**
+ * Attribute value for {@link #AXIS_ATTR} for time axis
+ */
+ public static final String T_AXIS = "T";
+
+ /**
+ * Variable attribute for missing values
+ */
+ public static final String MISSING_VAL_ATTR = "missing_value";
+
+ /**
+ * {@link #UNITS_ATTR} value for latitude dimension
+ */
+ public static final String LAT_UNITS = "degrees_north";
+
+ /**
+ * {@link #UNITS_ATTR} value for longitude dimension
+ */
+ public static final String LON_UNITS = "degrees_east";
+
+ /**
+ * Vertical dimension attribute to denote which direction is positive
+ */
+ public static final String POS_ATTR = "positive";
+
+ /**
+ * {@link #POS_ATTR} value indicating that up is positive
+ */
+ public static final String UP_POS = "up";
+
+ /**
+ * {@link #POS_ATTR} value indicating that down is positive
+ */
+ public static final String DWN_POS = "down";
+
+ /**
+ * Calendar attribute for Time Dimensions
+ */
+ public static final String CAL_ATTR = "calendar";
+
+ /**
+ * Default value for {@link #CAL_ATTR}
+ */
+ public static final String GREG_CALENDAR = "gregorian";
+
+ /**
+ * {@link #UNITS_ATTR} value for time dimension that uses UNIX time
+ */
+ public static final String UNIX_TIME_UNITS = "seconds since 1970-1-1 0:0:0";
+
+ /**
+ * attribute for coverage id
+ */
+ public static final String COVERAGE_ID_ATTR = "coverage_id";
+
+ /**
+ * Grid mapping name attribute
+ */
+ public static final String GRID_MAP_NAME_ATTR = "grid_mapping_name";
+
+ /**
+ * standard parallel attribute used in grid mapping variable
+ */
+ public static final String STD_PARALLEL_ATTR = "standard_parallel";
+
+ /**
+ * central meridian longitude attribute used in grid mapping variable
+ */
+ public static final String CENTRAL_MERID_LON_ATTR = "longitude_of_central_meridian";
+
+ /**
+ * projection origin latitude attribute used in grid mapping variable
+ */
+ public static final String PROJ_ORIGIN_LAT_ATTR = "latitude_of_projection_origin";
+
+ /**
+ * attribute for list of variables that contain geographic coordinates
+ */
+ public static final String COORDS_ATTR = "coordinates";
+
+ /**
+ * Standard name value for projected x dimension
+ */
+ public static final String X_STD_NAME = "projection_x_coordinate";
+
+ /**
+ * Standard name value for projected y dimension
+ */
+ public static final String Y_STD_NAME = "projection_y_coordinate";
+
+}
diff --git a/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfDimensions.java b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfDimensions.java
new file mode 100644
index 0000000000..f742a7f144
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfDimensions.java
@@ -0,0 +1,95 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.common.nc4.cf;
+
+import java.util.Arrays;
+
+import com.raytheon.uf.common.nc4.NcDimension;
+
+/**
+ * TODO Add Description
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * May 3, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public class CfDimensions {
+
+ private final CfHorizontalDims xyDims;
+
+ private final T zDim;
+
+ private final T tDim;
+
+ /**
+ * @param xyDims
+ * @param zDim
+ * @param tDim
+ */
+ public CfDimensions(CfHorizontalDims xyDims, T zDim, T tDim) {
+ this.xyDims = xyDims;
+ this.zDim = zDim;
+ this.tDim = tDim;
+ }
+
+ /**
+ * @return the xyDims
+ */
+ public CfHorizontalDims getXyDims() {
+ return xyDims;
+ }
+
+ /**
+ * @return the zDim
+ */
+ public T getzDim() {
+ return zDim;
+ }
+
+ /**
+ * @return the tDim
+ */
+ public T gettDim() {
+ return tDim;
+ }
+
+ @SuppressWarnings("unchecked")
+ public T[] toArray() {
+ T[] a = (T[]) java.lang.reflect.Array
+ .newInstance(zDim.getClass(), 4);
+ fill(a);
+ return a;
+ }
+
+ public T[] toArray(T[] a) {
+ if (a.length < 4) {
+ a = Arrays.copyOf(a, 4);
+ }
+ fill(a);
+ return a;
+ }
+
+ private void fill(T[] a) {
+ a[0] = tDim;
+ a[1] = zDim;
+ a[2] = xyDims.getY();
+ a[3] = xyDims.getX();
+ }
+
+}
diff --git a/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfGridMapper.java b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfGridMapper.java
new file mode 100644
index 0000000000..1a4b09ef6a
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfGridMapper.java
@@ -0,0 +1,61 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.common.nc4.cf;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+import com.raytheon.uf.common.status.IUFStatusHandler;
+import com.raytheon.uf.common.status.UFStatus;
+
+/**
+ * TODO Add Description
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * May 7, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public class CfGridMapper {
+
+ private static final Properties ATTRIB_MAP = new Properties();
+
+ private static final IUFStatusHandler log = UFStatus
+ .getHandler(CfGridMapper.class);
+
+ static {
+ ClassLoader loader = CfGridMapper.class.getClassLoader();
+ InputStream res = loader
+ .getResourceAsStream("META-INF/nc4-CF-grid-mapping.properties");
+ if (res == null) {
+ log.warn("Unable to find grid attribute map");
+ } else {
+ try {
+ ATTRIB_MAP.load(res);
+ } catch (IOException e) {
+ log.error("Unable to load mapping properties", e);
+ }
+ }
+ }
+
+ public static String getMappingAttributeName(String name) {
+ return ATTRIB_MAP.getProperty(name, name);
+ }
+
+}
diff --git a/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfHorizontalDims.java b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfHorizontalDims.java
new file mode 100644
index 0000000000..159dbe728d
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfHorizontalDims.java
@@ -0,0 +1,100 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.common.nc4.cf;
+
+import com.raytheon.uf.common.nc4.NcDimension;
+
+/**
+ * TODO Add Description
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * May 3, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public class CfHorizontalDims {
+
+ private final T x;
+
+ private final T y;
+
+ private final String coords;
+
+ private final String gridMapping;
+
+ private final boolean mapped;
+
+ public CfHorizontalDims(T x, T y) {
+ this(x, y, null, null, false);
+ }
+
+ /**
+ * @param dims
+ * @param coords
+ * @param gridMapping
+ */
+ public CfHorizontalDims(T x, T y, String coords,
+ String gridMapping) {
+ this(x, y, coords, gridMapping, true);
+ }
+
+ private CfHorizontalDims(T x, T y, String coords,
+ String gridMapping, boolean mapped) {
+ this.x = x;
+ this.y = y;
+ this.coords = coords;
+ this.gridMapping = gridMapping;
+ this.mapped = mapped;
+ }
+
+ /**
+ * @return the x
+ */
+ public T getX() {
+ return x;
+ }
+
+ /**
+ * @return the y
+ */
+ public T getY() {
+ return y;
+ }
+
+ /**
+ * @return the coords
+ */
+ public String getCoords() {
+ return coords;
+ }
+
+ /**
+ * @return the gridMapping
+ */
+ public String getGridMapping() {
+ return gridMapping;
+ }
+
+ /**
+ * @return the mapped
+ */
+ public boolean isMapped() {
+ return mapped;
+ }
+
+}
diff --git a/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfNetcdf.java b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfNetcdf.java
new file mode 100644
index 0000000000..3e9347ad81
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfNetcdf.java
@@ -0,0 +1,207 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.common.nc4.cf;
+
+import com.raytheon.uf.common.nc4.NcDimension;
+import com.raytheon.uf.common.nc4.Netcdf;
+import com.raytheon.uf.common.nc4.NetcdfException;
+
+/**
+ * Climate and Forecast conventions wrapper for netcdf
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Mar 7, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public class CfNetcdf extends Netcdf {
+
+ /**
+ * @param path
+ * @throws NetcdfException
+ */
+ public CfNetcdf(String path) throws NetcdfException {
+ super(path);
+ addDefaultAttributes();
+ }
+
+ /**
+ * @param path
+ * @param mode
+ * @throws NetcdfException
+ */
+ public CfNetcdf(String path, int mode) throws NetcdfException {
+ super(path, mode);
+ addDefaultAttributes();
+ }
+
+ /**
+ * @param path
+ * @param mode
+ * @param initialSize
+ * @param chunkSizeHint
+ * @throws NetcdfException
+ */
+ public CfNetcdf(String path, int mode, int initialSize, int chunkSizeHint)
+ throws NetcdfException {
+ super(path, mode, initialSize, chunkSizeHint);
+ addDefaultAttributes();
+ }
+
+ /**
+ * Add default global attributes for CF file
+ *
+ * @throws NetcdfException
+ */
+ private void addDefaultAttributes() throws NetcdfException {
+ putStringAttribute(CfConstants.CONVENTIONS_ATTR,
+ CfConstants.CONVENTIONS1_6);
+ }
+
+ /**
+ * Define the X dimension for file. If the X/Y axes are in Long/Lat the X
+ * dimension is longitude. The return value can be used to populate the
+ * dimension axis values after {@link #endFileDefinition()} is called
+ *
+ * @param
+ * data type specific {@link NcDimension} sub class
+ * @param name
+ * name of dimension
+ * @param longName
+ * long name of dimension
+ * @param len
+ * length of dimension
+ * @param units
+ * units that this axis is in
+ * @param dimClass
+ * class object for {@link NcDimension} sub class
+ * @return
+ * @throws NetcdfException
+ */
+ public T defineXDim(String name, String longName,
+ int len, String units, Class dimClass) throws NetcdfException {
+ T rval = super.defineDim(name, len, dimClass);
+ setDimAttrs(rval, longName, units, CfConstants.X_AXIS);
+ return rval;
+ }
+
+ /**
+ * Define the Y dimension for file. If the X/Y axes are in Long/Lat the Y
+ * dimension is latitude. The return value can be used to populate the
+ * dimension axis values after {@link #endFileDefinition()} is called
+ *
+ * @param
+ * data type specific {@link NcDimension} sub class
+ * @param name
+ * name of dimension
+ * @param longName
+ * long name of dimension
+ * @param len
+ * length of dimension
+ * @param units
+ * units that this axis is in
+ * @param dimClass
+ * class object for {@link NcDimension} sub class
+ * @return
+ * @throws NetcdfException
+ */
+ public T defineYDim(String name, String longName,
+ int len, String units, Class dimClass) throws NetcdfException {
+ T rval = super.defineDim(name, len, dimClass);
+ setDimAttrs(rval, longName, units, CfConstants.Y_AXIS);
+ return rval;
+ }
+
+ /**
+ * Define the Z dimension for file. This is the horizontal axis. The return
+ * value can be used to populate the dimension axis values after
+ * {@link #endFileDefinition()} is called
+ *
+ * @param
+ * data type specific {@link NcDimension} sub class
+ * @param name
+ * name of dimension
+ * @param longName
+ * long name of dimension
+ * @param len
+ * length of dimension
+ * @param units
+ * units that this axis is in
+ * @param upIsPositive
+ * true if increasing values on axis indicate an increase in
+ * horizontal distance
+ * @param dimClass
+ * class object for {@link NcDimension} sub class
+ * @return
+ * @throws NetcdfException
+ */
+ public T defineZDim(String name, String longName,
+ int len, String units, boolean upIsPositive, Class dimClass)
+ throws NetcdfException {
+ T rval = super.defineDim(name, len, dimClass);
+ setDimAttrs(rval, longName, units, CfConstants.Z_AXIS);
+ String posVal = upIsPositive ? CfConstants.UP_POS : CfConstants.DWN_POS;
+ rval.putStringAttribute(CfConstants.POS_ATTR, posVal);
+ return rval;
+ }
+
+ /**
+ * Define the T dimension for file. This is the temporal dimension. The
+ * return value can be used to populate the dimension axis values after
+ * {@link #endFileDefinition()} is called
+ *
+ * @param
+ * data type specific {@link NcDimension} sub class
+ * @param name
+ * name of dimension
+ * @param stdName
+ * standard name of dimension
+ * @param len
+ * length of dimension
+ * @param units
+ * units that this axis is in
+ * @param dimClass
+ * class object for {@link NcDimension} sub class
+ * @return
+ * @throws NetcdfException
+ */
+ public T defineTimeDim(String name, String stdName,
+ int len, String units, Class dimClass) throws NetcdfException {
+ T rval = super.defineDim(name, len, dimClass);
+ setDimAttrs(rval, stdName, units, CfConstants.T_AXIS);
+ rval.putStringAttribute(CfConstants.CAL_ATTR, CfConstants.GREG_CALENDAR);
+ return rval;
+ }
+
+ /**
+ * Set default dimension attributes
+ *
+ * @param dim
+ * @param stdName
+ * @param units
+ * @param axis
+ * @throws NetcdfException
+ */
+ private void setDimAttrs(NcDimension dim, String stdName, String units,
+ String axis) throws NetcdfException {
+ dim.putStringAttribute(CfConstants.LONG_NAME_ATTR, stdName);
+ dim.putStringAttribute(CfConstants.STANDARD_NAME_ATTR, stdName);
+ dim.putStringAttribute(CfConstants.UNITS_ATTR, units);
+ dim.putStringAttribute(CfConstants.AXIS_ATTR, axis);
+ }
+}
diff --git a/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfUtils.java b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfUtils.java
new file mode 100644
index 0000000000..48de686666
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.common.nc4/src/com/raytheon/uf/common/nc4/cf/CfUtils.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.common.nc4.cf;
+
+import java.util.regex.Pattern;
+
+/**
+ * TODO Add Description
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Mar 7, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public class CfUtils {
+
+ public static final Pattern CF_NAME_PATTERN = Pattern
+ .compile("^[a-zA-Z][a-zA-Z0-9_]*$");
+
+ public static boolean validName(String name) {
+ return CF_NAME_PATTERN.matcher(name).matches();
+ }
+}
diff --git a/edexOsgi/com.raytheon.uf.common.serialization/src/com/raytheon/uf/common/serialization/JAXBManager.java b/edexOsgi/com.raytheon.uf.common.serialization/src/com/raytheon/uf/common/serialization/JAXBManager.java
index d9d341f964..6e21e07ed5 100644
--- a/edexOsgi/com.raytheon.uf.common.serialization/src/com/raytheon/uf/common/serialization/JAXBManager.java
+++ b/edexOsgi/com.raytheon.uf.common.serialization/src/com/raytheon/uf/common/serialization/JAXBManager.java
@@ -51,6 +51,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
* Sep 24, 2008 chammack Initial creation
* Nov 13, 2008 njensen Added thrift methods
* May 22, 2013 1917 rjpeter Added non-pretty print option to jaxb serialize methods.
+ * Aug 18, 2013 #2097 dhladky Allowed extension by OGCJAXBManager
*
*
* @author chammack
@@ -106,7 +107,7 @@ public class JAXBManager {
private final JAXBContext jaxbContext;
- private final Queue unmarshallers = new ConcurrentLinkedQueue();
+ protected final Queue unmarshallers = new ConcurrentLinkedQueue();
protected final Queue marshallers = new ConcurrentLinkedQueue();
diff --git a/edexOsgi/com.raytheon.uf.common.spatial/src/com/raytheon/uf/common/spatial/reprojection/DataReprojector.java b/edexOsgi/com.raytheon.uf.common.spatial/src/com/raytheon/uf/common/spatial/reprojection/DataReprojector.java
index ae208ad2a2..1186cb2239 100644
--- a/edexOsgi/com.raytheon.uf.common.spatial/src/com/raytheon/uf/common/spatial/reprojection/DataReprojector.java
+++ b/edexOsgi/com.raytheon.uf.common.spatial/src/com/raytheon/uf/common/spatial/reprojection/DataReprojector.java
@@ -48,6 +48,7 @@ import org.geotools.coverage.grid.ViewType;
import org.geotools.coverage.processing.Operations;
import org.geotools.geometry.DirectPosition2D;
import org.geotools.geometry.jts.ReferencedEnvelope;
+import org.geotools.referencing.CRS;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.metadata.spatial.PixelOrientation;
@@ -157,6 +158,10 @@ public class DataReprojector {
String reprojectedDataset, ISpatialObject spatial,
CoordinateReferenceSystem crs, Request req) throws Exception {
IDataRecord dataRecord;
+ if (CRS.equalsIgnoreMetadata(crs, spatial.getCrs())) {
+ // original dataset, no reproject
+ reprojectedDataset = dataSet;
+ }
// check if data has already been reprojected
if (!datasetExists(group, reprojectedDataset)) {
// it hasn't lock and reproject
@@ -452,7 +457,7 @@ public class DataReprojector {
* @throws MismatchedDimensionException
* @throws FactoryException
*/
- protected RequestWrapper getRequest(ISpatialObject spatial,
+ public static RequestWrapper getRequest(ISpatialObject spatial,
ReferencedEnvelope nativeEnv, ReferencedEnvelope targetEnvelope)
throws MismatchedDimensionException,
TransformException, FactoryException {
@@ -492,7 +497,8 @@ public class DataReprojector {
* @throws MismatchedDimensionException
* @throws TransformException
*/
- protected RequestWrapper getSubSlice(GridGeometry2D geom, Envelope env,
+ protected static RequestWrapper getSubSlice(GridGeometry2D geom,
+ Envelope env,
int[] dims) throws MismatchedDimensionException, TransformException {
RequestWrapper rval = new RequestWrapper();
MathTransform2D crsToGrid2D = geom
@@ -517,7 +523,8 @@ public class DataReprojector {
* @throws MismatchedDimensionException
* @throws TransformException
*/
- protected ReferencedEnvelope transformGrid(MathTransform2D gridToCrs,
+ protected static ReferencedEnvelope transformGrid(
+ MathTransform2D gridToCrs,
int[][] minmax, CoordinateReferenceSystem crs)
throws MismatchedDimensionException, TransformException {
int[] min = minmax[0];
@@ -545,7 +552,8 @@ public class DataReprojector {
* @throws MismatchedDimensionException
* @throws TransformException
*/
- protected int[][] transformEnv(MathTransform2D crsToGrid, Envelope env,
+ protected static int[][] transformEnv(MathTransform2D crsToGrid,
+ Envelope env,
int[] dims) throws MismatchedDimensionException, TransformException {
DirectPosition lower = new DirectPosition2D(env.getMinX(),
env.getMinY());
diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.core.feature/feature.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.core.feature/feature.xml
index e6ccfef95f..735acec18d 100644
--- a/edexOsgi/com.raytheon.uf.edex.datadelivery.core.feature/feature.xml
+++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.core.feature/feature.xml
@@ -17,11 +17,9 @@
[Enter License Description here.]
-
-
-
-
-
+
-
-
+
+
diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.feature/feature.xml b/edexOsgi/com.raytheon.uf.edex.datadelivery.feature/feature.xml
index 9a0ad62bd5..54e4b0212b 100644
--- a/edexOsgi/com.raytheon.uf.edex.datadelivery.feature/feature.xml
+++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.feature/feature.xml
@@ -74,5 +74,18 @@
install-size="0"
version="0.0.0"
unpack="false"/>
+
+
+
+
diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval.wfs/META-INF/MANIFEST.MF b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval.wfs/META-INF/MANIFEST.MF
index a29b611ac6..dc9ed16838 100644
--- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval.wfs/META-INF/MANIFEST.MF
+++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval.wfs/META-INF/MANIFEST.MF
@@ -23,6 +23,7 @@ Require-Bundle: com.raytheon.uf.common.datadelivery.retrieval;bundle-version="1.
com.raytheon.uf.common.dataplugin.madis;bundle-version="1.0.0",
com.raytheon.uf.edex.plugin.madis.ogc;bundle-version="1.0.0",
com.raytheon.uf.edex.plugin.madis;bundle-version="1.0.0",
- com.raytheon.uf.edex.wfs;bundle-version="1.0.0"
+ com.raytheon.uf.edex.wfs;bundle-version="1.0.0",
+ org.eclipse.xsd;bundle-version="2.8.1"
Export-Package: com.raytheon.uf.edex.datadelivery.retrieval.wfs,
com.raytheon.uf.edex.datadelivery.retrieval.wfs.metadata
diff --git a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval.wfs/src/com/raytheon/uf/edex/datadelivery/retrieval/wfs/WfsRequestBuilder.java b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval.wfs/src/com/raytheon/uf/edex/datadelivery/retrieval/wfs/WfsRequestBuilder.java
index 3039cc3688..2b2e10bf48 100644
--- a/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval.wfs/src/com/raytheon/uf/edex/datadelivery/retrieval/wfs/WfsRequestBuilder.java
+++ b/edexOsgi/com.raytheon.uf.edex.datadelivery.retrieval.wfs/src/com/raytheon/uf/edex/datadelivery/retrieval/wfs/WfsRequestBuilder.java
@@ -32,6 +32,7 @@ import com.vividsolutions.jts.geom.Coordinate;
* May 31, 2013 2038 djohnson Move to correct repo.
* Jun 11, 2013 1763 dhladky Made operational.
* Jun 18, 2013 2120 dhladky Added times and max feature processing
+ * Aug 07, 2013 2097 dhladky Revamped WFS to use POST (still 1.1.0 WFS)
*
*
*
@@ -46,44 +47,55 @@ public class WfsRequestBuilder extends RequestBuilder {
protected static ServiceConfig wfsServiceConfig;
- public static final String separator = getServiceConfig().getConstantValue("COMMA");
+ public static final String SEPERATOR = getServiceConfig().getConstantValue("COMMA");
- public static final String slash = getServiceConfig().getConstantValue("FORWARD_SLASH");
+ public static final String SLASH = getServiceConfig().getConstantValue("FORWARD_SLASH");
- public static final String bbox = getServiceConfig().getConstantValue("BBOX_HEADER");
+ public static final String BBOX = getServiceConfig().getConstantValue("BBOX_HEADER");
- public static final String srs = getServiceConfig().getConstantValue("SRSNAME_HEADER");
+ public static final String SRS = getServiceConfig().getConstantValue("SRSNAME_HEADER");
- public static final String crs = getServiceConfig().getConstantValue("DEFAULT_CRS");
+ public static final String CRS = getServiceConfig().getConstantValue("DEFAULT_CRS");
- public static final String time = getServiceConfig().getConstantValue("TIME_HEADER");
+ public static final String TIME = getServiceConfig().getConstantValue("TIME_HEADER");
- public static final String equals = getServiceConfig().getConstantValue("EQUALS");
+ public static final String EQUALS = getServiceConfig().getConstantValue("EQUALS");
- public static final String blank = getServiceConfig().getConstantValue("BLANK");
+ public static final String BLANK = getServiceConfig().getConstantValue("BLANK");
- public static final String max = getServiceConfig().getConstantValue("MAX");
+ public static final String MAX = getServiceConfig().getConstantValue("MAX");
- public static final String ampersand = "&";
+ public static final String VERSION = getServiceConfig().getConstantValue("VERSION");
+
+ public static final String AMPERSAND = "&";
private final String wfsURL;
- WfsRequestBuilder(WfsRetrievalAdapter adapter,
+ private String typeName = null;
+
+ public WfsRequestBuilder(WfsRetrievalAdapter adapter,
RetrievalAttribute attXML) {
super(attXML);
- // Create URL
- // this works in this order
- StringBuilder buffer = new StringBuilder();
- // apply the base WFS service URL
- buffer.append(adapter.getProviderRetrievalXMl().getConnection()
- .getUrl());
- // process the coverage bounding box
- buffer.append(processCoverage());
- // process the time range you are trying to retrieve
- buffer.append(processTime(getRetrievalAttribute().getTime()));
- // max feature limit
- buffer.append(processMax());
+ // Create XML doc
+ this.typeName = attXML.getPlugin();
+ StringBuilder buffer = new StringBuilder(256);
+ buffer.append(createHeader());
+ buffer.append("\n");
+ if (attXML.getCoverage() != null && attXML.getTime() != null) {
+ buffer.append("\n");
+ }
+
+ buffer.append(processTime(attXML.getTime()));
+ buffer.append(processCoverage());
+
+ if (attXML.getCoverage() != null && attXML.getTime() != null) {
+ buffer.append(" \n");
+ }
+
+ buffer.append(" \n");
+ buffer.append(createFooter());
+
this.wfsURL = buffer.toString().trim();
}
@@ -98,92 +110,115 @@ public class WfsRequestBuilder extends RequestBuilder {
return sdf;
}
};
+
+ /**
+ * Creates the WFS XML Query header
+ * @return
+ */
+ private String createHeader() {
+ StringBuilder sb = new StringBuilder(256);
+ sb.append("\n");
+ sb.append("\n");
+ sb.append("\n");
+
+ return sb.toString();
+ }
+
+ /**
+ * Creates the WFS XML Query Footer
+ * @return
+ */
+ private String createFooter() {
+ String footer = " \n \n";
+ return footer;
+ }
+
@Override
public String processTime(Time inTime) {
try {
- if (inTime.getEndDate() != null && inTime.getStartDate() != null) {
+ if (inTime.getStartDate() != null) {
Date sDate = inTime.getStartDate();
Date eDate = inTime.getEndDate();
String endDateString = ogcDateFormat.get().format(eDate);
String startDateString = ogcDateFormat.get().format(sDate);
- StringBuilder sb = new StringBuilder();
- sb.append(ampersand);
- sb.append(time);
- sb.append(equals);
- sb.append(startDateString);
- sb.append(slash);
-
- if (!endDateString.equals(startDateString)) {
- sb.append(endDateString);
+
+ StringBuilder sb = new StringBuilder(256);
+ sb.append("\n");
+ sb.append("").append(typeName).append(":timeObs \n");
+ sb.append("").append(startDateString).append(" \n");
+ sb.append(" \n");
+
+ if (endDateString != null) {
+ sb.append("\n");
+ sb.append("").append(typeName).append(":timeObs \n");
+ sb.append("").append(endDateString).append(" \n");
+ sb.append(" \n");
}
return sb.toString();
}
} catch (Exception e) {
- statusHandler.error("Couldn't parse Time object." + e);
+ statusHandler.error("Couldn't parse Time object.", e);
}
- // no times, return blank
- return blank;
-
+ return BLANK;
}
@Override
public String processCoverage() {
- StringBuilder sb = new StringBuilder();
Coverage coverage = getRetrievalAttribute().getCoverage();
if (coverage != null) {
+ try {
+ StringBuilder sb = new StringBuilder(256);
+ ReferencedEnvelope re = coverage.getRequestEnvelope();
+ Coordinate ll = EnvelopeUtils.getLowerLeftLatLon(re);
+ Coordinate ur = EnvelopeUtils.getUpperRightLatLon(re);
+ // manage the box
+ double lowerLon = ll.x;
+ double lowerLat = ll.y;
+ double upperLon = ur.x;
+ double upperLat = ur.y;
- ReferencedEnvelope re = coverage.getRequestEnvelope();
- Coordinate ll = EnvelopeUtils.getLowerLeftLatLon(re);
- Coordinate ur = EnvelopeUtils.getUpperRightLatLon(re);
- // manage the box
- double lowerLon = ll.x;
- double lowerLat = ll.y;
- double upperLon = ur.x;
- double upperLat = ur.y;
+ sb.append("\n");
+ sb.append("location/location \n");
+ sb.append("\n");
+ sb.append("");
+ sb.append(lowerLon);
+ sb.append(" ");
+ sb.append(lowerLat);
+ sb.append(" \n");
+ sb.append("");
+ sb.append(upperLon);
+ sb.append(" ");
+ sb.append(upperLat);
+ sb.append(" \n");
+ sb.append(" \n");
+ sb.append(" \n");
- sb.append(ampersand);
- sb.append(srs);
- sb.append(equals);
- sb.append(crs);
- //TODO Revisit this when we have a better idea of how to switch them
- //sb.append(coverage.getEnvelope().getCoordinateReferenceSystem()
- // .getName());
- sb.append(ampersand);
- sb.append(bbox);
- sb.append(equals);
- sb.append(lowerLon);
- sb.append(separator);
- sb.append(lowerLat);
- sb.append(separator);
- sb.append(upperLon);
- sb.append(separator);
- sb.append(upperLat);
-
- return sb.toString();
+ return sb.toString();
+
+ } catch (Exception e) {
+ statusHandler.error("Couldn't parse Coverage object.", e);
+ }
}
- return blank;
+ return BLANK;
}
- /**
- * constrain to max amount of features
- * @return
- */
- public String processMax() {
- StringBuilder sb = new StringBuilder();
- sb.append(ampersand);
- sb.append(max);
-
- return sb.toString();
- }
-
@Override
public String getRequest() {
return wfsURL;
@@ -207,5 +242,5 @@ public class WfsRequestBuilder extends RequestBuilder {
return wfsServiceConfig;
}
-
+
}
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 944fb2b1c6..5191d7b8fd 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
@@ -3,7 +3,8 @@ package com.raytheon.uf.edex.datadelivery.retrieval.util;
import java.net.URI;
import java.net.URISyntaxException;
-import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.StringEntity;
import com.raytheon.uf.common.comm.HttpClient;
import com.raytheon.uf.common.comm.HttpClient.HttpClientResponse;
@@ -31,6 +32,7 @@ import com.raytheon.uf.common.status.UFStatus.Priority;
* Jun 18, 2013 2120 dhladky Times fixes and SSL changes
* Jul 10, 2013 2180 dhladky Updated credential requests
* Aug 23, 2013 2180 mpduff Implement changes to ProviderCredentialsUtil
+ * Aug 06, 2013 2097 dhladky WFS 2.0 compliance upgrade and switched to POST
*
*
*
@@ -54,16 +56,19 @@ public class WfsConnectionUtil {
* The data provider's name
* @return xml response
*/
- public static String wfsConnect(String url, Connection providerConn,
+ public static String wfsConnect(String request, Connection providerConn,
String providerName) {
+
String xmlResponse = null;
HttpClient http = null;
+ String rootUrl = null;
try {
- // TODO: consider using HTTP POST instead of GET
+
+ rootUrl = providerConn.getUrl();
http = HttpClient.getInstance();
- HttpGet get = new HttpGet();
- URI uri = new URI(url);
+ URI uri = new URI(rootUrl);
+ HttpPost post = new HttpPost(uri);
// check for the need to do a username password auth check
ProviderCredentials creds = ProviderCredentialsUtil
.retrieveCredentials(providerName);
@@ -84,12 +89,13 @@ public class WfsConnectionUtil {
userName, password);
}
- get.setURI(uri);
- HttpClientResponse response = http.executeRequest(get);
+ post.setEntity(new StringEntity(request, "text/xml", "ISO-8859-1"));
+ HttpClientResponse response = http.executeRequest(post);
xmlResponse = new String(response.data);
+
} catch (Exception e) {
statusHandler.handle(Priority.PROBLEM,
- "Couldn't connect to WFS server: " + url, e);
+ "Couldn't connect to WFS server: " + rootUrl, e);
}
return xmlResponse;
diff --git a/edexOsgi/com.raytheon.uf.edex.dataprovideragent.feature/feature.xml b/edexOsgi/com.raytheon.uf.edex.dataprovideragent.feature/feature.xml
index b52ce9f77f..e879c38096 100644
--- a/edexOsgi/com.raytheon.uf.edex.dataprovideragent.feature/feature.xml
+++ b/edexOsgi/com.raytheon.uf.edex.dataprovideragent.feature/feature.xml
@@ -17,15 +17,6 @@
[Enter License Description here.]
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ http://0.0.0.0:8080/notify
+
+
+
+
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/build.properties b/edexOsgi/com.raytheon.uf.edex.ogc.common/build.properties
index 2377de7022..e016089273 100644
--- a/edexOsgi/com.raytheon.uf.edex.ogc.common/build.properties
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/build.properties
@@ -1,5 +1,4 @@
source.. = src/
-output.. = bin/
bin.includes = .project,\
.classpath,\
META-INF/,\
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/overview.uml b/edexOsgi/com.raytheon.uf.edex.ogc.common/overview.uml
new file mode 100644
index 0000000000..ffd32ce6f1
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/overview.uml
@@ -0,0 +1,22 @@
+@startuml
+
+package "EDEX Common OGC" {
+ [Simple Dimension] as dim
+ [Simple Layer] as layer
+ [Abstract Layer Collector] as abscol
+}
+
+node "EDEX Data Plug-in Adapter" {
+ [Plug-in Dimension] as pdim
+ [Plug-in Layer] as player
+ [Plug-in Layer Collector] as collector
+}
+
+abscol <|-- collector
+layer <|-- player
+dim <|-- pdim
+
+collector o-left- "*"player
+player o-left- "*" pdim
+
+@enduml
\ No newline at end of file
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/res/spring/ogc-common-convert.xml b/edexOsgi/com.raytheon.uf.edex.ogc.common/res/spring/ogc-common-convert.xml
new file mode 100644
index 0000000000..59d85e0f55
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/res/spring/ogc-common-convert.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/res/spring/ogc-common.xml b/edexOsgi/com.raytheon.uf.edex.ogc.common/res/spring/ogc-common.xml
index b69428c58e..bc7cd6bde5 100644
--- a/edexOsgi/com.raytheon.uf.edex.ogc.common/res/spring/ogc-common.xml
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/res/spring/ogc-common.xml
@@ -9,5 +9,9 @@
-
+
+
+
+
+
\ No newline at end of file
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/AbstractFSQueryStore.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/AbstractFSQueryStore.java
new file mode 100644
index 0000000000..904b58be80
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/AbstractFSQueryStore.java
@@ -0,0 +1,263 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.edex.ogc.common;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.collections.map.LRUMap;
+
+import com.raytheon.uf.common.spatial.reprojection.KeyLocker;
+import com.raytheon.uf.common.spatial.reprojection.KeyLocker.KeyLock;
+import com.raytheon.uf.edex.ogc.common.OgcException.Code;
+
+/**
+ * TODO Add Description
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Feb 15, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public abstract class AbstractFSQueryStore extends AbstractFsStore {
+
+ /**
+ * @param storeLocation
+ */
+ public AbstractFSQueryStore(File storeLocation) {
+ super(storeLocation);
+ }
+
+ @SuppressWarnings("unchecked")
+ private final Map objCache = Collections
+ .synchronizedMap(new LRUMap(2));
+
+ @SuppressWarnings("unchecked")
+ private final Map strCache = Collections
+ .synchronizedMap(new LRUMap(2));
+
+ private final KeyLocker locker = new KeyLocker();
+
+ /**
+ * @param id
+ * @param query
+ * @throws Exception
+ */
+ public void store(String id, T query) throws OgcException {
+ KeyLock lock = locker.getLock(id);
+ lock.lock();
+ try {
+ storeObject(id, query);
+ } finally {
+ lock.unlock();
+ lock.release();
+ }
+ }
+
+ /**
+ * This must be externally synchronized
+ *
+ * @param id
+ * @param query
+ * @throws Exception
+ */
+ private void storeObject(String id, T query) throws OgcException {
+ objCache.put(id, query);
+ String xml = marshal(query);
+ storeString(id, xml);
+ }
+
+ protected abstract String marshal(T query) throws OgcException;
+
+ /**
+ * This must be externally synchronized
+ *
+ * @param id
+ * @param query
+ * @throws Exception
+ */
+ private void storeString(String id, String query) throws OgcException {
+ OutputStreamWriter out = null;
+ strCache.put(id, query);
+ try {
+ File storage = getStorageFile(id);
+ out = new OutputStreamWriter(new FileOutputStream(storage));
+ out.write(query);
+ } catch (Exception e) {
+ throw new OgcException(Code.InternalServerError, e);
+ } finally {
+ if (out != null) {
+ try {
+ out.close();
+ } catch (IOException e) {
+ throw new OgcException(Code.InternalServerError, e);
+ }
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.raytheon.uf.edex.wfs.querystore.QueryStore#retrieve(java.lang.String)
+ */
+ public T retrieve(String id) throws OgcException {
+ T rval;
+ KeyLock lock = locker.getLock(id);
+ lock.lock();
+ try {
+ rval = retrieveObject(id);
+ } finally {
+ lock.unlock();
+ lock.release();
+ }
+ return rval;
+ }
+
+ /**
+ * This must be externally synchronized
+ *
+ * @param id
+ * @return
+ * @throws Exception
+ */
+ private T retrieveObject(String id) throws OgcException {
+ T rval = objCache.get(id);
+ if (rval == null) {
+ String xml = retrieveStringInternal(id);
+ if (xml != null) {
+ rval = unmarshal(xml);
+ objCache.put(id, rval);
+ }
+ }
+ return rval;
+ }
+
+ /**
+ * This must be externally synchronized
+ *
+ * @param id
+ * @return
+ * @throws Exception
+ */
+ private String retrieveStringInternal(String id) throws OgcException {
+ String rval = strCache.get(id);
+ if (rval == null) {
+ File storage = getStorageFile(id);
+ if (storage.exists()) {
+ InputStream in;
+ try {
+ in = new FileInputStream(storage);
+ } catch (FileNotFoundException e) {
+ throw new OgcException(Code.InternalServerError, e);
+ }
+ try {
+ rval = new java.util.Scanner(in).useDelimiter("\\A").next();
+ strCache.put(id, rval);
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e) {
+ throw new OgcException(Code.InternalServerError, e);
+ }
+ }
+ }
+ }
+ return rval;
+ }
+
+ /**
+ * @param id
+ * @return
+ * @throws Exception
+ */
+ protected String retrieveString(String id) throws OgcException {
+ KeyLock lock = locker.getLock(id);
+ lock.lock();
+ try {
+ return retrieveStringInternal(id);
+ } finally {
+ lock.unlock();
+ lock.release();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.raytheon.uf.edex.wfs.querystore.QueryStore#remove(java.lang.String)
+ */
+ public void remove(String id) {
+ KeyLock lock = locker.getLock(id);
+ lock.lock();
+ try {
+ objCache.remove(id);
+ strCache.remove(id);
+ File storage = getStorageFile(id);
+ if (storage.exists()) {
+ storage.delete();
+ }
+ } finally {
+ lock.unlock();
+ lock.release();
+ }
+ }
+
+ /**
+ * @return
+ * @throws Exception
+ */
+ public List list() throws OgcException {
+ // NOTE: this is only synched by the file system
+ File[] files = storeLocation.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return f.isFile();
+ }
+ });
+ List rval = new ArrayList(files.length);
+ for (File f : files) {
+ String encoded = f.getName();
+ rval.add(decode(encoded));
+ }
+ return rval;
+ }
+
+ /**
+ * @param id
+ * @return file for storage
+ */
+ protected File getStorageFile(String id) {
+ return new File(storeLocation, encode(id));
+ }
+
+ protected abstract T unmarshal(String xml) throws OgcException;
+
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/AbstractFsStore.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/AbstractFsStore.java
new file mode 100644
index 0000000000..be155dc7d9
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/AbstractFsStore.java
@@ -0,0 +1,133 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.edex.ogc.common;
+
+import java.io.File;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+
+import com.raytheon.uf.common.localization.IPathManager;
+import com.raytheon.uf.common.localization.LocalizationContext;
+import com.raytheon.uf.common.localization.PathManagerFactory;
+
+/**
+ * Abstract File store
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Jun 4, 2013 bclement Initial creation
+ * Aug 18, 2013 #2097 dhladky Changed to configured
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public class AbstractFsStore {
+
+ protected static final char ESCAPE = '%';
+
+ protected static final String SPECIAL_CHARS = ESCAPE + "./\\?*:|\"<>~";
+
+ protected final File storeLocation;
+
+ /**
+ * @param storeLocation
+ */
+ public AbstractFsStore(File storeLocation) {
+ this.storeLocation = storeLocation;
+ ensureStorage();
+ }
+
+ protected static File findStore(String directoryName) {
+ IPathManager pathMgr = PathManagerFactory.getPathManager();
+ LocalizationContext edexStaticCONFIGURED = pathMgr.getContext(
+ LocalizationContext.LocalizationType.EDEX_STATIC,
+ LocalizationContext.LocalizationLevel.CONFIGURED);
+ return pathMgr.getFile(edexStaticCONFIGURED, directoryName);
+ }
+
+ /**
+ * Create storage location if necessary
+ *
+ * @throws IllegalArgumentException
+ * if unable to create storage directory or if provided location
+ * is not a directory
+ */
+ private void ensureStorage() throws IllegalArgumentException {
+ if (!storeLocation.exists()) {
+ if (!storeLocation.mkdirs()) {
+ throw new IllegalArgumentException(
+ "Unable to create store directory: " + storeLocation);
+ }
+ }
+ if (!storeLocation.isDirectory()) {
+ throw new IllegalArgumentException(
+ "Provided storage location is not a directory: "
+ + storeLocation);
+ }
+ if (!storeLocation.canWrite()) {
+ throw new IllegalArgumentException(
+ "Unable to write to storage directory: " + storeLocation);
+ }
+ }
+
+ /**
+ * Sanitize id for file system
+ *
+ * @param id
+ * @return
+ */
+ protected static String encode(String id) {
+ StringBuilder sb = new StringBuilder();
+ CharacterIterator iter = new StringCharacterIterator(id);
+ for (char ch = iter.first(); ch != CharacterIterator.DONE; ch = iter
+ .next()) {
+ if (SPECIAL_CHARS.indexOf(ch) != -1) {
+ sb.append(ESCAPE);
+ sb.append(String.format("%2h", ch));
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * de-sanitize file system name
+ *
+ * @param encoded
+ * @return
+ */
+ protected static String decode(String encoded) {
+ StringBuilder sb = new StringBuilder();
+ int index = 0;
+ int prev;
+ while (index < encoded.length()) {
+ prev = index;
+ index = encoded.indexOf(ESCAPE, prev);
+ if (index < 0) {
+ sb.append(encoded.substring(prev));
+ break;
+ }
+ sb.append(encoded.substring(prev, index));
+ String hex = encoded.substring(index + 1, index + 3);
+ char charNum = (char) Integer.parseInt(hex, 16);
+ sb.append(charNum);
+ index = index + 3;
+ }
+ return sb.toString();
+ }
+
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/AbstractOgcSource.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/AbstractOgcSource.java
new file mode 100644
index 0000000000..a6c54bc10e
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/AbstractOgcSource.java
@@ -0,0 +1,69 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.edex.ogc.common;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * base source for OGC
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 18, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public abstract class AbstractOgcSource {
+
+ private final Map, Object> extensionMap = new ConcurrentHashMap, Object>();
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.raytheon.uf.edex.wfs.reg.WfsSource#getExtension(java.lang.Class)
+ */
+ @SuppressWarnings("unchecked")
+ public E getExtension(Class c) {
+ E rval = (E) extensionMap.get(c);
+ if (rval == null) {
+ for (Class> key : extensionMap.keySet()) {
+ if (c.isAssignableFrom(key)) {
+ return (E) extensionMap.get(key);
+ }
+ }
+ }
+ return rval;
+ }
+
+ /**
+ * @param extension
+ */
+ public void setExtension(Object extension) {
+ extensionMap.put(extension.getClass(), extension);
+ }
+
+ /**
+ * @param extensions
+ */
+ public void setExtensions(Object[] extensions) {
+ for (Object obj : extensions) {
+ setExtension(obj);
+ }
+ }
+
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/AbstractOpDescriber.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/AbstractOpDescriber.java
new file mode 100644
index 0000000000..809b902460
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/AbstractOpDescriber.java
@@ -0,0 +1,191 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.edex.ogc.common;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.xml.bind.JAXBElement;
+
+import net.opengis.ows.v_1_1_0.AllowedValues;
+import net.opengis.ows.v_1_1_0.DCP;
+import net.opengis.ows.v_1_1_0.DomainType;
+import net.opengis.ows.v_1_1_0.HTTP;
+import net.opengis.ows.v_1_1_0.ObjectFactory;
+import net.opengis.ows.v_1_1_0.Operation;
+import net.opengis.ows.v_1_1_0.OperationsMetadata;
+import net.opengis.ows.v_1_1_0.RequestMethodType;
+import net.opengis.ows.v_1_1_0.ValueType;
+
+/**
+ * TODO Add Description
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * May 21, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public abstract class AbstractOpDescriber {
+
+ protected ObjectFactory owsFactory = new ObjectFactory();
+
+ /**
+ * Get OWS operations metadata from service info
+ *
+ * @param serviceinfo
+ * @return
+ */
+ public OperationsMetadata getOpData(OgcServiceInfo serviceinfo) {
+ OperationsMetadata rval = new OperationsMetadata();
+ List operations = new LinkedList();
+ for (OgcOperationInfo op : serviceinfo.getOperations()) {
+ Operation to = new Operation();
+ to.setName(op.getType().toString());
+ to.setDCP(getDcpList(op));
+ to.setParameter(getOpParams(op));
+ operations.add(to);
+ }
+ rval.setOperation(operations);
+ List params = getParams(serviceinfo);
+ if (params != null && !params.isEmpty()) {
+ rval.setParameter(params);
+ }
+ List constraints = getConstraints(serviceinfo);
+ if (constraints != null && !constraints.isEmpty()) {
+ rval.setConstraint(constraints);
+ }
+ Object extendedCapabilities = getExtendedCapabilities(serviceinfo);
+ if (extendedCapabilities != null) {
+ rval.setExtendedCapabilities(extendedCapabilities);
+ }
+ return rval;
+ }
+
+ /**
+ * @param serviceinfo
+ * @return
+ */
+ protected Object getExtendedCapabilities(OgcServiceInfo serviceinfo) {
+ return null;
+ }
+
+ /**
+ * @param serviceinfo
+ * @return
+ */
+ protected List getConstraints(OgcServiceInfo serviceinfo) {
+ return new ArrayList(0);
+ }
+
+ /**
+ * Get global parameters
+ *
+ * @param serviceinfo
+ * @return
+ */
+ protected abstract List getParams(OgcServiceInfo serviceinfo);
+
+ /**
+ * Get HTTP endpoint information for operation
+ *
+ * @param op
+ * @return
+ */
+ protected List getDcpList(OgcOperationInfo op) {
+ List rval = new LinkedList();
+ DCP dcp = new DCP();
+ HTTP http = new HTTP();
+ List> value = new LinkedList>();
+ if (op.hasHttpGet()) {
+ RequestMethodType req = getRequestType(op.getHttpGetRes(), "KVP");
+ value.add(owsFactory.createHTTPGet(req));
+ }
+ if (op.hasHttpPost()) {
+ RequestMethodType req = getRequestType(op.getHttpPostRes(),
+ op.getPostEncoding());
+ value.add(owsFactory.createHTTPPost(req));
+ }
+ http.setGetOrPost(value);
+ dcp.setHTTP(http);
+ rval.add(dcp);
+ return rval;
+ }
+
+ /**
+ * Create request method object
+ *
+ * @param value
+ * @param postEncoding
+ * @return
+ */
+ protected RequestMethodType getRequestType(String value, String postEncoding) {
+ RequestMethodType rval = owsFactory.createRequestMethodType();
+ rval.setHref(value);
+ rval.setConstraint(Arrays.asList(getAsDomainType("PostEncoding",
+ Arrays.asList(postEncoding))));
+ return rval;
+ }
+
+ /**
+ * Get parameters for operation
+ *
+ * @param op
+ * @return
+ */
+ protected abstract List getOpParams(OgcOperationInfo op);
+
+ /**
+ * Get keyed values as domain object
+ *
+ * @param name
+ * @param values
+ * @return
+ */
+ protected DomainType getAsDomainType(String name, String... values) {
+ return getAsDomainType(name, Arrays.asList(values));
+ }
+
+ /**
+ * Get keyed values as domain object
+ *
+ * @param name
+ * @param values
+ * @return
+ */
+ protected DomainType getAsDomainType(String name, Collection values) {
+ DomainType rval = new DomainType();
+ rval.setName(name);
+
+ AllowedValues avs = new AllowedValues();
+
+ List toVals = new LinkedList();
+ for (String val : values) {
+ ValueType vt = new ValueType();
+ vt.setValue(val);
+ toVals.add(vt);
+ }
+
+ avs.setValueOrRange(toVals);
+ rval.setAllowedValues(avs);
+
+ return rval;
+ }
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/BasicFileStore.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/BasicFileStore.java
new file mode 100644
index 0000000000..ddd7a65d53
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/BasicFileStore.java
@@ -0,0 +1,225 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.edex.ogc.common;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.CharacterIterator;
+import java.text.StringCharacterIterator;
+
+import org.apache.cxf.helpers.IOUtils;
+
+import com.raytheon.uf.common.localization.IPathManager;
+import com.raytheon.uf.common.localization.LocalizationContext;
+import com.raytheon.uf.common.localization.PathManagerFactory;
+
+/**
+ * Basic File Store
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Mar 11, 2013 bclement Initial creation
+ * Aug 18, 2013 #2097 dhladky Moved to configured
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public class BasicFileStore {
+
+ protected static final char ESCAPE = '%';
+
+ protected static final String SPECIAL_CHARS = ESCAPE + "./\\?*:|\"<>~";
+
+ private final Object fileMutex = new Object();
+
+ private final File storeLocation;
+
+ /**
+ * @param storeName
+ */
+ public BasicFileStore(String storeName) {
+ this(findStore(storeName));
+ }
+
+ /**
+ * @param storeLocation
+ */
+ public BasicFileStore(File storeLocation) {
+ this.storeLocation = storeLocation;
+ ensureStorage();
+ }
+
+ /**
+ * Create storage location if necessary
+ *
+ * @throws IllegalArgumentException
+ * if unable to create storage directory or if provided location
+ * is not a directory
+ */
+ private void ensureStorage() throws IllegalArgumentException {
+ if (!storeLocation.exists()) {
+ if (!storeLocation.mkdirs()) {
+ throw new IllegalArgumentException(
+ "Unable to create store directory: " + storeLocation);
+ }
+ }
+ if (!storeLocation.isDirectory()) {
+ throw new IllegalArgumentException(
+ "Provided storage location is not a directory: "
+ + storeLocation);
+ }
+ if (!storeLocation.canWrite()) {
+ throw new IllegalArgumentException(
+ "Unable to write to storage directory: " + storeLocation);
+ }
+ }
+
+ /**
+ * @param directoryName
+ * @return
+ */
+ protected static File findStore(String directoryName) {
+ IPathManager pathMgr = PathManagerFactory.getPathManager();
+ LocalizationContext edexStaticCONFIGURED = pathMgr.getContext(
+ LocalizationContext.LocalizationType.EDEX_STATIC,
+ LocalizationContext.LocalizationLevel.CONFIGURED);
+ return pathMgr.getFile(edexStaticCONFIGURED, directoryName);
+ }
+
+ /**
+ * @param id
+ * @return
+ */
+ private File createPath(String id) {
+ return new File(storeLocation, encode(id));
+ }
+
+ /**
+ * Get file from store
+ *
+ * @param id
+ * @return null if file isn't in store
+ */
+ public File getFile(String id) {
+ File rval = createPath(id);
+ if (!rval.exists()) {
+ return null;
+ }
+ return rval;
+ }
+
+ /**
+ * Creates an empty file in store. This is used when data is written to the
+ * file outside of the store. This cannot be used with
+ * {@link #store(String, InputStream)}
+ *
+ * @param id
+ * @return
+ * @throws IOException
+ * if file already exists in store
+ */
+ public File reserveFile(String id) throws IOException {
+ File f = createPath(id);
+ synchronized (fileMutex) {
+ if (!f.createNewFile()){
+ throw new IOException("File already exists in store with id: "
+ + id);
+ }
+ }
+ return f;
+ }
+
+ /**
+ * Delete file from store
+ *
+ * @param id
+ */
+ public void remove(String id) {
+ File f = createPath(id);
+ synchronized (fileMutex) {
+ if (f.exists()) {
+ f.delete();
+ }
+ }
+ }
+
+ /**
+ * Put data in store. This should not be used with
+ * {@link #reserveFile(String)}
+ *
+ * @param id
+ * @param in
+ * @throws IOException
+ */
+ public void store(String id, InputStream in) throws IOException {
+ File f = reserveFile(id);
+ FileOutputStream out = new FileOutputStream(f);
+ try {
+ IOUtils.copy(in, out);
+ } finally {
+ out.close();
+ }
+ }
+
+ /**
+ * Sanitize id for file system
+ *
+ * @param id
+ * @return
+ */
+ protected static String encode(String id) {
+ StringBuilder sb = new StringBuilder();
+ CharacterIterator iter = new StringCharacterIterator(id);
+ for (char ch = iter.first(); ch != CharacterIterator.DONE; ch = iter
+ .next()) {
+ if (SPECIAL_CHARS.indexOf(ch) != -1) {
+ sb.append(ESCAPE);
+ sb.append(String.format("%2h", ch));
+ } else {
+ sb.append(ch);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * de-sanitize file system name
+ *
+ * @param encoded
+ * @return
+ */
+ protected static String decode(String encoded) {
+ StringBuilder sb = new StringBuilder();
+ int index = 0;
+ int prev;
+ while (index < encoded.length()) {
+ prev = index;
+ index = encoded.indexOf(ESCAPE, prev);
+ if (index < 0) {
+ sb.append(encoded.substring(prev));
+ break;
+ }
+ sb.append(encoded.substring(prev, index));
+ String hex = encoded.substring(index + 1, index + 3);
+ char charNum = (char) Integer.parseInt(hex, 16);
+ sb.append(charNum);
+ index = index + 3;
+ }
+ return sb.toString();
+ }
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/InvalidVersionException.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/InvalidVersionException.java
new file mode 100644
index 0000000000..2620f05d4c
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/InvalidVersionException.java
@@ -0,0 +1,62 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.edex.ogc.common;
+
+/**
+ * TODO Add Description
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Oct 26, 2012 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+
+public class InvalidVersionException extends Exception {
+
+ private static final long serialVersionUID = -7212986504698593811L;
+
+ /**
+ *
+ */
+ public InvalidVersionException() {
+ // TODO Auto-generated constructor stub
+ }
+
+ /**
+ * @param message
+ */
+ public InvalidVersionException(String message) {
+ super(message);
+ }
+
+ /**
+ * @param cause
+ */
+ public InvalidVersionException(Throwable cause) {
+ super(cause);
+ }
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public InvalidVersionException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcException.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcException.java
index acf73b3d7f..930b14bd18 100644
--- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcException.java
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcException.java
@@ -29,7 +29,7 @@ public class OgcException extends Exception {
private static final long serialVersionUID = -5832661027013919871L;
public enum Code {
- InvalidFormat, InvalidCRS, LayerNotDefined, MissingDimensionValue, InvalidDimensionValue, OperationNotSupported, MissingParameterValue, InvalidParameterValue, InternalServerError
+ InvalidFormat, InvalidCRS, LayerNotDefined, MissingDimensionValue, InvalidDimensionValue, OperationNotSupported, MissingParameterValue, InvalidParameterValue, InternalServerError, InvalidRequest, VersionNegotiationFailed
}
protected Code code;
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcLayer.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcLayer.java
index a902793615..098d5c3087 100644
--- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcLayer.java
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcLayer.java
@@ -30,6 +30,8 @@ import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
+import org.apache.commons.lang.StringUtils;
+
/**
* @author bclement
*
@@ -66,7 +68,7 @@ public class OgcLayer {
protected List dimensions;
- protected static String keySeparator = "/";
+ public static String keySeparator = "/";
public void addCRS(String crs) {
this.crs = addToList(this.crs, crs);
@@ -118,16 +120,23 @@ public class OgcLayer {
return separateKey(layerName)[0];
}
+ public static String decodeLayerName(String layerName) {
+ if (layerName == null) {
+ return null;
+ }
+ try {
+ return URLDecoder.decode(layerName, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
public static String[] separateKey(String layerName) {
- if (layerName == null) {
- return null;
- }
- String lname;
- try {
- lname = URLDecoder.decode(layerName, "UTF-8");
- } catch (UnsupportedEncodingException e) {
- throw new RuntimeException(e);
- }
+ String lname = decodeLayerName(layerName);
+ if (lname == null) {
+ return null;
+ }
+ lname = StringUtils.strip(lname, OgcLayer.keySeparator);
return lname.split(OgcLayer.keySeparator, 2);
}
@@ -135,7 +144,7 @@ public class OgcLayer {
return getKey() + keySeparator + title;
}
- protected String createName(String key, String name) {
+ public static String createName(String key, String name) {
try {
return URLEncoder.encode(key + keySeparator + name, "UTF-8");
} catch (UnsupportedEncodingException e) {
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcNamespace.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcNamespace.java
index e9dd68f0cb..7f81d270a0 100644
--- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcNamespace.java
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcNamespace.java
@@ -66,6 +66,8 @@ public class OgcNamespace {
public static final String WCS112 = "http://www.opengis.net/wcs/1.1.2";
+ public static final String WCS11 = "http://www.opengis.net/wcs/1.1";
+
public static final String WMS = "http://www.opengis.net/wms";
public static final String WFS = "http://www.opengis.net/wfs";
@@ -78,4 +80,26 @@ public class OgcNamespace {
public static final String WMTS100 = "http://www.opengis.net/wmts/1.0";
+ public static final String WFS20 = "http://www.opengis.net/wfs/2.0";
+
+ public static final String FES20 = "http://www.opengis.net/fes/2.0";
+
+ public static final String GML32 = "http://www.opengis.net/gml/3.2";
+
+ public static final String SWE_GML32 = "http://www.opengis.net/swe/1.0/gml32";
+
+ public static final String AVWX11 = "http://www.eurocontrol.int/avwx/1.1";
+
+ public static final String OM_GML32 = "http://www.opengis.net/om/1.0/gml32";
+
+ public static final String SML_GML32 = "http://www.opengis.net/sensorML/1.0/gml32";
+
+ public static final String WX = "http://www.eurocontrol.int/wx/1.1";
+
+ public static final String WSNT = "http://docs.oasis-open.org/wsn/b-2";
+
+ public static final String WSA = "http://www.w3.org/2005/08/addressing";
+
+ public static final String OWSNT = "http://www.opengis.net/owsnt/1.1";
+
}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcOperationInfo.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcOperationInfo.java
index 7bc69e82ac..0f9341307e 100644
--- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcOperationInfo.java
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcOperationInfo.java
@@ -41,6 +41,8 @@ public class OgcOperationInfo {
protected String httpPostRes;
protected String httpGetRes;
+
+ protected String postEncoding;
protected List formats = new LinkedList();
@@ -206,4 +208,19 @@ public class OgcOperationInfo {
this.interpolationtypes = interpolationtypes;
}
+ /**
+ * @return the postEncoding
+ */
+ public String getPostEncoding() {
+ return postEncoding;
+ }
+
+ /**
+ * @param postEncoding
+ * the postEncoding to set
+ */
+ public void setPostEncoding(String postEncoding) {
+ this.postEncoding = postEncoding;
+ }
+
}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcPrefix.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcPrefix.java
index d47160e3fa..6de9a09e2a 100644
--- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcPrefix.java
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcPrefix.java
@@ -37,7 +37,7 @@ public class OgcPrefix {
*/
public static final String GML = "gml";
- public static final String ISM = "ism";
+ public static final String ISM = "icism";
/**
* Open Geospatial Consortium
@@ -109,4 +109,17 @@ public class OgcPrefix {
public static final String SLD = "sld";
public static final String SE = "se";
+
+ public static final String WX = "wx";
+
+ public static final String AVWX = "avwx";
+
+ public static final String FES = "fes";
+
+ public static final String WSNT = "wsn-b";
+
+ public static final String WSA = "wsa";
+
+ public static final String OWSNT = "owsnt";
+
}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcResponse.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcResponse.java
index 09b15f4bf5..f6a6b31624 100644
--- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcResponse.java
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/OgcResponse.java
@@ -24,12 +24,15 @@
**********************************************************************/
package com.raytheon.uf.edex.ogc.common;
+import com.raytheon.uf.edex.ogc.common.http.MimeType;
+
public class OgcResponse {
- public static final String TEXT_XML_MIME = "text/xml";
+ public static final MimeType TEXT_XML_MIME = new MimeType("text/xml");
- public static final String TEXT_HTML_MIME = "text/html";
+ public static final MimeType TEXT_HTML_MIME = new MimeType("text/html");
- public static final String APP_VND_OGC_SE_XML = "application/vnd.ogc.se_xml";
+ public static final MimeType APP_VND_OGC_SE_XML = new MimeType(
+ "application/vnd.ogc.se_xml");
public enum TYPE {
TEXT, IMAGE, BYTE, MULTIPART
@@ -39,7 +42,7 @@ public class OgcResponse {
NONE, BAD_REQ, INT_ERR, NOT_IMPLEMENTED
};
- protected String mimetype;
+ protected MimeType mimetype;
protected Object body;
@@ -49,19 +52,19 @@ public class OgcResponse {
protected ErrorType error = ErrorType.NONE;
- private String exceptionFormat = OgcResponse.TEXT_XML_MIME;
+ private MimeType exceptionFormat = OgcResponse.TEXT_XML_MIME;
- public OgcResponse(Object body, String mimetype, TYPE type) {
+ public OgcResponse(Object body, MimeType mimetype, TYPE type) {
this.body = body;
this.mimetype = mimetype;
this.type = type;
}
- public String getMimetype() {
+ public MimeType getMimetype() {
return mimetype;
}
- public void setMimetype(String mimetype) {
+ public void setMimetype(MimeType mimetype) {
this.mimetype = mimetype;
}
@@ -85,14 +88,14 @@ public class OgcResponse {
* @param exceptionFormat
* the exceptionFormat to set
*/
- public void setExceptionFormat(String exceptionFormat) {
+ public void setExceptionFormat(MimeType exceptionFormat) {
this.exceptionFormat = exceptionFormat;
}
/**
* @return the exceptionFormat
*/
- public String getExceptionFormat() {
+ public MimeType getExceptionFormat() {
return exceptionFormat;
}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/PeekingIterator.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/PeekingIterator.java
new file mode 100644
index 0000000000..aaaf5adc8c
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/PeekingIterator.java
@@ -0,0 +1,98 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.edex.ogc.common;
+
+import java.util.Iterator;
+
+/**
+ * Iterator that allows peeking at the next item without progressing
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Apr 29, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public class PeekingIterator implements Iterator {
+
+ private final Iterator iter;
+
+ private T next;
+
+ private boolean dirty = false;
+
+ /**
+ * @param iter
+ */
+ public PeekingIterator(Iterator iter) {
+ this.iter = iter;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Iterator#hasNext()
+ */
+ @Override
+ public boolean hasNext() {
+ if (dirty) {
+ return true;
+ }
+ return iter.hasNext();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.util.Iterator#next()
+ */
+ @Override
+ public T next() {
+ if (dirty) {
+ dirty = false;
+ return next;
+ }
+ return iter.next();
+ }
+
+ /**
+ * Look at next item without progressing. Will return the same item until
+ * {@link PeekingIterator#next()} is called.
+ *
+ * {@link PeekingIterator#hasNext()} should be called beforehand.
+ *
+ * @return
+ */
+ public T peek(){
+ if (dirty){
+ return next;
+ }
+ next = iter.next();
+ dirty = true;
+ return next;
+ }
+
+ /**
+ * Unsupported. Throws {@link UnsupportedOperationException}
+ */
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException(
+ "remove not supported on peeking iterator");
+ }
+
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/Version.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/Version.java
new file mode 100644
index 0000000000..f1a7889182
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/Version.java
@@ -0,0 +1,233 @@
+/**********************************************************************
+ *
+ * The following software products were developed by Raytheon:
+ *
+ * ADE (AWIPS Development Environment) software
+ * CAVE (Common AWIPS Visualization Environment) software
+ * EDEX (Environmental Data Exchange) software
+ * uFrame™ (Universal Framework) software
+ *
+ * Copyright (c) 2010 Raytheon Co.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ *
+ * Contractor Name: Raytheon Company
+ * Contractor Address:
+ * 6825 Pine Street, Suite 340
+ * Mail Stop B8
+ * Omaha, NE 68106
+ * 402.291.0100
+ *
+ **********************************************************************/
+package com.raytheon.uf.edex.ogc.common;
+
+import java.io.Serializable;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+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;
+
+@XmlAccessorType(XmlAccessType.NONE)
+@DynamicSerialize
+public class Version implements Comparable, Serializable {
+
+ private transient static final long serialVersionUID = -7496995218051649871L;
+
+ @DynamicSerializeElement
+ @XmlAttribute
+ protected int major = 0;
+
+ @DynamicSerializeElement
+ @XmlAttribute
+ protected int minor = 0;
+
+ @DynamicSerializeElement
+ @XmlAttribute
+ protected int micro = 0;
+
+ @DynamicSerializeElement
+ @XmlAttribute
+ protected String qualifier;
+
+ protected transient Pattern pattern = Pattern
+ .compile("^([0-9]+)(\\.([0-9]+)(\\.([0-9]+)(\\.([^\\.,]+))?)?)?$");
+
+ public Version() {
+ }
+
+ public Version(Version pv) {
+ this(pv.major, pv.minor, pv.micro, pv.qualifier);
+ }
+
+ public Version(int major, int minor, int micro) {
+ this(major, minor, micro, null);
+ }
+
+ public Version(int major, int minor, int micro, String qualifier) {
+ this.major = major;
+ this.micro = micro;
+ this.minor = minor;
+ this.qualifier = qualifier;
+ }
+
+ public Version(String version) throws InvalidVersionException {
+ fromString(version);
+ }
+
+ protected void fromString(String version) throws InvalidVersionException {
+ Matcher m = pattern.matcher(version.trim());
+ if (m.matches()) {
+ major = parseInt(m.group(1));
+ minor = parseInt(m.group(3));
+ micro = parseInt(m.group(5));
+ qualifier = m.group(7);
+ } else {
+ throw new InvalidVersionException("Invalid version string: '"
+ + version + "'");
+ }
+ }
+
+ public Version majorMinorOnly() {
+ return new Version(this.major, this.minor, 0);
+ }
+
+ protected int parseInt(String str) {
+ int rval = 0;
+ if (str != null) {
+ rval = Integer.parseInt(str);
+ }
+ return rval;
+ }
+
+ public int getMajor() {
+ return major;
+ }
+
+ public void setMajor(int major) {
+ this.major = major;
+ }
+
+ public int getMinor() {
+ return minor;
+ }
+
+ public void setMinor(int minor) {
+ this.minor = minor;
+ }
+
+ public int getMicro() {
+ return micro;
+ }
+
+ public void setMicro(int micro) {
+ this.micro = micro;
+ }
+
+ public String getQualifier() {
+ return qualifier;
+ }
+
+ public void setQualifier(String qualifier) {
+ this.qualifier = qualifier;
+ }
+
+ public String toString() {
+ String rval = String.format("%d.%d.%d", major, minor, micro);
+ if (this.qualifier != null && !this.qualifier.isEmpty()) {
+ rval += "." + qualifier;
+ }
+ return rval;
+ }
+
+ @Override
+ public int compareTo(Version o) {
+ if (o == null) {
+ return 1;
+ }
+ if (o == this) {
+ return 0;
+ }
+ int res = major - o.major;
+ if (res != 0) {
+ return res;
+ }
+ res = minor - o.minor;
+ if (res != 0) {
+ return res;
+ }
+ res = micro - o.micro;
+ if (res != 0) {
+ return res;
+ }
+ if (qualifier == null) {
+ if (o.qualifier != null) {
+ return -1;
+ }
+ } else if (o.qualifier == null) {
+ return 1;
+ } else {
+ return qualifier.compareTo(o.qualifier);
+ }
+
+ return 0;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + major;
+ result = prime * result + micro;
+ result = prime * result + minor;
+ result = prime * result
+ + ((qualifier == null) ? 0 : qualifier.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;
+ Version other = (Version) obj;
+ if (major != other.major)
+ return false;
+ if (micro != other.micro)
+ return false;
+ if (minor != other.minor)
+ return false;
+ if (qualifier == null) {
+ if (other.qualifier != null)
+ return false;
+ } else if (!qualifier.equals(other.qualifier))
+ return false;
+ return true;
+ }
+
+ /**
+ * @param other
+ * @return true if this and other have the same major and minor versions
+ */
+ public boolean equalsMajorMinor(Version other) {
+ if (other == null) {
+ return false;
+ }
+ if (major != other.major)
+ return false;
+ if (minor != other.minor)
+ return false;
+ return true;
+ }
+
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/colormap/StyleRuleLibrary.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/colormap/StyleRuleLibrary.java
index bfddc05b81..8995e44779 100644
--- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/colormap/StyleRuleLibrary.java
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/colormap/StyleRuleLibrary.java
@@ -32,15 +32,12 @@ package com.raytheon.uf.edex.ogc.common.colormap;
import java.io.InputStream;
import java.text.ParseException;
-import java.text.ParsePosition;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import javax.measure.converter.UnitConverter;
import javax.measure.unit.Unit;
-import javax.measure.unit.UnitFormat;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
@@ -50,8 +47,12 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlRootElement;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import com.raytheon.uf.common.dataplugin.PluginDataObject;
+import com.raytheon.uf.edex.ogc.common.spatial.AltUtil;
+import com.raytheon.uf.edex.ogc.common.spatial.VerticalCoordinate;
+import com.raytheon.uf.edex.ogc.common.spatial.VerticalCoordinate.Reference;
+import com.raytheon.uf.edex.ogc.common.spatial.VerticalEnabled;
+import com.raytheon.uf.edex.ogc.common.spatial.VerticalSpatialFactory;
/**
* TODO Add Description
@@ -66,8 +67,6 @@ public class StyleRuleLibrary {
@XmlElements({ @XmlElement(name = "styleRule", type = StyleRule.class) })
private List rules;
- private Log log = LogFactory.getLog(this.getClass());
-
private Map> _ruleMap;
public StyleRuleLibrary() {
@@ -111,43 +110,51 @@ public class StyleRuleLibrary {
return _ruleMap;
}
- /**
- * @param rule
- * @param dimensions
- * @param levelUnits
- * @return false if there was a range and it was out of bounds, true
- * otherwise
- * @throws ParseException
- */
- protected boolean initRule(StyleRule rule, Map dimensions,
- Map levelUnits) throws ParseException {
+ /**
+ * @param rule
+ * @param record
+ * @return false if there was a range and it was out of bounds, true
+ * otherwise
+ * @throws ParseException
+ */
+ protected boolean initRule(StyleRule rule, PluginDataObject record)
+ throws ParseException {
LevelRange range = rule.getLevelRange();
if (range != null) {
// only accept if range is ok
- return initRange(rule, dimensions, levelUnits);
+ return initRange(rule, record);
}
// if there is no range, we accept the rule
return true;
}
- /**
- * @param rule
- * @param dimensions
- * @param levelUnits
- * @return true if range is in bounds
- * @throws ParseException
- */
- protected boolean initRange(StyleRule rule, Map dimensions,
- Map levelUnits) throws ParseException {
+ /**
+ * @param rule
+ * @param record
+ * @return true if range is in bounds
+ * @throws ParseException
+ */
+ @SuppressWarnings("unchecked")
+ protected boolean initRange(StyleRule rule, PluginDataObject record)
+ throws ParseException {
LevelRange range = rule.getLevelRange();
- String level = range.getLevel();
- String levelValue = dimensions.get(level);
- if (levelValue != null) {
- Double lvlVal = Double.parseDouble(levelValue);
- String styleLevelUnit = range.getUnit();
- lvlVal = convert(lvlVal, styleLevelUnit, styleLevelUnit, levelUnits);
- if (lvlVal >= range.getLower() && lvlVal <= range.getUpper()) {
- setupLevelRange(rule, lvlVal);
+ VerticalEnabled enabled;
+ if (record instanceof VerticalEnabled>) {
+ enabled = (VerticalEnabled) record;
+ } else if ((enabled = (VerticalEnabled) VerticalSpatialFactory
+ .getEnabled(record.getClass())) != null) {
+ } else {
+ return false;
+ }
+ VerticalCoordinate vert = enabled.getVerticalCoordinate(record);
+
+ if (vert != null) {
+ Unit> styleLevelUnit = Unit.valueOf(range.getUnit());
+ double levelValue = AltUtil.convert(styleLevelUnit,
+ Reference.UNKNOWN, vert).getValue();
+ if (levelValue >= range.getLower()
+ && levelValue <= range.getUpper()) {
+ setupLevelRange(rule, levelValue);
// range is in bounds
return true;
}
@@ -156,43 +163,17 @@ public class StyleRuleLibrary {
return false;
}
- protected Double convert(Double lvlVal, String styleLevelUnit,
- String level, Map levelUnits) throws ParseException {
- if (styleLevelUnit == null || levelUnits == null) {
- return lvlVal;
- }
- String dataLevelUnit = levelUnits.get(level);
- if (dataLevelUnit == null) {
- return lvlVal;
- }
- UnitFormat formatter = UnitFormat.getInstance();
- try {
- Unit> ruleUnit = formatter.parseSingleUnit(styleLevelUnit,
- new ParsePosition(0));
- Unit> dataUnit = formatter.parseSingleUnit(dataLevelUnit,
- new ParsePosition(0));
-
- UnitConverter dataToRuleConv = dataUnit.getConverterTo(ruleUnit);
-
- return dataToRuleConv.convert(lvlVal.doubleValue());
-
- } catch (ParseException e) {
- log.error("Cannot convert units", e);
- throw e;
- }
- }
-
- public StyleRule getMatchForLayer(String layer,
- Map dimensions, Map levelUnits)
+ public StyleRule getMatchForLayer(PluginDataObject record)
throws ParseException {
- if (layer == null) {
+ if (record == null) {
return null;
}
+ String datauri = record.getDataURI();
for (StyleRule rule : rules) {
String pattern = rule.getLayerRegex();
- if (layer.matches(pattern)) {
+ if (datauri.matches(pattern)) {
// do not return rule if there is an invalid range
- if (initRule(rule, dimensions, levelUnits)) {
+ if (initRule(rule, record)) {
return rule;
}
}
@@ -200,10 +181,22 @@ public class StyleRuleLibrary {
return null;
}
- public StyleRule getLayerStyleWithNewCmap(String layer,
- Map dimensions, Map levelUnits,
+ public StyleRule getMatchForLayer(String layerName) throws ParseException {
+ if (layerName == null) {
+ return null;
+ }
+ for (StyleRule rule : rules) {
+ String pattern = rule.getLayerRegex();
+ if (layerName.matches(pattern)) {
+ return rule;
+ }
+ }
+ return null;
+ }
+
+ public StyleRule getLayerStyleWithNewCmap(PluginDataObject record,
String newColormap) throws ParseException {
- StyleRule rule = getMatchForLayer(layer, dimensions, levelUnits);
+ StyleRule rule = getMatchForLayer(record);
if (rule != null && newColormap != null) {
rule.setColorMapName(newColormap);
return rule;
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/CollectorAddonFactory.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/CollectorAddonFactory.java
new file mode 100644
index 0000000000..89f073cfd6
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/CollectorAddonFactory.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.edex.ogc.common.db;
+
+import com.raytheon.uf.common.dataplugin.PluginDataObject;
+
+/**
+ * Factory for creating collector addons
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 18, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public interface CollectorAddonFactory, R extends PluginDataObject> {
+
+ /**
+ * @return new instance of collector addon
+ */
+ public ICollectorAddon create();
+
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/DefaultLayerCollector.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/DefaultLayerCollector.java
index 8c6aeaa877..ba2c908d33 100644
--- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/DefaultLayerCollector.java
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/DefaultLayerCollector.java
@@ -1,73 +1,62 @@
-/**
- * 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.
- **/
- /**
- * SOFTWARE HISTORY
+/*
+ * The following software products were developed by Raytheon:
*
- * Date Ticket# Engineer Description
- * ------------ ---------- ----------- --------------------------
- * Nov 1, 2011 bclement Initial creation
+ * ADE (AWIPS Development Environment) software
+ * CAVE (Common AWIPS Visualization Environment) software
+ * EDEX (Environmental Data Exchange) software
+ * uFrame™ (Universal Framework) software
*
- **/
-
+ * Copyright (c) 2010 Raytheon Co.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ *
+ * Contractor Name: Raytheon Company
+ * Contractor Address:
+ * 6825 Pine Street, Suite 340
+ * Mail Stop B8
+ * Omaha, NE 68106
+ * 402.291.0100
+ *
+ */
package com.raytheon.uf.edex.ogc.common.db;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import com.raytheon.uf.common.dataplugin.PluginDataObject;
import com.raytheon.uf.common.status.IUFStatusHandler;
import com.raytheon.uf.common.status.UFStatus;
+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.query.DatabaseQuery;
+import com.raytheon.uf.edex.ogc.common.OgcException;
-/**
- *
- * Default Layer Collector
- *
- *
- * SOFTWARE HISTORY
- * Date Ticket# Engineer Description
- * ------------ ---------- ----------- --------------------------
- * 08/09/2012 754 dhladky initial creation, based on B Clements original
- * 04/01/2013 1746 dhladky Updated for MADIS configuration
- * 05/27/2013 753 dhladky Updated for wfs service
- *
- *
- * @author dhladky
- * @version 1.0
- */
+public abstract class DefaultLayerCollector, R extends PluginDataObject>
+ extends LayerCollector {
-public abstract class DefaultLayerCollector, R extends PluginDataObject>
- extends LayerCollector {
-
- private static final IUFStatusHandler statusHandler = UFStatus
+ protected static final IUFStatusHandler log = UFStatus
.getHandler(DefaultLayerCollector.class);
- protected Class recordClass;
+ protected Map layerMap;
- protected Class layerClass;
+ protected ReadWriteLock lock = new ReentrantReadWriteLock();
- public DefaultLayerCollector(LayerTransformer transformer,
- Class layerClass, Class recordClass) {
- super(transformer);
- this.recordClass = recordClass;
- this.layerClass = layerClass;
+ public DefaultLayerCollector(Class layerClass, Class recordClass,
+ ILayerStore store) {
+ super(layerClass, recordClass, store);
}
public void add(R... pdos) {
@@ -76,17 +65,38 @@ public abstract class DefaultLayerCollector coll);
-
- @Override
- protected L newLayer() {
- try {
- return layerClass.newInstance();
- } catch (Exception e) {
- statusHandler
- .error("Unable to instantiate class: " + layerClass, e);
- throw new RuntimeException(e);
+ @SuppressWarnings("unchecked")
+ public void addAll(Collection extends PluginDataObject> coll) {
+ if (layerMap == null) {
+ initMap();
}
+ Lock write = lock.writeLock();
+ write.lock();
+ ICollectorAddon addon = getAddon();
+ for (PluginDataObject pdo : coll) {
+ if (recordClass.equals(pdo.getClass())) {
+ R rec = (R) pdo;
+ String name = getLayerName(rec);
+ L layer = newLayer();
+ layer.setName(name);
+ if (!initializeLayer(layer, rec)) {
+ continue;
+ }
+ addToTimes(layer, rec);
+ addToDims(layer, rec);
+ L oldLayer = layerMap.get(name);
+ if (oldLayer == null) {
+ oldLayer = newLayer();
+ oldLayer.setName(name);
+ initializeLayer(oldLayer, rec);
+ layerMap.put(name, oldLayer);
+ }
+ oldLayer.update(layer);
+ addon.onCollect(layer, (R) pdo);
+ }
+ }
+ addon.onFinish();
+ write.unlock();
}
protected void addToTimes(L layer, R rec) {
@@ -100,7 +110,101 @@ public abstract class DefaultLayerCollector());
+ } catch (Exception e) {
+ log.error("Problem purging layers", e);
+ }
+ }
+ protected void clearLayersInternal() throws DataAccessLayerException {
+ Lock write = lock.writeLock();
+ write.lock();
+ if (layerMap != null) {
+ layerMap.clear();
+ }
+ write.unlock();
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void addFromDb() throws DataAccessLayerException {
+ DaoConfig conf = DaoConfig.forClass(recordClass);
+ CoreDao dao = new CoreDao(conf);
+ DatabaseQuery q = new DatabaseQuery(recordClass);
+ List recs = (List) dao.queryByCriteria(q);
+ addAll(recs);
+ }
+
+ public void purgeAll() {
+ try {
+ clearLayersInternal();
+ getAddon().onPurgeAll();
+ } catch (Exception e) {
+ log.error("problem purging layers", e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.raytheon.uf.edex.ogc.common.db.LayerCache#getLayers()
+ */
+ @Override
+ public List getLayers() throws OgcException {
+ List rval;
+ if (layerMap == null) {
+ initMap();
+ }
+ Lock read = lock.readLock();
+ read.lock();
+ rval = new ArrayList(layerMap.size());
+ for (String key : layerMap.keySet()) {
+ rval.add(copy(layerMap.get(key)));
+ }
+ read.unlock();
+ return rval;
+ }
+
+ protected void initMap() {
+ Lock write = lock.writeLock();
+ write.lock();
+ if (layerMap == null) {
+ layerMap = new ConcurrentHashMap();
+ try {
+ addFromDb();
+ } catch (DataAccessLayerException e) {
+ log.error("Problem loading layers from db", e);
+ // if we throw an internal server exception here, it would kill
+ // the ogc request, better to just not add those layers to
+ // response
+ }
+ }
+ write.unlock();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.raytheon.uf.edex.ogc.common.db.LayerCache#getLayer(java.lang.String)
+ */
+ @Override
+ public L getLayer(String name) throws OgcException {
+ if (layerMap == null) {
+ initMap();
+ }
+ L rval;
+ Lock read = lock.readLock();
+ read.lock();
+ rval = layerMap.get(name);
+ if (rval != null) {
+ rval = copy(layerMap.get(name));
+ }
+ read.unlock();
+ return rval;
+ }
}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/DefaultPointDataDimension.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/DefaultPointDataDimension.java
new file mode 100644
index 0000000000..16bece1b67
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/DefaultPointDataDimension.java
@@ -0,0 +1,51 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.edex.ogc.common.db;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * TODO Add Description
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * May 24, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public class DefaultPointDataDimension extends SimpleDimension {
+
+ private static final long serialVersionUID = 2947254963150347405L;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set getValues() {
+ return new HashSet(0);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getDefaultValue(SimpleLayer extends SimpleDimension> layer) {
+ return null;
+ }
+
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/FsLayerStore.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/FsLayerStore.java
new file mode 100644
index 0000000000..e4bf12b8b6
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/FsLayerStore.java
@@ -0,0 +1,368 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.edex.ogc.common.db;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
+
+import com.raytheon.uf.common.serialization.DynamicSerializationManager;
+import com.raytheon.uf.common.serialization.DynamicSerializationManager.SerializationType;
+import com.raytheon.uf.edex.ogc.common.AbstractFsStore;
+import com.raytheon.uf.edex.ogc.common.OgcException;
+import com.raytheon.uf.edex.ogc.common.OgcException.Code;
+
+/**
+ * Simple Layer store using file system
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Jun 4, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public class FsLayerStore extends AbstractFsStore implements ILayerStore {
+
+ private final DynamicSerializationManager serializer = DynamicSerializationManager
+ .getManager(SerializationType.Thrift);
+
+ private final Map, ReentrantReadWriteLock> _lockMap = new HashMap, ReentrantReadWriteLock>();
+
+ /**
+ * @param storeLocation
+ */
+ public FsLayerStore(File storeLocation) {
+ super(storeLocation);
+ }
+
+ /**
+ * @param storeName
+ * name of store relative to edex static base
+ */
+ public FsLayerStore(String storeName) {
+ this(findStore(storeName));
+ }
+
+ /**
+ * Get lock for class
+ *
+ * @param c
+ * @return
+ */
+ private ReentrantReadWriteLock getLock(Class> c) {
+ synchronized (_lockMap) {
+ ReentrantReadWriteLock rval = _lockMap.get(c);
+ if (rval == null) {
+ rval = new ReentrantReadWriteLock();
+ _lockMap.put(c, rval);
+ }
+ return rval;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see com.raytheon.uf.edex.ogc.common.db.LayerStore#get(java.lang.String,
+ * java.lang.Class)
+ */
+ @Override
+ public > L get(
+ String id, Class c) throws OgcException {
+ ReentrantReadWriteLock lock = getLock(c);
+ ReadLock readLock = lock.readLock();
+ readLock.lock();
+ try {
+ File layerFile = getLayerFileRead(id, c);
+ if (!layerFile.exists()) {
+ return null;
+ }
+ L rval = deserialize(layerFile, c);
+ return rval;
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private > L deserialize(
+ File f, Class c) throws OgcException {
+ try {
+ return (L) serializer.deserialize(new FileInputStream(f));
+ } catch (Exception e) {
+ throw new OgcException(Code.InternalServerError, e);
+ }
+ }
+
+ /**
+ * Get store directory for class, read only
+ *
+ * must be synchronized externally
+ *
+ * @param c
+ * @return file object that isn't guaranteed to exist
+ * @throws OgcException
+ */
+ private File getClassDirRead(Class> c) throws OgcException {
+ File rval = new File(storeLocation, c.getName());
+
+ if (!rval.isDirectory()) {
+ throw new OgcException(Code.InternalServerError,
+ rval.getAbsolutePath() + " is not a directory");
+ }
+ if (!rval.canRead()) {
+ throw new OgcException(Code.InternalServerError,
+ "Unable to read store directory: " + rval.getAbsolutePath());
+ }
+ return rval;
+ }
+
+ /**
+ * Get store directory for class for modification, creates if it doesn't
+ * exist
+ *
+ * must be synchronized externally
+ *
+ * @param c
+ * @param create
+ * true if method should create if non existent
+ * @return file object that is only guaranteed to exist if create is true
+ * @throws OgcException
+ */
+ private File getClassDirWrite(Class> c, boolean create)
+ throws OgcException {
+ File rval = new File(storeLocation, c.getName());
+ if (!rval.exists()) {
+ if (!create) {
+ return rval;
+ }
+ if (!rval.mkdir()) {
+ throw new OgcException(Code.InternalServerError,
+ "Unable to create store directory: "
+ + rval.getAbsolutePath());
+ }
+ }
+ if (!rval.isDirectory()) {
+ throw new OgcException(Code.InternalServerError,
+ rval.getAbsolutePath() + " is not a directory");
+ }
+ if (!rval.canWrite()) {
+ throw new OgcException(Code.InternalServerError,
+ "Unable to write to store directory: "
+ + rval.getAbsolutePath());
+ }
+ return rval;
+ }
+
+ /**
+ * Create file object for layer file for reading
+ *
+ * must be synchronized externally
+ *
+ * @param id
+ * @param c
+ * @return a file object whose path isn't guaranteed to exist
+ * @throws OgcException
+ */
+ private File getLayerFileRead(String id, Class> c) throws OgcException {
+ return new File(getClassDirRead(c), encode(id));
+ }
+
+ /**
+ * Create file object for layer file for writing
+ *
+ * must be synchronized externally
+ *
+ * @param id
+ * @param c
+ * @param createPath
+ * if true, path to file will be created if nonexistent
+ * @return
+ * @throws OgcException
+ */
+ private File getLayerFileWrite(String id, Class> c, boolean createPath)
+ throws OgcException {
+ return new File(getClassDirWrite(c, createPath), encode(id));
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.raytheon.uf.edex.ogc.common.db.LayerStore#getAll(java.lang.Class)
+ */
+ @Override
+ public > List getAll(
+ Class c) throws OgcException {
+ ReentrantReadWriteLock lock = getLock(c);
+ ReadLock readLock = lock.readLock();
+ readLock.lock();
+ try {
+ File classDir = getClassDirRead(c);
+ if (!classDir.exists()) {
+ return new ArrayList(0);
+ }
+ File[] listFiles = classDir.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File f) {
+ return f.isFile();
+ }
+ });
+ List rval = new ArrayList(listFiles.length);
+ for (File f : listFiles) {
+ rval.add(deserialize(f, c));
+ }
+ return rval;
+ } finally {
+ readLock.unlock();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.raytheon.uf.edex.ogc.common.db.LayerStore#createOrUpdate(com.raytheon
+ * .uf.edex.ogc.common.db.SimpleLayer)
+ */
+ @Override
+ public void createOrUpdate(SimpleLayer extends SimpleDimension> l)
+ throws OgcException {
+ Class> c = l.getClass();
+ ReentrantReadWriteLock lock = getLock(c);
+ WriteLock writeLock = lock.writeLock();
+ writeLock.lock();
+ try {
+ serialize(l, getLayerFileWrite(l.getIdentifier(), c, true));
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.raytheon.uf.edex.ogc.common.db.LayerStore#createOrUpdate(java.util
+ * .List)
+ */
+ @Override
+ public void createOrUpdate(
+ List> layers)
+ throws OgcException {
+ Map, List>> map = new HashMap, List>>();
+ for (SimpleLayer> l : layers) {
+ List> list = map.get(l.getClass());
+ if (list == null) {
+ list = new ArrayList>();
+ map.put(l.getClass(), list);
+ }
+ list.add(l);
+ }
+ for (Entry, List>> e : map.entrySet()) {
+ Class> c = e.getKey();
+ ReentrantReadWriteLock lock = getLock(c);
+ WriteLock writeLock = lock.writeLock();
+ writeLock.lock();
+ try {
+ for (SimpleLayer> l : e.getValue()) {
+ serialize(l, getLayerFileWrite(l.getIdentifier(), c, true));
+ }
+ } finally {
+ writeLock.unlock();
+ }
+ }
+ }
+
+ /**
+ * Store layer
+ *
+ * @param l
+ * @param f
+ * @throws OgcException
+ */
+ private void serialize(SimpleLayer> l, File f) throws OgcException {
+ try {
+ serializer.serialize(l, new FileOutputStream(f));
+ } catch (Exception e) {
+ throw new OgcException(Code.InternalServerError, e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.raytheon.uf.edex.ogc.common.db.LayerStore#delete(java.lang.String,
+ * java.lang.Class)
+ */
+ @Override
+ public void delete(String id, Class extends SimpleLayer>> c)
+ throws OgcException {
+ File layerFile = getLayerFileWrite(id, c, false);
+ if (!layerFile.exists()) {
+ return;
+ }
+ ReentrantReadWriteLock lock = getLock(c);
+ WriteLock writeLock = lock.writeLock();
+ writeLock.lock();
+ try {
+ if (layerFile.exists()) {
+ layerFile.delete();
+ }
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.raytheon.uf.edex.ogc.common.db.LayerStore#deleteAll(java.lang.Class)
+ */
+ @Override
+ public void deleteAll(Class extends SimpleLayer>> c)
+ throws OgcException {
+ ReentrantReadWriteLock lock = getLock(c);
+ WriteLock writeLock = lock.writeLock();
+ writeLock.lock();
+ try {
+ File classDir = getClassDirWrite(c, false);
+ if (!classDir.exists()) {
+ return;
+ }
+ for (File f : classDir.listFiles()) {
+ if (f.isFile()) {
+ f.delete();
+ }
+ }
+ } finally {
+ writeLock.unlock();
+ }
+ }
+
+}
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
new file mode 100644
index 0000000000..c9eb501a84
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/ICollectorAddon.java
@@ -0,0 +1,60 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.edex.ogc.common.db;
+
+import java.util.Date;
+import java.util.Set;
+
+import com.raytheon.uf.common.dataplugin.PluginDataObject;
+
+/**
+ * Interface for extending layer collectors to perform additional tasks
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Jul 17, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public interface ICollectorAddon, R extends PluginDataObject> {
+
+ /**
+ * Called after record is added to layer. Both should be treated as
+ * read-only.
+ *
+ * @param layer
+ * @param record
+ */
+ public void onCollect(final L layer, final R record);
+
+ /**
+ * Called after group of records have been added to layers
+ */
+ public void onFinish();
+
+ /**
+ * Called after collector has purged all data
+ */
+ public void onPurgeAll();
+
+ /**
+ * Called after collector has purged expired data
+ *
+ * @param timesToKeep
+ */
+ public void onPurgeExpired(Set timesToKeep);
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/ILayerCache.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/ILayerCache.java
new file mode 100644
index 0000000000..8967f08cbb
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/ILayerCache.java
@@ -0,0 +1,48 @@
+/*
+* The following software products were developed by Raytheon:
+*
+* ADE (AWIPS Development Environment) software
+* CAVE (Common AWIPS Visualization Environment) software
+* EDEX (Environmental Data Exchange) software
+* uFrame™ (Universal Framework) software
+*
+* Copyright (c) 2010 Raytheon Co.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+* http://www.eclipse.org/org/documents/epl-v10.php
+*
+*
+* Contractor Name: Raytheon Company
+* Contractor Address:
+* 6825 Pine Street, Suite 340
+* Mail Stop B8
+* Omaha, NE 68106
+* 402.291.0100
+*
+*
+* SOFTWARE HISTORY
+*
+* Date Ticket# Engineer Description
+* ------------ ---------- ----------- --------------------------
+* Sep 11, 2012 bclement Initial creation
+*
+*/
+package com.raytheon.uf.edex.ogc.common.db;
+
+import java.util.List;
+
+import com.raytheon.uf.edex.ogc.common.OgcException;
+
+/**
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public interface ILayerCache> {
+
+ public List getLayers() throws OgcException;
+
+ public L getLayer(String name) throws OgcException;
+
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/ILayerStore.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/ILayerStore.java
new file mode 100644
index 0000000000..67015384fa
--- /dev/null
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/ILayerStore.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright 09/24/12 Raytheon Company.
+ *
+ * Unlimited Rights
+ * This software was developed pursuant to Contract Number
+ * DTFAWA-10-D-00028 with the US Government. The US Government’s rights
+ * in and to this copyrighted software are as specified in DFARS
+ * 252.227-7014 which was made part of the above contract.
+ */
+package com.raytheon.uf.edex.ogc.common.db;
+
+import java.util.List;
+
+import com.raytheon.uf.edex.ogc.common.OgcException;
+
+/**
+ * Storage interface for layers
+ *
+ *
+ *
+ * SOFTWARE HISTORY
+ *
+ * Date Ticket# Engineer Description
+ * ------------ ---------- ----------- --------------------------
+ * Jun 4, 2013 bclement Initial creation
+ *
+ *
+ *
+ * @author bclement
+ * @version 1.0
+ */
+public interface ILayerStore {
+
+ /**
+ * Retrieve layer from store
+ *
+ * @param id
+ * @param c
+ * @return null if layer is not in store
+ * @throws OgcException
+ */
+ public > L get(
+ String id, Class c) throws OgcException;
+
+ /**
+ * Retrieve all layers for class
+ *
+ * @param c
+ * @return
+ * @throws OgcException
+ */
+ public > List getAll(
+ Class c) throws OgcException;
+
+ /**
+ * Persist layer
+ *
+ * @param layer
+ * @throws OgcException
+ */
+ public void createOrUpdate(SimpleLayer extends SimpleDimension> layer)
+ throws OgcException;
+
+ /**
+ * Persist layers
+ *
+ * @param layers
+ * @throws OgcException
+ */
+ public void createOrUpdate(
+ List> layers)
+ throws OgcException;
+
+ /**
+ * Remove layer with id from store
+ *
+ * @param id
+ * @param c
+ * @throws OgcException
+ */
+ public void delete(String id, Class extends SimpleLayer>> c)
+ throws OgcException;
+
+ /**
+ * Delete all layers with class c from store
+ *
+ * @param c
+ * @throws OgcException
+ */
+ public void deleteAll(Class extends SimpleLayer>> c)
+ throws OgcException;
+
+}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/LayerCollector.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/LayerCollector.java
index 0db22cf7e2..48f15b883d 100644
--- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/LayerCollector.java
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/LayerCollector.java
@@ -1,152 +1,139 @@
-/**
- * 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.
- **/
+/*
+ * The following software products were developed by Raytheon:
+ *
+ * ADE (AWIPS Development Environment) software
+ * CAVE (Common AWIPS Visualization Environment) software
+ * EDEX (Environmental Data Exchange) software
+ * uFrame™ (Universal Framework) software
+ *
+ * Copyright (c) 2010 Raytheon Co.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ *
+ * Contractor Name: Raytheon Company
+ * Contractor Address:
+ * 6825 Pine Street, Suite 340
+ * Mail Stop B8
+ * Omaha, NE 68106
+ * 402.291.0100
+ *
+ */
package com.raytheon.uf.edex.ogc.common.db;
+import java.lang.reflect.Constructor;
import java.util.Calendar;
import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.time.DateUtils;
-import com.raytheon.uf.common.datadelivery.harvester.HarvesterConfig;
-import com.raytheon.uf.common.datadelivery.harvester.HarvesterConfigurationManager;
-import com.raytheon.uf.common.datadelivery.harvester.OGCAgent;
-import com.raytheon.uf.common.datadelivery.registry.Coverage;
-import com.raytheon.uf.common.datadelivery.registry.DataLevelType;
-import com.raytheon.uf.common.datadelivery.registry.DataSet;
-import com.raytheon.uf.common.datadelivery.registry.DataSetMetaData;
-import com.raytheon.uf.common.datadelivery.registry.DataSetName;
-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.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.registry.handler.RegistryHandlerException;
+import com.raytheon.uf.common.dataplugin.PluginDataObject;
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.ogc.common.OgcException;
+import com.raytheon.uf.edex.ogc.common.OgcException.Code;
-/**
- *
- * Layer Collector
- *
- *
- * SOFTWARE HISTORY
- * Date Ticket# Engineer Description
- * ------------ ---------- ----------- --------------------------
- * 08/09/2012 754 dhladky initial creation, based on B Clements original
- * 04/22/2013 1746 dhladky Removed DB dependency from WFS code
- *
- *
- * @author dhladky
- * @version 1.0
- */
+public abstract class LayerCollector, R extends PluginDataObject>
+ implements ILayerCache {
-public abstract class LayerCollector> {
+ protected Class recordClass;
- private static final IUFStatusHandler statusHandler = UFStatus
- .getHandler(LayerCollector.class);
+ protected Class layerClass;
- protected LayerTransformer transformer;
-
- protected HarvesterConfig config = null;
-
- protected OGCAgent agent = null;
+ protected IUFStatusHandler log = UFStatus.getHandler(this.getClass());
- protected Map parameters = null;
+ protected final ILayerStore store;
- public LayerCollector(LayerTransformer transformer) {
- setTransformer(transformer);
- this.config = HarvesterConfigurationManager.getOGCConfiguration();
- setAgent((OGCAgent)config.getAgent());
- storeProvider(config.getProvider());
- }
+ protected CollectorAddonFactory addonFactory = new CollectorAddonFactory() {
+ @Override
+ public ICollectorAddon create() {
+ return new ICollectorAddon() {
+ @Override
+ public void onCollect(L layer, R record) {
+ }
- public HarvesterConfig getConfig() {
- return config;
- }
+ @Override
+ public void onFinish() {
+ }
- public void setConfig(HarvesterConfig config) {
- this.config = config;
- }
+ @Override
+ public void onPurgeAll() {
+ }
- public void update(L old, L shiny) {
- updateDates(old, shiny);
- updateDims(old, shiny);
- }
+ @Override
+ public void onPurgeExpired(Set timesToKeep) {
+ }
- public void updateDates(L old, L shiny) {
- Set shinyTimes = shiny.getTimes();
- Set oldTimes = old.getTimes();
- if (shinyTimes != null && shinyTimes != null) {
- for (Date time : shinyTimes) {
- oldTimes.add(time);
- }
+ };
}
+ };
+
+ public LayerCollector(Class layerClass, Class recordClass,
+ ILayerStore store) {
+ this.recordClass = recordClass;
+ this.layerClass = layerClass;
+ this.store = store;
}
- public void updateDims(L old, L shiny) {
- Set oldDims = old.getDimensions();
- Set shinyDims = shiny.getDimensions();
- if (oldDims != null) {
- if (shinyDims != null) {
- updateDimLists(oldDims, shinyDims);
- }
- }
+ /**
+ * Returns object for additional tasks at layer collection
+ *
+ * @return
+ */
+ public ICollectorAddon getAddon() {
+ return addonFactory.create();
}
- public Map getDimMap(Set dims) {
- HashMap rval = new HashMap(
- dims.size());
- for (DIMENSION sd : dims) {
- rval.put(sd.getName(), sd);
+ protected L copy(final L orig) throws OgcException {
+ L rval;
+ try {
+ Constructor constructor = layerClass.getConstructor(layerClass);
+ rval = constructor.newInstance(orig);
+ } catch (Exception e) {
+ log.error("Unable to copy layer: " + layerClass, e);
+ throw new OgcException(Code.InternalServerError);
}
return rval;
}
- public void updateDimLists(Set oldDims, Set shinyDims) {
- Map oldMap = getDimMap(oldDims);
- Map shinyMap = getDimMap(shinyDims);
- for (String name : shinyMap.keySet()) {
- DIMENSION shinyDim = shinyMap.get(name);
- DIMENSION oldDim = oldMap.get(name);
- if (oldDim == null) {
- oldDims.add(shinyDim);
- } else {
- updateDimValues(oldDim, shinyDim);
- }
+ protected L newLayer() {
+ try {
+ return layerClass.newInstance();
+ } catch (Exception e) {
+ log.error("Unable to instantiate class: " + layerClass, e);
+ throw new RuntimeException(e);
}
}
- public void updateDimValues(DIMENSION oldDim, DIMENSION shinyDim) {
- Set oldValues = oldDim.getValues();
- Set shinyValues = shinyDim.getValues();
- if (oldValues != null && shinyValues != null) {
- for (String val : shinyValues) {
- oldValues.add(val);
+ public void clearLayers(Class c) throws OgcException {
+ store.deleteAll(c);
+ }
+
+ public void replaceTimes(L layer) throws OgcException {
+ L old = store.get(layer.getIdentifier(), layerClass);
+ if (old == null) {
+ store.createOrUpdate(layer);
+ } else {
+ Set times = old.getTimes();
+ times.clear();
+ Set newTimes = layer.getTimes();
+ if (newTimes != null) {
+ times.addAll(newTimes);
}
+ store.createOrUpdate(layer);
+ }
+ }
+
+ public void updateLayer(L layer) throws OgcException {
+ L old = store.get(layer.getIdentifier(), layerClass);
+ if (old == null) {
+ store.createOrUpdate(layer);
+ } else {
+ old.update(layer);
+ store.createOrUpdate(layer);
}
}
@@ -172,6 +159,15 @@ public abstract class LayerCollector getDataLevelTypes(Parameter cp) {
- return cp.getLevelType();
- }
-
- protected abstract L newLayer();
-
- protected abstract void setCoverage(L layer);
-
- protected abstract Coverage getCoverage();
-
- public void setParameters(L layer) {
- synchronized (layer) {
- if (getParameters() == null || getParameters().isEmpty()) {
- parameters = new HashMap();
- for (Parameter parm : agent.getLayer(layer.getName())
- .getParameters()) {
- // place in map
- parameters.put(parm.getName(), parm);
- storeParameter(parm);
- }
- }
- }
- }
-
- public Map getParameters() {
- return parameters;
- }
-
- protected abstract void setDataSet(L layer);
-
- protected abstract DataSet getDataSet();
-
- protected abstract void setDataSetMetaData(L layer);
-
- protected abstract DataSetMetaData getDataSetMetaData();
-
- protected abstract DataType getDataType();
-
- public abstract Levels getLevels(DataLevelType type, String collectionName);
-
- public LayerTransformer getTransformer() {
- return transformer;
- }
-
- public void setTransformer(LayerTransformer transformer) {
- this.transformer = transformer;
- }
-
- public OGCAgent getAgent() {
- return agent;
- }
-
- public void setAgent(OGCAgent agent) {
- this.agent = agent;
+ public void setAddonFactory(CollectorAddonFactory addonFactory) {
+ this.addonFactory = addonFactory;
}
}
diff --git a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/LayerTransformer.java b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/LayerTransformer.java
index 6a96ed98bc..7e3e09faf4 100644
--- a/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/LayerTransformer.java
+++ b/edexOsgi/com.raytheon.uf.edex.ogc.common/src/com/raytheon/uf/edex/ogc/common/db/LayerTransformer.java
@@ -1,22 +1,26 @@
-/**
- * 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.
- **/
+/*
+ * The following software products were developed by Raytheon:
+ *
+ * ADE (AWIPS Development Environment) software
+ * CAVE (Common AWIPS Visualization Environment) software
+ * EDEX (Environmental Data Exchange) software
+ * uFrame™ (Universal Framework) software
+ *
+ * Copyright (c) 2010 Raytheon Co.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/org/documents/epl-v10.php
+ *
+ *
+ * Contractor Name: Raytheon Company
+ * Contractor Address:
+ * 6825 Pine Street, Suite 340
+ * Mail Stop B8
+ * Omaha, NE 68106
+ * 402.291.0100
+ *
+ */
package com.raytheon.uf.edex.ogc.common.db;
import java.util.ArrayList;
@@ -40,16 +44,13 @@ import org.geotools.geometry.jts.ReferencedEnvelope;
import org.opengis.referencing.ReferenceIdentifier;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
-import com.raytheon.uf.common.dataquery.db.QueryParam;
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.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.query.DatabaseQuery;
import com.raytheon.uf.edex.ogc.common.OgcBoundingBox;
import com.raytheon.uf.edex.ogc.common.OgcDimension;
+import com.raytheon.uf.edex.ogc.common.OgcException;
import com.raytheon.uf.edex.ogc.common.OgcGeoBoundingBox;
import com.raytheon.uf.edex.ogc.common.OgcLayer;
import com.raytheon.uf.edex.ogc.common.OgcStyle;
@@ -66,7 +67,6 @@ import com.vividsolutions.jts.geom.Polygon;
* Jun 13, 2011 bclement Initial creation
*
**/
-
public class LayerTransformer> {
protected static IUFStatusHandler log = UFStatus
@@ -78,14 +78,15 @@ public class LayerTransformer lcache;
+
protected static String timeUnit = "ISO8601";
- protected Class layerClass;
+ public static final Pattern frontDot = Pattern
+ .compile("^(-?[0-9]*\\.?[0-9]+)(.*)$");
- public static final Pattern frontDot = Pattern
- .compile("^(-?[0-9]*\\.?[0-9]+)(.*)$");
- public static final Pattern backDot = Pattern
- .compile("^(-?[0-9]+\\.?[0-9]*)(.*)$");
+ public static final Pattern backDot = Pattern
+ .compile("^(-?[0-9]+\\.?[0-9]*)(.*)$");
/**
* Construct a LayerTransformer that uses a different layerClass and
@@ -97,9 +98,9 @@ public class LayerTransformer layerClass) {
+ public LayerTransformer(String key, ILayerCache lcache) {
this.key = key;
- this.layerClass = layerClass;
+ this.lcache = lcache;
}
/**
@@ -107,18 +108,8 @@ public class LayerTransformer params = Arrays.asList(new QueryParam(field, name));
- List res;
- res = query(layerClass, params);
- if (res == null || res.isEmpty()) {
- return null;
- }
- if (res.size() > 1) {
- log.warn("Multiple layers found with the same name, returning first");
- }
- return layerClass.cast(res.get(0));
+ public L find(String name) throws OgcException {
+ return lcache.getLayer(name);
}
/**
@@ -127,32 +118,36 @@ public class LayerTransformer l = find(layer);
- return getDimension(l, dimension);
+ public DIMENSION getDimension(String layer, String dimension)
+ throws OgcException {
+ L l = find(layer);
+ if (l == null) {
+ return null;
+ }
+ return l.getDimension(dimension);
}
- /**
- * @param layer
- * @param dimension
- * @return null if layer/dimension not found
- */
- public static > DIMENSION getDimension(
- L layer,
- String dimension) {
- if (layer == null) {
- return null;
- }
- DIMENSION rval = null;
+ /**
+ * Get all dimensions that start with prefix. Case insensitive.
+ *
+ * @param layer
+ * @param prefix
+ * @return empty list if layer/dimension not found
+ */
+ public static > List getDimsByPrefix(
+ L layer, String prefix) {
+ List rval = new ArrayList(2);
+ if (layer == null) {
+ return rval;
+ }
for (DIMENSION d : layer.getDimensions()) {
- if (d.getName().equalsIgnoreCase(dimension)) {
- rval = d;
- break;
- }
- }
- return rval;
- }
+ String lower = d.getName().toLowerCase();
+ if (lower.startsWith(prefix.toLowerCase())) {
+ rval.add(d);
+ }
+ }
+ return rval;
+ }
/**
* @param dim
@@ -265,27 +260,28 @@ public class LayerTransformer(0);
}
- Set set = new TreeSet();
- set.addAll(times);
- Iterator i = set.iterator();
- StringBuilder sb = new StringBuilder();
- List rval = new ArrayList();
- Date curr = i.next();
- while (curr != null) {
- startRange(sb, curr);
- curr = endRange(curr, i, sb);
- if (curr != null) {
- rval.add(sb.toString());
- sb = new StringBuilder();
- }
+ if ( times.size() % 2 != 0){
+ String msg = "Odd number of times for layer " + layer.getName()
+ + ". Should be even to construct time ranges.";
+ log.warn(msg + " Dropping last time");
}
- String last = sb.toString();
- if (!last.isEmpty()) {
- rval.add(last);
+
+ Iterator iter = times.iterator();
+ int ranges = times.size() / 2;
+ List rval = new ArrayList(ranges);
+ for (int i = 0; i < ranges; ++i) {
+ Date start = iter.next();
+ Date end = iter.next();
+ rval.add(formatRange(start, end));
}
+
return rval;
}
+ protected static String formatRange(Date start, Date end) {
+ return format(start) + '/' + format(end) + "/0";
+ }
+
/**
* End a range started by startRange()
*
@@ -354,7 +350,7 @@ public class LayerTransformer getAllTimes() {
+ public TreeSet getAllTimes() throws OgcException {
TreeSet rval = new TreeSet();
List layers = getLayers();
for (L l : layers) {
@@ -363,16 +359,17 @@ public class LayerTransformer getLayers() {
- List rval = query(layerClass);
- return rval;
+ public List getLayers() throws OgcException {
+ return lcache.getLayers();
}
- public List getLayersAsOgc(TimeFormat tformat, StyleLookup lookup) {
+ public List getLayersAsOgc(TimeFormat tformat, StyleLookup lookup)
+ throws OgcException {
return transform(getLayers(), tformat, lookup);
}
- public List getLayersAsOgc(StyleLookup lookup) {
+ public List getLayersAsOgc(StyleLookup lookup)
+ throws OgcException {
return getLayersAsOgc(TimeFormat.LIST, lookup);
}
@@ -405,15 +402,9 @@ public class LayerTransformer List query(Class c) {
- return query(c, null);
- }
-
- protected List query(Class c, List params) {
- try {
- DatabaseQuery query = new DatabaseQuery(c);
- if (params != null && !params.isEmpty()) {
- for (QueryParam p : params) {
- query.addQueryParam(p);
- }
- }
- DaoConfig config = DaoConfig.forClass(layerClass);
- CoreDao dao = new CoreDao(config);
- @SuppressWarnings("unchecked")
- final List retVal = (List) dao.queryByCriteria(query);
- return retVal;
- } catch (Exception e) {
- log.error("Unable to query entity: " + c, e);
- return new ArrayList(0);
- }
- }
-
- protected > List unwrap(
- List holders) {
- List rval = new ArrayList(holders.size());
- for (H holder : holders) {
- rval.add(holder.getValue());
- }
- return rval;
- }
-
/**
* @param layerName
* @return null if layer name isn't found
* @throws DataAccessLayerException
*/
- public Date getLatestTime(String layerName) throws DataAccessLayerException {
+ public Date getLatestTime(String layerName) throws OgcException {
L simpleLayer = find(layerName);
return getLatestTime(simpleLayer);
}
@@ -557,25 +520,11 @@ public class LayerTransformer layerClass) {
- this.layerClass = layerClass;
- }
-
- /**
- * @return the layerClass
- */
- public Class getLayerClass() {
- return layerClass;
- }
-
/**
* @return
+ * @throws OgcException
*/
- public TreeSet getLatestTimes() {
+ public TreeSet getLatestTimes() throws OgcException {
List