/**
* $Id$
* $Date$
*
*/
package org.xmlsh.core;
import java.util.EnumSet;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;
import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.QName;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XQueryCompiler;
import net.sf.saxon.s9api.XQueryEvaluator;
import net.sf.saxon.s9api.XQueryExecutable;
import net.sf.saxon.s9api.XdmItem;
import net.sf.saxon.s9api.XdmValue;
import org.xml.sax.SAXException;
import org.xmlsh.sh.shell.Shell;
import org.xmlsh.util.NameValueMap;
import org.xmlsh.xpath.EvalDefinition;
import org.xmlsh.xpath.ShellContext;
public class XVariable {
private static final String sName = "name";
private static final String sVariable = "variable";
private static final String sType = "type";
private static final String sFlags = "flags";
public enum XVarFlag {
EXPORT , // to be exported to child shells
XEXPR , // participates in XEXPRs
READONLY
};
private String mName;
private XValue mValue;
private EnumSet<XVarFlag> mFlags;
private XQueryExecutable mTieExpr; // Tie expression
public XVariable( String name , XValue value , EnumSet<XVarFlag> flags)
{
mName = name ;
mValue = value;
mFlags = flags;
}
public XVariable clone()
{
XVariable that = new XVariable(mName,mValue,mFlags);
that.mTieExpr = mTieExpr ;
return that ;
}
public XVariable( String name , XValue value )
{
this( name , value , EnumSet.of( XVarFlag.EXPORT , XVarFlag.XEXPR ));
}
protected XVariable( String name , EnumSet<XVarFlag> flags )
{
this( name , null , flags );
}
/**
* @return the name
*/
public String getName() {
return mName;
}
/**
* @param name the name to set
*/
public void setName(String name) {
mName = name;
}
/**
* @return the value
*/
public XValue getValue() {
return mValue;
}
/**
* @param value the value to set
* @throws InvalidArgumentException
*/
public void setValue(XValue value) throws InvalidArgumentException {
if( mFlags.contains( XVarFlag.READONLY ))
throw new InvalidArgumentException("Cannot modify readonly variable: " + getName());
mValue = value;
}
/**
* @return the flags
*/
public EnumSet<XVarFlag> getFlags() {
return mFlags;
}
/**
* @param flags the flags to set
*/
public void setFlags(EnumSet<XVarFlag> flags) {
mFlags = flags;
}
public void serialize(XMLStreamWriter writer) throws SAXException, XMLStreamException {
/*
AttributesImpl atts = new AttributesImpl();
atts.addAttribute("", sName, sName, "CDATA", getName());
XValue value = this.getValue();
String type =
value.isString() ? "string" : "xml";
atts.addAttribute("", sType, sType, "CDATA", type );
// atts.addAttribute("", "value", "value", "CDATA", value.toString() );
String flagStr = mFlags.toString();
atts.addAttribute("", sFlags, sFlags, "CDATA", flagStr );
writer.startElement("", sVariable, sVariable, atts);
writer.endElement("", sVariable, sVariable);
*/
XValue value = this.getValue();
String flagStr = mFlags.toString();
writer.writeStartElement(sVariable);
writer.writeAttribute(sName, getName());
String type ;
if( value == null )
type = "null";
else
if( value.isObject() )
type = value.asObject().getClass().getName();
else
if( value.isAtomic())
type = "string";
else
type = "xml";
writer.writeAttribute(sType,type);
writer.writeAttribute(sFlags, flagStr );
writer.writeEndElement();
}
public void clear() throws InvalidArgumentException {
setValue( null );
}
public boolean isNull() {
return mValue == null ;
}
public void shift(int n) {
if( n <= 0 || mValue == null )
return ;
mValue = mValue.shift( n );
}
public void tie(Shell shell , String expr) throws SaxonApiException {
if( expr == null )
{
mTieExpr = null ;
return ;
}
Processor processor = Shell.getProcessor();
XQueryCompiler compiler = processor.newXQueryCompiler();
// Declare the extension function namespace
// This can be overridden by user declarations
compiler.declareNamespace("xmlsh", EvalDefinition.kXMLSH_EXT_NAMESPACE);
NameValueMap<String> ns = shell.getEnv().getNamespaces();
if( ns != null ){
for( String prefix : ns.keySet() ){
String uri = ns.get(prefix);
compiler.declareNamespace(prefix, uri);
}
}
StringBuffer sb = new StringBuffer();
sb.append("declare variable $_ external;\n");
sb.append(expr);
mTieExpr = compiler.compile( sb.toString() );
}
private XValue getTiedValue( Shell shell , XdmItem item , XValue arg)
{
Shell saved_shell = ShellContext.set(shell);
XQueryEvaluator eval = mTieExpr.load();
try {
eval.setExternalVariable( new QName("_") , arg.asXdmValue() );
eval.setContextItem(item);
XdmValue result = eval.evaluate();
return new XValue(result) ;
} catch (SaxonApiException e) {
shell.printErr("Error expanding xml expression",e);
}
finally {
ShellContext.set(saved_shell);
}
return null;
}
/*
* Get a variable value with an optional index and tie expression
*/
public XValue getValue(Shell shell, String ind, XValue arg) {
XValue xvalue = getValue();
if( xvalue == null )
return null;
if( xvalue.isObject() || xvalue.isNull() ){
if( arg == null )
return xvalue ;
/*
* Get method and args by evaluating arg
*/
return xvalue ;
}
XdmValue value = xvalue.asXdmValue(ind);
if( value == null )
return null ;
// TIE expression
if( arg != null && mTieExpr != null ){
if( value instanceof XdmItem )
return this.getTiedValue(shell, (XdmItem)value , arg);
}
return new XValue(value);
}
public boolean isExport() {
return getFlags().contains(XVarFlag.EXPORT);
}
}
//
//
//Copyright (C) 2008-2014 David A. Lee.
//
//The contents of this file are subject to the "Simplified BSD License" (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.opensource.org/licenses/bsd-license.php
//
//Software distributed under the License is distributed on an "AS IS" basis,
//WITHOUT WARRANTY OF ANY KIND, either express or implied.
//See the License for the specific language governing rights and limitations under the License.
//
//The Original Code is: all this file.
//
//The Initial Developer of the Original Code is David A. Lee
//
//Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
//
//Contributor(s): none.
//