diff options
author | Constantin <jucovschi@gmail.com> | 2010-06-02 20:11:10 +0200 |
---|---|---|
committer | Constantin <jucovschi@gmail.com> | 2010-06-02 20:11:10 +0200 |
commit | 93b5abce94b65529df95670dd45260bc469e120b (patch) | |
tree | b82ce43668fc6053e88d2ec4cc4a91e7527cbd4b /petascope/src/petascope/wcps/server | |
parent | 26c676d01aa3995556d83fbee6a84f87a51915a9 (diff) | |
parent | 40e12c6af9d05c3413efaf535c35c625b736cbb9 (diff) | |
download | rasdaman-upstream-93b5abce94b65529df95670dd45260bc469e120b.tar.gz rasdaman-upstream-93b5abce94b65529df95670dd45260bc469e120b.tar.xz rasdaman-upstream-93b5abce94b65529df95670dd45260bc469e120b.zip |
Merge branch 'master' of git://kahlua/petascope
Diffstat (limited to 'petascope/src/petascope/wcps/server')
68 files changed, 9434 insertions, 0 deletions
diff --git a/petascope/src/petascope/wcps/server/cli/f_grammar.java b/petascope/src/petascope/wcps/server/cli/f_grammar.java new file mode 100644 index 0000000..79dfca8 --- /dev/null +++ b/petascope/src/petascope/wcps/server/cli/f_grammar.java @@ -0,0 +1,60 @@ +package petascope.wcps.server.cli; + +import petascope.wcps.grammar.*; +import petascope.wcps.grammar.wcpsParser.*; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import org.antlr.runtime.ANTLRInputStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; +import org.apache.commons.io.FileUtils; + +/** Test the WCPS grammar parser (generated by ANTLR). + * Input the path that contains an Abstract Syntax query. + * Outputs the corresponding XML tree. + * + * @author Andrei Aiordachioaie + */ +public class f_grammar { + + private static String query; + private static String path; + + public static void main(String[] args) throws RecognitionException, IOException { + if (args.length != 1) { + System.err.println("AbstractGrammarGen: no parameter to specify input file !"); + path = "test/test-tmp/29.test"; + query = FileUtils.readFileToString(new File(path)); + } else { + path = args[0]; + query = FileUtils.readFileToString(new File(path)); + } + + System.out.println("Running with the following query: " + query); + + String xmlString = runQuery(query); + System.out.println("Output XML: \n****************\n" + xmlString); + + System.exit(0); + + } + + public static String runQuery(String query) throws IOException, RecognitionException { + InputStream stream = new ByteArrayInputStream(query.getBytes()); // defaults to ISO-1 + ANTLRInputStream inputStream = new ANTLRInputStream(stream); +// wcpsLexer lexer = new wcpsLexer( inputStream ); + wcpsLexer lexer = new wcpsLexer(inputStream); + + CommonTokenStream tokenStream = new CommonTokenStream(lexer); +// wcpsParser parser = new wcpsParser(tokenStream); + wcpsParser parser = new wcpsParser(tokenStream); + + wcpsRequest_return rrequest = parser.wcpsRequest(); + WCPSRequest request = rrequest.value; + + String result = request.toXML(); + return result; + } +} diff --git a/petascope/src/petascope/wcps/server/cli/grammar.java b/petascope/src/petascope/wcps/server/cli/grammar.java new file mode 100644 index 0000000..bc053dc --- /dev/null +++ b/petascope/src/petascope/wcps/server/cli/grammar.java @@ -0,0 +1,65 @@ +package petascope.wcps.server.cli; + +import petascope.wcps.grammar.*; +import petascope.wcps.grammar.wcpsParser.*; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import org.antlr.runtime.ANTLRInputStream; +import org.antlr.runtime.CommonTokenStream; +import org.antlr.runtime.RecognitionException; + +/** Test the WCPS grammar parser (generated by ANTLR). + * Input an Abstract Syntax query. + * Outputs the corresponding XML tree. + * + * @author Andrei Aiordachioaie + */ +public class grammar { + + static String query; + + public static void main(String[] args) throws RecognitionException, IOException { + if (args.length != 1) { + System.err.println("AbstractGrammarGen: no query as parameter !"); +// query = "for a in (rgb) return " + +// "condense + over $x x(1:10), $y y(25:75) " + +// "using $x * (a[x($x), y($y)]).red"; + query = "for c in (rgb) return encode(c[x:\"CRS:1\"(1:200)], \"jpeg\")"; + } else { + query = args[0]; + } + + System.out.println("Running with the following query: " + query); + + String xmlString = convertAbstractQueryToXml(query); + System.out.println("Output XML: \n****************\n" + xmlString); + + System.exit(0); + + } + + /** Converts a WCPS abstract syntax query to an XML query + * + * @param query Abstract Syntax query + * @return String XML query + * @throws java.io.IOException + * @throws org.antlr.runtime.RecognitionException + */ + public static String convertAbstractQueryToXml(String query) throws IOException, RecognitionException { + InputStream stream = new ByteArrayInputStream(query.getBytes()); // defaults to ISO-1 + ANTLRInputStream inputStream = new ANTLRInputStream(stream); +// wcpsLexer lexer = new wcpsLexer( inputStream ); + wcpsLexer lexer = new wcpsLexer(inputStream); + + CommonTokenStream tokenStream = new CommonTokenStream(lexer); +// wcpsParser parser = new wcpsParser(tokenStream); + wcpsParser parser = new wcpsParser(tokenStream); + + wcpsRequest_return rrequest = parser.wcpsRequest(); + WCPSRequest request = rrequest.value; + + String result = request.toXML(); + return result; + } +} diff --git a/petascope/src/petascope/wcps/server/cli/xml.java b/petascope/src/petascope/wcps/server/cli/xml.java new file mode 100644 index 0000000..e115c8e --- /dev/null +++ b/petascope/src/petascope/wcps/server/cli/xml.java @@ -0,0 +1,155 @@ +/*
+ * 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.cli;
+
+import petascope.wcps.server.core.DbMetadataSource;
+import petascope.wcps.server.core.ProcessCoveragesRequest;
+import petascope.wcps.server.core.WCPS;
+
+import java.io.File;
+import java.io.FileInputStream;
+
+import java.io.StringReader;
+import java.util.Properties;
+import org.xml.sax.InputSource;
+
+/**
+ * This is a small application around the WCPS core. It takes XML requests as files and runs them
+ * through WCPS. The resulting radaman queries are displayed, but not executed. This is very useful
+ * for testing whether your metadata is valid.
+ */
+public class xml {
+
+ private static WCPS wcps;
+ private static DbMetadataSource metadataSource;
+
+ private static void initMetadata() {
+ File cwd = new File(".");
+ System.out.println("Working in " + cwd.getAbsolutePath());
+ String pcSchemaFileName =
+ // "src/conf/" +
+ "xml" + File.separator + "ogc" + File.separator + "wcps"
+ + File.separator + "1.0.0" + File.separator + "wcpsProcessCoverages.xsd";
+ File pcSchemaFile = new File(pcSchemaFileName);
+
+ if (!pcSchemaFile.exists()) {
+ System.err.println("WCPS: could not find the WCPS ProcessCoverage schema ("
+ + pcSchemaFileName + ")");
+ System.exit(1);
+ }
+
+ metadataSource = null;
+
+ try {
+ Properties dbParams = new Properties();
+
+ dbParams.load(new FileInputStream("settings.properties"));
+ metadataSource =
+ new DbMetadataSource(dbParams.getProperty("metadata_driver"),
+ dbParams.getProperty("metadata_url"),
+ dbParams.getProperty("metadata_user"),
+ dbParams.getProperty("metadata_pass"), false);
+ wcps = new WCPS(pcSchemaFile, metadataSource);
+ } catch (Exception e) {
+ System.err.println("WCPS: could not initialize WCPS:");
+ e.printStackTrace(System.err);
+ System.exit(1);
+ }
+ }
+
+ public static void main(String[] args) {
+ if (args.length < 1) {
+ System.err.println("WCPS CLI: no input files");
+
+ System.err.println("\nWCPS CLI Usage: java wcps.server.cli.xml input.xml");
+ System.err.println("Where input.xml contains a ProcessCoverages Request ");
+// System.exit(1);
+
+ args = new String[1];
+ args[0] = "test/testcases-wcps_dollar/25.test.xml";
+ }
+ if (args.length > 1) {
+ System.err.println("WCPS: no input files");
+ System.exit(1);
+ }
+
+ initMetadata();
+
+ for (int i = 0; i < args.length; i++) {
+ File fileIn = null;
+ InputSource is = null;
+
+ try {
+ fileIn = new File(args[i]);
+ is = new InputSource(new FileInputStream(fileIn));
+ } catch (Exception fnfe) {
+ System.err.println("WCPS: " + args[i]
+ + ": no such file or directory" + fnfe);
+ System.exit(1);
+ }
+
+
+ String result = processCoverage(is, i);
+ if (result != null) {
+ System.out.println(result);
+ } else {
+ System.err.println("WCPS: " + args[i] + " failed");
+ System.exit(1);
+ }
+ }
+
+ metadataSource.close();
+ System.exit(0);
+
+ }
+
+ private static String processCoverage(InputSource is, int i) {
+ String result = null;
+
+ try {
+ ProcessCoveragesRequest r = wcps.pcPrepare("http://kahlua.eecs.jacobs-university.de:9001",
+ "RASSERVICE", is);
+ System.err.println("Request " + i);
+ String rasql = r.getRasqlQuery();
+ String mime = r.getMime();
+// result = "[" + mime + "] " + rasql;
+ result = rasql;
+ } catch (Exception e) {
+ System.err.println("WCPS: request " + i
+ + " failed with the following exception:");
+ e.printStackTrace(System.err);
+ }
+
+ return result;
+ }
+
+ /** Converts a WCPS XML query into a RasQL query string **/
+ public static String convertXmlToRasql(String query) {
+ String rasql = null;
+ if (metadataSource == null) {
+ initMetadata();
+ }
+ InputSource is = new InputSource(new StringReader(query));
+ rasql = processCoverage(is, 1);
+ return rasql;
+ }
+}
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; + } +} diff --git a/petascope/src/petascope/wcps/server/exceptions/InvalidCrsException.java b/petascope/src/petascope/wcps/server/exceptions/InvalidCrsException.java new file mode 100644 index 0000000..f1381ca --- /dev/null +++ b/petascope/src/petascope/wcps/server/exceptions/InvalidCrsException.java @@ -0,0 +1,29 @@ +/*
+ * 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.exceptions;
+
+public class InvalidCrsException extends Exception {
+
+ public InvalidCrsException(String message) {
+ super(message);
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/exceptions/InvalidMetadataException.java b/petascope/src/petascope/wcps/server/exceptions/InvalidMetadataException.java new file mode 100644 index 0000000..ac4d8d1 --- /dev/null +++ b/petascope/src/petascope/wcps/server/exceptions/InvalidMetadataException.java @@ -0,0 +1,36 @@ +/*
+ * 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.exceptions;
+
+/**
+ * Thrown when WCPS received a request, but could not evaluate it because the
+ * metadata for some coverage does not conform to the WCPS standard.
+ */
+public class InvalidMetadataException extends WCPSException {
+
+ private static final long serialVersionUID = 48924938L;
+
+ public InvalidMetadataException(String message) {
+ super(message, null);
+
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/exceptions/InvalidWcpsRequestException.java b/petascope/src/petascope/wcps/server/exceptions/InvalidWcpsRequestException.java new file mode 100644 index 0000000..d4d3449 --- /dev/null +++ b/petascope/src/petascope/wcps/server/exceptions/InvalidWcpsRequestException.java @@ -0,0 +1,38 @@ +/*
+ * 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.exceptions;
+
+/**
+ * This exception is throws whenever a user submits a request that is not valid in some way.
+ */
+public class InvalidWcpsRequestException extends WCPSException {
+
+ private static final long serialVersionUID = 65492846L;
+
+ public InvalidWcpsRequestException(String message) {
+ super(message, null);
+ }
+
+ public InvalidWcpsRequestException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/exceptions/ResourceException.java b/petascope/src/petascope/wcps/server/exceptions/ResourceException.java new file mode 100644 index 0000000..b7f7774 --- /dev/null +++ b/petascope/src/petascope/wcps/server/exceptions/ResourceException.java @@ -0,0 +1,40 @@ +/*
+ * 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.exceptions;
+
+/**
+ * This exception is thrown whenever some required resource is not available -
+ * a database connection, a file, etc.
+ */
+public class ResourceException extends WCPSException {
+
+ private static final long serialVersionUID = 45562458L;
+
+ public ResourceException(String message) {
+ super(message);
+ }
+
+ public ResourceException(String message, Throwable cause) {
+ super(message, cause);
+
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/exceptions/WCPSException.java b/petascope/src/petascope/wcps/server/exceptions/WCPSException.java new file mode 100644 index 0000000..0a6779c --- /dev/null +++ b/petascope/src/petascope/wcps/server/exceptions/WCPSException.java @@ -0,0 +1,39 @@ +/*
+ * 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.exceptions;
+
+/**
+ * This is the superclass of all WCPS exceptions.
+ */
+public class WCPSException extends Exception {
+
+ private static final long serialVersionUID = 113213254L;
+
+ public WCPSException(String message) {
+ super(message);
+ }
+
+ public WCPSException(String message, Throwable cause) {
+ super(message, cause);
+
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/servlet/WCPSServlet.java b/petascope/src/petascope/wcps/server/servlet/WCPSServlet.java new file mode 100644 index 0000000..4a00969 --- /dev/null +++ b/petascope/src/petascope/wcps/server/servlet/WCPSServlet.java @@ -0,0 +1,257 @@ +/*
+ * 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.servlet;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+
+
+//This is the servlet interface of WCPS. It mostly consists of sanity checks and initialization,
+//the meat is onyl a few lines. The WCPS class does the actual work.
+
+import petascope.wcps.server.core.DbMetadataSource;
+import petascope.wcps.server.core.ProcessCoveragesRequest;
+import petascope.wcps.server.core.WCPS;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Properties;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+
+//Note an important limitation: this will only return the first result if several are available.
+//The reason is that WCPS currently has no standardized way to return multiple byte streams to
+//the user.
+public class WCPSServlet extends HttpServlet {
+
+ private Properties dbParams;
+ private DbMetadataSource metadataSource;
+ private String rasdamanDatabase;
+ private String rasdamanUrl;
+ private WCPS wcps;
+ // path to the default HTML response of the servlet
+ private String servletHtmlPath = "/templates/wcps-servlet.html";
+ // String containing the HTML code for the default response
+ private String defaultHtmlResponse;
+
+ public void init() throws ServletException {
+ try {
+ dbParams = new Properties();
+ System.out.println("WCPS: loading database properties");
+ dbParams.load(
+ new FileInputStream(
+ getServletContext().getRealPath("/settings.properties")));
+ rasdamanUrl = dbParams.getProperty("rasdaman_url");
+ rasdamanDatabase = dbParams.getProperty("rasdaman_database");
+
+ System.out.println("WCPS: initializing metadata database");
+ metadataSource =
+ new DbMetadataSource(dbParams.getProperty("metadata_driver"),
+ dbParams.getProperty("metadata_url"),
+ dbParams.getProperty("metadata_user"),
+ dbParams.getProperty("metadata_pass"), false);
+
+ System.out.println("WCPS: initializing WCPS core");
+ wcps = new WCPS(
+ new File(getServletContext().getRealPath("/xml/ogc/wcps/1.0.0/wcpsProcessCoverages.xsd")),
+ // new CachedMetadataSource(metadataSource)); // removed metadata caching (andrei)
+ metadataSource);
+
+ servletHtmlPath = getServletContext().getRealPath(servletHtmlPath);
+ defaultHtmlResponse = FileUtils.readFileToString(new File(servletHtmlPath));
+
+ System.out.println("WCPS: initialization complete");
+ } catch (Exception e) {
+ System.out.println("WCPS: initialization error");
+ System.out.println("WCPS: closing metadata database");
+
+ if (metadataSource != null) {
+ metadataSource.close();
+ }
+
+ System.out.println("WCPS: done with init error");
+ throw new ServletException("WCPS initialization error", e);
+ }
+
+ }
+
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ System.out.println("WCPS: invoked with GET");
+ printUsage(response);
+ }
+
+ public void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ System.out.println("WCPS: invoked with POST");
+ OutputStream webOut = null;
+
+ try {
+ String xmlRequest = null;
+
+ if (ServletFileUpload.isMultipartContent(request)) {
+ @SuppressWarnings("unchecked")
+ Iterator<FileItem> fileItems =
+ (Iterator<FileItem>) (new ServletFileUpload(
+ new DiskFileItemFactory())).parseRequest(
+ request).iterator();
+
+ if (!fileItems.hasNext()) {
+ throw new IOException(
+ "Multipart POST request contains no parts");
+ }
+
+ FileItem fileItem = fileItems.next();
+
+ if (fileItems.hasNext()) {
+ throw new IOException(
+ "Multipart POST request contains too many parts");
+ }
+
+ if (!fileItem.isFormField()
+ && fileItem.getContentType().equals("text/xml")) {
+ xmlRequest = fileItem.getString();
+ }
+
+ if (xmlRequest == null) {
+ System.out.println(
+ "WCPS: no XML file was uploaded within multipart POST request");
+ printUsage(response);
+ return;
+ }
+
+ System.out.println(
+ "WCPS: received XML via a multipart POST request");
+ } else {
+ String xml = request.getParameter("xml");
+ String query = request.getParameter("query");
+
+ if (xml != null) {
+ System.out.println("WCPS: received XML via a 'xml' parameter in a POST request");
+ xmlRequest = xml;
+ } else if (query != null) {
+ System.out.println("WCPS: received the following query via a 'query' "
+ + "parameter in a POST request:");
+ System.out.println(query);
+
+ xmlRequest = ProcessCoveragesRequest.abstractQueryToXmlQuery(query);
+ System.out.println("WCPS: transformed the abstract syntax query into an XML query!");
+ } else {
+ System.out.println("WCPS: no request was received");
+ printUsage(response);
+ return;
+ }
+ }
+
+ System.out.println("WCPS: received the following request:");
+ System.out.println(xmlRequest);
+
+ System.out.println("WCPS: preparing request");
+ ProcessCoveragesRequest processCoverageRequest =
+ wcps.pcPrepare(rasdamanUrl, rasdamanDatabase, IOUtils.toInputStream(xmlRequest));
+
+ String query = processCoverageRequest.getRasqlQuery();
+ String mime = processCoverageRequest.getMime();
+
+ System.out.println("[" + mime + "] " + query);
+
+ System.out.println("Resulting RasQL query: " + query);
+
+ System.out.println("WCPS: executing request");
+
+ List<byte[]> results = processCoverageRequest.execute();
+
+ System.out.println("WCPS: setting response mimetype to " + mime);
+ response.setContentType(mime);
+ System.out.println("WCPS: returning response");
+ webOut = response.getOutputStream();
+ webOut.write(results.get(0));
+ System.out.println("WCPS: done");
+ } catch (Exception e) {
+ printError(response, "Error: " + e.getMessage(), e);
+ } finally {
+ if (webOut != null) {
+ try {
+ webOut.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ public void destroy() {
+ super.destroy();
+
+ }
+
+ public String getServletInfo() {
+ return "Web Coverage Processing Service (Project PetaScope)";
+
+ }
+
+ private void printError(HttpServletResponse response, String message, Exception e)
+ throws IOException {
+ System.out.println("WCPS: error");
+ System.out.println("WCPS: setting response mimetype to text/html; charset=utf-8");
+ response.setContentType("text/html; charset=utf-8");
+ System.out.println("WCPS: returning the following error message");
+ e.printStackTrace(System.out);
+ System.out.println("WCPS: end of error message");
+ PrintWriter out = new PrintWriter(response.getOutputStream());
+
+ out.println(
+ "<html><head><title>Web Coverage Processing Service</title></head><body>");
+ out.println("<h1>An error has occured</h1>");
+ out.println("<p>" + message + "</p>");
+ out.println("<p>Stack trace:<br/><small>");
+ e.printStackTrace(out);
+ out.println("</small></p></body></html>");
+ out.close();
+ System.out.println("WCPS: done with error");
+ }
+
+ private void printUsage(HttpServletResponse response) throws IOException {
+ System.out.println("WCPS: setting response mimetype to text/html; charset=utf-8");
+ System.out.println("WCPS: returning usage message");
+ response.setContentType("text/html; charset=utf-8");
+ PrintWriter out = new PrintWriter(response.getOutputStream());
+
+ out.println(defaultHtmlResponse);
+
+ out.close();
+ System.out.println("WCPS: done nothing");
+
+ }
+}
diff --git a/petascope/src/petascope/wcps/server/test/FullTestsOnline.java b/petascope/src/petascope/wcps/server/test/FullTestsOnline.java new file mode 100644 index 0000000..2c2bdff --- /dev/null +++ b/petascope/src/petascope/wcps/server/test/FullTestsOnline.java @@ -0,0 +1,380 @@ +/* + * 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.test; + +//~--- non-JDK imports -------------------------------------------------------- +import org.apache.commons.io.FileUtils; + +import petascope.wcps.server.cli.grammar; + +//~--- JDK imports ------------------------------------------------------------ + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStreamReader; + +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; + +import java.util.Arrays; +import java.util.HashMap; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import org.apache.commons.io.IOUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + * Runs all available testFiles against a deployed version of Petascope, + * available at some URL. In particular, here are the steps for each test: + * 1) Convert abstract syntax query to XML query + * 2) Convert XML query to a RasQL query + * 3) Send abstract syntax query to PetaScope WCPS + * 4) Send XML query to PetaScope WCPS + * + * Assumes that a testFiles succeeds if the server does not throw or display + * an error. Saves the intermediate results in a specified path. + * + * @author Andrei Aiordachioaie + */ +public class FullTestsOnline { + + public static String PetascopeURL = "http://localhost:8080/PetaScope/earthlook"; +// public static String PetascopeURL = "http://localhost:8080/petascope/wcps/"; +// public static String PetascopeURL = "http://kahlua.eecs.jacobs-university.de:8080/petascope/earthlook"; + // Tests are read from this folder + static String folder = "test/testcases-wcps/"; + // How many testFiles we have to run + int numTests = 0; + // Files are written in this folder + static String outputFolder = "test/tmp/"; + // How many successes? + int passCount = 0; + // message for testFiles + String[][] errors; + // success code + boolean[] ok; + // partial success codes + boolean[][] partialOk; + // queries + String[] queries; + String[] testNames; + // execution Times for XML queries + long[] xmlTimes; + // execution times for abstract sintax queries + long[] asTimes; + + public FullTestsOnline() { + System.out.println("==========================="); + System.out.println(" PetaScope Test Suite "); + System.out.println("===========================\n\n"); + System.out.println("Testing URL: " + PetascopeURL); + System.out.println("Reading test files from: " + folder); + System.out.println("Writing output files to: " + outputFolder + "\n\n"); + + // Find out how many grammar testFiles we have to run + File dir = new File(folder); + TestFileFilter filter = new TestFileFilter(); + testNames = dir.list(filter); + Arrays.sort(testNames); + numTests = testNames.length; +// numTests = 1; + + ok = new boolean[numTests]; + partialOk = new boolean[5][numTests]; + errors = new String[5][numTests]; + queries = new String[numTests]; + xmlTimes = new long[numTests]; + asTimes = new long[numTests]; + } + + public void printResults() { + HashMap strMap = new HashMap<Boolean, String>(); + + strMap.put(true, "ok"); + strMap.put(false, "failed"); + + System.out.println("\n \nRESULTS + EXECUTION TIMES\n"); + + for (int i = 0; i < numTests; i++) { + String tname = testNames[i]; + tname = tname.substring(0, tname.length() - 5); + + if (ok[i] == true) { + String time = (double) (asTimes[i] / 10) / 100 + " sec"; + System.out.println("*** Test '" + tname + "' ok (" + time + ")"); +// System.out.println("\t" + queries[i]); + } else { + System.out.println("*** Test '" + tname + "' FAILED"); + System.out.println("\t * Abstract Syntax -> Xml: " + strMap.get(partialOk[1][i])); + if (partialOk[1][i] == false) { + System.out.println("\t\t" + errors[1][i]); + } +// System.out.println("\t * Xml -> RasQL: " + strMap.get(partialOk[2][i])); +// if (partialOk[2][i] == false) +// System.out.println("\t\t" + errors[2][i]); + System.out.println("\t * Running Abstract Syntax query: " + strMap.get(partialOk[3][i])); + if (partialOk[3][i] == false) { + System.out.println("\t\t" + errors[3][i]); + } + System.out.println("\t * Running XML query: " + strMap.get(partialOk[4][i])); + if (partialOk[4][i] == false) { + System.out.println("\t\t" + errors[4][i]); + } + } + } + System.out.println("\n\nRESULTS\n"); + System.out.println("Tested PetaScope implementation from: " + PetascopeURL); + System.out.println("Tests succeeded: " + String.valueOf(passCount)); + System.out.println("Tests failed: " + String.valueOf(numTests - passCount)); + + System.out.println("\nWARNING: a test is considered to have passed when the web server does not report" + + " any erorrs. A human has to inspect the semantics of the result. For this, the first three lines" + + " of the output from the web service are printed for each test. For example, if a query involves" + + " encoding a coverage in JPEG format, the first line needs to look like \"����JFIF��C\""); + } + + public void runAllTests() { + String abstractQuery = ""; + String xmlQuery = ""; + String rasqlQuery = ""; + String tname = ""; + long start, end; // for measuring time + + for (int i = 0; i < numTests; i++) { + ok[i] = false; + partialOk[1][i] = false; + partialOk[2][i] = true; + partialOk[3][i] = false; + partialOk[4][i] = false; + errors[1][i] = ""; + errors[2][i] = ""; + errors[3][i] = ""; + errors[4][i] = ""; + + tname = testNames[i]; + tname = tname.substring(0, tname.length() - 5); + File testFile = new File(folder + testNames[i]); + System.out.println("-------------------------------------------------"); + System.out.println("\tTest '" + tname + "'..."); + System.out.println("-------------------------------------------------"); + // First of all: read file contents + try { + abstractQuery = FileUtils.readFileToString(testFile); + queries[i] = abstractQuery; + System.out.println("*** Query :\n" + abstractQuery); + } catch (IOException e) { + errors[1][i] = "Could not read file " + testFile.getName(); + + continue; + } + // Step 1: Convert abstract syntax query to XML query, and save files + try { + xmlQuery = grammar.convertAbstractQueryToXml(abstractQuery); + // Copy abstract syntax query to output folder + File abstractFile = new File(outputFolder + tname + ".test"); + + FileUtils.writeStringToFile(abstractFile, abstractQuery); + // Save XML query to a file in output folder + File xmlFile = new File(outputFolder + tname + ".xml"); + + FileUtils.writeStringToFile(xmlFile, xmlQuery); + + partialOk[1][i] = true; + } catch (Exception e) { + errors[1][i] = e.getMessage(); + } + // Step 2: Convert XML query to RasQL query, and save files +// try +// { +// rasqlQuery = xml.convertXmlToRasql(xmlQuery); +// // Save XML query to a file in output folder +// File rasqlFile = new File(outputFolder + tname + ".rasql"); +// FileUtils.writeStringToFile(rasqlFile, rasqlQuery); +// +// partialOk[2][i] = true; +// } +// catch (Exception e) +// { +// errors[2][i] = e.getMessage(); +// } + // Step 3: Send abstract syntax query to PetaScope WCPS + try { + System.out.println("*** Results from abstract query :"); + start = System.currentTimeMillis(); + String err = runOneTest("query", abstractQuery, "GET"); + end = System.currentTimeMillis(); + asTimes[i] = end - start; + + if (err == null) { + partialOk[3][i] = true; + } else { + errors[3][i] = err; + } + } catch (Exception e) { + e.printStackTrace(); + } + // Step 4: Send XML query to PetaScope WCPS + try { + System.out.println("*** Results from XML query :"); + start = System.currentTimeMillis(); +// String err = runOneTest("request", xmlQuery, "POST"); + String err = runOneTest("", xmlQuery, "POST"); + end = System.currentTimeMillis(); + xmlTimes[i] = end - start; + + if (err == null) { + partialOk[4][i] = true; + } else { + errors[4][i] = err; + } + } catch (Exception e) { + e.printStackTrace(); + } + + // Wrap up + ok[i] = partialOk[1][i] && partialOk[2][i] && partialOk[3][i] && partialOk[4][i]; + if (ok[i] == true) { + passCount++; + } + } + } + + /** + * Send an request to the WCPS server. + * Returns a message on error and null otherwise. + */ + public String runOneTest(String param, String query, String method) + throws MalformedURLException, IOException { +// System.out.println("--------------------"); +// System.out.println(query); +// System.out.println("\t--------------------"); + + // connect to the servlet + URL servlet = new URL(PetascopeURL); + HttpURLConnection conn = (HttpURLConnection) servlet.openConnection(); + + // inform the connection that we will send output and accept input + conn.setDoInput(true); + conn.setDoOutput(true); + + // Don't use a cached version of URL connection. + conn.setUseCaches(false); + conn.setDefaultUseCaches(false); + + // Default method is GET + if (method.equals("POST")) { + conn.setRequestMethod(method); + } + + // For POST: We send binary data + if (method.equals("POST")) { +// conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); +// query = URLEncoder.encode(query, "UTF-8"); + } + + if (param.equals("") == false) { + param += "="; + } + + String data = param + query; + DataOutputStream out = new DataOutputStream(conn.getOutputStream()); + + out.writeBytes(data); + out.flush(); + out.close(); + + BufferedReader cgiOutput = new BufferedReader(new InputStreamReader(conn.getInputStream())); + String line1 = cgiOutput.readLine(); + String line2 = cgiOutput.readLine(); + String line3 = cgiOutput.readLine(); + + System.out.println("\t" + line1); + System.out.println("\t" + line2); + System.out.println("\t" + line3); + + if ((line1 != null) && (line2 != null) && (line3 != null)) { + StringBuffer output = new StringBuffer(line1 + line2 + line3); + while (cgiOutput.ready()) { + output.append(cgiOutput.readLine()); + } + + // Try to parse error message + if (line1.startsWith("<")) { + DocumentBuilder builder = null; + try { + DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); + domFactory.setNamespaceAware(true); // never forget this! + builder = domFactory.newDocumentBuilder(); + Document doc = builder.parse(IOUtils.toInputStream(output.toString())); + Element rootElem = doc.getDocumentElement(); + if (rootElem.getNodeName().endsWith("ExceptionReport")) { + return output.toString(); + } + } catch (Exception e) { + } + } + + } + + return null; + } + + /** Runs the full test suite on a deployed version of PetaScope. + * If command-line arguments are not provided, default values are used. + * + * @param args Can contain up to three parameters, in order: PetaScopeURL testFolder, outputFolder + */ + public static void main(String args[]) { + if (args.length >= 1) { + FullTestsOnline.PetascopeURL = args[0]; + } + if (args.length >= 2) { + FullTestsOnline.folder = args[1]; + } + if (args.length == 3) { + FullTestsOnline.outputFolder = args[2]; + } + + FullTestsOnline tester = new FullTestsOnline(); + + tester.runAllTests(); + tester.printResults(); + } + + /* Accept all files with extension TEST. */ + private class TestFileFilter implements FilenameFilter { + + @Override + public boolean accept(File dir, String name) { + if (name.endsWith("test")) { + return true; + } + + return false; + } + } +} diff --git a/petascope/src/petascope/wcps/server/test/GrammarTest.java b/petascope/src/petascope/wcps/server/test/GrammarTest.java new file mode 100644 index 0000000..f85a259 --- /dev/null +++ b/petascope/src/petascope/wcps/server/test/GrammarTest.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.test; + +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import org.apache.commons.io.FileUtils; +import petascope.wcps.server.cli.grammar; + +/** + * Runs the available tests for the abstract syntax grammar, by calling the CLI. + * Assumes test passes if no error is thrown from the grammar CLI. + * @author Andrei Aiordachioaie + */ +public class GrammarTest { + // Put new test cases in this folder following the current naming scheme + + String folder = "test/testcases-wcps_dollar/"; + // How many tests we have to run + int numTests = 0; + // tests + File[] tests; + // queries + String[] queries; + // success code + boolean[] ok; + // message for tests + String[] errors; + // How many successes? + int passCount = 0; + + public void printResults() { + + for (int i = 0; i < numTests; i++) { + String tname = tests[i].getName(); + tname = tname.substring(0, tname.length() - 5); + if (ok[i] == true) { + System.out.println("*** Test '" + tname + "' ok"); +// System.out.println("\t" + queries[i]); + } else { + System.out.println("*** Test '" + tname + "' FAILED"); + System.out.println("\t" + queries[i]); + System.out.println("\t ERROR: " + errors[i]); + } + } + System.out.println("\n\nRESULTS\n"); + System.out.println("Tests succeeded: " + String.valueOf(passCount)); + System.out.println("Tests failed: " + String.valueOf(numTests - passCount)); + } + + public GrammarTest() { + // Find out how many tests we have to run + File dir = new File(folder); + System.out.println("Looking for tests in " + dir.getAbsolutePath() + "\n"); + GrammarFileFilter filter = new GrammarFileFilter(); + tests = dir.listFiles(filter); + numTests = tests.length; + ok = new boolean[numTests]; + errors = new String[numTests]; + queries = new String[numTests]; + } + + /* Accept all files with extension test. */ + private class GrammarFileFilter implements FilenameFilter { + + @Override + public boolean accept(File dir, String name) { + if (name.endsWith("test")) { + return true; + } + return false; + } + } + + public void runAllTests() { + String query = ""; + for (int i = 0; i < numTests; i++) { + ok[i] = false; + try { + query = FileUtils.readFileToString(tests[i]); + queries[i] = query; + } catch (IOException e) { + errors[i] = "Could not read file " + tests[i].getName(); + continue; + } + try { + grammar.convertAbstractQueryToXml(query); + ok[i] = true; + } catch (Exception e) { + errors[i] = e.getMessage(); + } + if (ok[i] == true) { + passCount++; + } + } + } + + public static void main(String args[]) { + GrammarTest tester = new GrammarTest(); + tester.runAllTests(); + tester.printResults(); + } +} diff --git a/petascope/src/petascope/wcps/server/test/GrammarTestOnline.java b/petascope/src/petascope/wcps/server/test/GrammarTestOnline.java new file mode 100644 index 0000000..6adf21b --- /dev/null +++ b/petascope/src/petascope/wcps/server/test/GrammarTestOnline.java @@ -0,0 +1,204 @@ +/* + * 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.test; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLEncoder; +import org.apache.commons.io.FileUtils; + +/** Runs the available Grammar tests against a deployed version of Petascope, + * available at some URL. + * + * Assumes that a tests succeeds if the server does not throw or display + * an error. + * + * @author Andrei Aiordachioaie + */ +public class GrammarTestOnline { + // Put new test cases in this folder +// public final String PetascopeURL = "http://localhost:8080/PetaScope/WCPService"; +// public final String PetascopeURL = "http://localhost:8080/petascope/wcps/"; + + public final String PetascopeURL = "http://kahlua.eecs.jacobs-university.de:8080/petascope-new/wcps/"; + String folder = "test/testcases-wcps/"; + // How many tests we have to run + int numTests = 0; + // tests + File[] tests; + // queries + String[] queries; + // success code + boolean[] ok; + // message for tests + String[] errors; + // How many successes? + int passCount = 0; + + public void printResults() { + System.out.println("\n \nRESULTS \n"); + + for (int i = 0; i < numTests; i++) { + String tname = tests[i].getName(); + tname = tname.substring(0, tname.length() - 5); + if (ok[i] == true) { + System.out.println("*** Test '" + tname + "' ok"); +// System.out.println("\t" + queries[i]); + } else { + System.out.println("*** Test '" + tname + "' FAILED"); + System.out.println("\t" + queries[i]); + System.out.println("\t ERROR: " + errors[i]); + } + } + System.out.println("\n\nRESULTS\n"); + System.out.println("Tested PetaScope implementation from: " + PetascopeURL); + System.out.println("Tests succeeded: " + String.valueOf(passCount)); + System.out.println("Tests failed: " + String.valueOf(numTests - passCount)); + } + + public GrammarTestOnline() { + // Find out how many tests we have to run + File dir = new File(folder); + System.out.println("Looking for tests in " + dir.getAbsolutePath() + "\n"); + TestFileFilter filter = new TestFileFilter(); + tests = dir.listFiles(filter); + numTests = tests.length; +// numTests = 3; + ok = new boolean[numTests]; + errors = new String[numTests]; + queries = new String[numTests]; + } + + /* Accept all files with extension TEST. */ + private class TestFileFilter implements FilenameFilter { + + @Override + public boolean accept(File dir, String name) { + if (name.endsWith("test")) { + return true; + } + return false; + } + } + + public void runAllTests() { + String query = ""; + String tname = ""; + for (int i = 0; i < numTests; i++) { + ok[i] = false; + tname = tests[i].getName(); + tname = tname.substring(0, tname.length() - 5); + System.out.println("Running test '" + tname + "'..."); + try { + query = FileUtils.readFileToString(tests[i]); + queries[i] = query; + } catch (IOException e) { + errors[i] = "Could not read file " + tests[i].getName(); + continue; + } + try { + String err = runOneTest("query", query); + if (err == null) { + ok[i] = true; + } else { + errors[i] = err; + } + } catch (Exception e) { + e.printStackTrace(); + } + if (ok[i] == true) { + passCount++; + } + } + } + + /** Send an XML request to the WCPS server. Hopefully it will succeed. + * Returns a message on error or null otherwise. + **/ + public String runOneTest(String param, String query) + throws MalformedURLException, IOException { + +// System.out.println("--------------------"); +// System.out.println(query); +// System.out.println("\t--------------------"); + + // connect to the servlet + URL servlet = new URL(PetascopeURL); + HttpURLConnection conn = (HttpURLConnection) servlet.openConnection(); + + // inform the connection that we will send output and accept input + conn.setDoInput(true); + conn.setDoOutput(true); + + // Don't use a cached version of URL connection. + conn.setUseCaches(false); + conn.setDefaultUseCaches(false); + + // Send POST request + conn.setRequestMethod("POST"); + + // Specify the content type that we will send binary data + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + + String data = param + "=" + URLEncoder.encode(query); + DataOutputStream out = new DataOutputStream(conn.getOutputStream()); + out.writeBytes(data); + out.flush(); + out.close(); + + BufferedReader cgiOutput = new BufferedReader( + new InputStreamReader(conn.getInputStream())); + String line1 = cgiOutput.readLine(); + String line2 = cgiOutput.readLine(); + String line3 = cgiOutput.readLine(); + System.out.println("\t" + line1); + System.out.println("\t" + line2); + System.out.println("\t" + line3); + + if (line1 != null && line2 != null && line3 != null + && line2.equals("<h1>An error has occured</h1>")) { + while (cgiOutput.ready()) { + System.out.println("\t" + cgiOutput.readLine()); + } +// System.out.println("Error executing query: "); + String error = line3.substring(10, line3.length() - 4); +// System.out.println("\t" + error); + return error; + } else { + return null; + } + + } + + public static void main(String args[]) { + GrammarTestOnline tester = new GrammarTestOnline(); + tester.runAllTests(); + tester.printResults(); + } +} diff --git a/petascope/src/petascope/wcps/server/test/XmlTestOnline.java b/petascope/src/petascope/wcps/server/test/XmlTestOnline.java new file mode 100644 index 0000000..49aa958 --- /dev/null +++ b/petascope/src/petascope/wcps/server/test/XmlTestOnline.java @@ -0,0 +1,204 @@ +/* + * 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.test; + +import java.io.BufferedReader; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import org.apache.commons.io.FileUtils; + +/** Runs the available XML tests against a deployed version of Petascope, + * available at some URL. + * + * Assumes that a tests succeeds if the server does not throw or display + * an error. + * + * @author Andrei Aiordachioaie + */ +public class XmlTestOnline { + // Put new test cases in this folder + + public final String PetascopeURL = "http://localhost:8080/PetaScope/interface"; +// public final String PetascopeURL = "http://localhost:8080/petascope/wcps/"; +// public final String PetascopeURL = "http://kahlua.eecs.jacobs-university.de:8080/petascope-new/wcps/"; + String folder = "test/testcases-wcps/"; + // How many tests we have to run + int numTests = 0; + // tests + File[] tests; + // queries + String[] queries; + // success code + boolean[] ok; + // message for tests + String[] errors; + // How many successes? + int passCount = 0; + + public void printResults() { + System.out.println("\n \nRESULTS \n"); + + for (int i = 0; i < numTests; i++) { + String tname = tests[i].getName(); + tname = tname.substring(0, tname.length() - 4); + if (ok[i] == true) { + System.out.println("*** Test '" + tname + "' ok"); +// System.out.println("\t" + queries[i]); + } else { + System.out.println("*** Test '" + tname + "' FAILED"); +// System.out.println("\t" + queries[i]); + System.out.println("\t ERROR: " + errors[i]); + } + } + System.out.println("\n\nRESULTS\n"); + System.out.println("Tested PetaScope implementation from: " + PetascopeURL); + System.out.println("Tests succeeded: " + String.valueOf(passCount)); + System.out.println("Tests failed: " + String.valueOf(numTests - passCount)); + } + + public XmlTestOnline() { + // Find out how many tests we have to run + File dir = new File(folder); + System.out.println("Looking for tests in " + dir.getAbsolutePath() + "\n"); + XmlFileFilter filter = new XmlFileFilter(); + tests = dir.listFiles(filter); + numTests = tests.length; +// numTests = 1; + ok = new boolean[numTests]; + errors = new String[numTests]; + queries = new String[numTests]; + } + + /* Accept all files with extension XML. */ + private class XmlFileFilter implements FilenameFilter { + + @Override + public boolean accept(File dir, String name) { + if (name.endsWith("xml")) { + return true; + } + return false; + } + } + + public void runAllTests() { + String query = ""; + String tname = ""; + for (int i = 0; i < numTests; i++) { + ok[i] = false; + tname = tests[i].getName(); + tname = tname.substring(0, tname.length() - 4); + + try { + query = FileUtils.readFileToString(tests[i]); + queries[i] = query; + } catch (IOException e) { + e.printStackTrace(); + errors[i] = "Could not read file " + tests[i].getName(); + continue; + } + System.out.println("Running test '" + tname + "'..."); + try { + String err = runOneTest("request", query); + if (err == null) { + ok[i] = true; + } else { + errors[i] = err; + } + } catch (Exception e) { + e.printStackTrace(); + } + if (ok[i] == true) { + passCount++; + } + } + } + + /** Send an XML request to the WCPS server. Hopefully it will succeed. + * Returns a message on error or null otherwise. + **/ + public String runOneTest(String param, String xml) + throws MalformedURLException, IOException { + +// System.out.println("--------------------"); +// System.out.println(xml); +// System.out.println("\t--------------------"); + + // connect to the servlet + URL servlet = new URL(PetascopeURL); + HttpURLConnection conn = (HttpURLConnection) servlet.openConnection(); + + // inform the connection that we will send output and accept input + conn.setDoInput(true); + conn.setDoOutput(true); + + // Don't use a cached version of URL connection. + conn.setUseCaches(false); + conn.setDefaultUseCaches(false); + + // Send POST request + conn.setRequestMethod("POST"); + + // Specify the content type that we will send binary data + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + + String service = "service=WCPS&"; + String data = service + param + "=" + xml; + DataOutputStream out = new DataOutputStream(conn.getOutputStream()); + out.writeBytes(data); + out.flush(); + out.close(); + + + BufferedReader cgiOutput = new BufferedReader( + new InputStreamReader(conn.getInputStream())); + String line1 = cgiOutput.readLine(); + String line2 = cgiOutput.readLine(); + String line3 = cgiOutput.readLine(); + System.out.println("\t" + line1); + System.out.println("\t" + line2); + System.out.println("\t" + line3); + + if (line1 != null && line2 != null && line3 != null + && line2.equals("<h1>An error has occured</h1>")) { + System.out.println("Error executing query: "); + String error = line3.substring(10, line3.length() - 4); + System.out.println("\t" + error); + return error; + } else { + return null; + } + + } + + public static void main(String args[]) { + XmlTestOnline tester = new XmlTestOnline(); + tester.runAllTests(); + tester.printResults(); + } +} |