Package org.exist.xquery.value

Source Code of org.exist.xquery.value.GroupedValueSequence$Entry

/*
*  eXist Open Source Native XML Database
*  Copyright (C) 2001-06 The eXist Project
*  http://exist-db.org
*  http://exist.sourceforge.net
*  
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*  
*  This program 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 Lesser General Public License for more details.
*  
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*  
*  $Id$
*/
package org.exist.xquery.value;

import org.exist.dom.ExtArrayNodeSet;
import org.exist.dom.NodeProxy;
import org.exist.dom.NodeSet;
import org.exist.xquery.GroupSpec;
import org.exist.xquery.XPathException;
import org.exist.xquery.XQueryContext;
import org.exist.xquery.util.ExpressionDumper;


/**
* A sequence that containts items of one group specified by the group specs of
* an "group by" clause. Used by 
* {@link org.exist.xquery.value.GroupedValueSequenceTable}.
* This class is based on {@link org.exist.xquery.value.OrderedValueSequence}.
* WARNING : don't use except for group by clause 
* @author Boris Verhaegen
*/
public class GroupedValueSequence extends AbstractSequence {
    
    private Entry[] items = null;
    private int count = 0;
    //grouping keys values of this group
    private GroupSpec groupSpecs[]
    private Sequence groupKey;
//    private XQueryContext context;
    @SuppressWarnings("unused")
  private int groupKeyLength;
    
    // used to keep track of the type of added items.
    private int itemType = Type.ANY_TYPE;
    
    public GroupedValueSequence(GroupSpec groupSpecs[], int size, Sequence keySequence, XQueryContext aContext) {
        this.groupSpecs = groupSpecs;
        this.items = new Entry[size];
        this.groupKey = keySequence;
//        this.context = aContext; //UNDERSTAND: do we need context here??? -shabanovd
        this.groupKeyLength = groupKey.getItemCount();
    }
    
    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#iterate()
     */
    public SequenceIterator iterate() throws XPathException {
        return new GroupedValueSequenceIterator();
    }
    /* (non-Javadoc)
     * @see org.exist.xquery.value.AbstractSequence#unorderedIterator()
     */
    public SequenceIterator unorderedIterator() throws XPathException {
        return new GroupedValueSequenceIterator();
    }
    
    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#getLength()
     */
    public int getItemCount() {
        return (items == null) ? 0 : count;
    }
    
    public Sequence getGroupKey() {
        return this.groupKey;
    }
    public boolean isEmpty() {
        return isEmpty;
    }
    public boolean hasOne() {
        return hasOne;
    }
    
    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#add(org.exist.xquery.value.Item)
     */
    public void add(Item item) throws XPathException {
        if (hasOne)
            {hasOne = false;}
        if (isEmpty)
            {hasOne = true;}
        isEmpty = false;
        if(count == items.length) {
            Entry newItems[] = new Entry[count * 2];
            System.arraycopy(items, 0, newItems, 0, count);
            items = newItems;
        }
        items[count++] = new Entry(item);
        checkItemType(item.getType());
    }
    /* (non-Javadoc)
     * @see org.exist.xquery.value.AbstractSequence#addAll(org.exist.xquery.value.Sequence)
     */
    public void addAll(Sequence other) throws XPathException {
        if(other.hasOne())
            {add(other.itemAt(0));}        
        else if(!other.isEmpty()) {
            for(final SequenceIterator i = other.iterate(); i.hasNext(); ) { 
                final Item next = i.nextItem();
                if(next != null)
                    {add(next);}
            }
        } 
    }
    
    public Item itemAt(int pos) {
        if(items != null && pos > -1 && pos < count)
            {return items[pos].item;}
        else
            {return null;}
    }
    private void checkItemType(int type) {
        if(itemType == Type.NODE || itemType == type)
            {return;}
        if(itemType == Type.ANY_TYPE)
            {itemType = type;}
        else
            {itemType = Type.NODE;}
    }
    
    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#getItemType()
     */
    public int getItemType() {
        return itemType;
    }
    
    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#toNodeSet()
     */
    public NodeSet toNodeSet() throws XPathException {
        // for this method to work, all items have to be nodes
        if(itemType != Type.ANY_TYPE && Type.subTypeOf(itemType, Type.NODE)) {
            final NodeSet set = new ExtArrayNodeSet();
            //We can't make it from an ExtArrayNodeSet (probably because it is sorted ?)
            //NodeSet set = new ArraySet(100);
            for (int i = 0; i < this.count; i++) {
                NodeValue v = null;
                final Entry temp = items[i];
                v = (NodeValue)temp.item;
                    if(v.getImplementationType() != NodeValue.PERSISTENT_NODE) {
                    set.add((NodeProxy)v);
                } else {
                    set.add((NodeProxy)v);
                }
            }
            return set;
        } else
            {throw new XPathException("Type error: the sequence cannot be converted into" +
                " a node set. Item type is " + Type.getTypeName(itemType));}
    }

    public MemoryNodeSet toMemNodeSet() throws XPathException {
        if(count == 0)
            {return MemoryNodeSet.EMPTY;}
        if(itemType == Type.ANY_TYPE || !Type.subTypeOf(itemType, Type.NODE)) {
            throw new XPathException("Type error: the sequence cannot be converted into" +
        " a node set. Item type is " + Type.getTypeName(itemType));
        }
        NodeValue v;
        for (int i = 0; i <= count; i++) {
            v = (NodeValue)items[i];
            if(v.getImplementationType() == NodeValue.PERSISTENT_NODE)
                {return null;}
        }
        return new ValueSequence(this);
    }

    /* (non-Javadoc)
     * @see org.exist.xquery.value.Sequence#removeDuplicates()
     */
    public void removeDuplicates() {
        // TODO: is this ever relevant?
    }
    
    private class Entry implements Comparable<Entry> {
        Item item;
        AtomicValue values[];
        public Entry(Item item) throws XPathException {
            this.item = item;
            values = new AtomicValue[groupSpecs.length];
            for(int i = 0; i < groupSpecs.length; i++) {
                final Sequence seq = groupSpecs[i].getGroupExpression().eval(null);
                values[i] = AtomicValue.EMPTY_VALUE;
                //TODO : get rid of getLength()
                if(seq.hasOne()) {
                    values[i] = seq.itemAt(0).atomize();
                } else if(seq.hasMany())
                    {throw new XPathException("expected a single value for group by expression " +
                        ExpressionDumper.dump(groupSpecs[i].getGroupExpression())
                        " ; found: " + seq.getItemCount());}
            }
        }
        /* (non-Javadoc)
         * @see java.lang.Comparable#compareTo(java.lang.Object)
         */
        public int compareTo(Entry other){
            int cmp = 0;
            AtomicValue a, b;
            for(int i = 0; i < values.length; i++) {
                a = values[i];
                b = other.values[i];
                if(a == AtomicValue.EMPTY_VALUE && b != AtomicValue.EMPTY_VALUE) {
                        cmp = 1;
               
                else{
                    cmp = a.compareTo(b);
                }
            }
            return cmp;
        }
    }
    
    private class GroupedValueSequenceIterator implements SequenceIterator {
        int pos = 0;
        /* (non-Javadoc)
         * @see org.exist.xquery.value.SequenceIterator#hasNext()
         */
        public boolean hasNext() {
            return pos < count;
        }
        
        /* (non-Javadoc)
         * @see org.exist.xquery.value.SequenceIterator#nextItem()
         */
        public Item nextItem() {
            if(pos < count) {
                return items[pos++].item;
            }
            return null;
        }
    }
}
     
TOP

Related Classes of org.exist.xquery.value.GroupedValueSequence$Entry

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.