[Mulgara-svn] r1878 - in trunk/src/jar: query/java/org/mulgara/query/xpath util/java/org/mulgara/util
pag at mulgara.org
pag at mulgara.org
Thu Dec 17 09:20:43 UTC 2009
Author: pag
Date: 2009-12-17 01:20:42 -0800 (Thu, 17 Dec 2009)
New Revision: 1878
Added:
trunk/src/jar/query/java/org/mulgara/query/xpath/AfnFunctionGroup.java
trunk/src/jar/query/java/org/mulgara/query/xpath/SmfFunctionGroup.java
Modified:
trunk/src/jar/query/java/org/mulgara/query/xpath/FnFunctionGroup.java
trunk/src/jar/query/java/org/mulgara/query/xpath/MulgaraXPathFunctionResolver.java
trunk/src/jar/query/java/org/mulgara/query/xpath/OpFunctionGroup.java
trunk/src/jar/util/java/org/mulgara/util/NumberUtil.java
trunk/src/jar/util/java/org/mulgara/util/URIUtil.java
Log:
Added a new set of functions for SPARQL, particularly the ARQ extensions
Added: trunk/src/jar/query/java/org/mulgara/query/xpath/AfnFunctionGroup.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/xpath/AfnFunctionGroup.java (rev 0)
+++ trunk/src/jar/query/java/org/mulgara/query/xpath/AfnFunctionGroup.java 2009-12-17 09:20:42 UTC (rev 1878)
@@ -0,0 +1,307 @@
+/*
+ * Copyright 2009 DuraSpace.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.mulgara.query.xpath;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URI;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.xpath.XPathFunctionException;
+
+import org.jrdf.graph.BlankNode;
+import org.mulgara.query.functions.MulgaraFunction;
+import org.mulgara.query.functions.MulgaraFunctionGroup;
+import org.mulgara.util.URIUtil;
+
+/**
+ * Container for functions in the afn domain.
+ *
+ * @created Dec 14, 2009
+ * @author Paul Gearon
+ * @copyright © 2009 <a href="http://www.duraspace.org/">DuraSpace</a>
+ */
+public class AfnFunctionGroup implements MulgaraFunctionGroup {
+
+ /** The prefix for the afn: namespace */
+ static final String PREFIX = "afn";
+
+ /** The afn: namespace */
+ static final String NAMESPACE = "http://jena.hpl.hp.com/ARQ/function#";
+ // static final String NAMESPACE = "http://openjena.org/ARQ/function#";
+
+ /**
+ * Get the prefix used for the namespace of these operations.
+ * @return The short string used for a prefix in a QName.
+ */
+ public String getPrefix() {
+ return PREFIX;
+ }
+
+ /**
+ * Get the namespace of these operations.
+ * @return The string of the namespace URI.
+ */
+ public String getNamespace() {
+ return NAMESPACE;
+ }
+
+ /**
+ * Get the set of SPARQL functions.
+ * @return A set of MulgaraFunction for this entire group.
+ */
+ public Set<MulgaraFunction> getAllFunctions() {
+ Set<MulgaraFunction> functions = new HashSet<MulgaraFunction>();
+ functions.add(new Substring2());
+ functions.add(new Substring3());
+ functions.add(new Substr2());
+ functions.add(new Substr3());
+ functions.add(new Strjoin());
+ functions.add(new Sha1sum());
+ functions.add(new Now());
+ functions.add(new Bnode());
+ functions.add(new Localname());
+ functions.add(new Namespace());
+ functions.add(new Min());
+ functions.add(new Max());
+ functions.add(new Pi());
+ functions.add(new E());
+ return functions;
+ }
+
+ /**
+ * As for {@link org.mulgara.query.xpath.FnFunctionGroup.Substring2}, but with Java semantics.
+ * @see http://jena.hpl.hp.com/ARQ/function#substr
+ */
+ static private class Substring2 extends MulgaraFunction {
+ public int getArity() { return 2; }
+ public String getName() { return "substring/2"; }
+ public Object eval(List<?> args) throws XPathFunctionException {
+ String source = args.get(0).toString();
+ int start = ((Number)args.get(1)).intValue();
+ // perform boundary checking
+ int len = source.length();
+ if (start < 0) start = 0;
+ if (start > len) start = len;
+ return source.substring(start);
+ }
+ }
+
+ /**
+ * As for {@link org.mulgara.query.xpath.FnFunctionGroup.Substring3} but with Java semantics.
+ * @see http://jena.hpl.hp.com/ARQ/function#substr
+ */
+ static private class Substring3 extends MulgaraFunction {
+ public int getArity() { return 3; }
+ public String getName() { return "substring/3"; }
+ public Object eval(List<?> args) throws XPathFunctionException {
+ String source = args.get(0).toString();
+ int start = ((Number)args.get(1)).intValue();
+ int end = ((Number)args.get(2)).intValue();
+ // perform boundary checking
+ if (start < 0) start = 0;
+ int len = source.length();
+ if (start > len) {
+ start = len;
+ end = len;
+ }
+ if (end > len) end = len;
+ if (end < start) end = start;
+
+ return source.substring(start, end);
+ }
+ }
+
+ /**
+ * Synonym for afn:substring
+ */
+ static private class Substr2 extends Substring2 {
+ public String getName() { return "substr/2"; }
+ }
+
+ /**
+ * Synonym for afn:substring
+ */
+ static private class Substr3 extends Substring3 {
+ public String getName() { return "substr/3"; }
+ }
+
+ /**
+ * Join all the arguments using a separator found in the first parameter.
+ * afn:strjoin(separator, sequence...)
+ * @see http://jena.hpl.hp.com/ARQ/function#strjoin
+ */
+ static private class Strjoin extends MulgaraFunction {
+ public String getName() { return "strjoin/*"; }
+ public int getArity() { return -1; }
+ public Object eval(List<?> args) throws XPathFunctionException {
+ StringBuilder s = new StringBuilder();
+ int lastIndex = args.size() - 1;
+ String separator = (String)args.get(0);
+ for (int i = 1; i < lastIndex; i++) {
+ if (i != 1) s.append(separator);
+ s.append(args.get(i));
+ }
+ return s.toString();
+ }
+ }
+
+ /**
+ * Calculate the SHA1 checkum of a literal or URI
+ * afn:sha1sum(resource)
+ * @see http://jena.hpl.hp.com/ARQ/function#sha1sum
+ */
+ static private class Sha1sum extends MulgaraFunction {
+ public String getName() { return "sha1sum/1"; }
+ public Object eval(List<?> args) throws XPathFunctionException {
+ String resource = args.get(0).toString();
+ try {
+ byte[] bytes = resource.getBytes("UTF8");
+ MessageDigest digest = MessageDigest.getInstance("SHA1");
+ digest.update(bytes, 0, bytes.length);
+
+ return toHexString(digest.digest());
+ } catch (UnsupportedEncodingException e) {
+ throw new XPathFunctionException("Unable to handle data as UTF-8: " + e.getMessage());
+ } catch (NoSuchAlgorithmException e) {
+ throw new XPathFunctionException("SHA1 algorithm is not available: " + e.getMessage());
+ }
+ }
+ static final String toHexString(byte[] data) {
+ StringBuilder s = new StringBuilder();
+ for (byte b: data) {
+ s.append(Integer.toHexString((b & 0xF0) >> 4));
+ s.append(Integer.toHexString(b & 0x0F));
+ }
+ return s.toString();
+ }
+ }
+
+ /**
+ * Returns the time this function is called. This will increase throughout a query if the
+ * query takes any measurable time.
+ * afn:now()
+ * @see http://jena.hpl.hp.com/ARQ/function#now
+ */
+ static private class Now extends MulgaraFunction {
+ public int getArity() { return 0; }
+ public Object eval(List<?> args) throws XPathFunctionException {
+ return new Date();
+ }
+ }
+
+ /**
+ * Return the blank node label if ?x is a blank node.
+ * afn:bnode(node)
+ * @see http://jena.hpl.hp.com/ARQ/function#bnode
+ */
+ static private class Bnode extends MulgaraFunction {
+ public Object eval(List<?> args) throws XPathFunctionException {
+ Object resource = args.get(0);
+ return (resource instanceof BlankNode) ? ((BlankNode)resource).toString() : "";
+ }
+ }
+
+ /**
+ * The local name of u if an IRI.
+ * Based on splitting the IRI, not on any prefixes in the query or dataset
+ * afn:localname(u)
+ * @see http://jena.hpl.hp.com/ARQ/function#localname
+ */
+ static private class Localname extends MulgaraFunction {
+ public Object eval(List<?> args) throws XPathFunctionException {
+ Object resource = args.get(0);
+ return (resource instanceof URI) ? localName((URI)resource) : "";
+ }
+ static String localName(URI u) {
+ return URIUtil.parseQName(u).getLocalPart();
+ }
+ }
+
+ /**
+ * The namespace of an IRI.
+ * Based on splitting the IRI, not on any prefixes in the query or dataset
+ * afn:namespace(u)
+ * @see http://jena.hpl.hp.com/ARQ/function#namespace
+ */
+ static private class Namespace extends MulgaraFunction {
+ public Object eval(List<?> args) throws XPathFunctionException {
+ Object resource = args.get(0);
+ return (resource instanceof URI) ? namespace((URI)resource) : "";
+ }
+ static String namespace(URI u) {
+ return URIUtil.parseQName(u).getNamespaceURI();
+ }
+ }
+
+ /**
+ * Return the minimum of two expressions evaluating to numbers.
+ * afn:min(x,y)
+ * @see http://jena.hpl.hp.com/ARQ/function#min
+ */
+ static private class Min extends MulgaraFunction {
+ public int getArity() { return 2; }
+ public Object eval(List<?> args) throws XPathFunctionException {
+ Number x = (Number)args.get(0);
+ Number y = (Number)args.get(1);
+ return x.doubleValue() < y.doubleValue() ? x : y;
+ }
+ }
+
+ /**
+ * Return the maximum of two expressions evaluating to numbers.
+ * afn:max(x,y)
+ * @see http://jena.hpl.hp.com/ARQ/function#max
+ */
+ static private class Max extends MulgaraFunction {
+ public int getArity() { return 2; }
+ public Object eval(List<?> args) throws XPathFunctionException {
+ Number x = (Number)args.get(0);
+ Number y = (Number)args.get(1);
+ return x.doubleValue() > y.doubleValue() ? x : y;
+ }
+ }
+
+ /**
+ * The value of pi.
+ * afn:pi()
+ * @see http://jena.hpl.hp.com/ARQ/function#pi
+ */
+ static private class Pi extends MulgaraFunction {
+ public int getArity() { return 0; }
+ public Object eval(List<?> args) throws XPathFunctionException {
+ return Math.PI;
+ }
+ }
+
+ /**
+ * The value of e.
+ * afn:e()
+ * @see http://jena.hpl.hp.com/ARQ/function#e
+ */
+ static private class E extends MulgaraFunction {
+ public int getArity() { return 0; }
+ public Object eval(List<?> args) throws XPathFunctionException {
+ return Math.E;
+ }
+ }
+
+}
Modified: trunk/src/jar/query/java/org/mulgara/query/xpath/FnFunctionGroup.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/xpath/FnFunctionGroup.java 2009-12-17 09:17:46 UTC (rev 1877)
+++ trunk/src/jar/query/java/org/mulgara/query/xpath/FnFunctionGroup.java 2009-12-17 09:20:42 UTC (rev 1878)
@@ -27,6 +27,7 @@
import org.apache.xerces.impl.xpath.regex.RegularExpression;
import org.mulgara.query.functions.MulgaraFunction;
import org.mulgara.query.functions.MulgaraFunctionGroup;
+import org.mulgara.util.NumberUtil;
/**
* Container for functions in the fn domain.
@@ -35,7 +36,6 @@
* @author Paul Gearon
* @copyright © 2009 <a href="http://www.duraspace.org/">DuraSpace</a>
*/
- at SuppressWarnings("unchecked")
public class FnFunctionGroup implements MulgaraFunctionGroup {
/** The prefix for the fn: namespace */
@@ -84,6 +84,14 @@
functions.add(new EncodeForUri());
functions.add(new IriToUri());
functions.add(new EscapeHtmlUri());
+ functions.add(new Contains());
+ functions.add(new StartsWith());
+ functions.add(new EndsWith());
+ functions.add(new StringJoin());
+ functions.add(new Round());
+ functions.add(new Abs());
+ functions.add(new Floor());
+ functions.add(new Ceiling());
return functions;
}
@@ -94,7 +102,7 @@
static private class Matches2 extends MulgaraFunction {
public String getName() { return "matches/2"; }
public int getArity() { return 2; }
- public Object eval(List args) {
+ public Object eval(List<?> args) {
String str = (String)args.get(0);
String pattern = (String)args.get(1);
return new RegularExpression(pattern).matches(str);
@@ -108,7 +116,7 @@
static private class Matches3 extends MulgaraFunction {
public String getName() { return "matches/3"; }
public int getArity() { return 3; }
- public Object eval(List args) {
+ public Object eval(List<?> args) {
String str = (String)args.get(0);
String pattern = (String)args.get(1);
String flags = (String)args.get(2);
@@ -123,7 +131,7 @@
static private class FnBoolean extends MulgaraFunction {
public String getName() { return "boolean"; }
public int getArity() { return 1; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
// no sequence info available here. Look at singleton only for the moment
return toBool(args.get(0));
}
@@ -137,7 +145,7 @@
*/
static private class Not extends MulgaraFunction {
public int getArity() { return 1; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
return !toBool(args.get(0));
}
}
@@ -149,7 +157,7 @@
static private class Concat extends MulgaraFunction {
public int getArity() { return -1; }
public String getName() { return "concat/*"; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
StringBuilder s = new StringBuilder();
for (Object o: args) s.append(o);
return s.toString();
@@ -163,9 +171,9 @@
static private class Substring2 extends MulgaraFunction {
public int getArity() { return 2; }
public String getName() { return "substring/2"; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
String source = args.get(0).toString();
- int start = ((Number)args.get(1)).intValue();
+ int start = ((Number)args.get(1)).intValue() - 1;
// perform boundary checking
int len = source.length();
if (start < 0) start = 0;
@@ -181,7 +189,7 @@
static private class Substring3 extends MulgaraFunction {
public int getArity() { return 3; }
public String getName() { return "substring/3"; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
String source = args.get(0).toString();
int start = ((Number)args.get(1)).intValue() - 1;
int end = ((Number)args.get(2)).intValue() + start;
@@ -205,7 +213,7 @@
*/
static private class StringLength extends MulgaraFunction {
public String getName() { return "string-length/1"; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
return args.get(0).toString().length();
}
}
@@ -216,7 +224,7 @@
*/
static private class NormalizeSpace extends MulgaraFunction {
public String getName() { return "normalize-space/1"; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
String str = args.get(0).toString().trim();
return str.replaceAll(" +", " ");
}
@@ -228,7 +236,7 @@
*/
static private class UpperCase extends MulgaraFunction {
public String getName() { return "upper-case/1"; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
return args.get(0).toString().toUpperCase();
}
}
@@ -239,7 +247,7 @@
*/
static private class LowerCase extends MulgaraFunction {
public String getName() { return "lower-case/1"; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
return args.get(0).toString().toLowerCase();
}
}
@@ -251,7 +259,7 @@
*/
static private class Translate extends MulgaraFunction {
public int getArity() { return 3; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
String str = args.get(0).toString();
String mapStr = args.get(1).toString();
String transStr = args.get(2).toString();
@@ -291,7 +299,7 @@
*/
static private class EncodeForUri extends MulgaraFunction {
public String getName() { return "encode-for-uri/1"; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
try {
return URLEncoder.encode(args.get(0).toString(), UTF8);
} catch (UnsupportedEncodingException e) {
@@ -307,7 +315,7 @@
*/
static private class IriToUri extends MulgaraFunction {
public String getName() { return "iri-to-uri/1"; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
StringBuilder str = new StringBuilder(args.get(0).toString());
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
@@ -334,7 +342,7 @@
*/
static private class EscapeHtmlUri extends MulgaraFunction {
public String getName() { return "escape-html-uri/1"; }
- public Object eval(List args) throws XPathFunctionException {
+ public Object eval(List<?> args) throws XPathFunctionException {
StringBuilder str = new StringBuilder(args.get(0).toString());
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
@@ -366,4 +374,115 @@
return result.toString();
}
+ /**
+ * Test whether a substring occurs in a string
+ * fn:contains(string,substr)
+ * @see http://www.w3.org/TR/xpath-functions/#contains
+ */
+ static private class Contains extends MulgaraFunction {
+ public int getArity() { return 2; }
+ public Object eval(List<?> args) {
+ String str = (String)args.get(0);
+ String substr = (String)args.get(1);
+ return str.contains(substr);
+ }
+ }
+
+ /**
+ * Test whether a string starts with substr
+ * fn:starts-with(string,substr)
+ * @see http://www.w3.org/TR/xpath-functions/#starts-with
+ */
+ static private class StartsWith extends MulgaraFunction {
+ public String getName() { return "starts-with/2"; }
+ public int getArity() { return 2; }
+ public Object eval(List<?> args) {
+ String str = (String)args.get(0);
+ String substr = (String)args.get(1);
+ return str.startsWith(substr);
+ }
+ }
+
+ /**
+ * Test whether a string ends with substr
+ * fn:ends-with(string,substr)
+ * @see http://www.w3.org/TR/xpath-functions/#ends-with
+ */
+ static private class EndsWith extends MulgaraFunction {
+ public String getName() { return "ends-with/2"; }
+ public int getArity() { return 2; }
+ public Object eval(List<?> args) {
+ String str = (String)args.get(0);
+ String substr = (String)args.get(1);
+ return str.endsWith(substr);
+ }
+ }
+
+ /**
+ * Join all the arguments except the last, using the last argument as a separator.
+ * fn:string-join(sequence..., separator)
+ * @see http://www.w3.org/TR/xpath-functions/#string-join
+ */
+ static private class StringJoin extends MulgaraFunction {
+ public String getName() { return "string-join/*"; }
+ public int getArity() { return -1; }
+ public Object eval(List<?> args) throws XPathFunctionException {
+ StringBuilder s = new StringBuilder();
+ int lastIndex = args.size() - 1;
+ String separator = (String)args.get(lastIndex);
+ for (int i = 0; i < lastIndex; i++) {
+ if (i != 0) s.append(separator);
+ s.append(args.get(i));
+ }
+ return s.toString();
+ }
+ }
+
+ /**
+ * Return the nearest integer value to the argument.
+ * fn:round(x)
+ * @see http://www.w3.org/TR/xpath-functions/#round
+ */
+ static private class Round extends MulgaraFunction {
+ public Object eval(List<?> args) throws XPathFunctionException {
+ Number x = (Number)args.get(0);
+ return Math.round(x.doubleValue());
+ }
+ }
+
+ /**
+ * Return the absolute value.
+ * fn:abs(x)
+ * @see http://www.w3.org/TR/xpath-functions/#abs
+ */
+ static private class Abs extends MulgaraFunction {
+ public Object eval(List<?> args) throws XPathFunctionException {
+ Number x = (Number)args.get(0);
+ return x.doubleValue() < 0 ? NumberUtil.minus(x) : x;
+ }
+ }
+
+ /**
+ * Return the greatest integer value less than the argument (as a double).
+ * fn:floor(x)
+ * @see http://www.w3.org/TR/xpath-functions/#floor
+ */
+ static private class Floor extends MulgaraFunction {
+ public Object eval(List<?> args) throws XPathFunctionException {
+ Number x = (Number)args.get(0);
+ return Math.floor(x.doubleValue());
+ }
+ }
+
+ /**
+ * Return the smallest integer value greater than the argument (as a double).
+ * fn:ceiling(x)
+ * @see http://www.w3.org/TR/xpath-functions/#ceiling
+ */
+ static private class Ceiling extends MulgaraFunction {
+ public Object eval(List<?> args) throws XPathFunctionException {
+ Number x = (Number)args.get(0);
+ return Math.ceil(x.doubleValue());
+ }
+ }
}
Modified: trunk/src/jar/query/java/org/mulgara/query/xpath/MulgaraXPathFunctionResolver.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/xpath/MulgaraXPathFunctionResolver.java 2009-12-17 09:17:46 UTC (rev 1877)
+++ trunk/src/jar/query/java/org/mulgara/query/xpath/MulgaraXPathFunctionResolver.java 2009-12-17 09:20:42 UTC (rev 1878)
@@ -34,6 +34,7 @@
addFunctionGroup(new SparqlFunctionGroup());
addFunctionGroup(new FnFunctionGroup());
addFunctionGroup(new OpFunctionGroup());
+ addFunctionGroup(new AfnFunctionGroup());
}
}
Modified: trunk/src/jar/query/java/org/mulgara/query/xpath/OpFunctionGroup.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/xpath/OpFunctionGroup.java 2009-12-17 09:17:46 UTC (rev 1877)
+++ trunk/src/jar/query/java/org/mulgara/query/xpath/OpFunctionGroup.java 2009-12-17 09:20:42 UTC (rev 1878)
@@ -32,10 +32,9 @@
* @author Paul Gearon
* @copyright © 2009 <a href="http://www.duraspace.org/">DuraSpace</a>
*/
- at SuppressWarnings("unchecked")
public class OpFunctionGroup implements MulgaraFunctionGroup {
- /** The prefix for the fn: namespace */
+ /** The prefix for the op: namespace */
static final String PREFIX = "op";
/** The op: namespace */
@@ -78,7 +77,7 @@
static private class NumericEqual extends MulgaraFunction {
public String getName() { return "numeric-equal/2"; }
public int getArity() { return 2; }
- public Object eval(List args) {
+ public Object eval(List<?> args) {
Number left = (Number)args.get(0);
Number right = (Number)args.get(1);
return left.doubleValue() == right.doubleValue();
@@ -92,7 +91,7 @@
static private class NumericLessThan extends MulgaraFunction {
public String getName() { return "numeric-less-than/2"; }
public int getArity() { return 2; }
- public Object eval(List args) {
+ public Object eval(List<?> args) {
Number left = (Number)args.get(0);
Number right = (Number)args.get(1);
return left.doubleValue() < right.doubleValue();
@@ -106,7 +105,7 @@
static private class NumericGreaterThan extends MulgaraFunction {
public String getName() { return "numeric-greater-than/2"; }
public int getArity() { return 2; }
- public Object eval(List args) {
+ public Object eval(List<?> args) {
Number left = (Number)args.get(0);
Number right = (Number)args.get(1);
return left.doubleValue() > right.doubleValue();
@@ -121,7 +120,7 @@
static private class NumericIntegerDivision extends MulgaraFunction {
public String getName() { return "numeric-integer-divide/2"; }
public int getArity() { return 2; }
- public Object eval(List args) {
+ public Object eval(List<?> args) {
Number left = (Number)args.get(0);
Number right = (Number)args.get(1);
if (left instanceof BigDecimal) {
@@ -146,7 +145,7 @@
static private class NumericMod extends MulgaraFunction {
public String getName() { return "numeric-mod/2"; }
public int getArity() { return 2; }
- public Object eval(List args) {
+ public Object eval(List<?> args) {
Number left = (Number)args.get(0);
Number right = (Number)args.get(1);
if (left instanceof Byte || left instanceof Short || left instanceof Integer || left instanceof Long) {
Added: trunk/src/jar/query/java/org/mulgara/query/xpath/SmfFunctionGroup.java
===================================================================
--- trunk/src/jar/query/java/org/mulgara/query/xpath/SmfFunctionGroup.java (rev 0)
+++ trunk/src/jar/query/java/org/mulgara/query/xpath/SmfFunctionGroup.java 2009-12-17 09:20:42 UTC (rev 1878)
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2009 DuraSpace.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.mulgara.query.xpath;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.xpath.XPathFunctionException;
+
+import org.mulgara.query.functions.MulgaraFunction;
+import org.mulgara.query.functions.MulgaraFunctionGroup;
+
+/**
+ * Container for functions in the smf domain.
+ *
+ * @created Dec 15, 2009
+ * @author Paul Gearon
+ * @copyright © 2009 <a href="http://www.duraspace.org/">DuraSpace</a>
+ */
+public class SmfFunctionGroup implements MulgaraFunctionGroup {
+
+ /** The prefix for the afn: namespace */
+ static final String PREFIX = "smf";
+
+ /** The afn: namespace */
+ static final String NAMESPACE = "http://www.topquadrant.com/sparqlmotion/smf.html#smf:";
+
+ /**
+ * Get the prefix used for the namespace of these operations.
+ * @return The short string used for a prefix in a QName.
+ */
+ public String getPrefix() {
+ return PREFIX;
+ }
+
+ /**
+ * Get the namespace of these operations.
+ * @return The string of the namespace URI.
+ */
+ public String getNamespace() {
+ return NAMESPACE;
+ }
+
+ /**
+ * Get the set of SPARQL functions.
+ * @return A set of MulgaraFunction for this entire group.
+ */
+ public Set<MulgaraFunction> getAllFunctions() {
+ Set<MulgaraFunction> functions = new HashSet<MulgaraFunction>();
+ functions.add(new IndexOf());
+ functions.add(new LastIndexOf());
+ functions.add(new TitleCase());
+ functions.add(new Trim());
+ return functions;
+ }
+
+ // can't do cast, as we don't control RDF types here
+
+ /**
+ * Gets the index of the first occurrence of a certain substring in a given search string.
+ * Returns null if the substring is not found.
+ * smf:indexOf(text, substr)
+ * @see http://www.topquadrant.com/sparqlmotion/smf.html#smf:indexOf
+ */
+ static private class IndexOf extends MulgaraFunction {
+ public int getArity() { return 2; }
+ public String getName() { return "indexOf/2"; }
+ public Object eval(List<?> args) throws XPathFunctionException {
+ String text = args.get(0).toString();
+ String substr = args.get(1).toString();
+ int i = text.indexOf(substr);
+ return i >= 0 ? i : null;
+ }
+ }
+
+ /**
+ * Gets the last index of the first occurrence of a certain substring in a given search string.
+ * Returns null if the substring is not found
+ * smf:lastIndexOf(text, substr)
+ * @see http://www.topquadrant.com/sparqlmotion/smf.html#smf:lastIndexOf
+ */
+ static private class LastIndexOf extends MulgaraFunction {
+ public int getArity() { return 2; }
+ public Object eval(List<?> args) throws XPathFunctionException {
+ String text = args.get(0).toString();
+ String substr = args.get(1).toString();
+ int i = text.lastIndexOf(substr);
+ return i >= 0 ? i : null;
+ }
+ }
+
+ // can't do setLanguage at this level
+
+ /**
+ * Converts an input string to title case. For example, germany becomes Germany.
+ * smf:titleCase(text)
+ * @see http://www.topquadrant.com/sparqlmotion/smf.html#smf:titleCase
+ */
+ static private class TitleCase extends MulgaraFunction {
+ public Object eval(List<?> args) throws XPathFunctionException {
+ StringBuilder text = new StringBuilder(args.get(0).toString());
+ int textLen = text.length();
+ if (textLen == 0) return "";
+ char c = text.charAt(0);
+ if (Character.isLowerCase(c)) text.setCharAt(0, Character.toUpperCase(c));
+ for (int i = 0; i < textLen; i++) {
+ if (text.charAt(i) == ' ' && i < textLen - 1) {
+ c = text.charAt(i + 1);
+ if (Character.isLowerCase(c)) text.setCharAt(i + 1, Character.toUpperCase(c));
+ }
+ }
+ return text.toString();
+ }
+ }
+
+ /**
+ * Creates a new string value by trimming an input string.
+ * Leading and trailing whitespaces are deleted
+ * smf:trim
+ * @see http://www.topquadrant.com/sparqlmotion/smf.html#smf:trim
+ */
+ static private class Trim extends MulgaraFunction {
+ public Object eval(List<?> args) throws XPathFunctionException {
+ return args.get(0).toString().trim();
+ }
+ }
+
+
+}
Modified: trunk/src/jar/util/java/org/mulgara/util/NumberUtil.java
===================================================================
--- trunk/src/jar/util/java/org/mulgara/util/NumberUtil.java 2009-12-17 09:17:46 UTC (rev 1877)
+++ trunk/src/jar/util/java/org/mulgara/util/NumberUtil.java 2009-12-17 09:20:42 UTC (rev 1878)
@@ -103,6 +103,21 @@
return (st == null) ? null : st.valueOf(str);
}
+ /**
+ * Returns The negation of a number, regardless of its type.
+ * @param n The number to negate.
+ * @return Negative the number, or null if the number was null.
+ */
+ static public Number minus(Number n) {
+ if (n instanceof Long) return new Long(-n.longValue());
+ if (n instanceof Integer) return new Integer(-n.intValue());
+ if (n instanceof Short) return new Short((short)-n.shortValue());
+ if (n instanceof Byte) return new Byte((byte)-n.byteValue());
+ if (n instanceof Double) return new Double(-n.doubleValue());
+ if (n instanceof Float) return new Float(-n.floatValue());
+ return null;
+ }
+
///////////////////////////////////////////////////////////////////////////////
// Internal structures for handling conversion of numeric types to XSD and back
///////////////////////////////////////////////////////////////////////////////
Modified: trunk/src/jar/util/java/org/mulgara/util/URIUtil.java
===================================================================
--- trunk/src/jar/util/java/org/mulgara/util/URIUtil.java 2009-12-17 09:17:46 UTC (rev 1877)
+++ trunk/src/jar/util/java/org/mulgara/util/URIUtil.java 2009-12-17 09:20:42 UTC (rev 1878)
@@ -20,6 +20,8 @@
import java.net.URISyntaxException;
import java.util.Map;
+import javax.xml.namespace.QName;
+
/**
* Utilities for working with URIs in Mulgara.
*
@@ -66,4 +68,60 @@
throw new RuntimeException("Bad URI syntax in resource", e);
}
}
+
+ /**
+ * Converts a URI into a QName, based entirely on parsing.
+ * @param u The URI to parse.
+ * @return A QName containing the URI as a namespace/localpart combination, or the entire
+ * uri as a localpart if it could not be parsed.
+ */
+ public static QName parseQName(URI u) {
+ String s = u.toString();
+ for (int i = s.length() - 1; i > 0; i--) {
+ if (!localNameChar(s.charAt(i))) {
+ // found the place where a name has to start after
+ for (int p = i + 1; p < s.length(); p++) {
+ if (localStartNameChar(s.charAt(p))) return new QName(s.substring(0, p), s.substring(p));
+ }
+ return new QName(s);
+ }
+ }
+ return new QName(s);
+ }
+
+ /**
+ * Indicates if the char is a valid XML name character, minus the colon character.
+ * @see http://www.w3.org/TR/REC-xml/#NT-NameStartChar
+ * @param c The character to test.
+ * @return <code>true</code> if the character is a valid start to an XML name.
+ */
+ private static final boolean localNameChar(char c) {
+ return localStartNameChar(c) ||
+ c == '-' || c == '.' || (c >= '0' && c <= '9') ||
+ c == 0xB7 || (c >= 0x0300 && c <= 0x036F) || (c >= 0x203F && c <= 0x2040);
+ }
+
+ /**
+ * Indicates if the char is a valid start for an XML name character, minus the colon character.
+ * @see http://www.w3.org/TR/REC-xml/#NT-NameStartChar
+ * @param c The character to test.
+ * @return <code>true</code> if the character is a valid start to an XML name.
+ */
+ private static final boolean localStartNameChar(char c) {
+ return (c >= 'A' && c <= 'Z') ||
+ (c >= 'a' && c <= 'z') ||
+ c == '_' ||
+ (c >= 0xC0 && c <= 0xD6) ||
+ (c >= 0xD8 && c <= 0xF6) ||
+ (c >= 0xF8 && c <= 0x2FF) ||
+ (c >= 0x370 && c <= 0x37D) ||
+ (c >= 0x37F && c <= 0x1FFF) ||
+ (c >= 0x200C && c <= 0x200D) ||
+ (c >= 0x2070 && c <= 0x218F) ||
+ (c >= 0x2C00 && c <= 0x2FEF) ||
+ (c >= 0x3001 && c <= 0xD7FF) ||
+ (c >= 0xF900 && c <= 0xFDCF) ||
+ (c >= 0xFDF0 && c <= 0xFFFD) ||
+ (c >= 0x10000 && c <= 0xEFFFF);
+ }
}
More information about the Mulgara-svn
mailing list