summaryrefslogtreecommitdiffstats
path: root/petascope/src/petascope/wcps/server/core
diff options
context:
space:
mode:
Diffstat (limited to 'petascope/src/petascope/wcps/server/core')
-rw-r--r--petascope/src/petascope/wcps/server/core/AxisIterator.java111
-rw-r--r--petascope/src/petascope/wcps/server/core/AxisName.java57
-rw-r--r--petascope/src/petascope/wcps/server/core/BinaryOperationCoverageExpr.java125
-rw-r--r--petascope/src/petascope/wcps/server/core/BooleanScalarExpr.java138
-rw-r--r--petascope/src/petascope/wcps/server/core/CellDomainElement.java79
-rw-r--r--petascope/src/petascope/wcps/server/core/ComplexConstant.java121
-rw-r--r--petascope/src/petascope/wcps/server/core/CondenseOperation.java73
-rw-r--r--petascope/src/petascope/wcps/server/core/CondenseScalarExpr.java98
-rw-r--r--petascope/src/petascope/wcps/server/core/ConstantCoverageExpr.java164
-rw-r--r--petascope/src/petascope/wcps/server/core/ConstantList.java104
-rw-r--r--petascope/src/petascope/wcps/server/core/ConstructCoverageExpr.java161
-rw-r--r--petascope/src/petascope/wcps/server/core/CoverageExpr.java179
-rw-r--r--petascope/src/petascope/wcps/server/core/CoverageExprPairType.java103
-rw-r--r--petascope/src/petascope/wcps/server/core/CoverageInfo.java168
-rw-r--r--petascope/src/petascope/wcps/server/core/CoverageIterator.java94
-rw-r--r--petascope/src/petascope/wcps/server/core/Crs.java124
-rw-r--r--petascope/src/petascope/wcps/server/core/CrsTransformCoverageExpr.java42
-rw-r--r--petascope/src/petascope/wcps/server/core/DbMetadataSource.java1174
-rw-r--r--petascope/src/petascope/wcps/server/core/DimensionIntervalElement.java221
-rw-r--r--petascope/src/petascope/wcps/server/core/DimensionIntervalList.java55
-rw-r--r--petascope/src/petascope/wcps/server/core/DimensionPointElement.java130
-rw-r--r--petascope/src/petascope/wcps/server/core/DomainElement.java193
-rw-r--r--petascope/src/petascope/wcps/server/core/DynamicMetadataSource.java105
-rw-r--r--petascope/src/petascope/wcps/server/core/EncodeDataExpr.java96
-rw-r--r--petascope/src/petascope/wcps/server/core/ExtendCoverageExpr.java132
-rw-r--r--petascope/src/petascope/wcps/server/core/FieldInterpolationElement.java79
-rw-r--r--petascope/src/petascope/wcps/server/core/FieldName.java52
-rw-r--r--petascope/src/petascope/wcps/server/core/ICoverageInfo.java27
-rw-r--r--petascope/src/petascope/wcps/server/core/IDynamicMetadataSource.java33
-rw-r--r--petascope/src/petascope/wcps/server/core/IMetadataSource.java44
-rw-r--r--petascope/src/petascope/wcps/server/core/IRasNode.java27
-rw-r--r--petascope/src/petascope/wcps/server/core/InducedOperationCoverageExpr.java88
-rw-r--r--petascope/src/petascope/wcps/server/core/InterpolationMethod.java84
-rw-r--r--petascope/src/petascope/wcps/server/core/Metadata.java704
-rw-r--r--petascope/src/petascope/wcps/server/core/MetadataScalarExpr.java37
-rw-r--r--petascope/src/petascope/wcps/server/core/NumericScalarExpr.java173
-rw-r--r--petascope/src/petascope/wcps/server/core/ProcessCoveragesRequest.java252
-rw-r--r--petascope/src/petascope/wcps/server/core/RangeComponent.java87
-rw-r--r--petascope/src/petascope/wcps/server/core/RangeCoverageExpr.java83
-rw-r--r--petascope/src/petascope/wcps/server/core/RangeElement.java163
-rw-r--r--petascope/src/petascope/wcps/server/core/RangeField.java54
-rw-r--r--petascope/src/petascope/wcps/server/core/ReduceScalarExpr.java68
-rw-r--r--petascope/src/petascope/wcps/server/core/SDU.java191
-rw-r--r--petascope/src/petascope/wcps/server/core/ScalarExpr.java171
-rw-r--r--petascope/src/petascope/wcps/server/core/ScaleCoverageExpr.java149
-rw-r--r--petascope/src/petascope/wcps/server/core/SetMetadataCoverageExpr.java42
-rw-r--r--petascope/src/petascope/wcps/server/core/SliceCoverageExpr.java131
-rw-r--r--petascope/src/petascope/wcps/server/core/StringScalarExpr.java63
-rw-r--r--petascope/src/petascope/wcps/server/core/SubsetOperationCoverageExpr.java70
-rw-r--r--petascope/src/petascope/wcps/server/core/TrimCoverageExpr.java133
-rw-r--r--petascope/src/petascope/wcps/server/core/UnaryOperationCoverageExpr.java153
-rw-r--r--petascope/src/petascope/wcps/server/core/VariableReference.java56
-rw-r--r--petascope/src/petascope/wcps/server/core/WCPS.java184
-rw-r--r--petascope/src/petascope/wcps/server/core/Wgs84Crs.java123
-rw-r--r--petascope/src/petascope/wcps/server/core/XmlQuery.java236
55 files changed, 7804 insertions, 0 deletions
diff --git a/petascope/src/petascope/wcps/server/core/AxisIterator.java b/petascope/src/petascope/wcps/server/core/AxisIterator.java
new file mode 100644
index 0000000..7421448
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/AxisIterator.java
@@ -0,0 +1,111 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import java.math.BigInteger;
+import org.w3c.dom.*;
+
+public class AxisIterator implements IRasNode {
+
+ private String var, varTranslation;
+ private AxisName axis;
+ private NumericScalarExpr hi, lo;
+
+ public AxisIterator(Node node, XmlQuery xq, String newIteratorName) throws WCPSException, InvalidCrsException {
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+ System.err.println("Trying to parse AxisIterator ");
+
+ while (node != null) {
+ String nodeName = node.getNodeName();
+
+ if (nodeName.equals("iteratorVar")) {
+ var = node.getTextContent();
+ // This variable will be referenced later on. Translate it.
+ xq.addReferenceVariable(var, newIteratorName);
+ varTranslation = xq.getReferenceVariableName(var);
+ } else if (nodeName.equals("axis")) {
+ axis = new AxisName(node, xq);
+ } else {
+ // Should contain the limits
+ // TODO: Implement ImageCrsDomainMetadataType class
+ if (lo == null) {
+ lo = new NumericScalarExpr(node, xq);
+ } else if (hi == null) {
+ hi = new NumericScalarExpr(node, xq);
+ } else {
+ throw new WCPSException("Unknown node in AxisIterator: " + nodeName);
+ }
+ }
+
+ node = node.getNextSibling();
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+ }
+ }
+
+ public String toRasQL() {
+ String result = varTranslation + " in [" + lo.toRasQL() + ":" + hi.toRasQL() + "]";
+ return result;
+ }
+
+ /** Sets a new name for the iterator variable, to be used in the rasql query**/
+ public void setVariableTranslation(String newName) {
+ varTranslation = newName;
+ }
+
+ /** Return the Higher bound for the axis iterator.
+ * This only works for constant expressions.
+ * TODO: implement arbitrary expressions.
+ * @return BigInteger
+ */
+ public BigInteger getHigh() {
+ return SDU.str2integer(hi.toRasQL()).get(0);
+ }
+
+ /** Return the Lower bound for the axis iterator.
+ * This only works for constant expressions.
+ * TODO: implement arbitrary expressions.
+ * @return BIgInteger
+ */
+ public BigInteger getLow() {
+ return SDU.str2integer(lo.toRasQL()).get(0);
+ }
+
+ /* Return the variable name used in this axis */
+ public String getVar() {
+ return var;
+ }
+
+ public String getAxisType() {
+ return axis.toRasQL();
+ }
+
+ /* Returns the m-interval that this axis iterates over in a string form */
+ public String getInterval() {
+ return lo.toRasQL() + ":" + hi.toRasQL();
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/AxisName.java b/petascope/src/petascope/wcps/server/core/AxisName.java
new file mode 100644
index 0000000..5dd14e5
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/AxisName.java
@@ -0,0 +1,57 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import java.util.Collection;
+import org.w3c.dom.*;
+
+public class AxisName implements IRasNode {
+
+ private String name;
+
+ public AxisName(Node node, XmlQuery xq) throws WCPSException {
+ System.err.println("Trying axis node: " + node.getNodeName());
+
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ if (node != null && node.getNodeName().equals("axis")) {
+ String axis = node.getTextContent();
+ // validate axis name
+ IDynamicMetadataSource meta = xq.getMetadataSource();
+ Collection<String> axisNames = meta.getAxisNames();
+ if (axisNames.contains(axis)) {
+ this.name = axis;
+ } else {
+ throw new WCPSException("Unknown axis name " + axis);
+ }
+ } else {
+ throw new WCPSException("Could not find an axis node !");
+ }
+ }
+
+ public String toRasQL() {
+ return name;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/BinaryOperationCoverageExpr.java b/petascope/src/petascope/wcps/server/core/BinaryOperationCoverageExpr.java
new file mode 100644
index 0000000..2d1fb96
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/BinaryOperationCoverageExpr.java
@@ -0,0 +1,125 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class BinaryOperationCoverageExpr implements IRasNode, ICoverageInfo {
+
+ private IRasNode first, second;
+ private CoverageExprPairType pair;
+ private CoverageInfo info;
+ private String operation;
+
+ public BinaryOperationCoverageExpr(Node node, XmlQuery xq)
+ throws WCPSException, InvalidCrsException {
+ String nodeName = node.getNodeName();
+
+ System.err.println("Trying to parse binary operation: " + nodeName);
+ boolean okay = false; // will be true if the node is recognized
+
+ if (nodeName.equals("plus")) {
+ operation = "+";
+ okay = true;
+ }
+
+ if (nodeName.equals("minus")) {
+ operation = "-";
+ okay = true;
+ }
+
+ if (nodeName.equals("mult")) {
+ operation = "*";
+ okay = true;
+ }
+
+ if (nodeName.equals("div")) {
+ operation = "/";
+ okay = true;
+ }
+
+ if (nodeName.equals("and") || nodeName.equals("or") || nodeName.equals("xor")) {
+ operation = nodeName;
+ okay = true;
+ }
+
+ if (nodeName.equals("equals")) {
+ operation = "=";
+ okay = true;
+ }
+
+ if (nodeName.equals("lessThan")) {
+ operation = "<";
+ okay = true;
+ }
+
+ if (nodeName.equals("greaterThan")) {
+ operation = ">";
+ okay = true;
+ }
+
+ if (nodeName.equals("lessOrEqual")) {
+ operation = "<=";
+ okay = true;
+ }
+
+ if (nodeName.equals("greaterOrEqual")) {
+ operation = ">=";
+ okay = true;
+ }
+
+ if (nodeName.equals("notEqual")) {
+ operation = "!=";
+ okay = true;
+ }
+
+ if (nodeName.equals("overlay")) {
+ operation = "overlay";
+ okay = true;
+ }
+
+ if (!okay) {
+ throw new WCPSException("Unexpected binary operation : " + nodeName);
+ }
+
+ Node operand = node.getFirstChild();
+
+ while (operand.getNodeName().equals("#text")) {
+ operand = operand.getNextSibling();
+ }
+
+ pair = new CoverageExprPairType(operand, xq);
+ info = new CoverageInfo(((ICoverageInfo) pair).getCoverageInfo());
+ first = pair.getFirst();
+ second = pair.getSecond();
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ public String toRasQL() {
+ return "((" + first.toRasQL() + ")" + operation + "(" + second.toRasQL() + "))";
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/BooleanScalarExpr.java b/petascope/src/petascope/wcps/server/core/BooleanScalarExpr.java
new file mode 100644
index 0000000..1cbe079
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/BooleanScalarExpr.java
@@ -0,0 +1,138 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class BooleanScalarExpr implements IRasNode {
+
+ private IRasNode first, second;
+ private String op;
+ private boolean simple; // true if the expression is just a value
+ private String value;
+
+ public BooleanScalarExpr(Node node, XmlQuery xq) throws WCPSException, InvalidCrsException {
+ if (node == null) {
+ throw new WCPSException("Unexpected null node !");
+ }
+
+ String nodeName = node.getNodeName();
+
+ simple = false;
+
+ System.err.println("Parsing boolean scalar operation ...");
+
+ if (nodeName.equals("booleanConstant")) {
+ simple = true;
+ value = node.getFirstChild().getNodeValue();
+ } else if (nodeName.equals("booleanAnd")
+ || nodeName.equals("booleanOr")
+ || nodeName.equals("booleanXor")
+ || nodeName.equals("booleanLessThan")
+ || nodeName.equals("booleanLessOrEqual")
+ || nodeName.equals("booleanGreaterThan")
+ || nodeName.equals("booleanGreaterOrEqual")
+ || nodeName.equals("booleanEqualNumeric")
+ || nodeName.equals("booleanNotEqualNumeric")
+ || nodeName.equals("booleanEqualString")
+ || nodeName.equals("booleanNotEqualString")) {
+ // Logical operations
+ if (nodeName.equals("booleanAnd")
+ || nodeName.equals("booleanOr")
+ || nodeName.equals("booleanXor")) {
+ // Remove the "boolean" in front
+ op = nodeName.substring(7).toLowerCase();
+
+ Node child = node.getFirstChild();
+
+ first = new BooleanScalarExpr(child, xq);
+ child = child.getNextSibling();
+ second = new BooleanScalarExpr(child, xq);
+ } else // Boolean Comparison operations between numbers or strings
+ {
+ if (nodeName.equals("booleanLessThan") || nodeName.equals("booleanLessOrEqual")
+ || nodeName.equals("booleanGreaterThan") || nodeName.equals("booleanGreaterOrEqual")
+ || nodeName.equals("booleanEqualNumeric") || nodeName.equals("booleanNotEqualNumeric")) {
+ if (nodeName.equals("booleanLessThan")) {
+ op = "<";
+ }
+ if (nodeName.equals("booleanLessOrEqual")) {
+ op = "<=";
+ }
+ if (nodeName.equals("booleanGreaterThan")) {
+ op = ">";
+ }
+ if (nodeName.equals("booleanGreaterOrEqual")) {
+ op = ">=";
+ }
+ if (nodeName.equals("booleanEqualNumeric")) {
+ op = "=";
+ }
+ if (nodeName.equals("booleanNotEqualNumeric")) {
+ op = "!=";
+ }
+
+ Node child = node.getFirstChild();
+
+ first = new NumericScalarExpr(child, xq);
+ child = child.getNextSibling();
+ second = new NumericScalarExpr(child, xq);
+ } else {
+ if (nodeName.equals("booleanEqualString")) {
+ op = "=";
+ }
+ if (nodeName.equals("booleanNotEqualString")) {
+ op = "!=";
+ }
+
+ Node child = node.getFirstChild();
+
+ first = new StringScalarExpr(child, xq);
+ child = child.getNextSibling();
+ second = new StringScalarExpr(child, xq);
+ }
+ }
+
+ } else if (nodeName.equals("booleanNot")) {
+ op = "not";
+ first = new BooleanScalarExpr(node.getFirstChild(), xq);
+ } else {
+ throw new WCPSException("Unexpected Binary Expression node : "
+ + node.getNodeName());
+ }
+ System.err.println("*** Boolean Scalar Expr SUCCESS: " + node.getNodeName());
+ }
+
+ public String toRasQL() {
+ if (simple) {
+ return value;
+ }
+
+ if (op.equals("not")) {
+ return "not(" + first.toRasQL() + ")";
+ }
+
+ return "(" + first.toRasQL() + ")" + op + "(" + second.toRasQL() + ")";
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/CellDomainElement.java b/petascope/src/petascope/wcps/server/core/CellDomainElement.java
new file mode 100644
index 0000000..f5e069f
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/CellDomainElement.java
@@ -0,0 +1,79 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidMetadataException;
+import java.math.BigInteger;
+
+//A coverage axis in pixel coordinates. See the WCPS standard.
+public class CellDomainElement implements Cloneable {
+
+ private BigInteger hi;
+ private BigInteger lo;
+
+ public CellDomainElement(BigInteger lo, BigInteger hi) throws InvalidMetadataException {
+ if ((lo == null) || (hi == null)) {
+ throw new InvalidMetadataException(
+ "Invalid cell domain element: Bounds may not be null");
+ }
+
+ if (lo.compareTo(hi) == 1) {
+ throw new InvalidMetadataException(
+ "Invalid cell domain element: Lower bound cannot be larger than upper bound");
+ }
+
+ this.lo = lo;
+ this.hi = hi;
+
+ }
+
+ public CellDomainElement clone() {
+ try {
+ return new CellDomainElement(BigInteger.ZERO.add(lo),
+ BigInteger.ZERO.add(hi));
+ } catch (InvalidMetadataException ime) {
+ throw new RuntimeException(
+ "Invalid metadata while cloning CellDomainElement. This is a software bug in WCPS.",
+ ime);
+ }
+
+ }
+
+ public boolean equals(CellDomainElement cde) {
+ return lo.equals(cde.lo) && hi.equals(cde.hi);
+
+ }
+
+ public BigInteger getHi() {
+ return hi;
+
+ }
+
+ public BigInteger getLo() {
+ return lo;
+ }
+
+ public String toString() {
+ String result = "CellDomainElement [" + lo + ", " + hi + "]";
+ return result;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/ComplexConstant.java b/petascope/src/petascope/wcps/server/core/ComplexConstant.java
new file mode 100644
index 0000000..2d7312c
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/ComplexConstant.java
@@ -0,0 +1,121 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class ComplexConstant implements IRasNode {
+
+ private String re, im;
+
+ public ComplexConstant(String str) throws WCPSException {
+ boolean ok = true;
+ // We only accept the following String representation of a complex number: {re,im}
+ if (str.startsWith("{") && str.endsWith("}")) {
+ str = str.substring(1, str.length() - 2);
+ if (str.indexOf(",") != -1 && str.lastIndexOf(",") != str.indexOf(",")) {
+ int comma = str.indexOf(",");
+ re = str.substring(0, comma - 1);
+ im = str.substring(comma + 1, str.length() - comma - 1);
+ } else {
+ ok = false;
+ }
+ } else {
+ ok = false;
+ }
+ if (ok == false) {
+ throw new WCPSException("Could not parse Complex Constant !");
+ }
+
+ // parse the real part
+ try {
+ Integer real = Integer.parseInt(re);
+ } catch (NumberFormatException e) {
+ try {
+ Float real = Float.parseFloat(re);
+ } catch (NumberFormatException e2) {
+ throw new WCPSException("Could not parse float or integer "
+ + "number for real part of complex number:" + re);
+ }
+ }
+ // parse the imaginary part
+ try {
+ Integer imag = Integer.parseInt(im);
+ } catch (NumberFormatException e) {
+ try {
+ Float imag = Float.parseFloat(im);
+ } catch (NumberFormatException e2) {
+ throw new WCPSException("Could not parse float or integer "
+ + "number for imaginary part of complex number" + im);
+ }
+ }
+ }
+
+ public ComplexConstant(Node node, XmlQuery xq) throws WCPSException {
+ System.err.println("Parsing complex constant: " + node.getNodeName());
+
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ while (node != null) {
+ String name = node.getNodeName();
+ if (name.equals("re")) {
+ re = node.getNodeValue();
+ } else if (name.equals("im")) {
+ im = node.getNodeValue();
+ } else {
+ throw new WCPSException("Unknown node while processing complex constant: " + name);
+ }
+
+ node = node.getNextSibling();
+ }
+
+ // parse the real part
+ try {
+ Integer real = Integer.parseInt(re);
+ } catch (NumberFormatException e) {
+ try {
+ Float real = Float.parseFloat(re);
+ } catch (NumberFormatException e2) {
+ throw new WCPSException("Could not parse float or integer "
+ + "number for real part of complex number:" + re);
+ }
+ }
+ // parse the imaginary part
+ try {
+ Integer imag = Integer.parseInt(im);
+ } catch (NumberFormatException e) {
+ try {
+ Float imag = Float.parseFloat(im);
+ } catch (NumberFormatException e2) {
+ throw new WCPSException("Could not parse float or integer "
+ + "number for imaginary part of complex number" + im);
+ }
+ }
+ }
+
+ public String toRasQL() {
+ return "complex ( " + re + ", " + im + " ) ";
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/CondenseOperation.java b/petascope/src/petascope/wcps/server/core/CondenseOperation.java
new file mode 100644
index 0000000..08ac95c
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/CondenseOperation.java
@@ -0,0 +1,73 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class CondenseOperation implements IRasNode {
+
+ private String name;
+
+ public CondenseOperation(Node node, XmlQuery xq) throws WCPSException {
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ System.err.println("Parsing condense Operation: " + node.getNodeName());
+
+ String text = node.getNodeName();
+ this.name = formatOperation(text);
+
+ if (name == null) {
+ throw new WCPSException("Unknown condense operation: " + text);
+ }
+ }
+
+ private String formatOperation(String name) {
+ String shortOp = null;
+ if (name.equals("opPlus")) {
+ shortOp = "+";
+ }
+ if (name.equals("opMult")) {
+ shortOp = "*";
+ }
+ if (name.equals("opMin")) {
+ shortOp = "min";
+ }
+ if (name.equals("opMax")) {
+ shortOp = "max";
+ }
+ if (name.equals("opAnd")) {
+ shortOp = "and";
+ }
+ if (name.equals("opOr")) {
+ shortOp = "or";
+ }
+
+ return shortOp;
+ }
+
+ public String toRasQL() {
+ return name;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/CondenseScalarExpr.java b/petascope/src/petascope/wcps/server/core/CondenseScalarExpr.java
new file mode 100644
index 0000000..d983b1c
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/CondenseScalarExpr.java
@@ -0,0 +1,98 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import java.util.Vector;
+import org.w3c.dom.*;
+
+public class CondenseScalarExpr implements IRasNode {
+
+ private CondenseOperation op;
+ private Vector<AxisIterator> iterators;
+ private IRasNode using;
+ private IRasNode where;
+ private String axisIteratorString;
+ private String newIteratorName;
+
+ public CondenseScalarExpr(Node node, XmlQuery xq) throws WCPSException, InvalidCrsException {
+ if (node.getNodeName().equals("condense")) {
+ node = node.getFirstChild();
+ }
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ iterators = new Vector();
+ newIteratorName = xq.registerNewExpressionWithVariables();
+ System.err.println("Parsing Condense Scalar Expression: " + node.getNodeName());
+
+ while (node != null) {
+ String name = node.getNodeName();
+ if (op == null) {
+ op = new CondenseOperation(node, xq);
+ } else if (name.equals("iterator")) {
+ AxisIterator it = new AxisIterator(node.getFirstChild(), xq, newIteratorName);
+ iterators.add(it);
+ } else if (name.equals("where")) {
+ where = new BooleanScalarExpr(node.getFirstChild(), xq);
+ } else {
+ using = new CoverageExpr(node, xq);
+ }
+
+ node = node.getNextSibling();
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+ }
+
+ buildAxisIteratorDomain();
+ }
+
+ public String toRasQL() {
+ String result = "condense " + op.toRasQL() + " over ";
+ result += axisIteratorString;
+ if (where != null) {
+ result += where.toRasQL();
+ }
+ result += " using " + using.toRasQL();
+ return result;
+ }
+
+ /* Concatenates all the AxisIterators into one large multi-dimensional object,
+ * that will be used to build to RasQL query */
+ private void buildAxisIteratorDomain() {
+ axisIteratorString = "";
+ axisIteratorString += newIteratorName + " in [";
+
+ for (int i = 0; i < iterators.size(); i++) {
+ if (i > 0) {
+ axisIteratorString += ", ";
+ }
+ AxisIterator ai = iterators.elementAt(i);
+ axisIteratorString += ai.getInterval();
+ }
+
+ axisIteratorString += "]";
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/ConstantCoverageExpr.java b/petascope/src/petascope/wcps/server/core/ConstantCoverageExpr.java
new file mode 100644
index 0000000..6bdb4ae
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/ConstantCoverageExpr.java
@@ -0,0 +1,164 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import petascope.wcps.server.exceptions.InvalidMetadataException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Vector;
+import org.w3c.dom.*;
+
+public class ConstantCoverageExpr implements IRasNode, ICoverageInfo {
+
+ private String covName;
+ private Vector<AxisIterator> iterators;
+ private ConstantList valueList;
+ private CoverageInfo info;
+ private String axisIteratorString;
+ private int requiredListSize = 1;
+
+ public ConstantCoverageExpr(Node node, XmlQuery xq)
+ throws WCPSException, InvalidCrsException {
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ iterators = new Vector();
+ System.err.println("Parsing Constant Coverage Expr: " + node.getNodeName());
+
+ while (node != null) {
+ String name = node.getNodeName();
+ if (name.equals("name")) {
+ covName = node.getTextContent();
+ } else if (name.equals("axisIterator")) {
+ AxisIterator it = new AxisIterator(node.getFirstChild(), xq, "temp");
+ iterators.add(it);
+ } else {
+ valueList = new ConstantList(node, xq);
+ node = valueList.getLastNode();
+ }
+
+ node = node.getNextSibling();
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+ }
+
+ buildMetadata(xq);
+ buildAxisIteratorDomain();
+
+ // Sanity check: dimensions should match number of constants in the list
+ if (valueList.getSize() != requiredListSize) {
+ throw new WCPSException("The number of constants in the list do "
+ + "not match the dimensions specified !");
+ }
+ // Sanity check: metadata should have already been build
+ if (info == null) {
+ throw new WCPSException("Could not build constant coverage metadata !!!");
+ }
+ }
+
+ public String toRasQL() {
+ String result = "< ";
+ result += axisIteratorString + " ";
+ result += valueList.toRasQL();
+ result += ">";
+
+ return result;
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ /* Concatenates all the AxisIterators into one large multi-dimensional object,
+ * that will be used to build to RasQL query. Also counts how many elements
+ * fit in the specified dimensions. */
+ private void buildAxisIteratorDomain() {
+ requiredListSize = 1;
+ axisIteratorString = "";
+ axisIteratorString += "[";
+
+ for (int i = 0; i < iterators.size(); i++) {
+ if (i > 0) {
+ axisIteratorString += ", ";
+ }
+ AxisIterator ai = iterators.elementAt(i);
+ axisIteratorString += ai.getInterval();
+ requiredListSize *= (ai.getHigh().intValue() - ai.getLow().intValue() + 1);
+ }
+
+ axisIteratorString += "]";
+
+ System.err.println("Axes for ConstantCoverage tell us that the constant"
+ + "list should have exactly " + requiredListSize + " elements !");
+ }
+
+ /** Builds full metadata for the newly constructed coverage **/
+ private void buildMetadata(XmlQuery xq) throws WCPSException {
+ List<CellDomainElement> cellDomainList = new LinkedList<CellDomainElement>();
+ List<RangeElement> rangeList = new LinkedList<RangeElement>();
+ HashSet<String> nullSet = new HashSet<String>();
+ String nullDefault = "0";
+ nullSet.add(nullDefault);
+ HashSet<InterpolationMethod> interpolationSet = new HashSet<InterpolationMethod>();
+ InterpolationMethod interpolationDefault = new InterpolationMethod("none", "none");
+ interpolationSet.add(interpolationDefault);
+ String coverageName = covName;
+ List<DomainElement> domainList = new LinkedList<DomainElement>();
+
+ Iterator<AxisIterator> i = iterators.iterator();
+ while (i.hasNext()) {
+ // Build domain metadata
+ AxisIterator ai = i.next();
+ cellDomainList.add(new CellDomainElement(ai.getLow(), ai.getHigh()));
+ String axisName = ai.getVar();
+ String axisType = ai.getAxisType();
+ String crs = DomainElement.WGS84_CRS;
+ HashSet<String> crsset = new HashSet<String>();
+ crsset.add(crs);
+ DomainElement domain = new DomainElement(axisName, axisType,
+ ai.getLow().doubleValue(), ai.getHigh().doubleValue(),
+ null, null, crsset, xq.getMetadataSource().getAxisNames());
+ domainList.add(domain);
+ }
+ // TODO: check element datatypes and their consistency
+ // "unsigned int" is default datatype
+ rangeList.add(new RangeElement("dynamic_type", "unsigned int"));
+
+ try {
+ Metadata metadata = new Metadata(cellDomainList, rangeList, nullSet,
+ nullDefault, interpolationSet, interpolationDefault,
+ coverageName, domainList, null);
+ // Let the top-level query know the full metadata about us
+ xq.getMetadataSource().addDynamicMetadata(covName, metadata);
+ info = new CoverageInfo(metadata);
+ } catch (InvalidMetadataException e) {
+ throw new WCPSException("Could not build coverage '" + covName
+ + "' metadata !", e);
+ }
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/ConstantList.java b/petascope/src/petascope/wcps/server/core/ConstantList.java
new file mode 100644
index 0000000..cbbff16
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/ConstantList.java
@@ -0,0 +1,104 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import org.w3c.dom.*;
+
+public class ConstantList implements IRasNode {
+
+ private ArrayList<String> list;
+ private String val;
+ private Node lastNode;
+
+ public ConstantList(Node node, XmlQuery xq) throws WCPSException {
+ list = new ArrayList<String>();
+
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+ System.err.println("Trying to parse ConstantList ");
+
+ while (node != null) {
+ String nodeName = node.getNodeName();
+
+ if (nodeName.equals("value")) {
+ val = node.getTextContent();
+ checkConstant(val);
+ list.add(val);
+ lastNode = node;
+ } else {
+ throw new WCPSException("Unknown node in ConstantList: " + nodeName);
+ }
+
+ node = node.getNextSibling();
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+ }
+
+ System.err.println("Parsed constant list with " + list.size() + " elements !");
+ }
+
+ private void checkConstant(String val) throws WCPSException {
+ boolean ok = false;
+ try {
+ Integer.parseInt(val);
+ ok = true;
+ } catch (NumberFormatException e1) {
+ }
+ try {
+ Float.parseFloat(val);
+ ok = true;
+ } catch (NumberFormatException e2) {
+ }
+ try {
+ new ComplexConstant(val);
+ ok = true;
+ } catch (WCPSException e1) {
+ }
+
+ if (ok == false) {
+ throw new WCPSException("'" + val + "' is not an integer, float, or complex constant !");
+ }
+ }
+
+ public String toRasQL() {
+ String result = list.get(0);
+ for (int i = 1; i < list.size(); i++) {
+ result += ", " + list.get(i);
+ }
+ return result;
+ }
+
+ /** Size of all elements in the constant list **/
+ public int getSize() {
+ return list.size();
+ }
+
+ /** Return the last node of the constant list. **/
+ public Node getLastNode() {
+ return lastNode;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/ConstructCoverageExpr.java b/petascope/src/petascope/wcps/server/core/ConstructCoverageExpr.java
new file mode 100644
index 0000000..89343e8
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/ConstructCoverageExpr.java
@@ -0,0 +1,161 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import petascope.wcps.server.exceptions.InvalidMetadataException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Vector;
+import org.w3c.dom.*;
+
+public class ConstructCoverageExpr implements IRasNode, ICoverageInfo {
+
+ private String covName;
+ private Vector<AxisIterator> iterators;
+ private IRasNode values;
+ private CoverageInfo info;
+ private String axisIteratorString;
+ private String newIteratorName;
+
+ public ConstructCoverageExpr(Node node, XmlQuery xq)
+ throws WCPSException, InvalidCrsException {
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ iterators = new Vector();
+ System.err.println("Parsing Construct Coverage Expr: " + node.getNodeName());
+ newIteratorName = xq.registerNewExpressionWithVariables();
+
+ while (node != null) {
+ String name = node.getNodeName();
+ if (name.equals("name")) {
+ covName = node.getTextContent();
+ } else if (name.equals("axisIterator")) {
+ AxisIterator it = new AxisIterator(node.getFirstChild(), xq, newIteratorName);
+ iterators.add(it);
+ // Top level structures need to know about these iterators
+ CoverageIterator dyn = new CoverageIterator(it.getVar(), covName);
+ xq.addDynamicCoverageIterator(dyn);
+ } else {
+ /* The iterator is probably used in the "values" section,
+ * so send the iterator to the top-level query */
+ if (covName != null && iterators.size() > 0) {
+ buildMetadata(xq);
+ } else {
+ throw new WCPSException("Cannot build coverage metadata !!!");
+ }
+ // And only then start parsing the "values" section
+ values = new ScalarExpr(node, xq);
+ }
+
+ node = node.getNextSibling();
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+ }
+
+ buildAxisIteratorDomain();
+
+ // Sanity check: metadata should have already been build
+ if (info == null) {
+ throw new WCPSException("Could not build coverage metadata !!!");
+ }
+ }
+
+ public String toRasQL() {
+ String result = "marray ";
+ result += axisIteratorString;
+ result += " values " + values.toRasQL();
+
+ return result;
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ /* Concatenates all the AxisIterators into one large multi-dimensional object,
+ * that will be used to build to RasQL query */
+ private void buildAxisIteratorDomain() {
+ axisIteratorString = "";
+ axisIteratorString += newIteratorName + " in [";
+
+ for (int i = 0; i < iterators.size(); i++) {
+ if (i > 0) {
+ axisIteratorString += ", ";
+ }
+ AxisIterator ai = iterators.elementAt(i);
+ axisIteratorString += ai.getInterval();
+ }
+
+ axisIteratorString += "]";
+ }
+
+ /** Builds full metadata for the newly constructed coverage **/
+ private void buildMetadata(XmlQuery xq) throws WCPSException {
+ List<CellDomainElement> cellDomainList = new LinkedList<CellDomainElement>();
+ List<RangeElement> rangeList = new LinkedList<RangeElement>();
+ HashSet<String> nullSet = new HashSet<String>();
+ String nullDefault = "0";
+ nullSet.add(nullDefault);
+ HashSet<InterpolationMethod> interpolationSet = new HashSet<InterpolationMethod>();
+ InterpolationMethod interpolationDefault = new InterpolationMethod("none", "none");
+ interpolationSet.add(interpolationDefault);
+ String coverageName = covName;
+ List<DomainElement> domainList = new LinkedList<DomainElement>();
+
+ Iterator<AxisIterator> i = iterators.iterator();
+ while (i.hasNext()) {
+ // Build domain metadata
+ AxisIterator ai = i.next();
+ cellDomainList.add(new CellDomainElement(ai.getLow(), ai.getHigh()));
+ String axisName = ai.getVar();
+ String axisType = ai.getAxisType();
+ String crs = DomainElement.WGS84_CRS;
+ HashSet<String> crsset = new HashSet<String>();
+ crsset.add(crs);
+ DomainElement domain = new DomainElement(axisName, axisType,
+ ai.getLow().doubleValue(), ai.getHigh().doubleValue(),
+ null, null, crsset, xq.getMetadataSource().getAxisNames());
+ domainList.add(domain);
+ }
+ // "unsigned int" is default datatype
+ rangeList.add(new RangeElement("dynamic_type", "unsigned int"));
+
+ try {
+ Metadata metadata = new Metadata(cellDomainList, rangeList, nullSet,
+ nullDefault, interpolationSet, interpolationDefault,
+ coverageName, domainList, null);
+ // Let the top-level query know the full metadata about us
+ xq.getMetadataSource().addDynamicMetadata(covName, metadata);
+ info = new CoverageInfo(metadata);
+ } catch (InvalidMetadataException e) {
+ throw new WCPSException("Could not build coverage '" + covName
+ + "' metadata !", e);
+ }
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/CoverageExpr.java b/petascope/src/petascope/wcps/server/core/CoverageExpr.java
new file mode 100644
index 0000000..d9d9c70
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/CoverageExpr.java
@@ -0,0 +1,179 @@
+ /*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+import java.util.Iterator;
+
+public class CoverageExpr implements IRasNode, ICoverageInfo {
+
+ private IRasNode child;
+ private String childInfo;
+ private CoverageInfo info;
+ private boolean scalarExpr = false;
+// private String var;
+ private boolean simpleCoverage; // True is the coverage is just a string
+
+ public CoverageExpr(Node node, XmlQuery xq) throws WCPSException, InvalidCrsException {
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ if (node == null) {
+ throw new WCPSException("CoverageExprType parsing error!");
+ }
+
+ String nodeName = node.getNodeName();
+
+ simpleCoverage = false;
+ System.err.println("CoverageExprType: node " + nodeName);
+
+ if (nodeName.equals("coverage")) {
+ simpleCoverage = true;
+ childInfo = node.getFirstChild().getNodeValue();
+
+ if (!xq.isIteratorDefined(childInfo)) {
+ throw new WCPSException("Iterator " + childInfo + " not defined!");
+ }
+
+ Iterator<String> coverages = xq.getCoverages(childInfo);
+
+ info = new CoverageInfo(xq.getMetadataSource().read(coverages.next()));
+
+ while (coverages.hasNext()) { // Check if all the coverages are compatible
+ CoverageInfo tmp = new CoverageInfo(
+ xq.getMetadataSource().read(
+ coverages.next()));
+
+ if (!tmp.isCompatible(info)) {
+ throw new WCPSException(
+ "Incompatible coverages within the same iterator");
+ }
+ }
+
+ System.err.println("Found simple coverage definition: " + childInfo + ", "
+ + info.toString());
+ } else if (nodeName.equals("crsTransform")) {
+ // TODO: implement CrsTransform class
+ child = new CrsTransformCoverageExpr(node, xq);
+ } else if (nodeName.equals("scale")) {
+ // TODO: implement class ScaleCoverageExprType
+ child = new ScaleCoverageExpr(node, xq);
+ } else if (nodeName.equals("construct")) {
+ child = new ConstructCoverageExpr(node.getFirstChild(), xq);
+ } else if (nodeName.equals("const")) {
+ child = new ConstantCoverageExpr(node.getFirstChild(), xq);
+ } // else if (nodeName.equals("variableRef"))
+ // {
+ // child = new VariableReference(node, xq);
+ // }
+ else { // Try one of the groups
+ child = null;
+
+ if (child == null) {
+ try {
+ child = new SetMetadataCoverageExpr(node, xq);
+ System.err.println("Matched set metadata operation.");
+ } catch (WCPSException e) {
+ System.err.println("Failed to match set metadata operation: "
+ + e.toString() + "\nRetrying");
+ child = null;
+ }
+ }
+
+ if (child == null) {
+ try {
+ child = new InducedOperationCoverageExpr(node, xq);
+ System.err.println("Matched induced coverage expression operation.");
+ } catch (WCPSException e) {
+ System.err.println("Failed to match induced coverage expression operation: "
+ + e.toString() + "\nRetrying");
+ child = null;
+ if (e.getMessage().equals("Method not implemented")) {
+ throw e;
+ }
+ }
+ }
+
+ if (child == null) {
+ try {
+ child = new SubsetOperationCoverageExpr(node, xq);
+ System.err.println("Matched subset operation.");
+ } catch (WCPSException e) {
+ System.err.println("Failed to match subset operation: "
+ + "\nRetrying");
+ child = null;
+ }
+ }
+
+ if (child == null) {
+ try {
+ child = new ScalarExpr(node, xq);
+ this.scalarExpr = true;
+ System.err.println("Matched scalar expression.");
+ } catch (WCPSException e) {
+ System.err.println("Failed to match scalar expression: "
+ + "\nRetrying");
+ child = null;
+ }
+ }
+ }
+
+ if (!simpleCoverage && (child == null)) {
+ throw new WCPSException("Invalid coverage Expression, next node: "
+ + node.getNodeName());
+ }
+
+ if (info == null) {
+ System.err.println(node.getNodeName());
+ info = new CoverageInfo(((ICoverageInfo) child).getCoverageInfo());
+ }
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ public boolean isScalarExpr()
+ {
+ return scalarExpr;
+ }
+
+ public ScalarExpr getScalarExpr()
+ {
+ ScalarExpr r = null;
+ if (scalarExpr)
+ r = (ScalarExpr) child;
+ return r;
+ }
+
+ public String toRasQL() {
+ if (simpleCoverage) {
+ return childInfo;
+ } else {
+ return child.toRasQL();
+ }
+ }
+};
diff --git a/petascope/src/petascope/wcps/server/core/CoverageExprPairType.java b/petascope/src/petascope/wcps/server/core/CoverageExprPairType.java
new file mode 100644
index 0000000..d52e74c
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/CoverageExprPairType.java
@@ -0,0 +1,103 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class CoverageExprPairType implements IRasNode, ICoverageInfo {
+
+ private IRasNode first, second;
+ private CoverageInfo info;
+ private boolean ok = false;
+
+ public CoverageExprPairType(Node node, XmlQuery xq)
+ throws WCPSException, InvalidCrsException {
+ String nodeName = node.getNodeName();
+
+ System.err.println("Trying to parse a coverage expression pair ... Starting at node "
+ + nodeName);
+
+ // Combination 1: CoverageExprType + ScalarExprType
+ if (ok == false) {
+ try {
+ first = new CoverageExpr(node, xq);
+ second = new ScalarExpr(node.getNextSibling(), xq);
+ info = new CoverageInfo(((ICoverageInfo) first).getCoverageInfo());
+ ok = true;
+ } catch (WCPSException e) {
+ System.err.println("Failed to parse CoverageExprType + ScalarExprType!");
+ }
+ }
+
+ // Combination 2: ScalarExprType + CoverageExprType
+ if (ok == false) {
+ try {
+ first = new ScalarExpr(node, xq);
+ second = new CoverageExpr(node.getNextSibling(), xq);
+ info = new CoverageInfo(((ICoverageInfo) second).getCoverageInfo());
+ ok = true;
+ } catch (WCPSException e) {
+ System.err.println("Failed to parse ScalarExprType + CoverageExprType!");
+ }
+ }
+
+ // Combination 3: CoverageExprType + CoverageExprType
+ if (ok == false) {
+ try {
+ first = new CoverageExpr(node, xq);
+ second = new CoverageExpr(node.getNextSibling(), xq);
+ info = new CoverageInfo(((ICoverageInfo) first).getCoverageInfo());
+ ok = true;
+ } catch (WCPSException e) {
+ System.err.println("Failed to parse a CoverageExprType + CoverageExprType!");
+ }
+ }
+
+
+
+ if (ok == false) {
+ throw new WCPSException("Could not parse a coverage expression pair !");
+ }
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ public String toRasQL() {
+ if (ok == true) {
+ return first.toRasQL() + second.toRasQL();
+ } else {
+ return " error ";
+ }
+ }
+
+ public IRasNode getFirst() {
+ return first;
+ }
+
+ public IRasNode getSecond() {
+ return second;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/CoverageInfo.java b/petascope/src/petascope/wcps/server/core/CoverageInfo.java
new file mode 100644
index 0000000..d5eb447
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/CoverageInfo.java
@@ -0,0 +1,168 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class CoverageInfo {
+
+ private List<CellDomainElement> cellDomains;
+ private List<DomainElement> domains;
+ private String coverageName;
+
+ public CoverageInfo(CoverageInfo other) {
+ cellDomains = new ArrayList<CellDomainElement>();
+ domains = new ArrayList<DomainElement>();
+ int N = other.getNumDimensions();
+
+ for (int i = 0; i < N; ++i) {
+ cellDomains.add(other.getCellDomainElement(i));
+ domains.add(other.getDomainElement(i));
+ }
+
+ coverageName = other.getCoverageName();
+ }
+
+ public CoverageInfo(Metadata m) {
+ cellDomains = new ArrayList<CellDomainElement>();
+ domains = new ArrayList<DomainElement>();
+ Iterator<CellDomainElement> itcde = m.getCellDomainIterator();
+
+ while (itcde.hasNext()) {
+ cellDomains.add(itcde.next());
+ }
+
+ Iterator<DomainElement> itde = m.getDomainIterator();
+
+ while (itde.hasNext()) {
+ domains.add(itde.next());
+ }
+
+ coverageName = m.getCoverageName();
+ }
+
+ public boolean isCompatible(CoverageInfo other) {
+ if (getNumDimensions() != other.getNumDimensions()) {
+ System.err.println("The number of dimensions doesn't match");
+ return false;
+ }
+
+ {
+ Iterator<CellDomainElement> it = cellDomains.iterator();
+ int index = 0;
+
+ while (it.hasNext()) {
+ CellDomainElement me, you;
+
+ me = it.next();
+ you = other.getCellDomainElement(index++);
+
+ if (!me.getHi().equals(you.getHi())) {
+ System.err.println("High values don't match: "
+ + me.getHi().toString() + ", "
+ + you.getHi().toString());
+ return false;
+ }
+
+ if (!me.getLo().equals(you.getLo())) {
+ System.err.println("Low values don't match: "
+ + me.getLo().toString() + ", "
+ + you.getLo().toString());
+ return false;
+ }
+ }
+ }
+ {
+ Iterator<DomainElement> it = domains.iterator();
+ int index = 0;
+
+ while (it.hasNext()) {
+ DomainElement me, you;
+
+ me = it.next();
+ you = other.getDomainElement(index++);
+
+ if (!me.getName().equals(you.getName())) {
+ System.err.println("Domain element names don't match: '"
+ + me.getName() + "' and '"
+ + you.getName() + "'.");
+ return false;
+ }
+
+ // if (me.getName() != you.getName()) return false;
+ }
+ }
+ return true;
+ }
+
+ int getNumDimensions() {
+ return cellDomains.size();
+ }
+
+ public CellDomainElement getCellDomainElement(int dim) {
+ return cellDomains.get(dim);
+ }
+
+ public DomainElement getDomainElement(int dim) {
+ return domains.get(dim);
+ }
+
+ public String getCoverageName() {
+ return coverageName;
+ }
+
+ public void removeDimension(int dim) {
+ cellDomains.remove(dim);
+ domains.remove(dim);
+ }
+
+ public void setDimension(int dim, CellDomainElement cde, DomainElement de) {
+ cellDomains.set(dim, cde);
+ domains.set(dim, de);
+ }
+
+ public void setCellDimension(int dim, CellDomainElement cde) {
+ cellDomains.set(dim, cde);
+ }
+
+ public int getDomainIndexByName(String name) throws WCPSException {
+ System.err.println("Searching for Domain name : " + name);
+ System.err.println("Available domain names are: " + domains.toString());
+
+ Iterator<DomainElement> it = domains.iterator();
+ int index = 0;
+
+ while (it.hasNext()) {
+ if (name.equals(it.next().getName())) {
+ return index;
+ }
+
+ index++;
+ }
+
+ System.err.println("ERROR: Axis name not found: " + name);
+ throw new WCPSException("Domain name not found: " + name);
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/CoverageIterator.java b/petascope/src/petascope/wcps/server/core/CoverageIterator.java
new file mode 100644
index 0000000..570295e
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/CoverageIterator.java
@@ -0,0 +1,94 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.ResourceException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class CoverageIterator implements IRasNode {
+
+ private List<String> coverageNames;
+ private String iteratorName;
+ private boolean dynamic = false; // created from a Construct Coverage expr?
+
+ public CoverageIterator(Node x, XmlQuery xq) throws WCPSException {
+ IDynamicMetadataSource source = xq.getMetadataSource();
+ coverageNames = new ArrayList<String>();
+ if (!x.getNodeName().equals("coverageIterator")) {
+ throw new WCPSException("Invalid cast from " + x.getNodeName()
+ + " XML node to CoverageIterator node");
+ }
+
+ Node it = x.getFirstChild();
+ while (it != null) {
+ if (it.getNodeName().equals("#text")) {
+ it = it.getNextSibling();
+ continue;
+ }
+
+ if (it.getNodeName().equals("iteratorVar")) {
+ iteratorName = it.getFirstChild().getNodeValue();
+ System.err.println("*** Iterator variable : " + iteratorName);
+ } else if (it.getNodeName().equals("coverageName")) {
+ String cn = it.getFirstChild().getNodeValue();
+ System.err.println("*** Coverage reference : " + cn);
+ try {
+ if (!source.coverages().contains(cn)) {
+ throw new WCPSException("Unknown coverage " + cn);
+ }
+ } catch (ResourceException e) {
+ throw new WCPSException(
+ "Cannot load coverage information!", e);
+ }
+
+ coverageNames.add(cn);
+ }
+
+ it = it.getNextSibling();
+ }
+ }
+
+ public CoverageIterator(String iterator, String coverage) throws WCPSException {
+ coverageNames = new ArrayList<String>();
+ iteratorName = iterator;
+ coverageNames.add(coverage);
+ this.dynamic = true;
+ }
+
+ public Iterator<String> getCoverages() {
+ return coverageNames.iterator();
+ }
+
+ public String getIteratorName() {
+ return iteratorName;
+ }
+
+ public String toRasQL() {
+ // TODO(andreia) : How to translate multiple coverages?
+ return coverageNames.get(0) + " AS " + iteratorName;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/Crs.java b/petascope/src/petascope/wcps/server/core/Crs.java
new file mode 100644
index 0000000..e83bed7
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/Crs.java
@@ -0,0 +1,124 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import java.util.Iterator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcs.server.exceptions.NoApplicableCodeException;
+
+public class Crs implements IRasNode {
+
+ Logger LOG = LoggerFactory.getLogger(Crs.class);
+ private String crsName;
+
+ public Crs(Node node, XmlQuery xq) throws WCPSException, InvalidCrsException {
+ System.err.println("Parsing crs name ...");
+
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ if (node != null && node.getNodeName().equals("srsName")) {
+ String val = node.getTextContent();
+ this.crsName = val;
+ if (crsName.equals(DomainElement.IMAGE_CRS) || crsName.equals(DomainElement.WGS84_CRS)) {
+ System.err.println("Found CRS: " + crsName);
+ } else {
+ throw new InvalidCrsException("Invalid CRS: '" + crsName + "'");
+ }
+ } else {
+ throw new WCPSException("Could not find a 'srsName' node !");
+ }
+ }
+
+ /***
+ * Converts an array of 4 coordinates (bounding box) expressed in the
+ * current CRS to pixel coordinates.
+ * @param u2 Left-most X point (CRS coordinate)
+ * @param u3 Right-most X point (CRS coordinate)
+ * @param v2 Lower-most Y point (CRS coordinate)
+ * @param v3 Upper-most Y point (CRS coordinate)
+ * @return array of integers, pixel coordinates that represent the given CRS
+ * coordinates.
+ */
+ public long[] convertToPixelCoordinates(Metadata meta, String axisName, Double u2, Double u3, Double v2, Double v3) throws NoApplicableCodeException {
+ Wgs84Crs crs = meta.getCrs();
+ long px0 = -1, px1 = -1, py0 = -1, py1 = -1;
+ // Convert bounding box values to pixel coordinates
+ if (crsName.equals(DomainElement.WGS84_CRS)) {
+ LOG.trace("Converting WGS84 axis {} interval to pixel coordinates ...", axisName);
+ /* Image coordinates */
+ Iterator<CellDomainElement> it = meta.getCellDomainIterator();
+ CellDomainElement X = it.next();
+ CellDomainElement Y = it.next();
+ if (X == null || Y == null) {
+ LOG.error("Could not find the X or Y axis for coverage: " + meta.getCoverageName());
+ throw new NoApplicableCodeException("Could not find the X or Y axis for coverage: " + meta.getCoverageName());
+ }
+ int x0 = X.getLo().intValue();
+ int x1 = X.getHi().intValue();
+ int y0 = Y.getLo().intValue();
+ int y1 = Y.getHi().intValue();
+
+ LOG.trace("Pixel Coordinates: X01 (" + x0 + "," + x1 + ") + Y01 (" + y0 + "," + y1 + ")");
+ /* CRS span */
+ double x2 = crs.getLow1();
+ double y2 = crs.getLow2();
+ double x3 = crs.getHigh1();
+ double y3 = crs.getHigh2();
+ LOG.trace("CRS Coordinates: X23 (" + x2 + "," + x3 + ") + Y23 (" + y2 + "," + y3 + ")");
+ /* For WGS84, the offset = (# pixels)/(CRS span) */
+ double oX = crs.getOffset1();
+ double oY = crs.getOffset2();
+
+ /* The actual conversion is below: */
+ if (axisName.equals("X")) {
+ px0 = Math.round((u2 - x2) / oX) + x0;
+ px1 = Math.round((u3 - u2) / oX) + px0;
+ LOG.debug("CRS Coordinates on axis X: U23 (" + u2 + "," + u3 + ")");
+ LOG.debug("Pixel Coordinates on axis X: U01 (" + px0 + "," + px1 + ") ");
+ }
+ if (axisName.equals("Y")) {
+ py0 = Math.round((y3 - v3) / oY) + y0;
+ py1 = Math.round((v3 - v2) / oY) + py0;
+ LOG.debug("CRS Coordinates on axis Y: V23 (" + v2 + "," + v3 + ")");
+ LOG.debug("Pixel Coordinates on axis Y: V01 (" + py0 + "," + py1 + ")");
+ }
+
+ }
+ long[] longCoord = {px0, px1, py0, py1};
+
+ return longCoord;
+ }
+
+ public String toRasQL() {
+ return crsName;
+ }
+
+ public String getName() {
+ return crsName;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/CrsTransformCoverageExpr.java b/petascope/src/petascope/wcps/server/core/CrsTransformCoverageExpr.java
new file mode 100644
index 0000000..42f900c
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/CrsTransformCoverageExpr.java
@@ -0,0 +1,42 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+//TODO(smsorin): how do we do combine this ?
+public class CrsTransformCoverageExpr implements IRasNode, ICoverageInfo {
+
+ public CrsTransformCoverageExpr(Node node, XmlQuery xq)
+ throws WCPSException {
+ throw new WCPSException("Method not implemented");
+ }
+
+ public String toRasQL() {
+ return "";
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return null;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/DbMetadataSource.java b/petascope/src/petascope/wcps/server/core/DbMetadataSource.java
new file mode 100644
index 0000000..90d6a77
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/DbMetadataSource.java
@@ -0,0 +1,1174 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+//~--- JDK imports ------------------------------------------------------------
+import petascope.wcps.server.exceptions.ResourceException;
+import petascope.wcps.server.exceptions.InvalidWcpsRequestException;
+import petascope.wcps.server.exceptions.InvalidMetadataException;
+import java.math.BigInteger;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Savepoint;
+import java.sql.Statement;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The DbMetadataSource is a IMetadataSource that uses a relational database. It
+ * keeps a global connection which is reused on future requests, as well as between
+ * threads. Before each read, the connection is verified to be valid, and
+ * recreated if necessary. This IMetadataSource is not particularly efficient,
+ * because it accesses the database at least once for every read. To increase
+ * efficiency, wrap a CachedMetadataSource around this one.
+ *
+ */
+public class DbMetadataSource implements IMetadataSource {
+
+ private static Logger LOG = LoggerFactory.getLogger(DbMetadataSource.class);
+
+ /* Status variables */
+ private boolean initializing;
+ private boolean checkAtInit;
+
+ /* Contents of static tables */
+ private Map<Integer, String> axisTypes;
+ private Map<Integer, String> crss;
+ private Map<Integer, String> dataTypes;
+ private Map<Integer, String> interpolationTypes;
+ private Map<Integer, String> nullResistances;
+ private Map<String, String> supportedFormats;
+
+ /* Contents of static tables (reversed, for easy access if you
+ know the something's name and want to find out its id) */
+ private Map<String, Integer> revAxisTypes;
+ private Map<String, Integer> revCrss;
+ private Map<String, Integer> revDataTypes;
+ private Map<String, Integer> revInterpolationTypes;
+ private Map<String, Integer> revNullResistances;
+ private Map<String, String> revSupportedFormats; // Not used
+
+ /* Database access info */
+ private String driver;
+ private String pass;
+ private String url;
+ private String user;
+
+ /* Global database key variables */
+ private Connection conn;
+ private Savepoint savepoint;
+ private String query;
+
+ public DbMetadataSource(String driver, String url, String user, String pass) throws ResourceException, InvalidMetadataException {
+ this(driver, url, user, pass, true);
+ }
+
+ public DbMetadataSource(String driver, String url, String user, String pass, boolean checkAtInit) throws ResourceException, InvalidMetadataException {
+ try {
+ this.driver = driver;
+ Class.forName(driver).newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new ResourceException("Metadata database error: Could not find JDBC driver: " + driver, e);
+ } catch (InstantiationException e) {
+ throw new ResourceException("Metadata database error: Could not instantiate JDBC driver: " + driver, e);
+ } catch (IllegalAccessException e) {
+ throw new ResourceException("Metadata database error: Access denied to JDBC driver: " + driver, e);
+ }
+
+ this.driver = driver;
+ this.url = url;
+ this.user = user;
+ this.pass = pass;
+ Statement s = null;
+
+ try {
+
+ /* Read contents of static metadata tables */
+ ensureConnection();
+
+ axisTypes = new HashMap<Integer, String>();
+ revAxisTypes = new HashMap<String, Integer>();
+ s = conn.createStatement();
+ ResultSet r = s.executeQuery("SELECT id, axisType FROM PS_AxisType");
+
+ while (r.next()) {
+ axisTypes.put(r.getInt("id"), r.getString("axisType"));
+ revAxisTypes.put(r.getString("axisType"), r.getInt("id"));
+ }
+
+ dataTypes = new HashMap<Integer, String>();
+ revDataTypes = new HashMap<String, Integer>();
+ r = s.executeQuery("SELECT id, dataType FROM PS_Datatype");
+
+ while (r.next()) {
+ dataTypes.put(r.getInt("id"), r.getString("dataType"));
+ revDataTypes.put(r.getString("dataType"), r.getInt("id"));
+ }
+
+ interpolationTypes = new HashMap<Integer, String>();
+ revInterpolationTypes = new HashMap<String, Integer>();
+ r = s.executeQuery("SELECT id, interpolationType FROM PS_InterpolationType");
+
+ while (r.next()) {
+ interpolationTypes.put(r.getInt("id"), r.getString("interpolationType"));
+ revInterpolationTypes.put(r.getString("interpolationType"), r.getInt("id"));
+ }
+
+ nullResistances = new HashMap<Integer, String>();
+ revNullResistances = new HashMap<String, Integer>();
+ r = s.executeQuery("SELECT id, nullResistance FROM PS_NullResistance");
+
+ while (r.next()) {
+ nullResistances.put(r.getInt("id"), r.getString("nullResistance"));
+ revNullResistances.put(r.getString("nullResistance"), r.getInt("id"));
+ }
+
+ crss = new HashMap<Integer, String>();
+ revCrss = new HashMap<String, Integer>();
+ r = s.executeQuery("SELECT id, name FROM PS_Crs");
+
+ while (r.next()) {
+ crss.put(r.getInt("id"), r.getString("name"));
+ revCrss.put(r.getString("name"), r.getInt("id"));
+ }
+
+ supportedFormats = new HashMap<String, String>();
+ revSupportedFormats = new HashMap<String, String>();
+ r = s.executeQuery("SELECT name, mimetype FROM PS_Format");
+
+ while (r.next()) {
+ supportedFormats.put(r.getString("name"), r.getString("mimetype"));
+ revSupportedFormats.put(r.getString("mimetype"), r.getString("name"));
+ }
+
+ s.close();
+
+ /* Debug checks for reverse static tables */
+// log(revAxisTypes.toString());
+// log(revCrss.toString());
+// log(revDataTypes.toString());
+// log(revInterpolationTypes.toString());
+// log(revNullResistances.toString());
+// log(revSupportedFormats.toString());
+
+ /* Check Metadata consistency at startup, if needed */
+ this.checkAtInit = checkAtInit;
+
+ if (checkAtInit) {
+ initializing = true;
+ boolean coveragesOk = false;
+
+ while (!coveragesOk) {
+ try {
+ Iterator<String> coverages = coverages().iterator();
+
+ while (coverages.hasNext()) {
+ read(coverages.next());
+ }
+ } catch (InvalidWcpsRequestException ire) {
+ throw (InvalidMetadataException) ire.getCause();
+ }
+
+ coveragesOk = true;
+ }
+
+ initializing = false;
+ }
+
+ } catch (SQLException sqle) {
+ if (s != null) {
+ try {
+ s.close();
+ } catch (SQLException e) {
+ }
+ }
+
+ close();
+
+ throw new ResourceException("Metadata database error", sqle);
+ }
+
+ }
+
+ public void close() {
+ if (conn != null) {
+ try {
+ conn.close();
+ } catch (SQLException sqle) {
+ }
+ conn = null;
+ }
+ }
+
+ /* List all available coverages */
+ @Override
+ public Set<String> coverages() throws ResourceException {
+ Statement s = null;
+ Set<String> coverages;
+
+ try {
+ ensureConnection();
+ s = conn.createStatement();
+
+ ResultSet r = s.executeQuery("SELECT name FROM PS_Coverage");
+
+ coverages = new HashSet<String>(r.getFetchSize());
+
+ while (r.next()) {
+ coverages.add(r.getString("name"));
+ }
+
+ s.close();
+
+ return coverages;
+ } catch (SQLException sqle) {
+ if (s != null) {
+ try {
+ s.close();
+ } catch (SQLException f) {
+ }
+ }
+
+ close();
+
+ throw new ResourceException("Metadata database error", sqle);
+ }
+
+ }
+
+ @Override
+ public String formatToMimetype(String format) {
+ return supportedFormats.get(format);
+ }
+
+ @Override
+ public Metadata read(String coverageName) throws InvalidWcpsRequestException, ResourceException {
+ LOG.debug("Reading metadata for coverage '{}'", coverageName);
+
+ if ((coverageName == null) || coverageName.equals("")) {
+ throw new InvalidWcpsRequestException("Cannot retrieve coverage with null or empty name");
+ }
+
+ Statement s = null;
+
+ try {
+ ensureConnection();
+ s = conn.createStatement();
+
+ ResultSet r = s.executeQuery("SELECT id, nullDefault, interpolationTypeDefault, nullResistanceDefault FROM PS_Coverage WHERE name = '" + coverageName + "'");
+
+ if (!r.next()) {
+ throw new InvalidWcpsRequestException("Coverage '" + coverageName + "' is not served by this server");
+ }
+
+ int coverage = r.getInt("id");
+ String nullDefault = r.getString("nullDefault");
+ String interpolationTypeDefault = interpolationTypes.get(r.getInt("interpolationTypeDefault"));
+ String nullResistanceDefault = nullResistances.get(r.getInt("nullResistanceDefault"));
+
+ r = s.executeQuery("SELECT lo, hi FROM PS_CellDomain WHERE coverage = '" + coverage + "' ORDER BY i ASC");
+ CellDomainElement X = null, Y = null, cell;
+ boolean twoDCoverage = true;
+ List<CellDomainElement> cellDomain = new ArrayList<CellDomainElement>(r.getFetchSize());
+
+ while (r.next()) {
+ cell = new CellDomainElement(BigInteger.valueOf(r.getInt("lo")), BigInteger.valueOf(r.getInt("hi")));
+ cellDomain.add(cell);
+ if (X == null) {
+ X = cell;
+ } else if (X != null && Y == null) {
+ Y = cell;
+ } else {
+ twoDCoverage = false;
+ }
+ }
+ if (X == null || Y == null) {
+ twoDCoverage = false;
+ }
+
+ r = s.executeQuery("SELECT name, type FROM PS_Range WHERE coverage = '" + coverage + "' ORDER BY i ASC");
+ List<RangeElement> range = new ArrayList<RangeElement>(r.getFetchSize());
+
+ while (r.next()) {
+ range.add(new RangeElement(r.getString("name"), dataTypes.get(r.getInt("type"))));
+ }
+
+ r = s.executeQuery("SELECT interpolationType, nullResistance FROM PS_InterpolationSet WHERE coverage = '" + coverage + "'");
+ Set<InterpolationMethod> interpolationSet = new HashSet<InterpolationMethod>(r.getFetchSize());
+
+ while (r.next()) {
+ interpolationSet.add(new InterpolationMethod(interpolationTypes.get(r.getInt("interpolationType")), nullResistances.get(r.getInt("nullResistance"))));
+ }
+
+ r = s.executeQuery("SELECT nullValue FROM PS_NullSet WHERE coverage = '" + coverage + "'");
+ Set<String> nullSet = new HashSet<String>(r.getFetchSize());
+
+ while (r.next()) {
+ nullSet.add(r.getString("nullValue"));
+ }
+
+ r = s.executeQuery("SELECT id, name, type, numLo, numHi, strLo, strHi FROM PS_Domain WHERE coverage = '" + coverage + "' ORDER BY i ASC");
+ List<DomainElement> domain = new ArrayList<DomainElement>(r.getFetchSize());
+ Statement ss = conn.createStatement();
+
+ while (r.next()) {
+ String strLo = r.getString("strLo");
+ String strHi = r.getString("strHi");
+
+ Double numLo = r.getDouble("numLo");
+
+ if (r.wasNull()) {
+ numLo = null;
+ }
+
+ Double numHi = r.getDouble("numHi");
+
+ if (r.wasNull()) {
+ numHi = null;
+ }
+
+ ResultSet rr = ss.executeQuery("SELECT crs FROM PS_CrsSet WHERE axis = '" + r.getInt("id") + "'");
+ Set<String> crsSet = new HashSet<String>(rr.getFetchSize());
+
+ while (rr.next()) {
+ crsSet.add(crss.get(rr.getInt("crs")));
+ }
+
+ DomainElement d = new DomainElement(r.getString("name"), axisTypes.get(r.getInt("type")),
+ numLo, numHi, strLo, strHi, crsSet, axisTypes.values());
+ domain.add(d);
+ }
+
+ String abstr = "";
+ String title = "";
+ String keywords = "";
+ r = s.executeQuery("SELECT title, abstract, keywords FROM PS_Descriptions WHERE coverage = '" + coverage + "'");
+ if (r.next()) {
+ abstr = r.getString("abstract");
+ title = r.getString("title");
+ keywords = r.getString("keywords");
+ }
+
+ /* WGS84 is the only CRS we understand (except IMAGE_CRS, of course) */
+ Wgs84Crs crs = null;
+ Double l1 = 0.0, l2 = 0.0, h1 = 0.0, h2 = 0.0;
+ Double o1 = null, o2 = null;
+ r = s.executeQuery("SELECT * FROM PS_CrsDetails WHERE coverage = '" + coverage + "'");
+ if (r.next()) {
+ /* Domain extent */
+ int x0 = X.getLo().intValue();
+ int y0 = Y.getLo().intValue();
+ int x1 = X.getHi().intValue();
+ int y1 = Y.getHi().intValue();
+ /* CRS Bounding box */
+ l1 = r.getDouble("low1");
+ l2 = r.getDouble("low2");
+ h1 = r.getDouble("high1");
+ h2 = r.getDouble("high2");
+ String off1 = r.getString("offset1");
+ String off2 = r.getString("offset2");
+ if (off1 != null) {
+ o1 = Double.parseDouble(off1);
+ }
+ if (off2 != null) {
+ o2 = Double.parseDouble(off2);
+ }
+ /* Compute axis offsets if not predefined */
+ if (o1 == null && o2 == null) {
+ o1 = (h1 - l1) / (double) (x1 - x0);
+ o2 = (h2 - l2) / (double) (y1 - y0);
+ LOG.debug("Calculated CRS axis offsets. For X: {}, for Y: {}", o1, o2);
+ LOG.debug(X.toString());
+ LOG.debug(Y.toString());
+ }
+ /* Only store CRS information if coverage is 2-D */
+ if (twoDCoverage == true) {
+ crs = new Wgs84Crs(l1, h1, l2, h2, o1, o2);
+ LOG.trace("Found CRS : ", crs.toString());
+ } else {
+ LOG.warn("Found CRS '{}', but coverage is not 2-dimensional. "
+ + "Ignoring CRS information.", crs.toString());
+ }
+ } else if (twoDCoverage) {
+ LOG.warn(" WGS84 bounding box missing for 2-D coverage '" + coverageName + "'...");
+ }
+
+ /* Done with SQL statements */
+ s.close();
+
+ /* Build the complete metadata object */
+ Metadata meta = new Metadata(cellDomain, range, nullSet, nullDefault, interpolationSet,
+ new InterpolationMethod(interpolationTypeDefault, nullResistanceDefault),
+ coverageName, domain, crs, title, abstr, keywords);
+ meta.setCoverageId(coverage);
+ return meta;
+ } catch (InvalidMetadataException ime) {
+ if (checkAtInit && !initializing) {
+ throw new ResourceException("Previously valid metadata is now invalid. The metadata for coverage '" + coverageName + "' has been modified incorrectly.", ime);
+ } else {
+ throw new InvalidWcpsRequestException("Coverage '" + coverageName + "' has invalid metadata", ime);
+ }
+ } catch (SQLException sqle) {
+ if (s != null) {
+ try {
+ s.close();
+ } catch (SQLException f) {
+ }
+ }
+
+ close();
+
+ throw new ResourceException("Metadata database error", sqle);
+ }
+
+ }
+
+ /** Write a coverage's metadata to the database. This function can be used
+ * for both inserting new coverages and updating coverage metadata.
+ *
+ * @param meta Metadata container for the information to be stored in the metadata database
+ * @param commit Boolean value, specifying if we want to commit immediately or not
+ */
+ private void write(Metadata meta, boolean commit) throws ResourceException {
+ String coverageName = meta.getCoverageName();
+ if (existsCoverageName(coverageName)) {
+ updateCoverageMetadata(meta, commit);
+ } else {
+ insertNewCoverageMetadata(meta, commit);
+ }
+ }
+
+ public void delete(Metadata meta, boolean commit) throws ResourceException {
+ String coverageName = meta.getCoverageName();
+ if (existsCoverageName(coverageName) == false) {
+ throw new ResourceException("Cannot delete inexistent coverage: " + coverageName);
+ }
+
+ /* Delete main coverage entry from "PS_Coverage". Auxiliary metadata are
+ * automatically deleted by the DB (via CASCADING) on
+ * deletion of the main entry in ps_coverage */
+ Statement s = null;
+ try {
+ s = conn.createStatement();
+ setQuery("DELETE FROM PS_Coverage WHERE name = '" + coverageName + "'");
+ int count = s.executeUpdate(query);
+ LOG.trace("Affected rows: " + count);
+ s.close();
+
+ if (commit) {
+ commitAndClose();
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ s.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ /**
+ * Check if there is metadata available for a given coverage name
+ * @param name coverage name
+ * @return true is coverage already exists
+ */
+ public boolean existsCoverageName(String name) {
+ boolean result = false;
+ Statement s = null;
+ try {
+ s = conn.createStatement();
+ setQuery("SELECT * FROM PS_Coverage WHERE name = '" + name + "'");
+ ResultSet r = s.executeQuery(query);
+ if (r.next()) {
+ result = true;
+ } else {
+ result = false;
+ }
+ s.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ s.close();
+ } catch (Exception e) {
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Check if there exists a coverage with a given ID in the metadata database.
+ * @param id coverage id
+ * @return true is coverage already exists
+ */
+ private boolean existsCoverageId(int id) {
+ boolean result = false;
+ Statement s = null;
+ try {
+ s = conn.createStatement();
+ ResultSet r = s.executeQuery(
+ "SELECT * FROM PS_Coverage WHERE id = '" + id + "'");
+ if (r.next()) {
+ result = true;
+ } else {
+ result = false;
+ }
+ s.close();
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ s.close();
+ } catch (Exception e) {
+ }
+ }
+ System.out.println("Coverage with ID " + id + (result == false ? " does not " : "") + " exists.");
+ return result;
+ }
+
+ /** Update metadata for an existing coverage. All information may change (including
+ * name), but the ID of the tuple in PS_Coverage will stay the same.
+ *
+ * @param meta Metadata object, container of the new information.
+ * @param commit True if we want to commit immediately, false to delay commit indefinitely
+ */
+ public void updateCoverageMetadata(Metadata meta, boolean commit) throws ResourceException {
+ Statement s = null;
+ int coverageId = meta.getCoverageId();
+ int count = -1;
+ String coverageName = meta.getCoverageName();
+
+ try {
+ ensureConnection();
+ s = conn.createStatement();
+
+ String name = coverageName;
+ String nulldefault = meta.getNullDefault();
+ int interpolatiotypendefault = revInterpolationTypes.get(meta.getInterpolationDefault());
+ int nullresistancedefault = revNullResistances.get(meta.getNullResistanceDefault());
+
+ // Table PS_Coverage
+ setQuery("UPDATE PS_Coverage SET "
+ + "(name, nullDefault, interpolationTypeDefault, nullResistanceDefault) "
+ + " = ('" + name + "', '" + nulldefault + "', '"
+ + interpolatiotypendefault + "', '" + nullresistancedefault + "')"
+ + " WHERE id='" + coverageId + "'");
+ count = s.executeUpdate(query);
+ if (count <= 0) {
+ throw new SQLException("Could not update table PS_Coverage.");
+ }
+
+ // Table PS_CellDomain
+ /* Delete old data */
+ setQuery("DELETE FROM PS_CellDomain WHERE coverage='" + coverageId + "'");
+ count = s.executeUpdate(query);
+ if (count <= 0) {
+ throw new SQLException("Could not delete old entries from table PS_CellDomain.");
+ }
+ /* Insert new data */
+ Iterator<CellDomainElement> cellIt = meta.getCellDomainIterator();
+ int i = 0;
+ while (cellIt.hasNext()) {
+ CellDomainElement cell = cellIt.next();
+ setQuery("INSERT INTO PS_CellDomain (coverage, i, lo, hi) VALUES "
+ + " ('" + coverageId + "', '" + i + "', '" + cell.getLo() + "', '"
+ + cell.getHi() + "')");
+ if (s.executeUpdate(query) <= 0) {
+ throw new SQLException("Could not insert axis " + i + " for coverage "
+ + coverageName + "( id " + coverageId + ") into table PS_CellDomain");
+ }
+ i++;
+ }
+
+ // Table PS_Range
+ /* Delete old data */
+ setQuery("DELETE FROM PS_Range WHERE coverage='" + coverageId + "'");
+ count = s.executeUpdate(query);
+ if (count <= 0) {
+ throw new SQLException("Could not delete old entries from table PS_Range.");
+ }
+ /* Insert new data */
+ Iterator<RangeElement> rangeIt = meta.getRangeIterator();
+ i = 0;
+ while (rangeIt.hasNext()) {
+ RangeElement range = rangeIt.next();
+ System.out.println(range);
+ int dataType = revDataTypes.get(range.getType());
+ setQuery("INSERT INTO PS_Range (coverage, i, name, type) VALUES "
+ + " ('" + coverageId + "', '" + i + "', '" + range.getName() + "', '"
+ + dataType + "')");
+ if (s.executeUpdate(query) <= 0) {
+ throw new SQLException("Could not insert range " + range.getName()
+ + "( id " + i + " ) for coverage "
+ + coverageName + "( id " + coverageId + ") into table PS_Range");
+ }
+ i++;
+ }
+
+ // Table PS_InterpolationSet
+ /* Delete old data */
+ setQuery("DELETE FROM PS_InterpolationSet WHERE coverage='" + coverageId + "'");
+ count = s.executeUpdate(query);
+ if (count <= 0) {
+ throw new SQLException("Could not delete old entries from table PS_InterpolationSet.");
+ }
+ /* Insert new data */
+ Iterator<InterpolationMethod> methodIt = meta.getInterpolationMethodIterator();
+ i = 0;
+ while (methodIt.hasNext()) {
+ InterpolationMethod method = methodIt.next();
+ int interp = revInterpolationTypes.get(method.getInterpolationType());
+ int nullRes = revNullResistances.get(method.getNullResistance());
+ setQuery("INSERT INTO PS_InterpolationSet (coverage, interpolationType, nullResistance) VALUES "
+ + " ('" + coverageId + "', '" + interp + "', '" + nullRes + "')");
+ if (s.executeUpdate(query) <= 0) {
+ throw new SQLException("Could not insert interpolation method (" + method.getInterpolationType()
+ + ", " + method.getNullResistance() + " ) for coverage "
+ + coverageName + "( id " + coverageId + ") into table PS_InterpolationSet");
+ }
+ i++;
+ }
+
+ // Table PS_NullSet
+ /* Delete old data */
+ setQuery("DELETE FROM PS_NullSet WHERE coverage='" + coverageId + "'");
+ count = s.executeUpdate(query);
+ if (count <= 0) {
+ throw new SQLException("Could not delete old entries from table PS_NullSet.");
+ }
+ /* Insert new data */
+ Iterator<String> nullIt = meta.getNullSetIterator();
+ while (nullIt.hasNext()) {
+ String nullValue = nullIt.next();
+ setQuery("INSERT INTO PS_NullSet (coverage, nullValue) VALUES "
+ + " ('" + coverageId + "', '" + nullValue + "')");
+ if (s.executeUpdate(query) <= 0) {
+ throw new SQLException("Could not insert null value '" + nullValue
+ + "' for coverage " + coverageName + "( id " + coverageId
+ + ") into table PS_NullSet");
+ }
+ }
+
+ // Tables PS_Domain and PS_CrsSet
+ /* Delete old data */
+ setQuery("SELECT * FROM PS_Domain WHERE coverage='" + coverageId + "'");
+ ResultSet r1 = s.executeQuery(query);
+ Vector axes = new Vector(5);
+ while (r1.next()) {
+ int axisId = r1.getInt("id");
+ axes.add((Integer) axisId);
+ }
+ System.out.println(axes);
+ for (i = 0; i < axes.size(); i++) {
+ int axisId = ((Integer) axes.elementAt(i)).intValue();
+ setQuery("DELETE FROM PS_CrsSet WHERE axis='" + axisId + "'");
+ count = s.executeUpdate(query);
+ /* Do not worry about inexisting entries in CRS Sets: this implementation
+ does not really use CRSs. */
+// if (count <= 0)
+// throw new SQLException("Could not delete old entries from table PS_CrsSet.");
+
+ }
+
+ setQuery("DELETE FROM PS_Domain WHERE coverage='" + coverageId + "'");
+ count = s.executeUpdate(query);
+ if (count <= 0) {
+ throw new SQLException("Could not delete old entries from table PS_Domain.");
+ }
+ /* Insert new data */
+ Iterator<DomainElement> domIt = meta.getDomainIterator();
+ i = 0;
+ while (domIt.hasNext()) {
+ // Table PS_Domain
+ DomainElement dom = domIt.next();
+ int axisType = revAxisTypes.get(dom.getType());
+ Double numLo = dom.getNumLo();
+ Double numHi = dom.getNumHi();
+ String sNumLo = numLo == null ? "null" : "'" + numLo.toString() + "'";
+ String sNumHi = numHi == null ? "null" : "'" + numHi.toString() + "'";
+ String strLo = dom.getStrLo();
+ String strHi = dom.getStrHi();
+ if (strLo != null && strLo.equals("null") == false) {
+ strLo = "'" + strLo + "'";
+ }
+ if (strHi != null && strHi.equals("null") == false) {
+ strHi = "'" + strHi + "'";
+ }
+
+ String sqlQuery = "INSERT INTO PS_Domain "
+ + "(coverage, i, name, type, numLo, numHi, strLo, strHi) VALUES "
+ + "('" + coverageId + "', '" + i + "', '" + dom.getName() + "', '"
+ + axisType + "', " + sNumLo + ", " + sNumHi
+ + ", " + strLo + ", " + strHi + ")";
+ /* Need to get ID of the newly inserted tuple. Postgres has a cool construct (RETURNING),
+ * but we can also fall-back to another generic JDBC driver */
+ int axisId = -1;
+ if (driver.equals("org.postgresql.Driver")) {
+ /* RETURNING clause is not standard SQL, only PostgreSQL understands it*/
+ setQuery(sqlQuery + " RETURNING id");
+
+ ResultSet r = s.executeQuery(query);
+ if (r.next() == false) {
+ throw new SQLException("Could not insert domain element (i = " + i
+ + ", name=" + dom.getName() + ", type=" + dom.getType()
+ + ", numLo=" + dom.getNumLo() + ", numHi=" + dom.getNumHi()
+ + ", strLo=" + dom.getStrLo() + ", strHi=" + dom.getStrHi()
+ + ") for coverage " + coverageName + "( id " + coverageId
+ + ") into table PS_Domain");
+ }
+ /* Retrieve the ID of the newly inserted tuple (PS_Domain) */
+ axisId = r.getInt("id");
+ } else {
+ /* Fallback to specific driver support on returning autogenerated keys. */
+ String[] keys = new String[1];
+ keys[0] = "id";
+ int c = s.executeUpdate(sqlQuery, keys);
+ if (c <= 0) {
+ throw new SQLException("Could not insert domain element (i = " + i
+ + ", name=" + dom.getName() + ", type=" + dom.getType()
+ + ", numLo=" + dom.getNumLo() + ", numHi=" + dom.getNumHi()
+ + ", strLo=" + dom.getStrLo() + ", strHi=" + dom.getStrHi()
+ + ") for coverage " + coverageName + "( id " + coverageId
+ + ") into table PS_Domain");
+ }
+ /* Retrieve the ID of the newly inserted tuple (PS_Domain) */
+ ResultSet rr = s.getGeneratedKeys();
+ if (rr.next() == false) {
+ throw new SQLException("Could not retrieve ID of the newly insterted tuple in table PS_Domain.");
+ }
+ axisId = rr.getInt("id");
+ }
+ /* check ID */
+ if (axisId < 0) {
+ throw new SQLException("Generated ID (" + axisId
+ + ") for the tuple in PS_Domain is not valid !");
+ }
+
+ /* Increment axis number */
+ i++;
+
+ // Table PS_CrsSet
+ Set<String> crsSet = dom.getCrsSet();
+ System.out.println(crsSet);
+ Iterator<String> crsIt = crsSet.iterator();
+ while (crsIt.hasNext()) {
+ String crs = crsIt.next();
+ int crsId = revCrss.get(crs);
+ setQuery("INSERT INTO PS_CrsSet (axis, crs) VALUES "
+ + "('" + axisId + "', '" + crsId + "')");
+ if (s.executeUpdate(query) <= 0) {
+ throw new SQLException("Could not insert Crs " + crs
+ + "for axis =" + axisId + " in table PS_CrsSet");
+ }
+ }
+ }
+
+ // Table PS_Descriptions
+ /* Delete old data */
+ setQuery("DELETE FROM PS_Descriptions WHERE coverage='" + coverageId + "'");
+ count = s.executeUpdate(query);
+ /* Coverage descriptions are not essential, do not throw an error if missing */
+// if (count <= 0)
+// throw new SQLException("Could not delete old data from table PS_Descriptions");
+ /* Insert new data */
+ String title = meta.getTitle();
+ String abstr = meta.getAbstract();
+ String keywords = meta.getKeywords();
+ if (title != null) {
+ title = "'" + title + "'";
+ }
+ if (abstr != null) {
+ abstr = "'" + abstr + "'";
+ }
+ if (keywords != null) {
+ keywords = "'" + keywords + "'";
+ }
+ setQuery("INSERT INTO PS_Descriptions (coverage, title, abstract, keywords)"
+ + " VALUES ('" + coverageId + "', " + title + ", " + abstr + ", " + keywords + ")");
+ if (s.executeUpdate(query) <= 0) {
+ throw new SQLException("Could not insert descriptive metadata in table "
+ + "PS_Descriptions for coverage " + coverageName + " (ID " + coverageId + ")");
+ }
+
+
+ s.close();
+
+ if (commit) {
+ commitAndClose();
+ }
+ } catch (SQLException sqle) {
+ /* Abort this transaction */
+ try {
+ if (s != null) {
+ s.close();
+ }
+ abortAndClose();
+ } catch (SQLException f) {
+ }
+
+ throw new ResourceException("Metadata database error", sqle);
+ }
+ }
+
+ /** Insert metadata for a new coverage.
+ *
+ * @param meta Metadata object, container of information
+ * @param commit Boolean value, specifying if we want to commit immediately or not
+ */
+ public void insertNewCoverageMetadata(Metadata meta, boolean commit) throws ResourceException {
+ Statement s = null;
+ String coverageName = meta.getCoverageName();
+ int coverageId = -1;
+
+ try {
+ ensureConnection();
+ s = conn.createStatement();
+
+ String name = coverageName;
+ /* FIXME: Table PS_COVERAGE: nullValue and CRS fields not USED !!! */
+// String nullvalue = "";
+// String crs = "";
+ String nulldefault = meta.getNullDefault();
+ int interpolatiotypendefault = revInterpolationTypes.get(meta.getInterpolationDefault());
+ int nullresistancedefault = revNullResistances.get(meta.getNullResistanceDefault());
+
+ // Table PS_Coverage
+ String sqlQuery = "INSERT INTO PS_Coverage "
+ + "(name, nullDefault, interpolationTypeDefault, nullResistanceDefault) "
+ + " VALUES ('" + name + "', '" + nulldefault + "', '"
+ + interpolatiotypendefault + "', '" + nullresistancedefault + "')";
+ /* Need to get ID of the newly inserted tuple. Postgres has a cool construct (RETURNING),
+ * but we can also fall-back to another generic JDBC driver */
+ if (driver.equals("org.postgresql.Driver")) {
+ /* RETURNING clause is not standard SQL, only PostgreSQL understands it*/
+ setQuery(sqlQuery + " RETURNING id");
+
+ ResultSet r = s.executeQuery(query);
+ if (r.next() == false) {
+ throw new SQLException("Could not insert new coverage in table PS_Coverage.");
+ }
+ /* Retrieve the ID of the newly inserted tuple (PS_Coverage) */
+ coverageId = r.getInt("id");
+ } else {
+ /* Fallback to specific driver support on returning autogenerated keys. */
+ String[] keys = new String[1];
+ keys[0] = "id";
+ int c = s.executeUpdate(sqlQuery, keys);
+ if (c <= 0) {
+ throw new SQLException("Could not insert new coverage in table PS_Coverage.");
+ }
+ /* Retrieve the ID of the newly inserted tuple (PS_Coverage) */
+ ResultSet rr = s.getGeneratedKeys();
+ if (rr.next() == false) {
+ throw new SQLException("Could not retrieve ID of the newly insterted tuple in table PS_Coverage.");
+ }
+ coverageId = rr.getInt("id");
+ }
+ /* check ID */
+ if (coverageId < 0) {
+ throw new SQLException("Generated ID (" + coverageId
+ + ") for the tuple in PS_Coverage is not valid !");
+ }
+
+ // Table PS_CellDomain
+ Iterator<CellDomainElement> cellIt = meta.getCellDomainIterator();
+ int i = 0;
+ while (cellIt.hasNext()) {
+ CellDomainElement cell = cellIt.next();
+ setQuery("INSERT INTO PS_CellDomain (coverage, i, lo, hi) VALUES "
+ + " ('" + coverageId + "', '" + i + "', '" + cell.getLo() + "', '"
+ + cell.getHi() + "')");
+ if (s.executeUpdate(query) <= 0) {
+ throw new SQLException("Could not insert axis " + i + " for coverage "
+ + coverageName + "( id " + coverageId + ") into table PS_CellDomain");
+ }
+ i++;
+ }
+
+ // Table PS_Range
+ Iterator<RangeElement> rangeIt = meta.getRangeIterator();
+ i = 0;
+ while (rangeIt.hasNext()) {
+ RangeElement range = rangeIt.next();
+ System.out.println(range);
+ int dataType = revDataTypes.get(range.getType());
+ setQuery("INSERT INTO PS_Range (coverage, i, name, type) VALUES "
+ + " ('" + coverageId + "', '" + i + "', '" + range.getName() + "', '"
+ + dataType + "')");
+ if (s.executeUpdate(query) <= 0) {
+ throw new SQLException("Could not insert range " + range.getName()
+ + "( id " + i + " ) for coverage "
+ + coverageName + "( id " + coverageId + ") into table PS_Range");
+ }
+ i++;
+ }
+
+ // Table PS_InterpolationSet
+ Iterator<InterpolationMethod> methodIt = meta.getInterpolationMethodIterator();
+ i = 0;
+ while (methodIt.hasNext()) {
+ InterpolationMethod method = methodIt.next();
+ int interp = revInterpolationTypes.get(method.getInterpolationType());
+ int nullRes = revNullResistances.get(method.getNullResistance());
+ setQuery("INSERT INTO PS_InterpolationSet (coverage, interpolationType, nullResistance) VALUES "
+ + " ('" + coverageId + "', '" + interp + "', '" + nullRes + "')");
+ if (s.executeUpdate(query) <= 0) {
+ throw new SQLException("Could not insert interpolation method (" + method.getInterpolationType()
+ + ", " + method.getNullResistance() + " ) for coverage "
+ + coverageName + "( id " + coverageId + ") into table PS_InterpolationSet");
+ }
+ i++;
+ }
+
+ // Table PS_NullSet
+ Iterator<String> nullIt = meta.getNullSetIterator();
+ while (nullIt.hasNext()) {
+ String nullValue = nullIt.next();
+ setQuery("INSERT INTO PS_NullSet (coverage, nullValue) VALUES "
+ + " ('" + coverageId + "', '" + nullValue + "')");
+ if (s.executeUpdate(query) <= 0) {
+ throw new SQLException("Could not insert null value '" + nullValue
+ + "' for coverage " + coverageName + "( id " + coverageId
+ + ") into table PS_NullSet");
+ }
+ }
+
+ Iterator<DomainElement> domIt = meta.getDomainIterator();
+ i = 0;
+ while (domIt.hasNext()) {
+ // Table PS_Domain
+ DomainElement dom = domIt.next();
+ int axisType = revAxisTypes.get(dom.getType());
+ Double numLo = dom.getNumLo();
+ Double numHi = dom.getNumHi();
+ String sNumLo = numLo == null ? "null" : "'" + numLo.toString() + "'";
+ String sNumHi = numHi == null ? "null" : "'" + numHi.toString() + "'";
+ String strLo = dom.getStrLo();
+ String strHi = dom.getStrHi();
+ if (strLo != null && strLo.equals("null") == false) {
+ strLo = "'" + strLo + "'";
+ }
+ if (strHi != null && strHi.equals("null") == false) {
+ strHi = "'" + strHi + "'";
+ }
+
+ sqlQuery = "INSERT INTO PS_Domain "
+ + "(coverage, i, name, type, numLo, numHi, strLo, strHi) VALUES "
+ + "('" + coverageId + "', '" + i + "', '" + dom.getName() + "', '"
+ + axisType + "', " + sNumLo + ", " + sNumHi
+ + ", " + strLo + ", " + strHi + ")";
+ /* Need to get ID of the newly inserted tuple. Postgres has a cool construct (RETURNING),
+ * but we can also fall-back to another generic JDBC driver */
+ int axisId = -1;
+ if (driver.equals("org.postgresql.Driver")) {
+ /* RETURNING clause is not standard SQL, only PostgreSQL understands it*/
+ setQuery(sqlQuery + " RETURNING id");
+
+ ResultSet r = s.executeQuery(query);
+ if (r.next() == false) {
+ throw new SQLException("Could not insert domain element (i = " + i
+ + ", name=" + dom.getName() + ", type=" + dom.getType()
+ + ", numLo=" + dom.getNumLo() + ", numHi=" + dom.getNumHi()
+ + ", strLo=" + dom.getStrLo() + ", strHi=" + dom.getStrHi()
+ + ") for coverage " + coverageName + "( id " + coverageId
+ + ") into table PS_Domain");
+ }
+ /* Retrieve the ID of the newly inserted tuple (PS_Domain) */
+ axisId = r.getInt("id");
+ } else {
+ /* Fallback to specific driver support on returning autogenerated keys. */
+ String[] keys = new String[1];
+ keys[0] = "id";
+ int c = s.executeUpdate(sqlQuery, keys);
+ if (c <= 0) {
+ throw new SQLException("Could not insert domain element (i = " + i
+ + ", name=" + dom.getName() + ", type=" + dom.getType()
+ + ", numLo=" + dom.getNumLo() + ", numHi=" + dom.getNumHi()
+ + ", strLo=" + dom.getStrLo() + ", strHi=" + dom.getStrHi()
+ + ") for coverage " + coverageName + "( id " + coverageId
+ + ") into table PS_Domain");
+ }
+ /* Retrieve the ID of the newly inserted tuple (PS_Domain) */
+ ResultSet rr = s.getGeneratedKeys();
+ if (rr.next() == false) {
+ throw new SQLException("Could not retrieve ID of the newly insterted tuple in table PS_Domain.");
+ }
+ axisId = rr.getInt("id");
+ }
+ /* check ID */
+ if (axisId < 0) {
+ throw new SQLException("Generated ID (" + axisId
+ + ") for the tuple in PS_Domain is not valid !");
+ }
+
+ /* Increment axis number */
+ i++;
+
+ // Table PS_CrsSet
+ Set<String> crsSet = dom.getCrsSet();
+ Iterator<String> crsIt = crsSet.iterator();
+ while (crsIt.hasNext()) {
+ String crs = crsIt.next();
+ int crsId = revCrss.get(crs);
+ setQuery("INSERT INTO PS_CrsSet (axis, crs) VALUES "
+ + "('" + axisId + "', '" + crsId + "')");
+ if (s.executeUpdate(query) <= 0) {
+ throw new SQLException("Could not insert Crs " + crs
+ + "for axis =" + axisId + " in table PS_CrsSet");
+ }
+ }
+ }
+
+ // Table PS_Descriptions
+ String title = meta.getTitle();
+ String abstr = meta.getAbstract();
+ String keywords = meta.getKeywords();
+ if (title != null) {
+ title = "'" + title + "'";
+ }
+ if (abstr != null) {
+ abstr = "'" + abstr + "'";
+ }
+ if (keywords != null) {
+ keywords = "'" + keywords + "'";
+ }
+ setQuery("INSERT INTO PS_Descriptions (coverage, title, abstract, keywords)"
+ + " VALUES ('" + coverageId + "', " + title + ", " + abstr + ", " + keywords + ")");
+ if (s.executeUpdate(query) <= 0) {
+ throw new SQLException("Could not insert descriptive metadata in table "
+ + "PS_Descriptions for coverage " + coverageName + " (ID " + coverageId + ")");
+ }
+
+ s.close();
+
+ if (commit) {
+ commitAndClose();
+ }
+ } catch (SQLException sqle) {
+ /* Abort this transaction */
+ try {
+ if (s != null) {
+ s.close();
+ }
+ abortAndClose();
+ } catch (SQLException f) {
+ }
+
+ throw new ResourceException("Metadata database error", sqle);
+ }
+
+ }
+
+ public void ensureConnection() throws SQLException {
+ synchronized (this) {
+ LOG.trace("Ensuring connection is valid...");
+// if( connection == null || !connection.isValid( CONNECTION_TIMEOUT ) ) { // Not implemented by PostgreSQL yet.
+ if ((conn == null) || conn.isClosed()) {
+ LOG.trace("*** Opening new DB connection !");
+ close();
+ openConnection();
+ LOG.trace("*** ok.");
+// try { throw new Exception(""); } catch (Exception e) {e.printStackTrace();}
+ }
+ }
+
+ }
+
+ public void openConnection() throws SQLException {
+ conn = DriverManager.getConnection(url, user, pass);
+ conn.setAutoCommit(false);
+ savepoint = conn.setSavepoint();
+ }
+
+ public void abortAndClose() throws SQLException {
+ if (conn != null) {
+ conn.rollback(savepoint);
+ conn.close();
+ conn = null;
+ }
+ }
+
+ public void commitAndClose() throws SQLException {
+ if (conn != null) {
+ conn.commit();
+ conn.close();
+ conn = null;
+ }
+ }
+
+ @Override
+ public Collection<String> getAxisNames() {
+ return axisTypes.values();
+ }
+
+ /* Logging function for SQL queries. */
+ private void setQuery(String q) {
+ this.query = q;
+ LOG.trace("SQL Query: {}", q);
+ }
+
+ /* Returns the available formatToMimetype formats, as stored in the metadata database */
+ public String[] getMimetypesList() {
+ return supportedFormats.values().toArray(new String[1]);
+ }
+
+ /* Translate a mime-type to a format name, if known to rasdaman. */
+ public String mimetypeToFormat(String mime) {
+ LOG.debug(revSupportedFormats.toString());
+ return revSupportedFormats.get(mime);
+ }
+
+ /**
+ * @return the dataTypes
+ */
+ public Collection<String> getDataTypes() {
+ return dataTypes.values();
+ }
+
+ /**
+ * @return the interpolationTypes
+ */
+ public Collection<String> getInterpolationTypes() {
+ return interpolationTypes.values();
+ }
+
+ /**
+ * @return the nullResistances
+ */
+ public Collection<String> getNullResistances() {
+ return nullResistances.values();
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/DimensionIntervalElement.java b/petascope/src/petascope/wcps/server/core/DimensionIntervalElement.java
new file mode 100644
index 0000000..e2aeef2
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/DimensionIntervalElement.java
@@ -0,0 +1,221 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+import petascope.wcs.server.exceptions.NoApplicableCodeException;
+
+public class DimensionIntervalElement implements IRasNode, ICoverageInfo {
+
+ Logger LOG = LoggerFactory.getLogger(DimensionIntervalElement.class);
+ private IRasNode child;
+ private CoverageInfo info = null;
+ private AxisName axis;
+ private Crs crs;
+ private ScalarExpr domain1, domain2; // lower and upper bound, or "DomainMetadataExprType" and null
+ private long coord1, coord2;
+ private int counter = 0; // counter for the domain vars
+ private Metadata meta = null; // metadata about the current coverage
+ private boolean finished = false;
+ private Node nextNode;
+ private boolean transformedCoordinates = false;
+
+ /**
+ * Constructs an element of a dimension interval.
+ * @param node XML Node
+ * @param xq WCPS Xml Query object
+ * @param covInfo CoverageInfo object about the Trim parent object
+ * @throws WCPSException
+ */
+ public DimensionIntervalElement(Node node, XmlQuery xq, CoverageInfo covInfo)
+ throws WCPSException, InvalidCrsException {
+
+ if (covInfo.getCoverageName() != null) {
+ // Add WGS84 CRS information from coverage metadata, may be useful
+ // for converting geo-coordinates to pixel-coordinates
+ String coverageName = covInfo.getCoverageName();
+ meta = xq.getMetadataSource().read(coverageName);
+ }
+
+ System.err.println("Trying to parse DimensionIntervalElement expression...");
+ String name;
+
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ while (node != null && finished == false) {
+ if (node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ continue;
+ }
+
+ name = node.getNodeName();
+ System.err.println("Current node is " + name);
+
+ // Try Axis
+ try {
+ axis = new AxisName(node, xq);
+ node = node.getNextSibling();
+ continue;
+ } catch (WCPSException e) {
+ System.err.println("Failed to parse an axis!");
+ }
+
+ // Try CRS name
+ try {
+ crs = new Crs(node, xq);
+ node = node.getNextSibling();
+ if (axis == null) {
+ throw new WCPSException("Expected Axis node before CRS !");
+ }
+ continue;
+ } catch (WCPSException e) {
+ System.err.println("Failed to parse a crs!");
+ }
+
+ // TODO: how to implement DomainMetadataExpr ?
+
+// // Try last thing
+// try
+// {
+// domain1 = new DomainMetadataExprType(node, xq);
+// counter = 1;
+// continue;
+// }
+// catch (WCPSException e)
+// {
+// System.err.println("Failed to parse domain metadata!");
+// }
+
+ // Then it must be a pair of nodes "lowerBound" + "upperBound"
+ if (node.getNodeName().equals("lowerBound")) {
+ counter = 2;
+ domain1 = new ScalarExpr(node.getFirstChild(), xq);
+ if (axis == null) {
+ throw new WCPSException("Expected <axis> node before <lowerBound> !");
+ }
+ } else if (node.getNodeName().equals("upperBound")) {
+ counter = 2;
+ domain2 = new ScalarExpr(node.getFirstChild(), xq);
+ if (axis == null) {
+ throw new WCPSException("Expected <lowerBound> node before <upperBound> !");
+ }
+ } else {
+ throw new WCPSException("Unexpected node: " + node.getFirstChild().getNodeName());
+ }
+
+ if (axis != null && counter == 1 && domain1 != null) {
+ finished = true;
+ }
+ if (axis != null && counter == 2 && domain1 != null && domain2 != null) {
+ finished = true;
+ }
+
+ if (finished == true) {
+ nextNode = node.getNextSibling();
+ }
+
+ node = node.getNextSibling();
+ }
+
+ if (finished == true) {
+ convertToPixelCoordinates();
+ }
+ }
+
+
+ /* If input coordinates are geo-, convert them to pixel coordinates. */
+ private void convertToPixelCoordinates() {
+ if (meta.getCrs() == null && crs != null && crs.getName().equals(DomainElement.WGS84_CRS)) {
+ throw new RuntimeException("Coverage '" + meta.getCoverageName()
+ + "' is not georeferenced with 'EPSG:4326' coordinate system.");
+ }
+ if (counter == 2 && crs != null && domain1.isSingleValue() && domain2.isSingleValue()) {
+ if (crs.getName().equals(DomainElement.WGS84_CRS)) {
+ LOG.debug("CRS is '{}' and should be equal to '{}'", crs.getName(), DomainElement.WGS84_CRS);
+ try {
+ this.transformedCoordinates = true;
+ // Convert to pixel coordinates
+ Double val1 = domain1.getSingleValue();
+ Double val2 = domain2.getSingleValue();
+ String axisName = axis.toRasQL().toUpperCase();
+ if (axisName.equals("X")) {
+ long[] pCoord = crs.convertToPixelCoordinates(meta, "X", val1, val2, null, null);
+ coord1 = pCoord[0];
+ coord2 = pCoord[1];
+ }
+ if (axisName.equals("Y")) {
+ long[] pCoord = crs.convertToPixelCoordinates(meta, "Y", null, null, val1, val2);
+ coord1 = pCoord[2];
+ coord2 = pCoord[3];
+ }
+ } catch (NoApplicableCodeException e) {
+ this.transformedCoordinates = false;
+ LOG.error("Error while transforming geo-coordinates to pixel coordinates."
+ + "The metadata is probably not valid.");
+ }
+ }
+ }
+ }
+
+ /* Not used */
+ public String toRasQL() {
+ return "<DimensionIntervalElement Not Converted to RasQL>";
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ public Node getNextNode() {
+ return nextNode;
+ }
+
+ public String getAxisName() {
+ return this.axis.toRasQL();
+ }
+
+ public String getAxisCoords() {
+ return this.domain1.toRasQL() + " : " + this.domain2.toRasQL();
+ }
+
+ public String getLowCoord() {
+ if (transformedCoordinates) {
+ return String.valueOf(coord1);
+ } else {
+ return this.domain1.toRasQL();
+ }
+ }
+
+ public String getHighCoord() {
+ if (transformedCoordinates) {
+ return String.valueOf(coord2);
+ } else {
+ return this.domain2.toRasQL();
+ }
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/DimensionIntervalList.java b/petascope/src/petascope/wcps/server/core/DimensionIntervalList.java
new file mode 100644
index 0000000..94e477c
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/DimensionIntervalList.java
@@ -0,0 +1,55 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import java.util.ArrayList;
+import java.util.List;
+import org.w3c.dom.*;
+
+public class DimensionIntervalList {
+
+ private ArrayList<IRasNode> list;
+
+ public DimensionIntervalList(Node node, XmlQuery xq, CoverageInfo info)
+ throws WCPSException, InvalidCrsException {
+ System.err.println("Parsing a Dimension Interval List ...");
+
+ while (node != null) {
+ list = new ArrayList<IRasNode>();
+ try {
+ System.err.println("Parsing one dimension interval element ...");
+ DimensionIntervalElement elem = new DimensionIntervalElement(node, xq, info);
+ node = elem.getNextNode();
+ list.add(elem);
+ } catch (WCPSException e) {
+ System.err.println("Failed to parse this dimension interval element !");
+ System.err.println("Current node: " + node);
+ }
+ }
+ }
+
+ public List getAxisList() {
+ return list;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/DimensionPointElement.java b/petascope/src/petascope/wcps/server/core/DimensionPointElement.java
new file mode 100644
index 0000000..b29dd8e
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/DimensionPointElement.java
@@ -0,0 +1,130 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class DimensionPointElement implements IRasNode {
+
+ private IRasNode domain, child;
+ private AxisName axis;
+ private Crs crs;
+ private boolean finished = false;
+ private Node nextNode;
+
+ public DimensionPointElement(Node node, XmlQuery xq)
+ throws WCPSException, InvalidCrsException {
+ System.err.println("Trying to parse DimensionPointElement expression...");
+ String name;
+
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ while (node != null && finished == false) {
+ if (node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ continue;
+ }
+
+ name = node.getNodeName();
+ System.err.println("Current node is " + name);
+
+ // Try Axis
+ try {
+ axis = new AxisName(node, xq);
+ node = node.getNextSibling();
+ continue;
+ } catch (WCPSException e) {
+ System.err.println("Failed to parse an axis!");
+ }
+
+ // Try CRS name
+ try {
+ crs = new Crs(node, xq);
+ node = node.getNextSibling();
+ if (axis == null) {
+ throw new WCPSException("Expected Axis node before CRS !");
+ }
+ continue;
+ } catch (WCPSException e) {
+ System.err.println("Failed to parse a crs!");
+ }
+
+ // TODO: how to implement DomainMetadataExpr ?
+
+// // Try last thing
+// try
+// {
+// domain1 = new DomainMetadataExprType(node, xq);
+// counter = 1;
+// continue;
+// }
+// catch (WCPSException e)
+// {
+// System.err.println("Failed to parse domain metadata!");
+// }
+
+ // Then it must be a "slicingPosition"
+ if (node.getNodeName().equals("slicingPosition")) {
+ domain = new ScalarExpr(node.getFirstChild(), xq);
+ if (axis == null) {
+ throw new WCPSException("Expected <axis> node before <slicingPosition> !");
+ }
+ } else {
+ throw new WCPSException("Unexpected node: " + node.getFirstChild().getNodeName());
+ }
+
+ if (axis != null && domain != null) {
+ finished = true;
+ }
+
+ if (finished == true) {
+ nextNode = node.getNextSibling();
+ }
+
+ node = node.getNextSibling();
+ }
+ }
+
+ public String toRasQL() {
+ return child.toRasQL();
+ }
+
+ public Node getNextNode() {
+ return nextNode;
+ }
+
+ public String getAxisName() {
+ return this.axis.toRasQL();
+ }
+
+ public String getCrsName() {
+ return this.crs.toRasQL();
+ }
+
+ public String getSlicingPosition() {
+ return this.domain.toRasQL();
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/DomainElement.java b/petascope/src/petascope/wcps/server/core/DomainElement.java
new file mode 100644
index 0000000..3bb18f1
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/DomainElement.java
@@ -0,0 +1,193 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidMetadataException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * This is an axis in geographic coordinates. See the WCPS standard.
+ */
+public class DomainElement implements Cloneable {
+
+ public static final String WGS84_CRS = "EPSG:4326";
+ public static final String IMAGE_CRS = "CRS:1";
+ private Set<String> crss;
+ private String name;
+ private Double numHi;
+ private Double numLo;
+ private String strHi;
+ private String strLo;
+ private String type;
+ private Collection<String> allowedAxes;
+
+ public DomainElement(String name, String type, Double numLo, Double numHi, String strLo,
+ String strHi, Set<String> crss, Collection<String> axes)
+ throws InvalidMetadataException {
+ this.allowedAxes = axes;
+
+ if ((name == null) || (type == null)) {
+ throw new InvalidMetadataException(
+ "Invalid domain element: Element name and type cannot be null");
+ }
+
+ if (name.equals("")) {
+ throw new InvalidMetadataException(
+ "Invalid domain element: Element name cannot be empty");
+ }
+
+ if (allowedAxes.contains(type) == false) {
+ throw new InvalidMetadataException(
+ "Invalid domain element: Invalid element type: " + type
+ + ". Allowed element types are: " + allowedAxes.toString());
+ }
+
+ if ((numLo != null) && (numHi != null) && (strLo == null) && (strHi == null)) {
+ if (numLo.compareTo(numHi) == 1) {
+ throw new InvalidMetadataException(
+ "Invalid domain element: Lower integer bound cannot be larger than upper integer bound");
+ }
+
+ this.numLo = numLo;
+ this.numHi = numHi;
+ } else if ((strLo != null) && (numHi != null) && (numLo == null) && (numHi == null)) {
+ if (strLo.equals("") || strHi.equals("")) {
+ throw new InvalidMetadataException(
+ "Invalid domain element: String bounds cannot be empty");
+ }
+
+ this.strLo = strLo;
+ this.strHi = strHi;
+ } else {
+ /* Allow both sources of info for time-axes */
+ if (type.equals("t")) {
+ this.strLo = strLo;
+ this.strHi = strHi;
+ this.numLo = numLo;
+ this.numHi = numHi;
+ } else {
+ throw new InvalidMetadataException(
+ "Invalid domain element: Integer bounds must both be non-null if string bounds are null, and vice versa at "
+ + name + ":" + type);
+ }
+ }
+
+ if ((type.equals("x") || type.equals("y")) && (numLo == null)) {
+ throw new InvalidMetadataException(
+ "Invalid domain element: A spatial axis must have integer extent");
+ } else if (type.equals("temporal") && (strLo == null)) {
+ throw new InvalidMetadataException(
+ "Invalid domain element: A temporal axis must have string extent");
+ } else if (type.equals("t") && (numLo == null) || (numHi == null)) {
+ throw new InvalidMetadataException("Invalid domain element: A \"t\" axis must have integer extent and optionally, string extent");
+ }
+
+ this.name = name;
+ this.type = type;
+
+ if ((crss == null) || !crss.contains(IMAGE_CRS)) {
+// throw new InvalidMetadataException(
+// "Invalid domain element: CRS set does not contain image CRS '"
+// + IMAGE_CRS + "'");
+ crss.add(IMAGE_CRS);
+ }
+
+ this.crss = crss;
+
+ }
+
+ @Override
+ public DomainElement clone() {
+ Set<String> c = new HashSet<String>(crss.size());
+ Iterator<String> i = crss.iterator();
+
+ while (i.hasNext()) {
+ c.add(new String(i.next()));
+ }
+
+ try {
+ String newName = name == null ? null : new String(name);
+ String newType = type == null ? null : new String(type);
+ Double newNumLo = numLo == null ? null : new Double(numLo);
+ Double newNumHi = numHi == null ? null : new Double(numHi);
+ String newStrLo = strLo == null ? null : new String(strLo);
+ String newStrHi = strHi == null ? null : new String(strHi);
+ return new DomainElement(newName, newType, newNumLo, newNumHi, newStrLo, newStrHi, c, allowedAxes);
+ } catch (InvalidMetadataException ime) {
+ throw new RuntimeException(
+ "Invalid metadata while cloning DomainElement. This is a software bug in WCPS.",
+ ime);
+ }
+
+ }
+
+ public boolean equals(DomainElement de) {
+ if ((numLo == null) && (de.numLo == null)) {
+ return strLo.equals(de.strLo) && strHi.equals(strHi)
+ && name.equals(de.name) && type.equals(de.type);
+ } else if ((strLo == null) && (de.strLo == null)) {
+ return numLo.equals(de.numLo) && numHi.equals(numHi)
+ && name.equals(de.name) && type.equals(de.type);
+ } else {
+ return false;
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Double getNumHi() {
+ return numHi;
+ }
+
+ public Double getNumLo() {
+ return numLo;
+ }
+
+ public String getStrHi() {
+ return strHi;
+ }
+
+ public String getStrLo() {
+ return strLo;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public Set<String> getCrsSet() {
+ return crss;
+ }
+
+ @Override
+ public String toString() {
+ String d = "Domain Element { Name: '" + name + "', Type: '" + type
+ + "', NumLow: '" + numLo + "', NumHi: '" + numHi + "', StrLow: '"
+ + strLo + "', StrHi: '" + strHi + "', CrsSet: '" + crss + "'}";
+ return d;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/DynamicMetadataSource.java b/petascope/src/petascope/wcps/server/core/DynamicMetadataSource.java
new file mode 100644
index 0000000..2918f84
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/DynamicMetadataSource.java
@@ -0,0 +1,105 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.ResourceException;
+import petascope.wcps.server.exceptions.InvalidWcpsRequestException;
+import petascope.wcps.server.exceptions.InvalidMetadataException;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A IMetadataSource that allows WCPS to store information about on-the-fly
+ * constructed coverages (for example Construct Coverage expr).
+ * Needs another MetadataSource as a backend, to retrieve metadata about
+ * static coverages.
+ */
+public class DynamicMetadataSource implements IDynamicMetadataSource {
+ // Static coverages, served by the server at all times
+
+ private Set<String> staticCoverageNames;
+ // Dynamic coverages, built on-the-fly in a query
+ private Set<String> dynamicCoverageNames;
+ // Union of static and dynamic coverages
+ private Set<String> allCoverageNames;
+ // Metadata information for all available coverages
+ private Map<String, Metadata> metadata;
+ // Other metadata class that serves as backend
+ private IMetadataSource metadataSource;
+
+ public DynamicMetadataSource(IMetadataSource metadataSource)
+ throws ResourceException, InvalidMetadataException {
+ this.metadataSource = metadataSource;
+ staticCoverageNames = metadataSource.coverages();
+ dynamicCoverageNames = new HashSet<String>();
+ allCoverageNames = staticCoverageNames;
+ metadata = new HashMap<String, Metadata>();
+
+ // Init metadata for static coverages
+ Iterator<String> i = staticCoverageNames.iterator();
+ try {
+ while (i.hasNext()) {
+ String coverage = i.next();
+ metadata.put(coverage, metadataSource.read(coverage));
+ }
+ } catch (InvalidWcpsRequestException ire) {
+ throw (InvalidMetadataException) ire.getCause();
+ }
+ }
+
+ public Set<String> coverages() throws ResourceException {
+ return metadataSource.coverages();
+ }
+
+ public String formatToMimetype(String format) {
+ return metadataSource.formatToMimetype(format);
+ }
+
+ public Metadata read(String coverageName) throws InvalidWcpsRequestException, ResourceException {
+ if ((coverageName == null) || coverageName.equals("")) {
+ throw new InvalidWcpsRequestException(
+ "Cannot retrieve coverage with null or empty name");
+ }
+
+ if (!this.coverages().contains(coverageName)) {
+ throw new InvalidWcpsRequestException("Coverage '" + coverageName
+ + "' is not served by this server");
+ }
+
+ return metadataSource.read(coverageName);
+ }
+
+ public void addDynamicMetadata(String coverageName, Metadata meta) {
+ metadata.put(coverageName, meta);
+ dynamicCoverageNames.add(coverageName);
+ allCoverageNames = staticCoverageNames;
+ allCoverageNames.addAll(dynamicCoverageNames);
+ }
+
+ public Collection<String> getAxisNames() {
+ return metadataSource.getAxisNames();
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/EncodeDataExpr.java b/petascope/src/petascope/wcps/server/core/EncodeDataExpr.java
new file mode 100644
index 0000000..2ed58ac
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/EncodeDataExpr.java
@@ -0,0 +1,96 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+// This is the equivalent of the "ProcessingExprType" complex XML type.
+public class EncodeDataExpr implements IRasNode {
+
+ private IRasNode coverageExprType;
+ private String extraParams;
+ private String format;
+ private String mime;
+ private Boolean store;
+
+ public EncodeDataExpr(Node node, XmlQuery request) throws WCPSException, InvalidCrsException {
+ Node child;
+ String nodeName;
+
+ for (child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
+ nodeName = child.getNodeName();
+
+ if (nodeName.equals("#text")) {
+ continue;
+ }
+
+ System.err.println("Encode : node : " + child.getNodeName());
+
+ if (nodeName.equals("format")) {
+ format = child.getFirstChild().getNodeValue();
+ mime = request.getMetadataSource().formatToMimetype(format);
+ continue;
+ }
+
+ if (nodeName.equals("extraParameters")) {
+ extraParams = child.getFirstChild().getNodeValue();
+ continue;
+ }
+
+ coverageExprType = new CoverageExpr(child, request);
+ }
+
+ Node _store = node.getAttributes().getNamedItem("store");
+
+ if (_store != null) {
+ store = _store.getNodeValue().equals("true");
+ }
+ }
+
+ public String getMime() {
+ return mime;
+ }
+
+ public String toRasQL() {
+ // TODO: cjucovschi - implement store
+
+ String result;
+
+ if (format.equals("raw")) {
+ result = coverageExprType.toRasQL();
+ } else {
+ result = format + "(" + coverageExprType.toRasQL();
+
+ if (extraParams != null) {
+ extraParams = '"' + extraParams + '"';
+ result = result + ", " + extraParams;
+ }
+
+ result = result + ")";
+ }
+
+ System.err.println("Returning EncodeExpression:" + result);
+ return result;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/ExtendCoverageExpr.java b/petascope/src/petascope/wcps/server/core/ExtendCoverageExpr.java
new file mode 100644
index 0000000..a711742
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/ExtendCoverageExpr.java
@@ -0,0 +1,132 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.w3c.dom.*;
+
+public class ExtendCoverageExpr implements IRasNode, ICoverageInfo {
+
+ private List<DimensionIntervalElement> axisList;
+ private CoverageExpr coverageExprType;
+ private CoverageInfo coverageInfo;
+ private String[] dim;
+ private int dims;
+ private DimensionIntervalElement elem;
+
+ public ExtendCoverageExpr(Node node, XmlQuery xq) throws WCPSException, InvalidCrsException {
+
+ Node child, axisNode;
+ String nodeName;
+
+ axisList = new ArrayList<DimensionIntervalElement>();
+
+ child = node.getFirstChild();
+ while (child != null) {
+ nodeName = child.getNodeName();
+
+ if (nodeName.equals("#text")) {
+ child = child.getNextSibling();
+ continue;
+ }
+
+ try {
+ System.err.println("Trying out an CoverageExprType group...");
+ coverageExprType = new CoverageExpr(child, xq);
+ coverageInfo = coverageExprType.getCoverageInfo();
+ child = child.getNextSibling();
+ continue;
+ } catch (WCPSException e) {
+ System.err.println("This was no CoverageExprType: " + nodeName);
+ }
+
+ try {
+ // Start a new axis and save it
+ elem = new DimensionIntervalElement(child, xq, coverageInfo);
+ axisList.add(elem);
+ child = elem.getNextNode();
+ continue;
+ } catch (WCPSException e) {
+ System.err.println("This was no Dimension Interval ELement: " + child.getNodeName());
+ }
+
+ // else unknown element
+ throw new WCPSException("Unknown node for ExtendCoverage expression:" + child.getNodeName());
+ }
+
+ dims = coverageInfo.getNumDimensions();
+ dim = new String[dims];
+
+ for (int j = 0; j < dims; ++j) {
+ dim[j] = "*:*";
+ }
+
+
+ Iterator<DimensionIntervalElement> i = axisList.iterator();
+ DimensionIntervalElement axis;
+ int axisId;
+ int axisLo, axisHi;
+
+ while (i.hasNext()) {
+ axis = i.next();
+ axisId = coverageInfo.getDomainIndexByName(axis.getAxisName());
+ System.out.println("Axis ID: " + axisId);
+ System.out.println("Axis name: " + axis.getAxisName());
+ System.out.print("Axis coords: ");
+
+ axisLo = Integer.parseInt(axis.getLowCoord());
+ axisHi = Integer.parseInt(axis.getHighCoord());
+ dim[axisId] = axisLo + ":" + axisHi;
+ coverageInfo.setCellDimension(
+ axisId,
+ new CellDomainElement(
+ BigInteger.valueOf(axisLo), BigInteger.valueOf(axisHi)));
+ }
+
+
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return coverageInfo;
+ }
+
+ public String toRasQL() {
+ String result = "extend(" + coverageExprType.toRasQL() + ",[";
+
+ for (int j = 0; j < dims; ++j) {
+ if (j > 0) {
+ result += ",";
+ }
+
+ result += dim[j];
+ }
+
+ result += "])";
+
+ return result;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/FieldInterpolationElement.java b/petascope/src/petascope/wcps/server/core/FieldInterpolationElement.java
new file mode 100644
index 0000000..74af1cf
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/FieldInterpolationElement.java
@@ -0,0 +1,79 @@
+ /*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+import petascope.wcps.server.exceptions.InvalidWcpsRequestException;
+
+public class FieldInterpolationElement implements IRasNode {
+
+ private FieldName name;
+ private InterpolationMethod interp;
+ private Node nextNode;
+
+ public FieldInterpolationElement(Node node, XmlQuery xq) throws WCPSException {
+
+ throw new InvalidWcpsRequestException("Currently, our implementation does not allow specifying " +
+ "interpolation methods or null resistances for the scale operation.");
+
+ /*
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ if (node == null) {
+ throw new WCPSException("FieldInterpolationElementType parsing error!");
+ }
+
+ while (node != null)
+ {
+ String nodeName = node.getNodeName();
+ while (node.getNodeName().equals("#text"))
+ node = node.getNextSibling();
+
+ if (nodeName.equals("name")) {
+ this.name = new FieldName(node, xq);
+ node = node.getNextSibling();
+ continue;
+ }
+ else
+ {
+ interp = new InterpolationMethod(node, xq);
+ node = interp.getNextNode();
+ }
+ }
+ nextNode = node;
+
+ */
+ }
+
+ public Node getNextNode()
+ {
+ return nextNode;
+ }
+
+ public String toRasQL() {
+ // Since we only accept the default rasdaman interpolation methods, we do not need to specify it further
+ return "";
+ }
+};
diff --git a/petascope/src/petascope/wcps/server/core/FieldName.java b/petascope/src/petascope/wcps/server/core/FieldName.java
new file mode 100644
index 0000000..0f6f71d
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/FieldName.java
@@ -0,0 +1,52 @@
+ /*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class FieldName implements IRasNode {
+
+ private String name;
+
+ public FieldName(Node node, XmlQuery xq) throws WCPSException {
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ if (node == null) {
+ throw new WCPSException("FieldNameType parsing error!");
+ }
+
+ String nodeName = node.getNodeName();
+
+ if (nodeName.equals("name")) {
+ this.name = node.getTextContent();
+
+ System.err.println("Found field name: " + name);
+ }
+ }
+
+ public String toRasQL() {
+ return this.name;
+ }
+};
diff --git a/petascope/src/petascope/wcps/server/core/ICoverageInfo.java b/petascope/src/petascope/wcps/server/core/ICoverageInfo.java
new file mode 100644
index 0000000..b3aa956
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/ICoverageInfo.java
@@ -0,0 +1,27 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+interface ICoverageInfo {
+
+ public CoverageInfo getCoverageInfo();
+}
diff --git a/petascope/src/petascope/wcps/server/core/IDynamicMetadataSource.java b/petascope/src/petascope/wcps/server/core/IDynamicMetadataSource.java
new file mode 100644
index 0000000..31e82a4
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/IDynamicMetadataSource.java
@@ -0,0 +1,33 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+/**
+ * A IDynamicMetadataSource is an IMetadataSource that can also add information
+ * about new coverages on-the-fly. This is useful for queries that construct
+ * new coverages (see ConstructCoverage expression) but are not stored in the
+ * database.
+ */
+public interface IDynamicMetadataSource extends IMetadataSource {
+
+ public void addDynamicMetadata(String coverageName, Metadata meta);
+}
diff --git a/petascope/src/petascope/wcps/server/core/IMetadataSource.java b/petascope/src/petascope/wcps/server/core/IMetadataSource.java
new file mode 100644
index 0000000..fb01453
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/IMetadataSource.java
@@ -0,0 +1,44 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.ResourceException;
+import petascope.wcps.server.exceptions.InvalidWcpsRequestException;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * A IMetadataSource is anything that can read metadata for a given coverage
+ * name. It must be able to list all coverages which it knows, return Metadata
+ * for each one, and also map a format (e.g. "png") to its formatToMimetype
+ * (e.g. "image/png").
+ */
+public interface IMetadataSource {
+
+ public Set<String> coverages() throws ResourceException;
+
+ public String formatToMimetype(String format);
+
+ public Metadata read(String coverageName) throws InvalidWcpsRequestException, ResourceException;
+
+ public Collection<String> getAxisNames();
+}
diff --git a/petascope/src/petascope/wcps/server/core/IRasNode.java b/petascope/src/petascope/wcps/server/core/IRasNode.java
new file mode 100644
index 0000000..8bf7aae
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/IRasNode.java
@@ -0,0 +1,27 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+interface IRasNode {
+
+ public String toRasQL();
+}
diff --git a/petascope/src/petascope/wcps/server/core/InducedOperationCoverageExpr.java b/petascope/src/petascope/wcps/server/core/InducedOperationCoverageExpr.java
new file mode 100644
index 0000000..4e20c4c
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/InducedOperationCoverageExpr.java
@@ -0,0 +1,88 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class InducedOperationCoverageExpr implements IRasNode, ICoverageInfo {
+
+ private IRasNode child;
+ private CoverageInfo info;
+ private String operation = "";
+
+ public InducedOperationCoverageExpr(Node node, XmlQuery xq)
+ throws WCPSException, InvalidCrsException {
+ String nodeName = node.getNodeName();
+
+ System.err.println("Trying induced operation: " + nodeName);
+ boolean okay = false; // will be true if the node is recognized
+
+ if (nodeName.equals("rangeConstructor")) {
+ operation = nodeName;
+ child = new RangeCoverageExpr(node, xq);
+ info = new CoverageInfo((((ICoverageInfo) child).getCoverageInfo()));
+ } else { // Try one of the groups
+ child = null;
+
+ if (child == null) {
+ try {
+ child = new UnaryOperationCoverageExpr(node, xq);
+ info = new CoverageInfo((((ICoverageInfo) child).getCoverageInfo()));
+ System.err.println("*** Induced Operation SUCCESS: " + node.getNodeName());
+ } catch (WCPSException e) {
+ System.err.println("InducedOperation failed: " + node.getNodeName());
+ child = null;
+ if (e.getMessage().equals("Method not implemented")) {
+ throw e;
+ }
+ }
+ }
+
+ if (child == null) {
+ try {
+ child = new BinaryOperationCoverageExpr(node, xq);
+ info = new CoverageInfo((((ICoverageInfo) child).getCoverageInfo()));
+ System.err.println("*** Binary Operation SUCCESS: " + node.getNodeName());
+ } catch (WCPSException e) {
+ System.err.println("Binary operation failed: " + node.getNodeName());
+ child = null;
+ }
+ }
+
+ if (child == null) {
+ throw new WCPSException("Invalid induced coverage expression, next node: "
+ + node.getNodeName());
+ }
+ }
+
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ public String toRasQL() {
+ return child.toRasQL();
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/InterpolationMethod.java b/petascope/src/petascope/wcps/server/core/InterpolationMethod.java
new file mode 100644
index 0000000..9b1cf65
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/InterpolationMethod.java
@@ -0,0 +1,84 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+//A pair of an interpolation type and a null resistance. See the WCPS standard for an explanation of these.
+import petascope.wcps.server.exceptions.InvalidMetadataException;
+
+public class InterpolationMethod implements Cloneable {
+
+ private String interpolationType;
+ private String nullResistance;
+
+ public InterpolationMethod(String interpolationType, String nullResistance)
+ throws InvalidMetadataException {
+ if ((interpolationType == null)
+ || !(interpolationType.equals("nearest") || interpolationType.equals("linear")
+ || interpolationType.equals("cubic")
+ || interpolationType.equals("quadratic")
+ || interpolationType.equals("none"))) {
+ throw new InvalidMetadataException("Invalid interpolation method: "
+ + interpolationType
+ + " is not a legal interpolation type");
+ }
+
+ this.interpolationType = interpolationType;
+
+ if ((nullResistance == null)
+ || !(nullResistance.equals("full") || nullResistance.equals("none")
+ || nullResistance.equals("half") || nullResistance.equals("other"))) {
+ throw new InvalidMetadataException("Invalid interpolation method: "
+ + nullResistance
+ + " is not a legal null resistance");
+ }
+
+ this.nullResistance = nullResistance;
+
+ }
+
+ public InterpolationMethod clone() {
+ try {
+ return new InterpolationMethod(interpolationType, nullResistance);
+ } catch (InvalidMetadataException ime) {
+ throw new RuntimeException(
+ "Invalid metadata while cloning InterpolationMethod. This is a software bug in WCPS.",
+ ime);
+ }
+
+ }
+
+ public boolean equals(InterpolationMethod im) {
+ return interpolationType.equals(im.interpolationType)
+ && nullResistance.equals(im.nullResistance);
+
+ }
+
+ public String getInterpolationType() {
+ return interpolationType;
+
+ }
+
+ public String getNullResistance() {
+ return nullResistance;
+
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/Metadata.java b/petascope/src/petascope/wcps/server/core/Metadata.java
new file mode 100644
index 0000000..21dd264
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/Metadata.java
@@ -0,0 +1,704 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+//~--- JDK imports ------------------------------------------------------------
+import petascope.wcps.server.exceptions.InvalidMetadataException;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import petascope.wcs.server.core.TimeString;
+
+/**
+ * This class implements WCPS metadata. For information on what each field
+ * means, see the WCPS standard. This class provides extensive error cheching
+ * and well as various utility functions.
+ */
+public class Metadata implements Cloneable {
+
+ private List<CellDomainElement> cellDomain;
+ private String coverageName;
+ private int coverageId = -1; // Used when reading metadata from the DB
+ private List<DomainElement> domain;
+ private InterpolationMethod interpolationDefault;
+ private Set<InterpolationMethod> interpolationSet;
+ private String nullDefault;
+ private Set<String> nullSet;
+ private List<RangeElement> range;
+ private String titleStr = "";
+ private String abstractStr = "";
+ private String keywordsStr = "";
+ private Wgs84Crs crs = null;
+ private CellDomainElement cellX, cellY, cellT;
+ private DomainElement domX, domY, domT;
+
+ public Metadata(List<CellDomainElement> cellDomain, List<RangeElement> range, Set<String> nullSet, String nullDefault, Set<InterpolationMethod> interpolationSet, InterpolationMethod interpolationDefault, String coverageName, List<DomainElement> domain, Wgs84Crs crs, String title, String abstr, String keywords) throws InvalidMetadataException {
+ this(cellDomain, range, nullSet, nullDefault, interpolationSet, interpolationDefault, coverageName, domain, crs);
+ this.titleStr = title;
+ this.abstractStr = abstr;
+ this.keywordsStr = keywords;
+ }
+
+ public Metadata(List<CellDomainElement> cellDomain, List<RangeElement> range, Set<String> nullSet, String nullDefault, Set<InterpolationMethod> interpolationSet, InterpolationMethod interpolationDefault, String coverageName, List<DomainElement> domain, Wgs84Crs crs) throws InvalidMetadataException {
+ if ((cellDomain == null) || (range == null) || (coverageName == null) || (nullSet == null) || (interpolationSet == null)) {
+ throw new InvalidMetadataException("Cell domain, range list, "
+ + "coverage name, null set, and interpolation set cannot be null for coverage " + coverageName);
+ }
+
+ if (cellDomain.size() == 0) {
+ throw new InvalidMetadataException("Invalid cell domain: At least "
+ + "one element is required for coverage " + coverageName);
+ }
+
+ this.cellDomain = cellDomain;
+
+ if (range.size() == 0) {
+ throw new InvalidMetadataException("At least one range element is "
+ + "required for coverage " + coverageName);
+ }
+
+ this.range = new ArrayList<RangeElement>(range.size());
+ Iterator<RangeElement> ir = range.iterator();
+
+ while (ir.hasNext()) {
+ RangeElement next = ir.next();
+ Iterator<RangeElement> j = this.range.iterator();
+
+ while (j.hasNext()) {
+ if (j.next().getName().equals(next.getName())) {
+ throw new InvalidMetadataException("Duplicate range element"
+ + " name encountered for coverage " + coverageName);
+ }
+ }
+
+ this.range.add(next);
+ }
+
+ if (nullSet.size() == 0) {
+ throw new InvalidMetadataException("Invalid null set: At least one "
+ + "null value is required for coverage " + coverageName);
+ }
+
+ if (nullDefault == null) {
+ throw new InvalidMetadataException("Invalid null default: Null "
+ + "default cannot be null for coverage " + coverageName);
+ }
+
+ if (!nullSet.contains(nullDefault)) {
+ throw new InvalidMetadataException("Invalid null default: Default "
+ + "null value " + nullDefault + " is not part of the null set"
+ + " for coverage " + coverageName);
+ }
+
+ Iterator<String> ns = nullSet.iterator();
+
+ while (ns.hasNext()) {
+ String nullVal = ns.next();
+ List<String> nulls = SDU.str2string(nullVal);
+
+ if (nulls.size() != range.size()) {
+ throw new InvalidMetadataException("Invalid null value: "
+ + nullVal + " must have " + range.size() + " axes "
+ + "according to the range specified for coverage " + coverageName);
+ }
+
+ Iterator<String> i = nulls.iterator();
+ Iterator<RangeElement> j = range.iterator();
+
+ while (j.hasNext()) {
+ RangeElement re = j.next();
+
+ if (re.isBoolean()) {
+ SDU.str2boolean(i.next());
+ } else if (re.isIntegral()) {
+ SDU.str2integer(i.next());
+ } else if (re.isFloating()) {
+ SDU.str2double(i.next());
+ } else if (re.isComplex()) {
+ SDU.str2complex(i.next());
+ }
+ }
+ }
+
+ this.nullSet = nullSet;
+ this.nullDefault = nullDefault;
+
+ if (interpolationSet.size() == 0) {
+ throw new InvalidMetadataException("Invalid interpolation set: "
+ + "At least one interpolation method is required for "
+ + "coverage " + coverageName);
+ }
+
+ if (interpolationDefault == null) {
+ interpolationDefault = new InterpolationMethod("none", "none");
+ }
+
+ boolean defaultContainedInSet = false;
+ Iterator<InterpolationMethod> is = interpolationSet.iterator();
+
+ while (is.hasNext()) {
+ if (interpolationDefault.equals(is.next())) {
+ defaultContainedInSet = true;
+ }
+ }
+
+ if (!defaultContainedInSet) {
+ throw new InvalidMetadataException("Invalid interpolation default:"
+ + " Default interpolation method ("
+ + interpolationDefault.getInterpolationType() + ","
+ + interpolationDefault.getNullResistance() + ") is not part "
+ + "of the interpolation set for coverage " + coverageName);
+ }
+
+ this.interpolationSet = interpolationSet;
+ this.interpolationDefault = interpolationDefault;
+ this.crs = crs;
+
+ this.coverageName = coverageName;
+
+ if (domain != null) {
+ if (domain.size() != cellDomain.size()) {
+ throw new InvalidMetadataException("Domain and cell domain "
+ + "must have equal number of elements for coverage " + coverageName);
+ }
+
+ this.domain = new ArrayList<DomainElement>(domain.size());
+ Iterator<DomainElement> i = domain.iterator();
+ Iterator<CellDomainElement> ci = cellDomain.iterator();
+
+ while (i.hasNext() && ci.hasNext()) {
+ DomainElement next = i.next();
+ CellDomainElement cell = ci.next();
+ Iterator<DomainElement> j = this.domain.iterator();
+ if (next.getType().equals("x")) {
+ cellX = cell;
+ }
+ if (next.getType().equals("y")) {
+ cellY = cell;
+ }
+ if (next.getType().equals("t") // || next.getType().equals("temporal")
+ ) {
+ cellT = cell;
+ domT = next;
+ }
+
+ while (j.hasNext()) {
+ DomainElement previous = j.next();
+
+ // don't compare same objects
+ if (next == previous) {
+ continue;
+ }
+
+ if (previous.getName().equals(next.getName())) {
+ throw new InvalidMetadataException("Duplicate domain "
+ + "element name encountered for coverage " + coverageName);
+ }
+
+ if (previous.getType().equals("temporal") && next.getType().equals("temporal")) {
+ throw new InvalidMetadataException("Domain can contain"
+ + " at most one temporal axis for coverage " + coverageName);
+ }
+
+ if (previous.getType().equals("elevation") && next.getType().equals("elevation")) {
+ throw new InvalidMetadataException("Domain can contain"
+ + " at most one elevation axis for coverage " + coverageName);
+ }
+
+ if (previous.getType().equals("x") && next.getType().equals("x")) {
+ throw new InvalidMetadataException("Domain can contain"
+ + " at most one x axis for coverage " + coverageName);
+ }
+
+ if (previous.getType().equals("y") && next.getType().equals("y")) {
+ throw new InvalidMetadataException("Domain can contain"
+ + " at most one y axis for coverage " + coverageName);
+ }
+
+ if (next.getType().equals("x")) {
+ boolean l = false;
+ Iterator<DomainElement> k = domain.iterator();
+
+ while (k.hasNext()) {
+ if (k.next().getType().equals("y")) {
+ l = true;
+ }
+ }
+
+ if (l == false) {
+ throw new InvalidMetadataException("If domain "
+ + "contains a x axis, it must contain a y "
+ + "axis as well for coverage " + coverageName);
+ }
+ } else if (next.getType().equals("y")) {
+ boolean l = false;
+ Iterator<DomainElement> k = domain.iterator();
+
+ while (k.hasNext()) {
+ if (k.next().getType().equals("x")) {
+ l = true;
+ }
+ }
+
+ if (l == false) {
+ throw new InvalidMetadataException("If domain "
+ + "contains a y axis, it must contain a x "
+ + "axis as well for coverage " + coverageName);
+ }
+ }
+ }
+
+ this.domain.add(next);
+ }
+ }
+
+ }
+
+ @Override
+ public Metadata clone() {
+ try {
+ List<CellDomainElement> cd = new ArrayList<CellDomainElement>(cellDomain.size());
+ Iterator<CellDomainElement> i = cellDomain.iterator();
+
+ while (i.hasNext()) {
+ cd.add(i.next().clone());
+ }
+
+ List<RangeElement> r = new ArrayList<RangeElement>(range.size());
+ Iterator<RangeElement> j = range.iterator();
+
+ while (j.hasNext()) {
+ r.add(j.next().clone());
+ }
+
+ List<DomainElement> d = new ArrayList<DomainElement>(domain.size());
+ Iterator<DomainElement> k = domain.iterator();
+
+ while (k.hasNext()) {
+ d.add(k.next().clone());
+ }
+
+ Set<String> ns = new HashSet<String>(nullSet.size());
+ Iterator<String> l = nullSet.iterator();
+
+ while (l.hasNext()) {
+ ns.add(new String(l.next()));
+ }
+
+ Set<InterpolationMethod> is = new HashSet<InterpolationMethod>(interpolationSet.size());
+ Iterator<InterpolationMethod> m = interpolationSet.iterator();
+
+ while (m.hasNext()) {
+ is.add(m.next().clone());
+ }
+
+ return new Metadata(cd, r, ns, new String(nullDefault), is, interpolationDefault.clone(), new String(coverageName), d, crs, getAbstract(), getTitle(), getKeywords());
+ } catch (InvalidMetadataException ime) {
+ throw new RuntimeException("Invalid metadata while cloning "
+ + "Metadata. This is a software bug in WCPS.", ime);
+ }
+
+ }
+
+// public CellDomainElement getCellDomain( int index ) {
+//
+// return cellDomain.get( index );
+//
+// }
+ protected void setCoverageId(int id) {
+ this.coverageId = id;
+ }
+
+ public int getCoverageId() {
+ return coverageId;
+ }
+
+ public String getCoverageName() {
+ return coverageName;
+ }
+
+ public String getAbstract() {
+ return abstractStr;
+ }
+
+ public String getTitle() {
+ return titleStr;
+ }
+
+ public String getKeywords() {
+ return keywordsStr;
+ }
+
+ public Iterator<CellDomainElement> getCellDomainIterator() {
+ return cellDomain.iterator();
+
+ }
+
+ public Iterator<DomainElement> getDomainIterator() {
+ return domain.iterator();
+ }
+
+ public Iterator<RangeElement> getRangeIterator() {
+ return range.iterator();
+ }
+
+ public Iterator<InterpolationMethod> getInterpolationMethodIterator() {
+ return interpolationSet.iterator();
+ }
+
+// public Iterator<CrsName> getCrsSetIterator()
+// {
+// return crsset.iterator();
+// }
+ public Iterator<String> getNullSetIterator() {
+ return nullSet.iterator();
+ }
+
+ public int getDimension() {
+ return cellDomain.size();
+ }
+
+ public int getDomainIndexByName(String name) {
+ Iterator<DomainElement> i = domain.iterator();
+
+ for (int index = 0; i.hasNext(); index++) {
+ if (i.next().getName().equals(name)) {
+ return index;
+ }
+ }
+
+ return -1;
+ }
+
+ public DomainElement getDomainByName(String name) {
+ Iterator<DomainElement> i = domain.iterator();
+
+ for (int index = 0; i.hasNext(); index++) {
+ DomainElement dom = i.next();
+ if (dom.getName().equals(name)) {
+ return dom;
+ }
+ }
+
+ return null;
+ }
+
+ public String getNullDefault() {
+ return nullDefault;
+
+ }
+
+ public Set<String> getNullSet() {
+ return nullSet;
+
+ }
+
+ public boolean isRangeBoolean() {
+ Iterator<RangeElement> i = range.iterator();
+
+ while (i.hasNext()) {
+ if (!i.next().isBoolean()) {
+ return false;
+ }
+ }
+
+ return true;
+
+ }
+
+ public boolean isRangeComplex() {
+ Iterator<RangeElement> i = range.iterator();
+
+ while (i.hasNext()) {
+ if (!i.next().isComplex()) {
+ return false;
+ }
+ }
+
+ return true;
+
+ }
+
+ public boolean isRangeIntegral() {
+ Iterator<RangeElement> i = range.iterator();
+
+ while (i.hasNext()) {
+ if (!i.next().isIntegral()) {
+ return false;
+ }
+ }
+
+ return true;
+
+ }
+
+ public boolean isRangeFloating() {
+ Iterator<RangeElement> i = range.iterator();
+
+ while (i.hasNext()) {
+ if (!i.next().isFloating()) {
+ return false;
+ }
+ }
+
+ return true;
+
+ }
+
+ public boolean isRangeNumeric() {
+ Iterator<RangeElement> i = range.iterator();
+
+ while (i.hasNext()) {
+ if (!i.next().isNumeric()) {
+ return false;
+ }
+ }
+
+ return true;
+
+ }
+
+ public void setCoverageName(String coverageName) throws InvalidMetadataException {
+ if (coverageName == null) {
+ throw new InvalidMetadataException("Metadata transformation: Coverage name cannot be null");
+ }
+
+ this.coverageName = coverageName;
+
+ }
+
+// public void setCrs( String crs ) throws InvalidMetadataException {
+//
+// if( crs == null ) {
+// throw new InvalidMetadataException( "Metadata transformation: CRS cannot be null" );
+// }
+// if( !(crs.equals( "" ) || crs.startsWith( "urn:ogc:def:crs:EPSG::" )) ) {
+// throw new InvalidMetadataException( "Metadata transformation: Invalid CRS" );
+// }
+// this.crs = crs;
+//
+// }
+// public void setInterpolationMethodList( List<String> interpolationMethodList ) throws InvalidMetadataException {
+//
+// this.interpolationMethodList = interpolationMethodList;
+// Iterator<String> is = interpolationMethodList.iterator();
+// while( is.hasNext() ) {
+// String next = is.next();
+// if( !(next.equals( "nearest neighbor" ) || next.equals( "bilinear" ) || next.equals( "bicubic" ) || next.equals( "lost area" ) || next.equals( "barycentric" )) ) {
+// throw new InvalidMetadataException( "Metadata transformation: Invalid interpolation method" );
+// }
+// }
+//
+// }
+// public void setNullValue( String nullValue ) {
+//
+// this.nullValue = nullValue;
+//
+// }
+ public void setRangeType(String type) throws InvalidMetadataException {
+ Iterator<RangeElement> i = range.iterator();
+
+ while (i.hasNext()) {
+ i.next().setType(type);
+ }
+
+ }
+
+// public void setRangeType( List<String> types ) throws InvalidMetadataException {
+//
+// if( types.size() != range.size() ) {
+// throw new InvalidMetadataException( "Invalid range type: New type has " + types.size() + " elements, but range has " + range.size() + " elements" );
+// }
+// Iterator<RangeElement> i = range.iterator();
+// Iterator<String> j = types.iterator();
+// while( i.hasNext() ) {
+// i.next().setType( j.next() );
+// }
+//
+// }
+// public void updateCellDomain( int index, BigInteger lo, BigInteger hi ) throws InvalidMetadataException {
+//
+// cellDomain.set( index, new CellDomainElement( lo, hi ) );
+//
+// }
+// public void updateDomain( int index, Double numLo, Double numHi, String strLo, String strHi ) throws InvalidMetadataException {
+//
+// DomainElement old = domain.get( index );
+// domain.set( index, new DomainElement( old.getName(), old.getType(), numLo, numHi, strLo, strHi ) );
+//
+// }
+ public void updateNulls(Set<String> nullSet, String nullDefault) throws InvalidMetadataException {
+ if (nullSet.size() == 0) {
+ throw new InvalidMetadataException("Invalid null set: At least one null value is required");
+ }
+
+ if (nullDefault == null) {
+ nullDefault = "0";
+ }
+
+ if (!nullSet.contains(nullDefault)) {
+ throw new InvalidMetadataException("Invalid null default: Default null value " + nullDefault + " is not part of the null set");
+ }
+
+ this.nullSet = nullSet;
+ this.nullDefault = nullDefault;
+
+ }
+
+ public String getInterpolationDefault() {
+ return interpolationDefault.getInterpolationType();
+ }
+
+ public String getNullResistanceDefault() {
+ return interpolationDefault.getNullResistance();
+ }
+
+ public Wgs84Crs getCrs() {
+ return crs;
+ }
+
+ /**
+ * @return the X if it exists
+ */
+ public CellDomainElement getXCellDomain() {
+ return cellX;
+ }
+
+ /**
+ * @return the Y if it exists
+ */
+ public CellDomainElement getYCellDomain() {
+ return cellY;
+ }
+
+ /**
+ * @return the T if it exists
+ */
+ public CellDomainElement getTCellDomain() {
+ return cellT;
+ }
+
+ /**
+ * @param titleStr the titleStr to set
+ */
+ public void setTitle(String titleStr) {
+ this.titleStr = titleStr;
+ }
+
+ /**
+ * @param abstractStr the abstractStr to set
+ */
+ public void setAbstract(String abstractStr) {
+ this.abstractStr = abstractStr;
+ }
+
+ /**
+ * @param keywordsStr the keywordsStr to set
+ */
+ public void setKeywords(String keywordsStr) {
+ this.keywordsStr = keywordsStr;
+ }
+
+ /**
+ * @param cellDomain the cellDomain to set
+ */
+ public void setCellDomain(List<CellDomainElement> cellDomain) {
+ this.cellDomain = cellDomain;
+ }
+
+ /**
+ * @param domain the domain to set
+ */
+ public void setDomain(List<DomainElement> domain) {
+ this.domain = domain;
+ }
+
+ /**
+ * @param range the range to set
+ */
+ public void setRange(List<RangeElement> range) {
+ this.range = range;
+ }
+
+ /**
+ * @param interpolationSet the interpolationSet to set
+ */
+ public void setInterpolationSet(Set<InterpolationMethod> interpolationSet) {
+ this.interpolationSet = interpolationSet;
+ }
+
+ /**
+ * @param interpolationDefault the interpolationDefault to set
+ */
+ public void setDefaultInterpolation(InterpolationMethod interpolationDefault) {
+ this.interpolationDefault = interpolationDefault;
+ }
+
+ /**
+ * Returns the maximal time position of the current coverage in ISO 8601 format, as string.
+ * If there is no time-axis, returns null
+ */
+ public String getTimePeriodBeginning() {
+ if (domT == null) {
+ return null;
+ }
+ return domT.getStrLo();
+ }
+
+ /**
+ * Returns the minimal time position of the current coverage in ISO 8601 format, as string.
+ * If there is no time-axis, returns null
+ */
+ public String getTimePeriodEnd() {
+ if (domT == null) {
+ return null;
+ }
+ return domT.getStrHi();
+ }
+
+ /**
+ * Returns the time span of the current coverage, as described in the metadata (in miliseconds).
+ * If there is no metadata, returns -1.
+ * Note that this function returns the absolute difference. It is the administrator's
+ * responsibility to make sure that the metadata values are correct.
+ */
+ public long getTimeSpan() {
+ if (domT == null) {
+ return -1;
+ }
+ long result = TimeString.difference(getTimePeriodEnd(), getTimePeriodBeginning());
+ return Math.abs(result);
+ }
+
+ /* Returns the difference between the maximum and the minimum time axis index.
+ Returns -1 if there is no metadata. */
+ public long getTimeIndexesSpan() {
+ if (cellT == null) {
+ return -1;
+ }
+ BigInteger big = cellT.getHi().subtract(cellT.getLo());
+ return big.longValue();
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/MetadataScalarExpr.java b/petascope/src/petascope/wcps/server/core/MetadataScalarExpr.java
new file mode 100644
index 0000000..233242d
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/MetadataScalarExpr.java
@@ -0,0 +1,37 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+// TODO: implement class MetadataScalarExprType
+public class MetadataScalarExpr implements IRasNode {
+
+ public MetadataScalarExpr(Node node, XmlQuery xq) throws WCPSException {
+ throw new WCPSException("Method not yet implemented !");
+ }
+
+ public String toRasQL() {
+ return "";
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/NumericScalarExpr.java b/petascope/src/petascope/wcps/server/core/NumericScalarExpr.java
new file mode 100644
index 0000000..30ef3da
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/NumericScalarExpr.java
@@ -0,0 +1,173 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class NumericScalarExpr implements IRasNode {
+
+ private IRasNode first, second;
+ private String op, value;
+ private boolean twoChildren;
+ private double dvalue;
+
+ public NumericScalarExpr(Node node, XmlQuery xq) throws WCPSException, InvalidCrsException {
+ twoChildren = false;
+ String nodeName = node.getNodeName();
+
+ op = "";
+
+ System.err.println("Trying to parse numeric scalar expression ...");
+
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ if (nodeName.equals("numericConstant")) {
+ twoChildren = false;
+ op = code(nodeName);
+ value = node.getFirstChild().getNodeValue();
+ try {
+ dvalue = Double.parseDouble(value);
+ } catch (NumberFormatException e) {
+ throw new WCPSException("Could not understand constant: " + value);
+ }
+ } else if (nodeName.equals("complexConstant")
+ || nodeName.equals("condense")
+ || nodeName.equals("reduce")) {
+ op = code(nodeName);
+ twoChildren = false;
+ if (nodeName.equals("complexConstant")) {
+ first = new ComplexConstant(node, xq);
+ }
+ if (nodeName.equals("condense")) {
+ first = new CondenseScalarExpr(node, xq);
+ }
+ if (nodeName.equals("reduce")) {
+ first = new ReduceScalarExpr(node, xq);
+ }
+ } else if (nodeName.equals("numericUnaryMinus")
+ || nodeName.equals("numericSqrt")
+ || nodeName.equals("numericAbs")) {
+ op = code(nodeName);
+ twoChildren = false;
+ first = new NumericScalarExpr(node.getFirstChild(), xq);
+ } else if (nodeName.equals("numericAdd")
+ || nodeName.equals("numericMinus")
+ || nodeName.equals("numericMult")
+ || nodeName.equals("numericDiv")) {
+ try {
+ op = code(nodeName);
+ twoChildren = true;
+ Node child = node.getFirstChild();
+ first = new NumericScalarExpr(child, xq);
+ second = new NumericScalarExpr(child.getNextSibling(), xq);
+ } catch (WCPSException e) {
+ System.err.println("Failed to parse a numeric expression pair !");
+ }
+ } else if (nodeName.equals("variableRef")) {
+ try {
+ op = code(nodeName);
+ twoChildren = false;
+ first = new VariableReference(node, xq);
+ System.err.println("Matched variable reference: " + first.toRasQL());
+ } catch (WCPSException e) {
+ System.err.println("Failed to match variable reference: "
+ + e.toString());
+ }
+ } else {
+ throw new WCPSException("Unexpected Numeric Scalar Expression node : "
+ + node.getNodeName());
+ }
+ }
+
+ public String toRasQL() {
+ String result = "";
+ if (twoChildren == false)
+ {
+ if (op.equals("variable")) {
+ result = first.toRasQL();
+ } else if (op.equals("value")) {
+ result = value;
+ } else if (op.equals("-")) {
+ result = "-" + first.toRasQL();
+ } else if (op.equals("sqrt")) {
+ result = "sqrt(" + first.toRasQL() + ")";
+ } else if (op.equals("child")) {
+ result = first.toRasQL();
+ } else if (op.equals("abs")) {
+ result = "abs(" + first.toRasQL() + ")";
+ }
+ }else if (twoChildren == true) {
+ result = "(" + first.toRasQL() + ")" + op
+ + "(" + second.toRasQL() + ")";
+ } else {
+ return " error ";
+ }
+
+ return result;
+ }
+
+ private String code(String name) {
+ String op = "";
+ if (name.equals("numericConstant")) {
+ op = "value";
+ }
+ if (name.equals("numericUnaryMinus") || name.equals("numericMinus")) {
+ op = "-";
+ }
+ if (name.equals("numericAdd")) {
+ op = "+";
+ }
+ if (name.equals("numericMult")) {
+ op = "*";
+ }
+ if (name.equals("numericDiv")) {
+ op = "/";
+ }
+ if (name.equals("numericSqrt")) {
+ op = "sqrt";
+ }
+ if (name.equals("numericAbs")) {
+ op = "abs";
+ }
+ if (name.equals("condense") || name.equals("reduce")
+ || name.equals("complexConstant")) {
+ op = "child";
+ }
+ if (name.equals("variableRef")) {
+ op = "variable";
+ }
+
+ return op;
+ }
+
+ public boolean isSingleValue() {
+ return op.equals("value");
+ }
+
+ public double getSingleValue() {
+ return dvalue;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/ProcessCoveragesRequest.java b/petascope/src/petascope/wcps/server/core/ProcessCoveragesRequest.java
new file mode 100644
index 0000000..36840cc
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/ProcessCoveragesRequest.java
@@ -0,0 +1,252 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.ResourceException;
+import petascope.wcps.server.exceptions.WCPSException;
+import petascope.wcps.server.exceptions.InvalidWcpsRequestException;
+import petascope.wcps.grammar.WCPSRequest;
+import petascope.wcps.grammar.wcpsLexer;
+import petascope.wcps.grammar.wcpsParser;
+import petascope.wcps.grammar.wcpsParser.wcpsRequest_return;
+import java.io.IOException;
+import java.io.StringReader;
+import org.antlr.runtime.RecognitionException;
+import org.odmg.DBag;
+import org.odmg.Database;
+import org.odmg.Implementation;
+import org.odmg.ODMGException;
+import org.odmg.OQLQuery;
+import org.odmg.QueryException;
+import org.odmg.Transaction;
+
+import org.w3c.dom.*;
+
+import org.xml.sax.SAXException;
+import rasj.RasGMArray;
+import rasj.RasImplementation;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.antlr.runtime.ANTLRStringStream;
+import org.antlr.runtime.CharStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.xml.sax.InputSource;
+
+/** A WCPS ProcessCoveragesRequest request provides a (just one) rasdaman query, that it executes.
+ *
+ * Internally, it relies on XmlRequest, which computes the RasQL query.
+ *
+ */
+public class ProcessCoveragesRequest {
+
+ private String database;
+ private IDynamicMetadataSource source;
+ private String url;
+ private WCPS wcps;
+ private String rasqlQuery;
+ private String mime;
+ private XmlQuery xmlQuery;
+
+ public ProcessCoveragesRequest(String url, String database, Node node, IDynamicMetadataSource source, WCPS wcps)
+ throws WCPSException, InvalidWcpsRequestException, ResourceException, SAXException, IOException, InvalidCrsException {
+ super();
+ this.source = source;
+ this.url = url;
+ this.database = database;
+ this.wcps = wcps;
+ Node child = node.getFirstChild();
+ this.rasqlQuery = null;
+
+ System.err.println("Parsing ProcessCoveragesRequest node: " + child.getNodeName());
+
+ if (child.getNodeName().equals("ProcessCoveragesRequest") == false) {
+ throw new WCPSException("The document contains an unrecognized node : "
+ + child.getNodeName());
+ }
+
+ child = child.getFirstChild();
+ while (child.getNodeName().equals("#text")) {
+ child = child.getNextSibling();
+ }
+
+ if (child.getNodeName().equals("query") == false) {
+ throw new WCPSException("Could not find node <query>: " + child.getNodeName());
+ }
+
+ // "child" is now the node <query>.
+ Node queryNode = child.getFirstChild();
+ while (queryNode.getNodeName().equals("#text")) {
+ queryNode = queryNode.getNextSibling();
+ }
+
+ /**
+ * The following code is essential. It handles the two cases:
+ * 1) the xml contains an <xmlSyntax> request
+ * 2) the xml contains an <abstractSyntax> request
+ */
+ if (queryNode.getNodeName().equals("xmlSyntax")) {
+ System.err.println("Found XML Syntax query");
+ this.xmlQuery = new XmlQuery(this.source);
+ xmlQuery.startParsing(queryNode);
+ } else if (queryNode.getNodeName().equals("abstractSyntax")) {
+ try {
+ String abstractQuery = queryNode.getFirstChild().getNodeValue();
+ System.err.println("Found Abstract Syntax query: " + abstractQuery);
+ String xmlString = abstractQueryToXmlQuery(abstractQuery);
+ InputSource xmlStringSource = new InputSource(new StringReader(xmlString));
+ System.err.println("Coverted the Abstract syntax query to an XML query:");
+ System.err.println("***********************************************");
+ System.err.println(xmlString);
+ System.err.println("***********************************************");
+ ProcessCoveragesRequest newRequest = wcps.pcPrepare(url, database, xmlStringSource);
+ this.xmlQuery = newRequest.getXmlRequestStructure();
+ } catch (RecognitionException e) {
+ throw new WCPSException("Abstract Syntax query is invalid: "
+ + e.getMessage());
+ }
+ } else {
+ throw new WCPSException("Error ! Unexpected node: " + queryNode.getNodeName());
+ }
+
+ // If everything went well, we now have a proper value for "xmlQuery"
+ this.rasqlQuery = xmlQuery.toRasQL();
+ System.err.println("Final RasQL query: " + rasqlQuery);
+ this.mime = xmlQuery.getMimeType();
+ }
+
+ public static String abstractQueryToXmlQuery(String abstractQuery) throws RecognitionException {
+ CharStream cs = new ANTLRStringStream(abstractQuery);
+ wcpsLexer lexer = new wcpsLexer(cs);
+ CommonTokenStream tokens = new CommonTokenStream();
+ tokens.setTokenSource(lexer);
+ wcpsParser parser = new wcpsParser(tokens);
+ wcpsRequest_return rrequest = parser.wcpsRequest();
+ WCPSRequest request = rrequest.value;
+ String xmlRequest = request.toXML();
+
+ return xmlRequest;
+ }
+
+ public String getMime() {
+ return mime;
+ }
+
+ private XmlQuery getXmlRequestStructure() {
+ return xmlQuery;
+ }
+
+ public String getRasqlQuery() {
+ return this.rasqlQuery;
+ }
+
+ public List<byte[]> execute() throws ResourceException {
+ ArrayList<byte[]> results = new ArrayList<byte[]>();
+
+ if (this.rasqlQuery != null) {
+ Implementation impl = new RasImplementation(url);
+ Database db = impl.newDatabase();
+
+ try {
+ db.open(database, Database.OPEN_READ_ONLY);
+ } catch (ODMGException odmge) {
+ try {
+ db.close();
+ } catch (ODMGException e) {
+ }
+
+ throw new ResourceException("Could not connect to rasdaman at "
+ + url + ", database "
+ + database, odmge);
+ }
+
+ Transaction tr = impl.newTransaction();
+
+ tr.begin();
+ OQLQuery q = impl.newOQLQuery();
+ DBag resultSet;
+
+ try {
+ q.create(this.getRasqlQuery());
+ resultSet = (DBag) q.execute();
+
+ if (resultSet != null) {
+ Iterator resultIterator = resultSet.iterator();
+
+ while (resultIterator.hasNext()) {
+ Object current = resultIterator.next();
+
+ try {
+ RasGMArray resultArray =
+ (RasGMArray) current;
+
+ results.add(resultArray.getArray());
+ } catch (ClassCastException e) { // not a RasGMarray
+ if (!mime.equals("text/plain")) {
+ throw new ResourceException(
+ "Incompatible mime and data type!");
+ }
+
+ System.err.println("result="
+ + current.toString());
+ results.add(current.toString().getBytes());
+
+ }
+
+
+ /*
+ * if (mime.equals("text/plain")) {
+ * System.err.println("dataType is :" + resultArray.getBaseTypeSchema().toString());
+ * }
+ */
+
+ }
+ }
+ } catch (QueryException qe) {
+ tr.commit();
+
+ try {
+ db.close();
+ } catch (ODMGException odmge) {
+ }
+
+ throw new ResourceException("Could not evaluate rasdaman query: '"
+ + getRasqlQuery() + "'. Cause: " + qe.getMessage(), qe);
+ }
+
+ tr.commit();
+
+ try {
+ db.close();
+ } catch (ODMGException odmge) {
+ }
+ }
+
+ if (mime.equals("text/plain")) {
+ }
+
+ return results;
+
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/RangeComponent.java b/petascope/src/petascope/wcps/server/core/RangeComponent.java
new file mode 100644
index 0000000..c94698c
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/RangeComponent.java
@@ -0,0 +1,87 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+import petascope.wcps.server.exceptions.InvalidCrsException;
+
+
+/**
+ * This is a component of a RangeStructure.
+ * @author Andrei Aiordachioaie
+ */
+public class RangeComponent implements IRasNode, ICoverageInfo {
+
+ private String field = null;
+ private CoverageInfo info = null;
+ private CoverageExpr expr = null;
+
+ public RangeComponent(Node node, XmlQuery xq)
+ throws WCPSException {
+
+ String nodeName = node.getNodeName();
+ if (nodeName.equals("component"))
+ node = node.getFirstChild();
+
+ while (node != null)
+ {
+ nodeName = node.getNodeName();
+ if (nodeName.equals("#text"))
+ {
+ node = node.getNextSibling();
+ continue;
+ }
+
+ if (nodeName.equals("field"))
+ this.field = node.getTextContent();
+ else
+ try
+ {
+ this.expr = new CoverageExpr(node, xq);
+ this.info = expr.getCoverageInfo();
+ }
+ catch (InvalidCrsException e2)
+ {}
+ catch (WCPSException e)
+ {
+ System.err.println("Could not match CoverageExpr inside RangeExpr. Next node: " + nodeName);
+ throw e;
+ }
+
+ node = node.getNextSibling();
+ }
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ public String toRasQL() {
+ String result = "";
+
+ if (this.expr != null)
+ result = expr.toRasQL();
+
+ return result;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/RangeCoverageExpr.java b/petascope/src/petascope/wcps/server/core/RangeCoverageExpr.java
new file mode 100644
index 0000000..2be4d61
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/RangeCoverageExpr.java
@@ -0,0 +1,83 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.w3c.dom.*;
+
+public class RangeCoverageExpr implements IRasNode, ICoverageInfo {
+
+ private IRasNode child;
+ private CoverageInfo info = null;
+ List<IRasNode> components;
+
+ public RangeCoverageExpr(Node node, XmlQuery xq)
+ throws WCPSException {
+
+ components = new ArrayList<IRasNode>();
+
+ if (node.getNodeName().equals("rangeConstructor"))
+ node = node.getFirstChild();
+
+ if (node.getNodeName().equals("#text"))
+ node = node.getNextSibling();
+
+ String nodeName = node.getNodeName();
+ System.err.println("Trying to parse a range coverage expression... Starting at node "
+ + nodeName);
+
+ while (node != null) {
+ if (node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ continue;
+ }
+ if (node.getNodeName().equals("component")) {
+ RangeComponent elem = new RangeComponent(node, xq);
+ info = elem.getCoverageInfo();
+ components.add(elem);
+ }
+
+ node = node.getNextSibling();
+ }
+
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ // FIXME: Returns currently only the info for the last range component
+ return info;
+ }
+
+ public String toRasQL() {
+ String result = "";
+ int length = components.size();
+ for (int i = 0; i < length - 1; i++)
+ result += components.get(i).toRasQL() + ",";
+ result += components.get(length - 1).toRasQL();
+
+ result = "{ " + result + " }";
+
+ return result;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/RangeElement.java b/petascope/src/petascope/wcps/server/core/RangeElement.java
new file mode 100644
index 0000000..29df3b6
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/RangeElement.java
@@ -0,0 +1,163 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+//A single component of a coverage's range. See the WCPS standard for more information.
+import petascope.wcps.server.exceptions.InvalidMetadataException;
+
+public class RangeElement implements Cloneable {
+
+ private String name;
+ private String type;
+
+ public RangeElement(String name, String type) throws InvalidMetadataException {
+ if ((name == null) || (type == null)) {
+ throw new InvalidMetadataException(
+ "Invalid range element: Element name and type cannot be null");
+ }
+
+ if (name.equals("")) {
+ throw new InvalidMetadataException(
+ "Invalid range element: Element name cannot be empty");
+ }
+
+ if (!(type.equals("boolean") || type.equals("char") || type.equals("unsigned char")
+ || type.equals("short") || type.equals("unsigned short") || type.equals("int")
+ || type.equals("unsigned int") || type.equals("long")
+ || type.equals("unsigned long") || type.equals("float")
+ || type.equals("double") || type.equals("complex") || type.equals("complex2"))) {
+ throw new InvalidMetadataException(
+ "Invalid range element: Invalid element type:" + type);
+ }
+
+ this.name = name;
+ this.type = type;
+
+ }
+
+ public RangeElement clone() {
+ try {
+ return new RangeElement(new String(name), new String(type));
+ } catch (InvalidMetadataException ime) {
+ throw new RuntimeException(
+ "Invalid metadata while cloning RangeElement. This is a software bug in WCPS.",
+ ime);
+ }
+
+ }
+
+ public boolean equals(RangeElement re) {
+ return name.equals(re.type);
+
+ }
+
+ public String getName() {
+ return name;
+
+ }
+
+ public String getType() {
+ return type;
+
+ }
+
+ public boolean isBoolean() {
+ return type.equals("boolean");
+
+ }
+
+ public static boolean isBoolean(String type) {
+ return type.equals("boolean");
+
+ }
+
+ public boolean isComplex() {
+ return type.equals("complex") || type.equals("complex2");
+
+ }
+
+ public static boolean isComplex(String type) {
+ return type.equals("complex") || type.equals("complex2");
+
+ }
+
+ public boolean isIntegral() {
+ return type.equals("char") || type.equals("short") || type.equals("unsigned short")
+ || type.equals("int") || type.equals("unsigned int") || type.equals("long")
+ || type.equals("unsigend long");
+
+ }
+
+ public static boolean isIntegral(String type) {
+ return type.equals("char") || type.equals("short") || type.equals("unsigned short")
+ || type.equals("int") || type.equals("unsigned int") || type.equals("long")
+ || type.equals("unsigend long");
+
+ }
+
+ public boolean isFloating() {
+ return type.equals("float") || type.equals("double");
+
+ }
+
+ public static boolean isFloating(String type) {
+ return type.equals("float") || type.equals("double");
+
+ }
+
+ public boolean isNumeric() {
+ return type.equals("char") || type.equals("short") || type.equals("unsigned short")
+ || type.equals("int") || type.equals("unsigned int") || type.equals("long")
+ || type.equals("unsigend long") || type.equals("float")
+ || type.equals("double") || type.equals("complex")
+ || type.equals("complex2");
+
+ }
+
+ public static boolean isNumeric(String type) {
+ return type.equals("char") || type.equals("short") || type.equals("unsigned short")
+ || type.equals("int") || type.equals("unsigned int") || type.equals("long")
+ || type.equals("unsigend long") || type.equals("float")
+ || type.equals("double") || type.equals("complex")
+ || type.equals("complex2");
+
+ }
+
+ public void setType(String type) throws InvalidMetadataException {
+ if (!(type.equals("boolean") || type.equals("char") || type.equals("unsigned char")
+ || type.equals("short") || type.equals("unsigned short") || type.equals("int")
+ || type.equals("unsigned int") || type.equals("long")
+ || type.equals("unsigned long") || type.equals("float")
+ || type.equals("double") || type.equals("complex") || type.equals("complex2"))) {
+ throw new InvalidMetadataException(
+ "Invalid range element: Invalid element type:" + type);
+ }
+
+ this.type = type;
+
+ }
+
+ public String toString() {
+ String r = "Range Element { Name '" + name + "', Type '" + type + "'}";
+ return r;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/RangeField.java b/petascope/src/petascope/wcps/server/core/RangeField.java
new file mode 100644
index 0000000..9256661
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/RangeField.java
@@ -0,0 +1,54 @@
+ /*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+import java.util.Iterator;
+
+public class RangeField implements IRasNode {
+
+ private String type;
+
+ public RangeField(Node node, XmlQuery xq) throws WCPSException {
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ if (node == null) {
+ throw new WCPSException("RangeFieldType parsing error!");
+ }
+
+ String nodeName = node.getNodeName();
+
+ if (nodeName.equals("type")) {
+ this.type = node.getTextContent();
+
+ System.err.println("Found range field type: " + type);
+ }
+ }
+
+ public String toRasQL() {
+ return this.type;
+ }
+};
diff --git a/petascope/src/petascope/wcps/server/core/ReduceScalarExpr.java b/petascope/src/petascope/wcps/server/core/ReduceScalarExpr.java
new file mode 100644
index 0000000..d7e343c
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/ReduceScalarExpr.java
@@ -0,0 +1,68 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class ReduceScalarExpr implements IRasNode {
+
+ CoverageExpr expr;
+ String op;
+
+ public ReduceScalarExpr(Node node, XmlQuery xq) throws WCPSException, InvalidCrsException {
+ if (node.getNodeName().equals("reduce")) {
+ node = node.getFirstChild();
+ }
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ System.err.println("Trying to parse ReduceScalarExpr ");
+ String nodeName = node.getNodeName();
+
+ if (nodeName.equals("all") || nodeName.equals("some") || nodeName.equals("count")
+ || nodeName.equals("add") || nodeName.equals("avg") || nodeName.equals("min")
+ || nodeName.equals("max")) {
+ op = nodeName;
+
+ if (!op.equals("all") && !op.equals("some")) {
+ op = op + "_cells";
+ }
+
+ node = node.getFirstChild();
+
+ while ((node != null) && (node.getNodeName().equals("#text"))) {
+ node = node.getNextSibling();
+ }
+
+ expr = new CoverageExpr(node, xq);
+ } else {
+ throw new WCPSException("invalid ReduceScalarExprType node : " + nodeName);
+ }
+ }
+
+ public String toRasQL() {
+ return op + "(" + expr.toRasQL() + ")";
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/SDU.java b/petascope/src/petascope/wcps/server/core/SDU.java
new file mode 100644
index 0000000..e69ecb2
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/SDU.java
@@ -0,0 +1,191 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+//~--- non-JDK imports --------------------------------------------------------
+import org.apache.commons.math.complex.Complex;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.math.BigInteger;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * This is a static utility class, which provides encoding and decoding of various datatypes
+ * from/to strings. It also handles packing and unpacking of structures.
+ */
+public class SDU {
+
+ public static String boolean2str(List<Boolean> boolea) {
+ List<String> strings = new ArrayList<String>(boolea.size());
+ Iterator<Boolean> i = boolea.iterator();
+
+ while (i.hasNext()) {
+ strings.add(i.next().toString());
+ }
+
+ return string2str(strings);
+
+ }
+
+ public static String complex2str(List<Complex> complex) {
+ List<String> strings = new ArrayList<String>(complex.size());
+ Iterator<Complex> i = complex.iterator();
+
+ while (i.hasNext()) {
+ Complex c = i.next();
+
+ strings.add(c.getReal() + "#" + c.getImaginary());
+ }
+
+ return string2str(strings);
+
+ }
+
+ public static String double2str(List<Double> doubl) {
+ List<String> strings = new ArrayList<String>(doubl.size());
+ Iterator<Double> i = doubl.iterator();
+
+ while (i.hasNext()) {
+ strings.add(i.next().toString());
+ }
+
+ return string2str(strings);
+
+ }
+
+ public static String integer2str(List<BigInteger> integer) {
+ List<String> strings = new ArrayList<String>(integer.size());
+ Iterator<BigInteger> i = integer.iterator();
+
+ while (i.hasNext()) {
+ strings.add(i.next().toString());
+ }
+
+ return string2str(strings);
+
+ }
+
+ public static List<Boolean> str2boolean(String string) {
+ List<String> strings = str2string(string);
+
+ List<Boolean> booleans = new ArrayList<Boolean>(strings.size());
+ Iterator<String> i = strings.iterator();
+
+ while (i.hasNext()) {
+ booleans.add(new Boolean(i.next().equals("true")));
+ }
+
+ return booleans;
+
+ }
+
+ public static List<Complex> str2complex(String string) {
+ List<String> strings = str2string(string);
+
+ List<Complex> complexes = new ArrayList<Complex>(strings.size());
+ Iterator<String> i = strings.iterator();
+
+ while (i.hasNext()) {
+ String[] complex = i.next().split("#");
+
+ complexes.add(new Complex(new Double(complex[0]), new Double(complex[1])));
+ }
+
+ return complexes;
+
+ }
+
+ public static List<Double> str2double(String string) {
+ List<String> strings = str2string(string);
+
+ List<Double> doubles = new ArrayList<Double>(strings.size());
+ Iterator<String> i = strings.iterator();
+
+ while (i.hasNext()) {
+ doubles.add(new Double(i.next()));
+ }
+
+ return doubles;
+
+ }
+
+ public static List<BigInteger> str2integer(String string) {
+ List<String> strings = str2string(string);
+
+ List<BigInteger> integers = new ArrayList<BigInteger>(strings.size());
+ Iterator<String> i = strings.iterator();
+
+ while (i.hasNext()) {
+ integers.add(new BigInteger(i.next()));
+ }
+
+ return integers;
+
+ }
+
+ public static List<String> str2string(String string) {
+ List<String> strings;
+
+ if (string.startsWith("{") && string.contains(",") && string.endsWith("}")) {
+ String[] components = string.substring(1, string.length() - 1).split(",");
+
+ strings = new ArrayList<String>(components.length);
+
+ for (int i = 0; i < components.length; i++) {
+ strings.add(new String(components[i]));
+ }
+
+ return strings;
+ } else {
+ strings = new ArrayList<String>(1);
+ strings.add(new String(string));
+
+ return strings;
+ }
+
+ }
+
+ public static String string2str(List<String> strin) {
+ if (strin == null) {
+ return null;
+ }
+ if (strin.size() == 0) {
+ return "";
+ }
+
+ String string = "{";
+ Iterator<String> i = strin.iterator();
+
+ while (i.hasNext()) {
+ string += i.next() + (i.hasNext()
+ ? ","
+ : "}");
+ }
+
+ return string;
+
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/ScalarExpr.java b/petascope/src/petascope/wcps/server/core/ScalarExpr.java
new file mode 100644
index 0000000..0ec20b6
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/ScalarExpr.java
@@ -0,0 +1,171 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import petascope.wcps.server.exceptions.InvalidMetadataException;
+import java.math.BigInteger;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import org.w3c.dom.*;
+
+public class ScalarExpr implements IRasNode, ICoverageInfo {
+
+ private IRasNode child;
+ private CoverageInfo info;
+ private boolean singleNumericValue = false;
+ private double dvalue;
+
+ public ScalarExpr(Node node, XmlQuery xq) throws WCPSException, InvalidCrsException {
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ // Try one of the groups
+ child = null;
+
+// TODO: Implement class MetadataScalarExprType
+// MetadataScalarExprType
+ if (child == null) {
+ try {
+ child = new MetadataScalarExpr(node, xq);
+ System.err.println("Matched metadata scalar expression.");
+ } catch (WCPSException e) {
+ System.err.println("Failed to match metadata scalar expression: "
+ + e.toString() + "\nRetrying");
+ child = null;
+ }
+ }
+
+// BooleanScalarExprType
+ if (child == null) {
+ try {
+ child = new BooleanScalarExpr(node, xq);
+ System.err.println("Matched boolean scalar expression.");
+ } catch (WCPSException e) {
+ System.err.println("Failed to match boolean scalar expression : "
+ + e.toString() + "\nRetrying");
+ child = null;
+ }
+ }
+
+// NumericScalarExprType
+ if (child == null) {
+ try {
+ child = new NumericScalarExpr(node, xq);
+ singleNumericValue = ((NumericScalarExpr) child).isSingleValue();
+ dvalue = ((NumericScalarExpr) child).getSingleValue();
+ System.err.println("Matched numeric scalar expression.");
+ } catch (WCPSException e) {
+ System.err.println("Failed to match numeric scalar expression : "
+ + e.toString() + "\nRetrying");
+ child = null;
+ }
+ }
+
+// ReduceScalarExprType
+ if (child == null) {
+ try {
+ child = new ReduceScalarExpr(node, xq);
+ System.err.println("Matched reduce scalar expression.");
+ } catch (WCPSException e) {
+ System.err.println("Failed to match reduce scalar expression: "
+ + e.toString() + "\nRetrying");
+ child = null;
+ }
+ }
+
+// StringScalarExprType
+ if (child == null) {
+ try {
+ child = new StringScalarExpr(node, xq);
+ System.err.println("Matched string scalar expression.");
+ } catch (WCPSException e) {
+ System.err.println("Failed to match string scalar expression: "
+ + e.toString() + "\nRetrying");
+ child = null;
+ }
+ }
+
+ // Error check
+ if (child == null) {
+ throw new WCPSException("Invalid coverage Expression, next node: "
+ + node.getNodeName());
+ }
+
+ Metadata meta = createScalarExprMetadata(xq);
+ info = new CoverageInfo(meta);
+ }
+
+ public String toRasQL() {
+ return child.toRasQL();
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ /** Builds full metadata for the newly constructed coverage **/
+ private Metadata createScalarExprMetadata(XmlQuery xq) throws WCPSException {
+ List<CellDomainElement> cellDomainList = new LinkedList<CellDomainElement>();
+ List<RangeElement> rangeList = new LinkedList<RangeElement>();
+ HashSet<String> nullSet = new HashSet<String>();
+ String nullDefault = "0";
+ nullSet.add(nullDefault);
+ HashSet<InterpolationMethod> interpolationSet = new HashSet<InterpolationMethod>();
+ InterpolationMethod interpolationDefault = new InterpolationMethod("none", "none");
+ interpolationSet.add(interpolationDefault);
+ String coverageName = "scalarExpr";
+ List<DomainElement> domainList = new LinkedList<DomainElement>();
+
+ // Build domain metadata
+ cellDomainList.add(new CellDomainElement(new BigInteger("1"), new BigInteger("1")));
+ String crs = DomainElement.IMAGE_CRS;
+ HashSet<String> crsset = new HashSet<String>();
+ crsset.add(crs);
+ Collection<String> allowedAxes = xq.getMetadataSource().getAxisNames();
+ DomainElement domain = new DomainElement("x", "x", 1.0, 1.0, null, null, crsset, allowedAxes);
+ domainList.add(domain);
+ // "unsigned int" is default datatype
+ rangeList.add(new RangeElement("dynamic_type", "unsigned int"));
+
+ try {
+ Metadata metadata = new Metadata(cellDomainList, rangeList, nullSet,
+ nullDefault, interpolationSet, interpolationDefault,
+ coverageName, domainList, null);
+ return metadata;
+ } catch (InvalidMetadataException e) {
+ throw new WCPSException("Could not build metadata for scalar expression !", e);
+ }
+ }
+
+ public boolean isSingleValue() {
+ return singleNumericValue;
+ }
+
+ public double getSingleValue() {
+ return dvalue;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/ScaleCoverageExpr.java b/petascope/src/petascope/wcps/server/core/ScaleCoverageExpr.java
new file mode 100644
index 0000000..feb7e3f
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/ScaleCoverageExpr.java
@@ -0,0 +1,149 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+import petascope.wcps.server.exceptions.InvalidWcpsRequestException;
+
+
+public class ScaleCoverageExpr implements IRasNode, ICoverageInfo {
+
+ private List<DimensionIntervalElement> axisList;
+ private CoverageExpr coverageExprType;
+ private CoverageInfo coverageInfo;
+ private String[] dim;
+ private int dims;
+ private DimensionIntervalElement elem;
+ private FieldInterpolationElement fieldInterp;
+
+ public ScaleCoverageExpr(Node node, XmlQuery xq) throws WCPSException, InvalidCrsException
+ {
+ Node child;
+ String nodeName;
+
+ axisList = new ArrayList<DimensionIntervalElement>();
+
+ child = node.getFirstChild();
+ while (child != null) {
+ nodeName = child.getNodeName();
+
+ if (nodeName.equals("#text")) {
+ child = child.getNextSibling();
+ continue;
+ }
+
+ try {
+ System.err.println("Trying out an CoverageExprType group...");
+ coverageExprType = new CoverageExpr(child, xq);
+ coverageInfo = coverageExprType.getCoverageInfo();
+ child = child.getNextSibling();
+ continue;
+ } catch (WCPSException e) {
+ System.err.println("This was no CoverageExprType: " + nodeName);
+ }
+
+ try {
+ // Start a new axis and save it
+ elem = new DimensionIntervalElement(child, xq, coverageInfo);
+ axisList.add(elem);
+ child = elem.getNextNode();
+ continue;
+ } catch (WCPSException e) {
+ System.err.println("This was no Dimension Interval ELement: " + child.getNodeName());
+ }
+
+ try {
+ fieldInterp = new FieldInterpolationElement(child, xq);
+ child = fieldInterp.getNextNode();
+ continue;
+ }
+ catch (InvalidWcpsRequestException e2)
+ {
+ throw e2;
+ }
+ catch (WCPSException e)
+ {
+ System.err.println("This was no Field Interpolation Element: " + child.getNodeName());
+ }
+
+ // else unknown element
+ throw new WCPSException("Unknown node for ScaleCoverageExpr expression:" + child.getNodeName());
+ }
+
+ dims = coverageInfo.getNumDimensions();
+ dim = new String[dims];
+
+ for (int j = 0; j < dims; ++j) {
+ dim[j] = "*:*";
+ }
+
+
+ Iterator<DimensionIntervalElement> i = axisList.iterator();
+
+ System.out.println("Axis List count:" + axisList.size());
+ DimensionIntervalElement axis;
+ int axisId;
+ int axisLo, axisHi;
+
+ while (i.hasNext()) {
+ axis = i.next();
+ axisId = coverageInfo.getDomainIndexByName(axis.getAxisName());
+ System.out.println("Axis ID: " + axisId);
+ System.out.println("Axis name: " + axis.getAxisName());
+ System.out.print("Axis coords: ");
+
+ axisLo = Integer.parseInt(axis.getLowCoord());
+ axisHi = Integer.parseInt(axis.getHighCoord());
+ dim[axisId] = axisLo + ":" + axisHi;
+ coverageInfo.setCellDimension(
+ axisId,
+ new CellDomainElement(
+ BigInteger.valueOf(axisLo), BigInteger.valueOf(axisHi)));
+ }
+
+ }
+
+ public String toRasQL() {
+ String result = "scale( " + coverageExprType.toRasQL() + ", [";
+
+ for (int j = 0; j < dims; ++j) {
+ if (j > 0) {
+ result += ",";
+ }
+
+ result += dim[j];
+ }
+
+ result += "] )";
+ return result;
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return coverageInfo;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/SetMetadataCoverageExpr.java b/petascope/src/petascope/wcps/server/core/SetMetadataCoverageExpr.java
new file mode 100644
index 0000000..1c6bad3
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/SetMetadataCoverageExpr.java
@@ -0,0 +1,42 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+// TODO: Implement class SetMetadataCoverageExprType
+public class SetMetadataCoverageExpr implements IRasNode, ICoverageInfo {
+
+ public SetMetadataCoverageExpr(Node node, XmlQuery xq)
+ throws WCPSException {
+ throw new WCPSException("Method not implemented");
+ }
+
+ public String toRasQL() {
+ return "";
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return null;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/SliceCoverageExpr.java b/petascope/src/petascope/wcps/server/core/SliceCoverageExpr.java
new file mode 100644
index 0000000..6eeca36
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/SliceCoverageExpr.java
@@ -0,0 +1,131 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.w3c.dom.Node;
+
+public class SliceCoverageExpr implements IRasNode, ICoverageInfo {
+
+ private List<DimensionPointElement> axisList;
+ private CoverageExpr coverageExprType;
+ private CoverageInfo coverageInfo = null;
+ private String[] dim;
+ private DimensionPointElement elem;
+ private int dims;
+
+ public SliceCoverageExpr(Node node, XmlQuery xq) throws WCPSException, InvalidCrsException {
+ Node child = node.getFirstChild();
+ String nodeName;
+
+ axisList = new ArrayList<DimensionPointElement>();
+
+ while (child != null) {
+ nodeName = child.getNodeName();
+
+ if (nodeName.equals("#text")) {
+ child = child.getNextSibling();
+ continue;
+ }
+
+ try {
+ System.err.println("Trying out an CoverageExprType group...");
+ coverageExprType = new CoverageExpr(child, xq);
+ coverageInfo = coverageExprType.getCoverageInfo();
+ child = child.getNextSibling();
+ continue;
+ } catch (WCPSException e) {
+ System.err.println("This was no CoverageExprType: " + nodeName);
+ }
+
+ try {
+ // Start a new axis and save it
+ elem = new DimensionPointElement(child, xq);
+ axisList.add(elem);
+ child = elem.getNextNode();
+ continue;
+ } catch (WCPSException e) {
+ System.err.println("This was no Dimension Point ELement: " + child.getNodeName());
+ }
+
+ // else unknown element
+ throw new WCPSException("Unknown node for TrimCoverage expression:" + child.getNodeName());
+ }
+
+ dims = coverageInfo.getNumDimensions();
+ dim = new String[dims];
+
+ for (int j = 0; j < dims; ++j) {
+ dim[j] = "*:*";
+ }
+
+ Iterator<DimensionPointElement> i = axisList.iterator();
+ DimensionPointElement axis;
+ int axisId;
+ int slicingPosInt;
+ String slicingPosStr;
+
+ while (i.hasNext()) {
+ axis = i.next();
+ /* TODO: BUG: This searches the axis types list using name, not type */
+ axisId = coverageInfo.getDomainIndexByName(axis.getAxisName());
+ slicingPosStr = axis.getSlicingPosition();
+ dim[axisId] = slicingPosStr;
+ // Slicing position can be a constant number or a variable reference
+ try {
+ slicingPosInt = Integer.parseInt(slicingPosStr);
+ } catch (NumberFormatException e) {
+ slicingPosInt = 1;
+ }
+ coverageInfo.setCellDimension(
+ axisId,
+ new CellDomainElement(
+ BigInteger.valueOf(slicingPosInt), BigInteger.valueOf(slicingPosInt)));
+
+ }
+
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return coverageInfo;
+ }
+
+ public String toRasQL() {
+ String result = "(" + coverageExprType.toRasQL() + ") [";
+
+ for (int j = 0; j < dims; ++j) {
+ if (j > 0) {
+ result += ",";
+ }
+
+ result += dim[j];
+ }
+
+ result += "]";
+ return result;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/StringScalarExpr.java b/petascope/src/petascope/wcps/server/core/StringScalarExpr.java
new file mode 100644
index 0000000..87fb23c
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/StringScalarExpr.java
@@ -0,0 +1,63 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class StringScalarExpr implements IRasNode {
+
+ private String op, string;
+ private CoverageExpr cov;
+
+ public StringScalarExpr(Node node, XmlQuery xq) throws WCPSException, InvalidCrsException {
+ while ((node != null) && (node.getNodeName().equals("#text"))) {
+ node = node.getNextSibling();
+ }
+
+ System.err.println("Parsing String Scalar expr : " + node.getNodeName());
+
+ if (node.getNodeName().equals("stringIdentifier")) {
+ Node child = node.getFirstChild();
+ cov = new CoverageExpr(child, xq);
+ op = "id";
+ } else if (node.getNodeName().equals("stringConstant")) {
+ op = "constant";
+ string = node.getNodeValue();
+ } else {
+ throw new WCPSException("Unknown String expr node: " + node.getNodeName());
+ }
+ }
+
+ public String toRasQL() {
+ String result = "";
+ if (op.equals("constant")) {
+ result = string;
+ }
+ if (op.equals("id")) {
+ result = cov.toRasQL();
+ }
+
+ return result;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/SubsetOperationCoverageExpr.java b/petascope/src/petascope/wcps/server/core/SubsetOperationCoverageExpr.java
new file mode 100644
index 0000000..0b9d4fb
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/SubsetOperationCoverageExpr.java
@@ -0,0 +1,70 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+// TODO: Implement class SubsetOperation
+public class SubsetOperationCoverageExpr implements IRasNode, ICoverageInfo {
+
+ private IRasNode child;
+ private CoverageInfo info = null;
+
+ public SubsetOperationCoverageExpr(Node node, XmlQuery xq)
+ throws WCPSException, InvalidCrsException {
+
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ if (node == null) {
+ throw new WCPSException("SubsetOperationCoverageExpr parsing error!");
+ }
+
+ String nodeName = node.getNodeName();
+
+ System.err.println("SubsetOperationCoverageExpr: node " + nodeName);
+
+ if (nodeName.equals("trim")) {
+ child = new TrimCoverageExpr(node, xq);
+ info = ((TrimCoverageExpr) child).getCoverageInfo();
+ } else if (nodeName.equals("extend")) {
+ child = new ExtendCoverageExpr(node, xq);
+ info = ((ExtendCoverageExpr) child).getCoverageInfo();
+ } else if (nodeName.equals("slice")) {
+ child = new SliceCoverageExpr(node, xq);
+ info = ((SliceCoverageExpr) child).getCoverageInfo();
+ } else {
+ throw new WCPSException("Failed to match SubsetOperation: " + nodeName);
+ }
+ }
+
+ public String toRasQL() {
+ return child.toRasQL();
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/TrimCoverageExpr.java b/petascope/src/petascope/wcps/server/core/TrimCoverageExpr.java
new file mode 100644
index 0000000..68ab8a9
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/TrimCoverageExpr.java
@@ -0,0 +1,133 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+import java.math.BigInteger;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class TrimCoverageExpr implements IRasNode, ICoverageInfo {
+
+ private List<DimensionIntervalElement> axisList;
+ private CoverageExpr coverageExprType;
+ private CoverageInfo coverageInfo;
+ private String[] dim;
+ private int dims;
+ private DimensionIntervalElement elem;
+
+ public TrimCoverageExpr(Node node, XmlQuery xq) throws WCPSException, InvalidCrsException {
+ Node child, axisNode;
+ String nodeName;
+
+ axisList = new ArrayList<DimensionIntervalElement>();
+
+ child = node.getFirstChild();
+ while (child != null) {
+ nodeName = child.getNodeName();
+
+ if (nodeName.equals("#text")) {
+ child = child.getNextSibling();
+ continue;
+ }
+
+ try {
+ System.err.println("Trying out an CoverageExprType group...");
+ coverageExprType = new CoverageExpr(child, xq);
+ coverageInfo = coverageExprType.getCoverageInfo();
+ child = child.getNextSibling();
+ continue;
+ } catch (WCPSException e) {
+ System.err.println("This was no CoverageExprType: " + nodeName);
+ }
+
+ try {
+ // Start a new axis and save it
+ elem = new DimensionIntervalElement(child, xq, coverageInfo);
+ axisList.add(elem);
+ child = elem.getNextNode();
+ continue;
+ } catch (WCPSException e) {
+ System.err.println("This was no Dimension Interval ELement: " + child.getNodeName());
+ }
+
+ // else unknown element
+ throw new WCPSException("Unknown node for TrimCoverage expression:" + child.getNodeName());
+ }
+
+ dims = coverageInfo.getNumDimensions();
+ dim = new String[dims];
+
+ for (int j = 0; j < dims; ++j) {
+ dim[j] = "*:*";
+ }
+
+
+ Iterator<DimensionIntervalElement> i = axisList.iterator();
+
+ System.out.println("Axis List count:" + axisList.size());
+ DimensionIntervalElement axis;
+ int axisId;
+ int axisLo, axisHi;
+
+ while (i.hasNext()) {
+ axis = i.next();
+ axisId = coverageInfo.getDomainIndexByName(axis.getAxisName());
+ System.out.println("Axis ID: " + axisId);
+ System.out.println("Axis name: " + axis.getAxisName());
+ System.out.print("Axis coords: ");
+
+ axisLo = Integer.parseInt(axis.getLowCoord());
+ axisHi = Integer.parseInt(axis.getHighCoord());
+ dim[axisId] = axisLo + ":" + axisHi;
+ coverageInfo.setCellDimension(
+ axisId,
+ new CellDomainElement(
+ BigInteger.valueOf(axisLo), BigInteger.valueOf(axisHi)));
+ }
+
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return coverageInfo;
+ }
+
+ public String toRasQL() {
+ String result = coverageExprType.toRasQL() + "[";
+
+ for (int j = 0; j < dims; ++j) {
+ if (j > 0) {
+ result += ",";
+ }
+
+ result += dim[j];
+ }
+
+ result += "]";
+ return result;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/UnaryOperationCoverageExpr.java b/petascope/src/petascope/wcps/server/core/UnaryOperationCoverageExpr.java
new file mode 100644
index 0000000..00b80ec
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/UnaryOperationCoverageExpr.java
@@ -0,0 +1,153 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class UnaryOperationCoverageExpr implements IRasNode, ICoverageInfo {
+
+ private CoverageExpr child;
+ private CoverageInfo info;
+ private String operation;
+ private String params;
+
+ public UnaryOperationCoverageExpr(Node node, XmlQuery xq)
+ throws WCPSException, InvalidCrsException {
+ String nodeName = node.getNodeName();
+
+ System.err.println("Trying to parse unary operation: " + nodeName);
+
+ if (nodeName.equals("unaryPlus")) {
+ operation = "+";
+ child = new CoverageExpr(node.getFirstChild(), xq);
+ } else if (nodeName.equals("unaryMinus")) {
+ operation = "-";
+ child = new CoverageExpr(node.getFirstChild(), xq);
+ } else if (nodeName.equals("sqrt") || nodeName.equals("abs")
+ || nodeName.equals("exp") || nodeName.equals("log") || nodeName.equals("ln")
+ || nodeName.equals("sin") || nodeName.equals("cos") || nodeName.equals("tan")
+ || nodeName.equals("sinh") || nodeName.equals("cosh")
+ || nodeName.equals("tanh") || nodeName.equals("arcsin")
+ || nodeName.equals("arccos") || nodeName.equals("arctan")
+ || nodeName.equals("not") || nodeName.equals("re") || nodeName.equals("im")) {
+ operation = nodeName;
+ child = new CoverageExpr(node.getFirstChild(), xq);
+ } else if (nodeName.equals("bit")) {
+ operation = "bit";
+ Node c = node.getFirstChild();
+
+ while (c != null) {
+ if (c.getNodeName().equals("#text")) {
+ c = c.getNextSibling();
+ continue;
+ }
+
+ if (c.getNodeName().equals("bitIndex")) {
+ try {
+ params = c.getFirstChild().getNodeValue();
+ int i = Integer.parseInt(params);
+ System.err.println("Found bitIndex = " + params);
+ } catch (NumberFormatException e) {
+ throw new WCPSException("Invalid Number as bitIndex: " + params);
+ }
+ } else {
+ child = new CoverageExpr(c, xq);
+ }
+
+ c = c.getNextSibling();
+ }
+ } else if (nodeName.equals("cast")) {
+ operation = "cast";
+ Node c = node.getFirstChild();
+
+ while (c != null) {
+ if (c.getNodeName().equals("#text")) {
+ c = c.getNextSibling();
+ continue;
+ }
+
+ if (c.getNodeName().equals("type")) {
+ RangeField typeNode = new RangeField(c, xq);
+ params = typeNode.toRasQL();
+ } else {
+ child = new CoverageExpr(c, xq);
+ }
+
+ c = c.getNextSibling();
+ }
+ } else if (nodeName.equals("fieldSelect")) {
+ operation = "select";
+ Node c = node.getFirstChild();
+
+ while (c != null) {
+ if (c.getNodeName().equals("#text")) {
+ c = c.getNextSibling();
+ continue;
+ }
+
+ if (c.getNodeName().equals("field")) {
+ FieldName nameNode = new FieldName(c.getFirstChild(), xq);
+ params = nameNode.toRasQL();
+ } else {
+ child = new CoverageExpr(c, xq);
+ }
+
+ c = c.getNextSibling();
+ }
+ } else {
+ throw new WCPSException("Unknown unary operation: " + nodeName);
+ }
+
+ info = new CoverageInfo(child.getCoverageInfo());
+ }
+
+ public CoverageInfo getCoverageInfo() {
+ return info;
+ }
+
+ public String toRasQL() {
+ if (operation.equals("sqrt") || operation.equals("abs") || operation.equals("exp")
+ || operation.equals("log") || operation.equals("ln") || operation.equals("sin")
+ || operation.equals("cos") || operation.equals("tan")
+ || operation.equals("sinh") || operation.equals("cosh")
+ || operation.equals("tanh") || operation.equals("arcsin")
+ || operation.equals("arccos") || operation.equals("arctan")
+ || operation.equals("not") || operation.equals("+") || operation.equals("-")) {
+ return operation + "(" + child.toRasQL() + ")";
+ } else if (operation.equals("cast")) {
+ // Use rasql's direct "type-casting" facility for constant scalar expressions
+ // For example, (char)1 does not work, but 1c is a valid expression.
+ if (child.isScalarExpr() && params.equals("char"))
+ return child.toRasQL() + "c";
+ else
+ return "(" + params + ")(" + child.toRasQL() + ")";
+ } else if (operation.equals("select")) {
+ return "(" + child.toRasQL() + ")." + params;
+ } else if (operation.equals("bit")) {
+ return "bit(" + child.toRasQL() + "," + params + ")";
+ }
+
+ return " error ";
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/VariableReference.java b/petascope/src/petascope/wcps/server/core/VariableReference.java
new file mode 100644
index 0000000..613d9e2
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/VariableReference.java
@@ -0,0 +1,56 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+public class VariableReference implements IRasNode {
+
+ private String name;
+ private String translatedName;
+
+ public VariableReference(Node node, XmlQuery xq) throws WCPSException {
+ System.err.println("Parsing variable reference: " + node.getNodeName());
+
+ while ((node != null) && node.getNodeName().equals("#text")) {
+ node = node.getNextSibling();
+ }
+
+ if (node != null && node.getNodeName().equals("variableRef")) {
+ name = node.getTextContent();
+ translatedName = xq.getReferenceVariableName(name);
+ System.err.println("Variable " + name + " has been renamed into "
+ + translatedName);
+ } else {
+ throw new WCPSException("Could not find any variable reference !");
+ }
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String toRasQL() {
+ return translatedName;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/WCPS.java b/petascope/src/petascope/wcps/server/core/WCPS.java
new file mode 100644
index 0000000..34f7fb2
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/WCPS.java
@@ -0,0 +1,184 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.ResourceException;
+import petascope.wcps.server.exceptions.WCPSException;
+import petascope.wcps.server.exceptions.InvalidWcpsRequestException;
+import petascope.wcps.server.exceptions.InvalidMetadataException;
+import javax.xml.parsers.ParserConfigurationException;
+import org.w3c.dom.*;
+
+import org.xml.sax.*;
+import org.xml.sax.SAXException;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+
+import java.util.List;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+/**
+ * This is the WCPS entry point. Processing a ProcessCoverage request happens in two stages.
+The first stage is the various pcPrepare functions, where XML is parsed, metadata is loaded,
+and the request is translated into an instance of a ProcessCoverageRequest. This data structure,
+for the time being, is just a list of rasdaman queries (RasQuery). The second stage is pcExecute,
+which executes a ProcessCoverageRequests and returns data.
+ */
+public class WCPS {
+
+ private static final String SCHEMA_PACKAGE_PROCESSCOVERAGE = "wcps.xml.processcoverage";
+ private IMetadataSource metadataSource;
+ private IDynamicMetadataSource dynamicMetadataSource;
+ private DocumentBuilder wcpsDocumentBuilder;
+
+ public WCPS(File pcSchema, IMetadataSource metadataSource) throws WCPSException {
+ try {
+ System.out.println("WCPS: Loading and parsing XML Schema ...");
+ DocumentBuilderFactory dbconfig = DocumentBuilderFactory.newInstance();
+
+ dbconfig.setValidating(false); // use XML schema not DTD
+ dbconfig.setIgnoringComments(true); // comments are not relevant
+ dbconfig.setIgnoringElementContentWhitespace(true); // remve the ignorable whitespace
+// Schema wcpsProcessCoverageSchema =
+// SchemaFactory.newInstance(
+// XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(pcSchema);
+
+// dbconfig.setSchema(wcpsProcessCoverageSchema);
+
+ wcpsDocumentBuilder = dbconfig.newDocumentBuilder();
+ System.out.println("WCPS: Finished loading the schema !");
+ } catch (Exception e) {
+ throw new WCPSException(
+ "Error while loading the document builder interface!", e);
+ }
+
+ this.dynamicMetadataSource = new DynamicMetadataSource(metadataSource);
+ }
+
+ public WCPS(IMetadataSource metadataSource) throws ParserConfigurationException,
+ ResourceException, InvalidMetadataException {
+ this.dynamicMetadataSource = new DynamicMetadataSource(metadataSource);
+ wcpsDocumentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ }
+
+ public List<byte[]> pcExecute(String url, String database, ProcessCoveragesRequest pcRequest)
+ throws ResourceException {
+ throw new ResourceException("Mothod not implemented! pcExecute");
+
+ /*
+ * List<RasQuery> queries = pcRequest.getQueries();
+ * List<byte[]> results = new ArrayList<byte[]>( queries.size() );
+ * synchronized( this ) {
+ * Implementation impl = new RasImplementation( url );
+ * Database db = impl.newDatabase();
+ * try {
+ * db.open( database, Database.OPEN_READ_ONLY );
+ * }
+ * catch( ODMGException odmge ) {
+ * try {
+ * db.close();
+ * }
+ * catch (ODMGException e) {}
+ * throw new ResourceException( "Could not connect to rasdaman at " + url + ", database " +
+ * database, odmge );
+ * }
+ * Transaction tr = impl.newTransaction();
+ * tr.begin();
+ * Iterator<RasQuery> queryIterator = queries.iterator();
+ * while( queryIterator.hasNext() ) {
+ * String query = queryIterator.next().toString();
+ * OQLQuery q = impl.newOQLQuery();
+ * DBag resultSet;
+ * try {
+ * q.create( query );
+ * resultSet = (DBag) q.execute();
+ * if( resultSet != null ) {
+ * Iterator resultIterator = resultSet.iterator();
+ * while( resultIterator.hasNext() ) {
+ * RasGMArray result = (RasGMArray) resultIterator.next();
+ * results.add( result.getArray() );
+ * }
+ * }
+ * }
+ * catch (QueryException qe) {
+ * tr.commit();
+ * try {
+ * db.close();
+ * }
+ * catch (ODMGException odmge) {}
+ * throw new ResourceException ( "Could not evaluate rasdaman query: '" + query + "'", qe );
+ * }
+ * }
+ * tr.commit();
+ * try {
+ * db.close();
+ * }
+ * catch (ODMGException odmge) {}
+ * }
+ * return results;
+ */
+ }
+
+ public ProcessCoveragesRequest pcPrepare(String url, String database, File f)
+ throws WCPSException, InvalidWcpsRequestException, ResourceException, SAXException,
+ IOException, InvalidCrsException {
+ return pcPrepare(url, database, wcpsDocumentBuilder.parse(f));
+ }
+
+ public ProcessCoveragesRequest pcPrepare(String url, String database, InputStream is,
+ String systemId)
+ throws WCPSException, InvalidWcpsRequestException, ResourceException, SAXException,
+ IOException, InvalidCrsException {
+ return pcPrepare(url, database, wcpsDocumentBuilder.parse(is, systemId));
+ }
+
+ public ProcessCoveragesRequest pcPrepare(String url, String database, String uri)
+ throws WCPSException, InvalidWcpsRequestException, ResourceException, SAXException,
+ IOException, InvalidCrsException {
+ return pcPrepare(url, database, wcpsDocumentBuilder.parse(uri));
+ }
+
+ public ProcessCoveragesRequest pcPrepare(String url, String database, InputSource is)
+ throws WCPSException, InvalidWcpsRequestException, ResourceException, SAXException,
+ IOException, InvalidCrsException {
+ return pcPrepare(url, database, wcpsDocumentBuilder.parse(is));
+ }
+
+ public ProcessCoveragesRequest pcPrepare(String url, String database, InputStream is)
+ throws WCPSException, InvalidWcpsRequestException, ResourceException, SAXException,
+ IOException, InvalidCrsException {
+ return pcPrepare(url, database, wcpsDocumentBuilder.parse(is));
+ }
+
+ private ProcessCoveragesRequest pcPrepare(String url, String database, Document doc)
+ throws WCPSException, InvalidWcpsRequestException, ResourceException, SAXException, IOException, InvalidCrsException {
+ ProcessCoveragesRequest req = new ProcessCoveragesRequest(url, database, doc, dynamicMetadataSource, this);
+ return req;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/Wgs84Crs.java b/petascope/src/petascope/wcps/server/core/Wgs84Crs.java
new file mode 100644
index 0000000..e712ad6
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/Wgs84Crs.java
@@ -0,0 +1,123 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidMetadataException;
+
+/**
+ * Represents a WGS Coordinate Reference System (CRS) and its bounding box.
+ *
+ *
+ * @version 10.Sep 2009
+ * @author Andrei Aiordachioaie
+ */
+public class Wgs84Crs implements Cloneable {
+
+ private String name = "WGS84";
+ private Double low1, high1, low2, high2;
+ private Double offset1, offset2; // precomputed world-to-crs offsets
+
+ public Wgs84Crs(Double l1, Double h1, Double l2, Double h2, Double o1, Double o2)
+ throws InvalidMetadataException {
+ if ((l1 == null) || (h1 == null) || (l2 == null) || (h2 == null)) {
+ throw new InvalidMetadataException(
+ "Invalid WGS 84 bounding box: null element encountered.");
+ }
+ if ((o1 == null) || (o2 == null)) {
+ throw new InvalidMetadataException("Invalid WGS 84 offsets: null element encountered.");
+ }
+
+ low1 = l1;
+ low2 = l2;
+ high1 = h1;
+ high2 = h2;
+
+ offset1 = o1;
+ offset2 = o2;
+ }
+
+ public Wgs84Crs clone() {
+ try {
+ return new Wgs84Crs(new Double(getLow1()), new Double(getHigh1()),
+ new Double(getLow2()), new Double(getHigh2()),
+ new Double(getOffset1()), new Double(getOffset2()));
+ } catch (InvalidMetadataException e) {
+ return null;
+ }
+ }
+
+ public String toString() {
+ String d = "CRS '" + getName() + "' { Bounding Box [X(" + getLow1() + ", " + getHigh1() + "), "
+ + "Y(" + getLow2() + ", " + getHigh2() + ")], "
+ + "Offsets [X(" + getOffset1() + "), Y(" + getOffset2() + ")]}";
+ return d;
+ }
+
+ /**
+ * @return the low1
+ */
+ public Double getLow1() {
+ return low1;
+ }
+
+ /**
+ * @return the high1
+ */
+ public Double getHigh1() {
+ return high1;
+ }
+
+ /**
+ * @return the low2
+ */
+ public Double getLow2() {
+ return low2;
+ }
+
+ /**
+ * @return the high2
+ */
+ public Double getHigh2() {
+ return high2;
+ }
+
+ /**
+ * @return the offset1
+ */
+ public Double getOffset1() {
+ return offset1;
+ }
+
+ /**
+ * @return the offset2
+ */
+ public Double getOffset2() {
+ return offset2;
+ }
+
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/core/XmlQuery.java b/petascope/src/petascope/wcps/server/core/XmlQuery.java
new file mode 100644
index 0000000..ed1a304
--- /dev/null
+++ b/petascope/src/petascope/wcps/server/core/XmlQuery.java
@@ -0,0 +1,236 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcps.server.core;
+
+import petascope.wcps.server.exceptions.InvalidCrsException;
+import petascope.wcps.server.exceptions.WCPSException;
+import org.w3c.dom.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class XmlQuery implements IRasNode {
+
+ private String mime;
+ private ArrayList<CoverageIterator> iterators;
+ private BooleanScalarExpr where;
+ private IRasNode coverageExpr;
+ private IDynamicMetadataSource meta;
+ private ArrayList<CoverageIterator> dynamicIterators;
+ /* Variables used in the XML query are renamed. The renaming is explained below.
+ *
+ * Variables declared in the same expression (construct, const, condense)
+ will be collapsed into one multidimensional variable name. For
+ "construct img over $px x(1:10), $py y(1:10) values ... ", the variables could
+ be translated as: $px -> "iteratorA[0]", $py -> "iteratorA[1]".
+ * Variables declared in different expression will have different prefixes,
+ built from "varPrefix" + "varStart".
+ *
+
+ * Used in condenser, construct and constant coverage expressions. */
+ // VariableIndexCount stores the dimensionality of each renamed variable
+ private HashMap<String, Integer> varDimension;
+ // VariableNewName is used to translate the old var name into the multi-dim var name
+ private HashMap<String, String> variableTranslator;
+ private String varPrefix = "i_";
+ private char varSuffix = 'i';
+
+ public String getMimeType() {
+ return mime;
+ }
+
+ public XmlQuery(IDynamicMetadataSource source) {
+ super();
+ this.meta = source;
+ iterators = new ArrayList<CoverageIterator>();
+ dynamicIterators = new ArrayList<CoverageIterator>();
+ variableTranslator = new HashMap<String, String>();
+ varDimension = new HashMap<String, Integer>();
+ }
+
+ public XmlQuery(Node node) throws WCPSException, InvalidCrsException {
+ iterators = new ArrayList<CoverageIterator>();
+ dynamicIterators = new ArrayList<CoverageIterator>();
+ variableTranslator = new HashMap<String, String>();
+ varDimension = new HashMap<String, Integer>();
+ this.startParsing(node);
+ }
+
+ public void startParsing(Node node) throws WCPSException, InvalidCrsException {
+ System.err.println("Processing XML Request: " + node.getNodeName());
+
+ Node x = node.getFirstChild();
+
+
+ while (x != null) {
+ if (x.getNodeName().equals("#text")) {
+ x = x.getNextSibling();
+ continue;
+ }
+
+ System.err.println("The current node is: " + x.getNodeName());
+
+ if (x.getNodeName().equals("coverageIterator")) {
+ iterators.add(new CoverageIterator(x, this));
+ } else if (x.getNodeName().equals("where")) {
+ where = new BooleanScalarExpr(x.getFirstChild(), this);
+ } else if (x.getNodeName().equals("encode")) {
+ EncodeDataExpr encode;
+
+ encode = new EncodeDataExpr(x, this);
+ coverageExpr = encode;
+ mime = encode.getMime();
+ } else {
+ // It has to be a scalar Expr
+ coverageExpr = new ScalarExpr(x, this);
+ mime = "text/plain";
+ }
+
+ x = x.getNextSibling();
+ }
+ }
+
+ public Boolean isIteratorDefined(String iteratorName) {
+ Iterator<CoverageIterator> it = iterators.iterator();
+ while (it.hasNext()) {
+ CoverageIterator tmp = it.next();
+ if (iteratorName.equals(tmp.getIteratorName())) {
+ return true;
+ }
+ }
+
+ it = dynamicIterators.iterator();
+ while (it.hasNext()) {
+ CoverageIterator tmp = it.next();
+ if (iteratorName.equals(tmp.getIteratorName())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /* Stores information about dynamically created iterators, as metadata.
+ * For example, from a Construct Coverage expression.
+ */
+ public void addDynamicCoverageIterator(CoverageIterator i) {
+ dynamicIterators.add(i);
+ }
+
+ public Iterator<String> getCoverages(String iteratorName) throws WCPSException {
+ for (int i = 0; i < iterators.size(); ++i) {
+ if (iterators.get(i).getIteratorName().equals(iteratorName)) {
+ return iterators.get(i).getCoverages();
+ }
+ }
+
+ for (int i = 0; i < dynamicIterators.size(); ++i) {
+ if (dynamicIterators.get(i).getIteratorName().equals(iteratorName)) {
+ return dynamicIterators.get(i).getCoverages();
+ }
+ }
+
+ throw new WCPSException("Iterator " + iteratorName + " not defined");
+ }
+
+ public boolean isDynamicCoverage(String coverageName) {
+ for (int i = 0; i < dynamicIterators.size(); ++i) {
+ Iterator<String> iterator =
+ ((CoverageIterator) dynamicIterators.get(i)).getCoverages();
+ while (iterator.hasNext()) {
+ if (iterator.next().equals(coverageName)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /** Creates a new (translated) variable name for an expression that
+ * has referenceable variables.
+ * @return String a new variable name assigned
+ */
+ public String registerNewExpressionWithVariables() {
+ String name = varPrefix + varSuffix;
+ varDimension.put(name, 0);
+ varSuffix++;
+ return name;
+ }
+
+ /** Remember a variable that can be referenced in the future. This function
+ * assigns it a index code, that should then be used to reference that variable
+ * in the RasQL query.
+ *
+ * If the variable is already referenced, then this function does nothing.
+ * @param name Variable name
+ */
+ public boolean addReferenceVariable(String name, String translatedName) {
+ if (varDimension.containsKey(translatedName) == false) {
+ return false;
+ }
+
+ Integer index = varDimension.get(translatedName);
+ Integer newIndex = index + 1;
+ varDimension.put(translatedName, newIndex);
+ variableTranslator.put(name, translatedName + "[" + index + "]");
+
+ return true;
+ }
+
+ /** Retrieve the translated name assigned to a specific reference (scalar) variable */
+ public String getReferenceVariableName(String name) throws WCPSException {
+ String newName = variableTranslator.get(name);
+ return newName;
+ }
+
+ public String toRasQL() {
+ String result = "select " + coverageExpr.toRasQL() + " from ";
+ Iterator<CoverageIterator> it = iterators.iterator();
+ boolean first = true;
+
+ while (it.hasNext()) {
+ if (first) {
+ first = false;
+ } else {
+ result += ", ";
+ }
+
+ result += it.next().toRasQL();
+ }
+
+ if (where != null) {
+ result += " where " + where.toRasQL();
+ }
+
+ return result;
+ }
+
+ public IDynamicMetadataSource getMetadataSource() {
+ return meta;
+ }
+}