org.apache.jena.sparql.expr.E_Regex Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jena-arq Show documentation
Show all versions of jena-arq Show documentation
ARQ is a SPARQL 1.1 query engine for Apache Jena
/*
* 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 java.util.List ;
import org.apache.commons.lang3.StringUtils ;
import org.apache.jena.atlas.logging.Log ;
import org.apache.jena.graph.Node ;
import org.apache.jena.query.ARQ ;
import org.apache.jena.sparql.expr.nodevalue.NodeFunctions ;
import org.apache.jena.sparql.sse.Tags ;
import org.apache.jena.sparql.util.FmtUtils ;
import org.apache.jena.sparql.util.Symbol ;
/** Indirect to the chosen regular expression implementation */
public class E_Regex extends ExprFunctionN
{
private static Symbol regexImpl = null ;
static
{
Object v = ARQ.getContext().get(ARQ.regexImpl, ARQ.javaRegex) ;
if ( v instanceof Symbol )
regexImpl = (Symbol)v ;
if ( v instanceof String )
regexImpl = Symbol.create((String)v) ;
if ( regexImpl == null )
{
Log.warn(E_Regex.class, "Regex implementation some weird setting: default to Java") ;
regexImpl = ARQ.javaRegex;
}
if ( !regexImpl.equals(ARQ.javaRegex) &&
!regexImpl.equals(ARQ.xercesRegex) )
{
Log.warn(E_Regex.class, "Regex implementation not recognized : default to Java") ;
regexImpl = ARQ.javaRegex;
}
}
private static final String name = Tags.tagRegex ;
private RegexEngine regexEngine = null ;
public E_Regex(Expr expr, Expr pattern, Expr flags)
{
super(name, expr, pattern, flags) ;
init(pattern, flags) ;
}
// Not used by parser
public E_Regex(Expr expr, String pattern, String flags)
{
super(name, expr, NodeValue.makeString(pattern), NodeValue.makeString(flags)) ;
init(getArg(2), getArg(3)) ;
}
private void init(Expr pattern, Expr flags)
{
if ( ! ARQ.isStrictMode() ) {
try {
if ( pattern.isConstant() && pattern.getConstant().isString() && ( flags==null || flags.isConstant() ) )
regexEngine = makeRegexEngine(pattern.getConstant(), (flags==null)?null:flags.getConstant()) ;
} catch (ExprEvalException ex) {
// Here, we are doing static compilation of the pattern.
// ExprEvalException does not have a stacktrace.
// We could throw a non-eval exception.
throw ex; //new ExprException(ex.getMessage(), ex.getCause());
}
}
}
private String currentFailMessage = null;
@Override
public NodeValue eval(List args)
{
Node arg = NodeFunctions.checkAndGetStringLiteral("REGEX", args.get(0)) ;
NodeValue vPattern = args.get(1) ;
NodeValue vFlags = ( args.size() == 2 ? null : args.get(2) ) ;
RegexEngine regex = regexEngine ;
if ( regex == null ) {
// Execution time regex compile (not a constant pattern).
try {
regex = makeRegexEngine(vPattern, vFlags) ;
} catch (ExprEvalException ex) {
// Avoid multiple logging of the same message (at least if adjacent)
String m = ex.getMessage();
if ( m != null && ! m.equals(currentFailMessage) )
Log.warn(this, m);
currentFailMessage = m;
// This becomes an eval error, the FILTER is false and the current row rejected.
throw ex;
}
}
boolean b = regex.match(arg.getLiteralLexicalForm()) ;
return b ? NodeValue.TRUE : NodeValue.FALSE ;
}
public static RegexEngine makeRegexEngine(NodeValue vPattern, NodeValue vFlags)
{
if ( ! vPattern.isString() )
throw new ExprException("REGEX: Pattern is not a string: "+vPattern) ;
if ( vFlags != null && ! vFlags.isString() )
throw new ExprException("REGEX: Pattern flags are not a string: "+vFlags) ;
String s = (vFlags==null)?null:vFlags.getString() ;
checkFlags(s);
return makeRegexEngine(vPattern.getString(), s) ;
}
private static void checkFlags(String flags) {
if ( flags == null )
return;
// F&O spec defines regex: Can only contain s, m, i, x, q
// Not all are supported by all regex engines.
if ( ! StringUtils.containsOnly(flags, "smixq") )
throw new ExprEvalException("REGEX: Only 'smixq' are legal as pattern flags: got \""+FmtUtils.stringEsc(flags)+"\"");
}
public static RegexEngine makeRegexEngine(String pattern, String flags)
{
if ( regexImpl.equals(ARQ.xercesRegex))
return new RegexXerces(pattern, flags) ;
return new RegexJava(pattern, flags) ;
}
// /** @return Returns the expr of the regex */
// public final Expr getRegexExpr() { return expr1 ; }
//
// /** @return Returns the pattern. */
// public final Expr getPattern() { return expr2 ; }
//
// /** @return Returns the flags. */
// public final Expr getFlags() { return expr3 ; }
@Override
public Expr copy(ExprList newArgs)
{
if ( newArgs.size() == 2 )
return new E_Regex(newArgs.get(0), newArgs.get(1), null) ;
return new E_Regex(newArgs.get(0), newArgs.get(1), newArgs.get(2)) ;
}
}