<commit_before>/*
 *  eXist Open Source Native XML Database
 *  Copyright (C) 2001-04 The eXist Project
 *  http://exist-db.org
 *  
 *  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.dom;

import java.util.Arrays;
import java.util.Iterator;

import org.exist.util.ArrayUtils;
import org.exist.util.FastQSort;
import org.exist.util.Range;
import org.exist.xquery.value.Item;
import org.exist.xquery.value.SequenceIterator;
import org.w3c.dom.Node;

/**
 * A fast node set implementation, based on arrays to store nodes and documents.
 * 
 * The class uses an array to store all nodes belonging to one document. Another sorted
 * array is used to keep track of the document ids. For each document, we maintain an inner
 * class, Part, which stores the array of nodes.
 * 
 * Nodes are just appended to the nodes array. No order is guaranteed and calls to
 * get/contains may fail although a node is present in the array (get/contains
 * do a binary search and thus assume that the set is sorted). Also, duplicates
 * are allowed. If you have to ensure that calls to get/contains return valid
 * results at any time and no duplicates occur, use class
 * {@link org.exist.dom.AVLTreeNodeSet}.
 * 
 * Use this class, if you can either ensure that items are added in order, or
 * no calls to contains/get are required during the creation phase. Only after
 * a call to one of the iterator methods, the set will get sorted and
 * duplicates removed.
 * 
 * @author Wolfgang <<EMAIL>>
 * @since 0.9.3
 */
public class ExtArrayNodeSet extends AbstractNodeSet {

    private final static int INITIAL_DOC_SIZE = 64;
    
    private int documentIds[];
    private Part parts[];
    
    protected int initalSize = 128;
    protected int size = 0;
    
    private int partCount = 0;
    
    private boolean isSorted = false;
    private boolean isInDocumentOrder = false;
    
    protected int lastDoc = -1;
    protected Part lastPart = null;
    
    private int state = 0;

    private DocumentSet cachedDocuments = null;
    
    private DocumentOrderComparator docOrderComparator = new DocumentOrderComparator();
    
    public ExtArrayNodeSet() {
        documentIds = new int[INITIAL_DOC_SIZE];
        parts = new Part[INITIAL_DOC_SIZE];
        Arrays.fill(documentIds, 0);
    }

    public ExtArrayNodeSet(int initialDocsCount, int initialArraySize) {
        initalSize = initialArraySize;
        documentIds = new int[initialDocsCount];
        parts = new Part[initialDocsCount];
        Arrays.fill(documentIds, 0);
    }

    public ExtArrayNodeSet(int initialArraySize) {
        initalSize = initialArraySize;
        documentIds = new int[INITIAL_DOC_SIZE];
        parts = new Part[INITIAL_DOC_SIZE];
        Arrays.fill(documentIds, 0);
    }

    protected Part getPart(DocumentImpl doc, boolean create, int sizeHint) {
        if (doc.docId == lastDoc && lastPart != null)
            return lastPart;
        int idx = ArrayUtils.binarySearch(documentIds, doc.docId, partCount);
        Part part = null;
        if (idx >= 0) {
            part = parts[idx];
        } else if (create) {
            idx = - (idx + 1);
            part = new Part(sizeHint, doc);
            insertPart(doc.docId, part, idx);
        }
        return part;
    }
    
    public boolean containsDoc(DocumentImpl doc) {
        return ArrayUtils.binarySearch(documentIds, doc.docId, partCount) > -1;
    }
    
    private void insertPart(int docId, Part part, int idx) {
        if (partCount == parts.length) {
            int ndocs[] = new int[documentIds.length * 2];
            System.arraycopy(documentIds, 0, ndocs, 0, documentIds.length);
            Arrays.fill(documentIds, -1);
            
            Part nparts[] = new Part[parts.length * 2];
            System.arraycopy(parts, 0, nparts, 0, parts.length);
            
            documentIds = ndocs;
            parts = nparts;
        }
        
        if (idx == partCount) {
            // insert at the end
            documentIds[idx] = docId;
            parts[idx] = part;
        } else {
            // insert at idx
            System.arraycopy(documentIds, idx, documentIds, idx + 1, partCount - idx);
            System.arraycopy(parts, idx, parts, idx + 1, partCount - idx);
            documentIds[idx] = docId;
            parts[idx] = part;
        }
        ++partCount;
    }
    
    public void add(NodeProxy proxy) {
        getPart(proxy.getDocument(), true, initalSize).add(proxy);
        ++size;
        isSorted = false;
        isInDocumentOrder = false;
        setHasChanged();
    }

    /**
     * Add a new node to the set. If a new array of nodes has to be allocated
     * for the document, use the sizeHint parameter to determine the size of
     * the newly allocated array. This will overwrite the default array size.
     * 
     * If the size hint is correct, no further reallocations will be required.
     */
    public void add(NodeProxy proxy, int sizeHint) {
        getPart(proxy.getDocument(), true, sizeHint > -1 ? sizeHint : initalSize).add(
                proxy);
        ++size;
        isSorted = false;
        isInDocumentOrder = false;
        setHasChanged();
    }
<commit_msg>Keep track of the node types added to the node set and overwrite AbstractNodeSet.getItemType().<commit_after>/*
 *  eXist Open Source Native XML Database
 *  Copyright (C) 2001-04 The eXist Project
 *  http://exist-db.org
 *  
 *  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.dom;

import java.util.Arrays;
import java.util.Iterator;

import org.exist.util.ArrayUtils;
import org.exist.util.FastQSort;
import org.exist.util.Range;
import org.exist.xquery.value.Item;
import org.exist.xquery.value.SequenceIterator;
import org.exist.xquery.value.Type;
import org.w3c.dom.Node;

/**
 * A fast node set implementation, based on arrays to store nodes and documents.
 * 
 * The class uses an array to store all nodes belonging to one document. Another sorted
 * array is used to keep track of the document ids. For each document, we maintain an inner
 * class, Part, which stores the array of nodes.
 * 
 * Nodes are just appended to the nodes array. No order is guaranteed and calls to
 * get/contains may fail although a node is present in the array (get/contains
 * do a binary search and thus assume that the set is sorted). Also, duplicates
 * are allowed. If you have to ensure that calls to get/contains return valid
 * results at any time and no duplicates occur, use class
 * {@link org.exist.dom.AVLTreeNodeSet}.
 * 
 * Use this class, if you can either ensure that items are added in order, or
 * no calls to contains/get are required during the creation phase. Only after
 * a call to one of the iterator methods, the set will get sorted and
 * duplicates removed.
 * 
 * @author Wolfgang <<EMAIL>>
 * @since 0.9.3
 */
public class ExtArrayNodeSet extends AbstractNodeSet {

    private final static int INITIAL_DOC_SIZE = 64;
    
    private int documentIds[];
    private Part parts[];
    
    protected int initalSize = 128;
    protected int size = 0;
    
    private int partCount = 0;
    
    private boolean isSorted = false;
    private boolean isInDocumentOrder = false;
    
    protected int lastDoc = -1;
    protected Part lastPart = null;
    
    private int state = 0;

    private DocumentSet cachedDocuments = null;
    
    private DocumentOrderComparator docOrderComparator = new DocumentOrderComparator();
    
    //  used to keep track of the type of added items.
    private int itemType = Type.ANY_TYPE;
    
    public ExtArrayNodeSet() {
        documentIds = new int[INITIAL_DOC_SIZE];
        parts = new Part[INITIAL_DOC_SIZE];
        Arrays.fill(documentIds, 0);
    }

    public ExtArrayNodeSet(int initialDocsCount, int initialArraySize) {
        initalSize = initialArraySize;
        documentIds = new int[initialDocsCount];
        parts = new Part[initialDocsCount];
        Arrays.fill(documentIds, 0);
    }

    public ExtArrayNodeSet(int initialArraySize) {
        initalSize = initialArraySize;
        documentIds = new int[INITIAL_DOC_SIZE];
        parts = new Part[INITIAL_DOC_SIZE];
        Arrays.fill(documentIds, 0);
    }

    protected Part getPart(DocumentImpl doc, boolean create, int sizeHint) {
        if (doc.docId == lastDoc && lastPart != null)
            return lastPart;
        int idx = ArrayUtils.binarySearch(documentIds, doc.docId, partCount);
        Part part = null;
        if (idx >= 0) {
            part = parts[idx];
        } else if (create) {
            idx = - (idx + 1);
            part = new Part(sizeHint, doc);
            insertPart(doc.docId, part, idx);
        }
        return part;
    }
    
    public boolean containsDoc(DocumentImpl doc) {
        return ArrayUtils.binarySearch(documentIds, doc.docId, partCount) > -1;
    }
    
    private void insertPart(int docId, Part part, int idx) {
        if (partCount == parts.length) {
            int ndocs[] = new int[documentIds.length * 2];
            System.arraycopy(documentIds, 0, ndocs, 0, documentIds.length);
            Arrays.fill(documentIds, -1);
            
            Part nparts[] = new Part[parts.length * 2];
            System.arraycopy(parts, 0, nparts, 0, parts.length);
            
            documentIds = ndocs;
            parts = nparts;
        }
        
        if (idx == partCount) {
            // insert at the end
            documentIds[idx] = docId;
            parts[idx] = part;
        } else {
            // insert at idx
            System.arraycopy(documentIds, idx, documentIds, idx + 1, partCount - idx);
            System.arraycopy(parts, idx, parts, idx + 1, partCount - idx);
            documentIds[idx] = docId;
            parts[idx] = part;
        }
        ++partCount;
    }
    
    public void add(NodeProxy proxy) {
        getPart(proxy.getDocument(), true, initalSize).add(proxy);
        ++size;
        isSorted = false;
        isInDocumentOrder = false;
        setHasChanged();
        checkItemType(proxy.getType());
    }

    /**
     * Add a new node to the set. If a new array of nodes has to be allocated
     * for the document, use the sizeHint parameter to determine the size of
     * the newly allocated array. This will overwrite the default array size.
     * 
     * If the size hint is correct, no further reallocations will be required.
     */
    public void add(NodeProxy proxy, int sizeHint) {
        getPart(proxy.getDocument(), true, sizeHint > -1 ? sizeHint : initalSize).add(
                proxy);
        ++size;
        isSorted = false;
        isInDocumentOrder = false;
        setHasChanged();
        checkItemType(proxy.getType());
    }

    private void checkItemType(int type) {
        if(itemType == Type.NODE || itemType == type)
            return;
        if(itemType == Type.ANY_TYPE)
            itemType = type;
        else
            itemType = Type.NODE;
    }
    
    public int getItemType() {
        return itemType;
    }
    
{'fraction_non_alphanumeric': 0.08364774825399374, 'fraction_numerical': 0.007064301196114634, 'mean_word_length': 2.44905869324474, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7044213', 'n_tokens_mistral': 3545, 'n_tokens_neox': 3431, 'n_words': 1286}