package org.basex.query.item; import static org.basex.query.util.Err.*; import java.io.IOException; import org.basex.api.dom.BXAttr; import org.basex.api.dom.BXComm; import org.basex.api.dom.BXDoc; import org.basex.api.dom.BXElem; import org.basex.api.dom.BXPI; import org.basex.api.dom.BXText; import org.basex.build.MemBuilder; import org.basex.build.xml.DOMWrapper; import org.basex.core.Prop; import org.basex.query.QueryContext; import org.basex.query.QueryException; import org.basex.query.util.Err; import org.basex.util.InputInfo; import org.basex.util.Token; import org.basex.util.TokenBuilder; import org.basex.util.Util; import org.basex.util.hash.TokenMap; import org.w3c.dom.Attr; import org.w3c.dom.Comment; import org.w3c.dom.Document; import org.w3c.dom.DocumentFragment; import org.w3c.dom.Element; import org.w3c.dom.ProcessingInstruction; import org.w3c.dom.Text; /** * XQuery node types. * * @author BaseX Team 2005-12, BSD License * @author Leo Woerteler */ public enum NodeType implements Type { /** Node type. */ NOD("node", AtomType.ITEM), /** Text type. */ TXT("text", NOD) { @Override public ANode cast(final Object o, final InputInfo ii) { return o instanceof BXText ? ((BXText) o).getNod() : new FTxt((Text) o); } }, /** PI type. */ PI("processing-instruction", NOD) { @Override public ANode cast(final Object o, final InputInfo ii) { return o instanceof BXPI ? ((BXPI) o).getNod() : new FPI((ProcessingInstruction) o); } }, /** Element type. */ ELM("element", NOD) { @Override public ANode cast(final Object o, final InputInfo ii) { return o instanceof BXElem ? ((BXElem) o).getNod() : new FElem((Element) o, null, new TokenMap()); } }, /** Document type. */ DOC("document-node", NOD) { @Override public ANode cast(final Object o, final InputInfo ii) throws QueryException { if(o instanceof BXDoc) return ((BXDoc) o).getNod(); if(o instanceof Document) { try { final DOMWrapper p = new DOMWrapper((Document) o, ""); return new DBNode(MemBuilder.build(p, new Prop()), 0); } catch(final IOException ex) { UNDOC.thrw(ii, ex); } } // document fragment final DocumentFragment df = (DocumentFragment) o; final String bu = df.getBaseURI(); return new FDoc(df, bu != null ? Token.token(bu) : Token.EMPTY); } }, /** Document element type. */ DEL("document-node(element())", NOD), /** Attribute type. */ ATT("attribute", NOD) { @Override public ANode cast(final Object o, final InputInfo ii) { return o instanceof BXAttr ? ((BXAttr) o).getNod() : new FAttr((Attr) o); } }, /** Comment type. */ COM("comment", NOD) { @Override public ANode cast(final Object o, final InputInfo ii) { return o instanceof BXComm ? ((BXComm) o).getNod() : new FComm((Comment) o); } }, /** Namespace type. */ NSP("namespace-node", NOD); /** String representation. */ private final byte[] string; /** Parent type. */ private final Type par; /** Sequence type. */ private SeqType seq; @Override public final boolean isNode() { return true; } @Override public boolean isNumber() { return false; } @Override public boolean isString() { return false; } @Override public boolean isUntyped() { return true; } @Override public boolean isDuration() { return false; } @Override public boolean isDate() { return false; } @Override public final boolean isFunction() { return false; } @Override public final boolean isMap() { return false; } @Override public Item cast(final Item it, final QueryContext ctx, final InputInfo ii) throws QueryException { return it.type != this ? error(it, ii) : it; } @Override public Item cast(final Object o, final InputInfo ii) throws QueryException { Util.notexpected(o); return null; } /** * Constructor. * @param nm string representation * @param pr parent type */ NodeType(final String nm, final Type pr) { string = Token.token(nm); par = pr; } @Override public SeqType seqType() { // cannot be statically instantiated due to circular dependency if(seq == null) seq = new SeqType(this); return seq; } /** * Throws a casting exception. * @param it item to be included in the error message * @param ii input info * @return dummy item * @throws QueryException query exception */ Item error(final Item it, final InputInfo ii) throws QueryException { Err.cast(ii, this, it); return null; } // PUBLIC AND STATIC METHODS ================================================ @Override public final boolean instanceOf(final Type t) { return this == t || par != null && par.instanceOf(t); } /** * Finds and returns the specified node type. * @param type type as string * @return type or {@code null} */ public static NodeType find(final QNm type) { if(type.uri().length == 0) { final byte[] ln = type.local(); for(final NodeType t : values()) { if(Token.eq(ln, t.string)) return t; } } return null; } @Override public int id() { return ordinal() + 8; } @Override public String toString() { return new TokenBuilder(string).add("()").toString(); } @Override public byte[] string() { return string; } }