Skip to content

Commit

Permalink
apacheGH-1272: Use static in-scope base for IRI()
Browse files Browse the repository at this point in the history
  • Loading branch information
afs committed May 31, 2022
1 parent 1d3b90d commit eafc23a
Show file tree
Hide file tree
Showing 17 changed files with 382 additions and 93 deletions.
1 change: 0 additions & 1 deletion jena-arq/Grammar/main.jj
Original file line number Diff line number Diff line change
Expand Up @@ -1949,7 +1949,6 @@ Expr BuiltInCall() : { Expr expr ;
// ARQ extension
// IRI(expr rel:String or IRI)
// IRI(expr base:IRI, expr rel:String or IRI)
//
| <IRI> <LPAREN> expr1 = Expression() (<COMMA> expr2 = Expression())? <RPAREN>
{ return makeFunction_IRI(expr1, expr2) ; }

Expand Down
83 changes: 45 additions & 38 deletions jena-arq/src/main/java/org/apache/jena/sparql/expr/E_IRI.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,69 +24,53 @@
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.expr.nodevalue.NodeFunctions;
import org.apache.jena.sparql.function.FunctionEnv;
import org.apache.jena.sparql.serializer.SerializationContext;
import org.apache.jena.sparql.sse.Tags;

/**
* IRI(expr). The function URI(expr) is the same, but under a different name as a
* IRI(expr), oen argument, SPARQL standard form.
* The function URI(expr) is the same, but under a different name as a
* subclass.
* <p>
* As an ARQ extension , there is also {@code IRI(base, relative)} form which is E_IRI2.
* The relative URI (string or IRI) is resolved against the result of the "base" expression.
* which in turn is resolved as per the one-argument form.
*/
public class E_IRI extends ExprFunction1 {
private static final String symbol = Tags.tagIri;

private static final String sparqlPrintName = "IRI";
private static final String sseFunctionName = Tags.tagIri;

// The base in force when the function was created.
// Kept separate from baseExpr so we can see whether it was the one argument or two argument form.
protected final String parserBase;

// ARQ extension: "IRI(base, relative)"
protected final Expr baseExpr;
protected final Expr relExpr;

public E_IRI(Expr relExpr) {
this(null, null, relExpr);
this(null, relExpr);
}

public E_IRI(String parserBaseURI, Expr relExpr) {
this(null, parserBaseURI, relExpr);
}

public E_IRI(Expr baseExpr, Expr relExpr) {
this(baseExpr, null, relExpr);
this(parserBaseURI, relExpr, sparqlPrintName, sseFunctionName);
}

public E_IRI(Expr baseExpr, String parserBaseURI, Expr relExpr) {
this(baseExpr, parserBaseURI, relExpr, symbol);
}

protected E_IRI(Expr baseExpr, String baseStr, Expr relExpr, String altSymbol) {
super(relExpr, symbol);
protected E_IRI(String baseStr, Expr relExpr, String sparqlName, String sseName) {
//super(relExpr, sparqlName, sseName);
super(relExpr, sseName);
this.parserBase = baseStr;
this.baseExpr = baseExpr;
this.relExpr = relExpr;
}

// Evaluation of a "one argument or two" function.
// Evaluation of a "one argument with access to the env.
@Override
protected NodeValue evalSpecial(Binding binding, FunctionEnv env) {
// IRI(<base>, relative) or IRI(relative);
// IRI(relative)
// relative can be a string or an IRI.
// <base> can be relative (becomes IRI(IRI(<base>), rel)).

String baseIRI = null;
if ( baseExpr != null ) {
NodeValue baseValue = baseExpr.eval(binding, env);
// Check: IRI.
NodeValue baseValueResolved = evalOneArg(baseValue, parserBase, env);
// Check for errors.
baseIRI = baseValueResolved.getNode().getURI();
} else {
baseIRI = parserBase;
}

String baseIRI = parserBase;
NodeValue nvRel = relExpr.eval(binding, env);
return evalOneArg(nvRel, baseIRI, env);
return resolve(nvRel, baseIRI, env);
}

private NodeValue evalOneArg(NodeValue relative, String baseIRI, FunctionEnv env) {
/*package*/ static NodeValue resolve(NodeValue relative, String baseIRI, FunctionEnv env) {
if ( baseIRI == null ) {
// Legacy
if ( env.getContext() != null ) {
Expand All @@ -106,16 +90,39 @@ private NodeValue evalOneArg(NodeValue relative, String baseIRI, FunctionEnv env
@Override
public NodeValue eval(NodeValue v, FunctionEnv env) {
// Shouldn't be called. Legacy only. Does not support baseExpr!=null
return evalOneArg(v, parserBase, env);
return resolve(v, parserBase, env);
}

@Override
public Expr copy(Expr expr) {
return new E_IRI(baseExpr, parserBase, expr);
return new E_IRI(parserBase, expr);
}

@Override
public NodeValue eval(NodeValue v) {
throw new ARQInternalErrorException("Should not be called");
}

@Override
public String getFunctionPrintName(SerializationContext cxt)
{ return sparqlPrintName ; }

/**
* Get the parser base - the base URI a a string at the point in parsing when
* this object was created. If there is an explicit base expression (2 argument
* form), the parse base is used to make the base expression absolute.
* <p>
* This may be null - the object may not have been created by the parser.
*/
public String getParserBase() {
return parserBase;
}

/**
* Expression for the relative URI. This is the argument to the one-argument form
* or the second argument for the two-argument form.
*/
public Expr getRelExpr() {
return relExpr;
}
}
130 changes: 130 additions & 0 deletions jena-arq/src/main/java/org/apache/jena/sparql/expr/E_IRI2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.jena.sparql.expr;

import static org.apache.jena.sparql.expr.E_IRI.resolve;

import org.apache.jena.sparql.ARQInternalErrorException;
import org.apache.jena.sparql.engine.binding.Binding;
import org.apache.jena.sparql.function.FunctionEnv;
import org.apache.jena.sparql.serializer.SerializationContext;
import org.apache.jena.sparql.sse.Tags;

/**
* IRI(base, expr). Two arguemnt SPARQl extension. The function URI(expr) is the same, but under a different name as a
* subclass.
* <p>
* As an ARQ extension, {@code IRI(base, relative)} resolves the relative
* URI (string or IRI) against the result of the "base" expression,
* which in turn is resolved as per the one-argument form.
*/
public class E_IRI2 extends ExprFunction2 {

private static final String sparqlPrintName = "IRI";
private static final String sseFunctionName = Tags.tagIri2;

// The base in force when the function was created.
// Kept separate from baseExpr so we can see whether it was the one argument or two argument form.
protected final String parserBase;

// ARQ extension: "IRI(base, relative)"
protected final Expr baseExpr;
protected final Expr relExpr;

public E_IRI2(Expr baseExpr, String parserBaseURI, Expr relExpr) {
this(baseExpr, parserBaseURI, relExpr, sparqlPrintName, sseFunctionName);
}

protected E_IRI2(Expr baseExpr, String baseStr, Expr relExpr, String sparqlName, String sseName) {
//super(baseExpr, relExpr, sparqlName, sseName);
super(baseExpr, relExpr, sseName);
this.parserBase = baseStr;
this.baseExpr = baseExpr;
this.relExpr = relExpr;
}

// Evaluation of a "one argument or two" function.
@Override
protected NodeValue evalSpecial(Binding binding, FunctionEnv env) {
// IRI(<base>, relative) or IRI(relative);
// relative can be a string or an IRI.
// <base> can be relative (becomes IRI(IRI(<base>), rel)).

String baseIRI = null;
if ( baseExpr != null ) {
NodeValue baseValue = baseExpr.eval(binding, env);
// Check: IRI.
NodeValue baseValueResolved = resolve(baseValue, parserBase, env);
// Check for errors.
baseIRI = baseValueResolved.getNode().getURI();
} else {
baseIRI = parserBase;
}

NodeValue nvRel = relExpr.eval(binding, env);
return resolve(nvRel, baseIRI, env);
}

@Override
public NodeValue eval(NodeValue v1, NodeValue v2, FunctionEnv env) {
// Shouldn't be called. Legacy only. Does not support baseExpr!=null
return resolve(v1, parserBase, env);
}

@Override
public Expr copy(Expr expr1, Expr expr2) {
return new E_IRI2(expr1, parserBase, expr2);
}

@Override
public NodeValue eval(NodeValue v1, NodeValue v2) {
throw new ARQInternalErrorException("Should not be called");
}

@Override
public String getFunctionPrintName(SerializationContext cxt)
{ return sparqlPrintName ; }

/**
* Get the parser base - the base URI a a string at the point in parsing when
* this object was created. If there is an explicit base expression (2 argument
* form), the parse base is used to make the base expression absolute.
* <p>
* This may be null - the object may not have been created by the parser.
*/
public String getParserBase() {
return parserBase;
}

/**
* Expression for the relative URI. This is the argument to the one-argument form
* or the second argument for the two-argument form.
*/
public Expr getRelExpr() {
return relExpr;
}

/*
* Base expression - 2 argument for of "IRI(base, relative)".
* This is an ARQ extension.
*/
public Expr getBaseExpr() {
return baseExpr;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class E_LogicalNot extends ExprFunction1
{
// See logicalOR for truth table.

// Errors propage as normal.
// Errors propagate as normal.
private static final String functionName = Tags.tagNot ;
private static final String symbol = Tags.symNot ;

Expand All @@ -39,7 +39,7 @@ public NodeValue eval(NodeValue v)
{
return XSDFuncOp.not(v) ;
}

@Override
public Expr copy(Expr expr) { return new E_LogicalNot(expr) ; }
public Expr copy(Expr expr) { return new E_LogicalNot(expr) ; }
}
27 changes: 14 additions & 13 deletions jena-arq/src/main/java/org/apache/jena/sparql/expr/E_URI.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,31 @@

package org.apache.jena.sparql.expr;

import org.apache.jena.sparql.serializer.SerializationContext;
import org.apache.jena.sparql.sse.Tags;

/**
* This class is an alternative name for {@linkplain E_IRI}.
* See the javadoc for {@linkplain E_IRI}.
*/
public class E_URI extends E_IRI {
private static final String symbol = Tags.tagUri;
private static final String sparqlPrintName = "URI";
private static final String sseFunctionName = Tags.tagUri;

public E_URI(Expr relExpr) {
this(null, null, relExpr);
}

public E_URI(String baseURI, Expr relExpr) {
this(null, baseURI, relExpr);
this(null, relExpr);
}

public E_URI(Expr baseExpr, Expr relExpr) {
this(baseExpr, null, relExpr);
}

public E_URI(Expr baseExpr, String baseStr, Expr relExpr) {
super(baseExpr, baseStr, relExpr, symbol);
public E_URI(String baseStr, Expr relExpr) {
super(baseStr, relExpr, sparqlPrintName, sseFunctionName);
}

@Override
public String getFunctionPrintName(SerializationContext cxt)
{ return sparqlPrintName ; }

@Override
public Expr copy(Expr expr) {
return new E_URI(baseExpr, parserBase, expr);
return new E_URI(parserBase, expr);
}
}
48 changes: 48 additions & 0 deletions jena-arq/src/main/java/org/apache/jena/sparql/expr/E_URI2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.jena.sparql.expr;

import org.apache.jena.sparql.serializer.SerializationContext;
import org.apache.jena.sparql.sse.Tags;

/**
* This class is an alternative name for {@linkplain E_IRI}.
* See the javadoc for {@linkplain E_IRI}.
*/
public class E_URI2 extends E_IRI2 {
private static final String sparqlPrintName = "URI";
private static final String sseFunctionName = Tags.tagUri2;

public E_URI2(String baseURI, Expr relExpr) {
this(null, baseURI, relExpr);
}

public E_URI2(Expr baseExpr, String baseStr, Expr relExpr) {
super(baseExpr, baseStr, relExpr, sparqlPrintName, sseFunctionName);
}

@Override
public String getFunctionPrintName(SerializationContext cxt)
{ return sparqlPrintName ; }

@Override
public Expr copy(Expr expr1, Expr expr2) {
return new E_URI2(expr1, parserBase, expr2);
}
}
Loading

0 comments on commit eafc23a

Please sign in to comment.