/******************************************************************************* * Copyright (c) 2004, 2007 IBM Corporation and Cambridge Semantics Incorporated. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * File: $Source: /cvsroot/slrp/glitter/com.ibm.adtech.glitter/src/com/ibm/adtech/glitter/expression/builtin/RegEx.java,v $ * Created by: Lee Feigenbaum (<a href="mailto:feigenbl@us.ibm.com">feigenbl@us.ibm.com</a>) * Created on: 10/23/06 * Revision: $Id: RegEx.java 164 2007-07-31 14:11:09Z mroy $ * * Contributors: IBM Corporation - initial API and implementation * Cambridge Semantics Incorporated - Fork to Anzo *******************************************************************************/ package org.openanzo.glitter.expression.builtin; import java.util.HashMap; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.openanzo.glitter.exception.ExpressionEvaluationException; import org.openanzo.glitter.exception.IncompatibleTypeException; import org.openanzo.glitter.exception.InvalidArgumentCountException; import org.openanzo.glitter.expression.ScalarFunctionBase; import org.openanzo.glitter.expression.ScalarFunctionOnValues; import org.openanzo.glitter.util.Constants; import org.openanzo.glitter.util.Glitter; import org.openanzo.glitter.util.TypeConversions; import org.openanzo.rdf.Literal; import org.openanzo.rdf.URI; import org.openanzo.rdf.Value; import org.openanzo.rdf.Constants.NAMESPACES; /** * Implements <a href="http://www.w3.org/TR/rdf-sparql-query/#func-regEx">the SPARQL regex function</a>. * * @author lee <lee@cambridgesemantics.com> * */ public class RegEx extends ScalarFunctionBase implements ScalarFunctionOnValues { private final static HashMap<Character, Integer> flag_map; /** * Thrown for an unrecognized regular expression flag. * * @author lee <lee@cambridgesemantics.com> * */ static class InvalidRegularExpressionFlagException extends ExpressionEvaluationException { private static final long serialVersionUID = 1656708447585086309L; /** * Default constructor. * * @param s * The invalid regex flag. */ protected InvalidRegularExpressionFlagException(String s) { super(s); } } static { flag_map = new HashMap<Character, Integer>(); flag_map.put('s', Pattern.DOTALL); flag_map.put('m', Pattern.MULTILINE); flag_map.put('i', Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE); // java doesn't support x (extra whitespace) // flag_map.put('x', ...); // TODO - only type errors get suppressed by logical-or/and } public Value call(List<Value> arguments) throws ExpressionEvaluationException { int argCount = arguments.size(); if (argCount < 2 || argCount > 3) throw new InvalidArgumentCountException(arguments.size(), 2, 3); Value inputTerm = arguments.get(0), patternTerm = arguments.get(1), flagsTerm = argCount == 3 ? arguments.get(2) : null; if (!TypeConversions.isSimpleLiteral(inputTerm)) throw new IncompatibleTypeException(inputTerm, "simple literal"); if (!TypeConversions.isSimpleLiteral(patternTerm)) throw new IncompatibleTypeException(patternTerm, "simple literal"); if (flagsTerm != null && !TypeConversions.isSimpleLiteral(flagsTerm)) throw new IncompatibleTypeException(flagsTerm, "simple literal"); String input = ((Literal) inputTerm).getLabel(), pattern = ((Literal) patternTerm).getLabel(), flags = flagsTerm != null ? ((Literal) flagsTerm).getLabel() : ""; // TODO - not sure if Java reg. ex. matches the syntax/semantics of // XPath's fn:matches as per: // http://www.w3.org/TR/xpath-functions/#regex-syntax int iFlags = 0; for (int i = 0; i < flags.length(); i++) { Integer val = flag_map.get(flags.charAt(i)); if (val == null) throw new InvalidRegularExpressionFlagException(flags.charAt(i) + " is not a valid regular expression flag."); iFlags |= val; } Pattern regex = Pattern.compile(pattern, iFlags); Matcher matcher = regex.matcher(input); return matcher.find() ? Constants.TRUE : Constants.FALSE; } public URI getIdentifier() { return Glitter.createURI(NAMESPACES.FN_NAMESPACE + "matches"); } @Override public String toString() { return "regex"; } }