blob: 01a757454cd77603f4a47c10ce870dd3861edb1c [file] [log] [blame]
/* Generated By:JJTree: Do not edit this line. Instanceof.java */
package org.apache.xpath.types;
import java.io.PrintStream;
import java.util.Vector;
import javax.xml.transform.TransformerException;
import org.apache.xml.dtm.DTM;
import org.apache.xml.dtm.DTMFilter;
import org.apache.xml.dtm.XType;
import org.apache.xml.utils.QName;
import org.apache.xpath.Expression;
import org.apache.xpath.ExpressionNode;
import org.apache.xpath.ExpressionOwner;
import org.apache.xpath.VariableComposeState;
import org.apache.xpath.XPathContext;
import org.apache.xpath.XPathVisitor;
import org.apache.xpath.objects.XBoolean;
import org.apache.xpath.objects.XNodeSet;
import org.apache.xpath.objects.XObject;
import org.apache.xpath.objects.XSequence;
import org.apache.xpath.parser.Node;
import org.apache.xpath.parser.SchemaContext;
import org.apache.xpath.parser.SequenceType;
import org.apache.xpath.parser.SimpleNode;
import org.apache.xpath.parser.XPath;
/**
* This class implements the "instance of" production for XPath 2.0.
*
* <p>(For easy reference, until the spec is more stable...)</p>
* <pre>
* [9] InstanceofExpr ::= {Expr} ( <"instance" "of"> SequenceType )?
* [51] SequenceType ::= (ItemType OccurrenceIndicator) | "empty"
* [52] ItemType ::= (("element" | "attribute") ElemOrAttrType?)
* | "node"
* | "processing-instruction"
* | "comment"
* | "text"
* | "document"
* | "item"
* | AtomicType
* | "untyped"
* | <"atomic" "value">
* [53] ElemOrAttrType ::= (QName (SchemaType | SchemaContext?)) | SchemaType
* [54] SchemaType ::= <"of" "type"> QName
* [55] AtomicType ::= QName
* [56] OccurrenceIndicator ::= ("*" | "+" | "?")?
* </pre>
*
* <p>Notes to Joe: You can call just the parser to give a diagnostic dump
* of the expression by calling org.apache.xpath.parser.XPath.main() with
* an argument of a an expression string (quote it): "foo instance of xsd:integer".
* This will dump out thus:</p>
* <pre>
* Test[0]: foo instance of xsd:integer
* |instance of
* | child::foo org.apache.xpath.axes.ChildTestIterator
* | m_atomicTypeID: 2
* | m_elemOrAttrName: null
* | m_occurrenceIndicator: 2
* | m_schemaContext: null
* | m_schemaTypeName: null
* | m_whatToShow: 0
* Success!!!!
* I've only tested:
* "foo instance of xsd:integer"
* "foo instance of element of type baz"
* "foo instance of element yada of type baz"
* "foo instance of node"
* "foo instance of text"
* "foo instance of comment"
* "foo instance of untyped"
* </pre>
*
* <p>It's highly likely that there are bugs in the construction with
* other expressions. Come get me if that happens.</p>
* <p>SchemaContext &amp; co is unimplemented right now. Don't worry about
* it for right now.</p>
*
* Created Jul 17, 2002
* @author sboag
*/
public class InstanceofExpr extends Expression implements ExpressionOwner
{
/** The sequence on which to act. **/
private Expression m_targetExpr;
/** The node type value, one of DTMFilter.SHOW_ATTRIBUTE, etc.
* %REVIEW% Why isn't this just the node type? **/
private int m_whatToShow;
/** The atomic type ID, one of XType.BOOLEAN, etc. **/
private int m_atomicTypeID;
// Occurence indicator ID values.
public static final int ZERO_OR_MORE = 1;
public static final int ONE_OR_MORE = 2;
public static final int ZERO_OR_ONE = 3;
public static final int EMPTY_SEQ = 4;
/** The occurance indicator ID. One of ZERO_OR_MORE, etc. or EMPTY_SEQ **/
private int m_occurrenceIndicator = ONE_OR_MORE;
/** The ElemOrAttrType name, meaning the tag QName, may be null. */
private QName m_elemOrAttrName;
/** The SchemaType name, meaning the tag QName, may be null. */
private QName m_schemaTypeName;
/** SchemaContext is not executable for the moment, so leave it
* as a NEE until we figure out what we want to do with it. **/
private SchemaContext m_schemaContext;
public InstanceofExpr() {
super();
}
/** Accept the visitor. **/
public Object jjtAccept(org.apache.xpath.parser.XPathVisitor visitor, Object data) {
return visitor.visit(this, data);
}
/**
* @see Expression#deepEquals(Expression)
*/
public boolean deepEquals(Expression expr)
{
if(!(expr instanceof InstanceofExpr))
return false;
return false;
}
/**
* @see Expression#fixupVariables(Vector, int)
*/
public void fixupVariables(VariableComposeState vcs)
{
m_targetExpr.fixupVariables(vcs);
}
/**
* @see Expression#execute(XPathContext)
*/
public XObject execute(XPathContext xctxt) throws TransformerException
{
// m_atomicTypeID: Integer XType primitive, IFF no m_schemaTypeName
// m_schemaContext: SchemaContext, UNSPECIFIED AT THIS TIME
// and hence unsupported.
boolean isInstance=true;
XObject value=m_targetExpr.execute(xctxt);
switch(value.getType())
{
case XObject.CLASS_UNKNOWN:
// If not XSLT type, can't be instance of ...?
// %REVIEW% what SHOW_ITEM and SHOW_UNTYPED mean
case XObject.CLASS_NULL:
isInstance=false;
break;
case XObject.CLASS_NODESET:
case XObject.CLASS_RTREEFRAG:
int len=0;
XSequence valNodeSet= value.xseq();
for( XObject next=valNodeSet.next();
isInstance && next!=null;
next=valNodeSet.next(),++len)
{
int handle = next.getNodeHandle();
if(DTM.NULL == handle)
continue;
if(m_whatToShow!=0)
{
int nodetype=xctxt.getDTM(handle).getNodeType(handle);
if(0==(m_whatToShow & 1<<(nodetype-1)))
isInstance=false;
else if(m_elemOrAttrName!=null)
{
isInstance&=
(m_elemOrAttrName.getNamespace/*URI*/()
==xctxt.getDTM(handle).getNamespaceURI(handle))
&&
(m_elemOrAttrName.getLocalName()
==xctxt.getDTM(handle).getLocalName(handle));
}
}
if(m_schemaTypeName!=null)
{
isInstance&=
xctxt.getDTM(handle).isNodeSchemaType(
handle,
m_schemaTypeName.getNamespaceURI(),
m_schemaTypeName.getLocalName());
}
else if(m_atomicTypeID!=0)
{
// Unless DTM implements awareness of these
// typenumbers, or our sequence/nodeset layers
// handle this for us, we need to convert back
// to strings. We also have to convert from the
// Schema_datatype namespace, used in requesting the
// primitive, to the Schema namespace used when
// the node was declared.
isInstance&=
xctxt.getDTM(handle).isNodeSchemaType(
handle,
XType.XMLSCHEMA_NAMESPACE,
XType.getLocalNameFromType(m_atomicTypeID));
}
} // End scan contents
switch(m_occurrenceIndicator)
{
case ZERO_OR_MORE:
break; // Anything is OK
case ONE_OR_MORE:
isInstance&=(len>=1);
break;
case ZERO_OR_ONE:
isInstance&=(len<2);
break;
case EMPTY_SEQ:
isInstance&=(len==0);
break;
}
break;
case XObject.CLASS_BOOLEAN:
isInstance&=(m_elemOrAttrName==null);
isInstance&=(m_schemaTypeName==null);
isInstance&=(m_whatToShow==0);
isInstance&=(m_atomicTypeID==XType.BOOLEAN);
break;
case XObject.CLASS_NUMBER:
isInstance&=(m_elemOrAttrName==null);
isInstance&=(m_schemaTypeName==null);
isInstance&=(m_whatToShow==0);
// %REVIEW% XNumber is just that, a number.
// We want *it* to tell *us* whether it's straight
// decimal or double or whatever...?
isInstance&=(m_atomicTypeID==XType.DECIMAL
|| m_atomicTypeID==XType.DOUBLE);
break;
case XObject.CLASS_STRING:
isInstance&=(m_elemOrAttrName==null);
isInstance&=(m_schemaTypeName==null);
isInstance&=(m_whatToShow==0);
isInstance&=(m_atomicTypeID==XType.STRING);
break;
default:
// Should never arise
isInstance=false;
break;
}
return isInstance ? XBoolean.S_TRUE : XBoolean.S_FALSE;
}
/**
* @see XPathVisitable#callVisitors(ExpressionOwner, XPathVisitor)
*/
public void callVisitors(ExpressionOwner owner, XPathVisitor visitor)
{
m_targetExpr.callVisitors(this, visitor);
}
/**
* @see ExpressionOwner#getExpression()
*/
public Expression getExpression()
{
return m_targetExpr;
}
/**
* @see ExpressionOwner#setExpression(Expression)
*/
public void setExpression(Expression exp)
{
m_targetExpr = exp;
}
/**
* @see SimpleNode#shouldReduceIfOneChild()
*/
public boolean shouldReduceIfOneChild()
{
return (m_whatToShow == 0 && m_atomicTypeID == 0) ? true : false;
}
/**
* Returns the occurrenceIndicator.
* @return int
*/
public int getOccurrenceIndicator()
{
return m_occurrenceIndicator;
}
/**
* Returns the schemaContext.
* @return SchemaContext
*/
public SchemaContext getSchemaContext()
{
return m_schemaContext;
}
/**
* Returns the schemaTypeName.
* @return QName
*/
public QName getSchemaTypeName()
{
return m_schemaTypeName;
}
/**
* Returns the targetExpr.
* @return Expression
*/
public Expression getTargetExpr()
{
return m_targetExpr;
}
/**
* Returns the whatToShow.
* @return int
*/
public int getWhatToShow()
{
return m_whatToShow;
}
/**
* Sets the occurrenceIndicator.
* @param occurrenceIndicator The occurrenceIndicator to set
*/
public void setOccurrenceIndicator(int occurrenceIndicator)
{
m_occurrenceIndicator = occurrenceIndicator;
}
/**
* Sets the schemaContext.
* @param schemaContext The schemaContext to set
*/
public void setSchemaContext(SchemaContext schemaContext)
{
m_schemaContext = schemaContext;
}
/**
* Sets the schemaTypeName.
* @param schemaTypeName The schemaTypeName to set
*/
public void setSchemaTypeName(QName schemaTypeName)
{
m_schemaTypeName = schemaTypeName;
}
/**
* Sets the targetExpr.
* @param targetExpr The targetExpr to set
*/
public void setTargetExpr(Expression targetExpr)
{
m_targetExpr = targetExpr;
}
/**
* Sets the whatToShow.
* @param whatToShow The whatToShow to set
*/
public void setWhatToShow(int whatToShow)
{
m_whatToShow = whatToShow;
}
/**
* @see org.apache.xpath.parser.Node#jjtAddChild(Node, int)
*/
public void jjtAddChild(Node n, int i)
{
if(0 == i)
{
n = this.fixupPrimarys(n);
m_targetExpr = (Expression)n;
}
else if(2 == i) // skip the child at index 1, which is the instance of keyword.
{
SequenceType stype = (SequenceType)n;
m_atomicTypeID = stype.getAtomicTypeID();
m_elemOrAttrName = stype.getElemOrAttrName();
m_occurrenceIndicator = stype.getOccurrenceIndicator();
m_schemaContext = stype.getSchemaContext();
m_schemaTypeName = stype.getSchemaTypeName();
m_whatToShow = stype.getWhatToShow();
}
}
/**
* @see org.apache.xpath.ExpressionNode#exprGetChild(int)
*/
public ExpressionNode exprGetChild(int i)
{
// This doesn't work perfectly, but it's good enough.
return (0 == i) ? m_targetExpr : (1 == 0) ? m_schemaContext : null;
}
/**
* @see org.apache.xpath.ExpressionNode#exprGetNumChildren()
*/
public int exprGetNumChildren()
{
// This doesn't work perfectly, but it's good enough.
return ((null == m_targetExpr) ? 1 : 0)+((null == m_schemaContext) ? 1 : 0);
}
/**
* @see org.apache.xpath.parser.SimpleNode#dump(String, PrintStream)
*/
public void dump(String prefix, PrintStream ps)
{
super.dump(prefix, ps);
prefix = prefix+" ";
ps.print(prefix);
ps.println("m_atomicTypeID: "+m_atomicTypeID);
ps.print(prefix);
ps.println("m_elemOrAttrName: "+m_elemOrAttrName);
ps.print(prefix);
ps.println("m_occurrenceIndicator: "+m_occurrenceIndicator);
ps.print(prefix);
ps.println("m_schemaContext: "+m_schemaContext);
ps.print(prefix);
ps.println("m_schemaTypeName: "+m_schemaTypeName);
ps.print(prefix);
ps.println("m_whatToShow: "+m_whatToShow);
}
/**
* @see java.lang.Object#toString()
*/
public String toString()
{
return "instance of";
}
}