Package com.jclark.xsl.tr

Source Code of com.jclark.xsl.tr.AnyLevelNumberAction$Cache

// $Id: AnyLevelNumberAction.java 99 2005-02-28 21:37:53Z blindsey $

package com.jclark.xsl.tr;

import com.jclark.xsl.om.*;
import com.jclark.xsl.conv.NumberListFormat;
import com.jclark.xsl.expr.Pattern;
import com.jclark.xsl.expr.DescendantsOrSelfNodeIterator;
import java.util.Hashtable;

class AnyLevelNumberAction implements Action
{
    private Pattern count;
    private Pattern from;
    private NumberListFormatTemplate formatTemplate;

    AnyLevelNumberAction(Pattern count, Pattern from,
                         NumberListFormatTemplate formatTemplate)
    {
        this.count = count;
        this.from = from;
        this.formatTemplate = formatTemplate;
    }

    static final class Cache
    {
        Cache() {
            nodes = new Node[10];
            used = 0;
        }
        Node[] nodes;
        int[] numbers;
        int used;
        private void append(Node node, int n) {
            if (used == nodes.length) {
                Node[] oldNodes = nodes;
                nodes = new Node[oldNodes.length * 2];
                System.arraycopy(oldNodes, 0, nodes, 0, oldNodes.length);
                if (numbers != null) {
                    int[] oldNumbers = numbers;
                    numbers = new int[oldNumbers.length * 2];
                    System.arraycopy(oldNumbers, 0, numbers, 0, oldNumbers.length);
                }
            }
            nodes[used] = node;
            if (numbers != null) {
                numbers[used] = n;
            } else if (n != used) {
                numbers = new int[nodes.length];
                for (int i = 0; i < used; i++) {
                    numbers[i] = i;
                }
                numbers[used] = n;
            }
            used++;
        }

        private int numberOf(int i) {
            if (numbers == null) {
                return i + 1;
            }
            return numbers[i] + 1;
        }

        int getNumber(Node node) {
            int start = 0;
            int end = used;
            // find last entry before or equal to node
            while (start != end) {
                int mid = (start + end) >> 1;
                int cmp = node.compareTo(nodes[mid]);
                if (cmp == 0) {
                    return numberOf(mid);
                }
                if (cmp < 0) {
                    end = mid;
                } else {
                    start = mid;
                }
            }
            if (start == 0) {
                return 0;
            }
            return numberOf(start - 1);
        }
    }

    public void invoke(ProcessContext context, Node node,
                       Result result) throws XSLException
    {
        NumberListFormat format = formatTemplate.instantiate(context, node);
        Node root = node.getRoot();
        Hashtable documentTable = (Hashtable)context.get(this);
        if (documentTable == null) {
            documentTable = new Hashtable();
            context.put(this, documentTable);
        }
        Cache cache;
        if (count != null) {
            cache = (Cache)documentTable.get(root);
            if (cache == null) {
                cache = new Cache();
                documentTable.put(root, cache);
                int n = 0;
                for (NodeIterator iter =
                         new DescendantsOrSelfNodeIterator(root);;) {
                    Node tem = iter.next();
                    if (tem == null) {
                        break;
                    }
                    if (from != null && from.matches(tem, context)) {
                        n = 0;
                    } else if (count.matches(tem, context)) {
                        cache.append(tem, n++);
                    }
                }
            }
        }
        else if (node.getType() == Node.ELEMENT) {
            Hashtable elementTable = (Hashtable)documentTable.get(root);
            if (elementTable == null) {
                elementTable = new Hashtable();
                documentTable.put(root, elementTable);
            }
            Name name = node.getName();
            cache = (Cache)elementTable.get(name);
            if (cache == null) {
                cache = new Cache();
                elementTable.put(name, cache);
                int n = 0;
                for (NodeIterator iter = new DescendantsOrSelfNodeIterator(root);;) {
                    Node tem = iter.next();
                    if (tem == null)
                        break;
                    if (from != null && from.matches(tem, context))
                        n = 0;
                    else if (name.equals(tem.getName()) && tem.getType() == Node.ELEMENT)
                        cache.append(tem, n++);
                }
            }
        }
        else
            return;
        result.characters(format.getPrefix(0));
        result.characters(format.formatNumber(0, cache.getNumber(node)));
        result.characters(format.getSuffix());
    }
}
TOP

Related Classes of com.jclark.xsl.tr.AnyLevelNumberAction$Cache

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.