/**
* Copyright 2011 meltmedia
*
* 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.xchain.framework.util;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.namespace.QName;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.regex.PatternSyntaxException;
import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.jxpath.JXPathException;
import javax.xml.XMLConstants;
import javax.xml.namespace.NamespaceContext;
/**
* Utility class for JXPathContext related methods.
*
* @author Christian Trimble
* @author Devon Tackett
* @author Josh Kennedy
*/
public class JXPathContextUtil
{
public static Logger log = LoggerFactory.getLogger( JXPathContextUtil.class );
/** A regex pattern the matches qNames of the form '{uri}local-name' */
public static Pattern uriLocalNamePattern;
/** A regex pattern that matches qNames of the form 'prefix:local-name' */
public static Pattern prefixLocalNamePattern;
/** A regex pattern that matches qNames of the form 'local-name' */
public static Pattern localNamePattern;
static {
try {
uriLocalNamePattern = Pattern.compile("\\{([^{]*)\\}(.+)");
prefixLocalNamePattern = Pattern.compile("([^:]*):([^:]+)");
localNamePattern = Pattern.compile("([^:]+)");
}
catch( PatternSyntaxException pse ) {
if( log.isErrorEnabled() ) {
log.error("Could not compile a qName pattern.", pse);
}
}
}
/**
* Converts a string to a qName based on the mappings in the context object.
*/
public static QName stringToQName( JXPathContext context, String value )
{
Matcher matcher = uriLocalNamePattern.matcher(value);
if( matcher.matches() ) {
String uri = matcher.group(1);
String localName = matcher.group(2);
return new QName(uri, localName);
}
matcher = prefixLocalNamePattern.matcher(value);
if( matcher.matches() ) {
String prefix = matcher.group(1);
String localName = matcher.group(2);
// get the uri for the prefix.
String uri = context.getNamespaceURI(prefix);
if( uri != null ) {
return new QName(uri, localName);
}
else {
throw new RuntimeException("Could not find uri for prefix '"+prefix+"'.");
}
}
matcher = localNamePattern.matcher(value);
if( matcher.matches() ) {
return new QName( matcher.group(1) );
}
throw new RuntimeException("Could not parse the qName '"+value+"'.");
}
public static String stringToQNameString( JXPathContext context, String value )
{
return stringToQName(context, value).toString();
}
/**
* <p>A conversion utility that will properly convert enumeration types. All other conversion are done with
* org.apache.commons.beanutils.ConvertUtils.convert( Object, Class ).</p>
*
* @param value the value to convert.
* @param type the target type for the value.
* @return the converted type.
*/
public static Object convert( Object value, Class type )
{
if( Enum.class.isAssignableFrom(type) ) {
//System.out.println("The type "+type+" is assignable to Enum.");
Object result = org.apache.commons.beanutils.ConvertUtils.convert( value, type );
if( result == null ) {
return null;
}
else if( type.isAssignableFrom(result.getClass()) ) {
return result;
}
else {
return Enum.valueOf( type, result.toString() );
}
}
else {
//System.out.println("The type "+type+" is not assignable to Enum.");
return org.apache.commons.beanutils.ConvertUtils.convert( value, type );
}
}
public static void validate( String value, NamespaceContext namespaceContext )
{
Matcher matcher = uriLocalNamePattern.matcher(value);
if( matcher.matches() ) {
// this is valid, so return.
return;
}
matcher = prefixLocalNamePattern.matcher(value);
if( matcher.matches() ) {
String prefix = matcher.group(1);
if( prefix != null && !XMLConstants.DEFAULT_NS_PREFIX.equals(prefix) && XMLConstants.NULL_NS_URI.equals(namespaceContext.getNamespaceURI(prefix)) ) {
throw new JXPathException("There is not namespace mapping for the prefix of qname '"+value+"'.");
}
return;
}
matcher = localNamePattern.matcher(value);
if( matcher.matches() ) {
return;
}
throw new JXPathException("There is a syntax error in the qname '"+value+"'.");
}
}