Package org.exist.xquery.value

Source Code of org.exist.xquery.value.AbstractSequence

/*
*  eXist Open Source Native XML Database
*  Copyright (C) 2001-06,  Wolfgang M. Meier (meier@ifs.tu-darmstadt.de)
*
*  This library is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Library General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*
*  This library is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Library General Public License for more details.
*
*  You should have received a copy of the GNU Library General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
*  $Id$
*/
package org.exist.xquery.value;

import org.exist.collections.Collection;
import org.exist.dom.DocumentSet;
import org.exist.dom.EmptyNodeSet;
import org.exist.dom.NodeProxy;
import org.exist.dom.StoredNode;
import org.exist.numbering.NodeId;
import org.exist.xquery.Cardinality;
import org.exist.xquery.XPathException;
import org.exist.xquery.XQueryContext;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
* An abstract implementation of {@link org.exist.xquery.value.Sequence} with
* default implementations for some methods.
*/
public abstract class AbstractSequence implements Sequence {

    /** To retain compatibility with eXist versions before september 20th 2005 ,
     * for conversion to boolean;
     * @see http://cvs.sourceforge.net/viewcvs.py/exist/eXist-1.0/src/org/exist/xquery/value/AbstractSequence.java?r1=1.11&r2=1.12 */
    private static final boolean OLD_EXIST_VERSION_COMPATIBILITY = false;

    protected boolean isEmpty;
    protected boolean hasOne;

    protected AbstractSequence() {
        isEmpty = true;
        hasOne = false;
    }

    public abstract int getItemType();

    public abstract SequenceIterator iterate() throws XPathException;

    public abstract SequenceIterator unorderedIterator() throws XPathException;
 
    public abstract int getItemCount();

    public int getCardinality() {
        if (isEmpty())
            {return Cardinality.EMPTY;}
        if (hasOne())
            {return Cardinality.EXACTLY_ONE;}
        if (hasMany())
            {return Cardinality.ONE_OR_MORE;}
        throw new IllegalArgumentException("Illegal argument");
    }

    public AtomicValue convertTo(int requiredType) throws XPathException {
        final Item first = itemAt(0);
        if(Type.subTypeOf(first.getType(), Type.ATOMIC))
            {return ((AtomicValue)first).convertTo(requiredType);}
        else
            //TODO : clean atomization
            {return new StringValue(first.getStringValue()).convertTo(requiredType);}
    }

    public abstract boolean isEmpty();

    public abstract boolean hasOne();

    public boolean hasMany() {
        return !isEmpty() && !hasOne();
    }

    @Override
    public Sequence tail() throws XPathException {
      final ValueSequence tmp = new ValueSequence(getItemCount() - 1);
      Item item;
        final SequenceIterator iterator = iterate();
        iterator.nextItem();
        while (iterator.hasNext()) {
            item = iterator.nextItem();
            tmp.add(item);
        }
        return tmp;
    }
   
    public String getStringValue() throws XPathException {
        if(isEmpty())
            {return "";}
        final Item first = iterate().nextItem();
        return first.getStringValue();
    }

    public String toString() {
        try {
            final StringBuilder buf = new StringBuilder();
            buf.append("(");
            boolean gotOne = false;
            for (final SequenceIterator i = iterate(); i.hasNext(); ) {
                if (gotOne)
                    {buf.append(", ");}
                buf.append(i.nextItem());
                gotOne = true;
            }
            buf.append(")");
            return buf.toString();
        } catch (final XPathException e) {
            return "toString() fails: " + e.getMessage();
        }
    }

    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#add(org.exist.xquery.value.Item)
     */
    public abstract void add(Item item) throws XPathException;

    public void addAll(Sequence other) throws XPathException {
        for (final SequenceIterator i = other.iterate(); i.hasNext(); )
            add(i.nextItem());
    }

    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#itemAt(int)
     */
    public abstract Item itemAt(int pos);

    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#getDocumentSet()
     */
    public DocumentSet getDocumentSet() {
        return DocumentSet.EMPTY_DOCUMENT_SET;
    }

    public Iterator<Collection> getCollectionIterator() {
        return EmptyNodeSet.EMPTY_COLLECTION_ITERATOR;
    }

    public void nodeMoved(NodeId oldNodeId, StoredNode newNode) {
        //Nothing to do
    }

    /** See
     * <a <href="http://www.w3.org/TR/xquery/#id-ebv">2.4.3 Effective Boolean Value</a>
     * @see org.exist.xquery.value.Sequence#effectiveBooleanValue()
     */
    public boolean effectiveBooleanValue() throws XPathException {   
        if (isEmpty())
            {return false;}
        final Item first = itemAt(0);
        //If its operand is a sequence whose first item is a node, fn:boolean returns true.   
        if (Type.subTypeOf(first.getType(), Type.NODE))
            {return true;}
        if (hasMany()) {
            if (OLD_EXIST_VERSION_COMPATIBILITY)   
                {return true;}
            else
                {throw new XPathException(
                    "err:FORG0006: effectiveBooleanValue: first item of '" +
                    (toString().length() < 20 ? toString() : toString().substring(0, 20)+ "...") +
                    "' is not a node, and sequence length > 1");}
        }
        //From now, we'll work with singletons...
        //Not sure about this one : does it mean than any singleton, including false() and 0 will return true ?
        if (OLD_EXIST_VERSION_COMPATIBILITY)
            {return true;}
        else
            {return ((AtomicValue)first).effectiveBooleanValue();}
    }

    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#conversionPreference(java.lang.Class)
     */
    public int conversionPreference(Class<?> javaClass) {
        if (javaClass.isAssignableFrom(Sequence.class))
            {return 0;}
        else if (javaClass.isAssignableFrom(List.class) || javaClass.isArray())
            {return 1;}
        else if (javaClass == Object.class)
            {return 20;}
        if(!isEmpty())
            {return itemAt(0).conversionPreference(javaClass);}
        return Integer.MAX_VALUE;
    }

    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#toJavaObject(java.lang.Class)
     */
    @Override
    public <T> T toJavaObject(final Class<T> target) throws XPathException {
        if(Sequence.class.isAssignableFrom(target)) {
            return (T)this;
        } else if(target.isArray()) {
            final Class<?> componentType = target.getComponentType();
            // assume single-dimensional, then double-check that instance really matches desired type
            final Object array = Array.newInstance(componentType, getItemCount());
            if(!target.isInstance(array)) {
                return null;
            }
            int index = 0;
            for(final SequenceIterator i = iterate(); i.hasNext(); index++) {
                final Item item = i.nextItem();
                final Object obj = item.toJavaObject(componentType);
                Array.set(array, index, obj);
            }
            return (T)array;
        } else if(target.isAssignableFrom(List.class)) {
            final List<Item> l = new ArrayList<Item>(getItemCount());
            for(final SequenceIterator i = iterate(); i.hasNext(); ) {
                l.add(i.nextItem());
            }
            return (T)l;
        }
        if(!isEmpty()) {
            return (T)itemAt(0).toJavaObject(target);
        }
        return null;
    }

    public void clearContext(int contextIdthrows XPathException {
        Item next;
        for (final SequenceIterator i = unorderedIterator(); i.hasNext(); ) {
            next = i.nextItem();
            if (next instanceof NodeProxy)
                {((NodeProxy)next).clearContext(contextId);}
        }
    }

    public void setSelfAsContext(int contextId) throws XPathException {
        Item next;
        NodeValue node;
        for (final SequenceIterator i = unorderedIterator(); i.hasNext();) {
            next = i.nextItem();
            if (Type.subTypeOf(next.getType(), Type.NODE)) {
                node = (NodeValue) next;
                node.addContextNode(contextId, node);
            }
        }
    }

    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#isCached()
     */
    public boolean isCached() {
        // always return false by default
        return false;
    }

    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#setIsCached(boolean)
     */
    public void setIsCached(boolean cached) {
        // ignore by default
    }

    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#isPersistentSet()
     */
    public boolean isPersistentSet() {
        // always return false by default
        return false;
    }

    public boolean isCacheable() {
        return false;
    }

    public int getState() {
        return 0;
    }

    public boolean hasChanged(int previousState) {
        return true;
    }

    @Override
    public void destroy(XQueryContext context, Sequence contextSequence) {
        // do nothing by default
    }
}
TOP

Related Classes of org.exist.xquery.value.AbstractSequence

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.