All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.htmlunit.cyberneko.xerces.util.NamespaceSupport Maven / Gradle / Ivy

/*
 * Copyright (c) 2017-2024 Ronald Brill
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.htmlunit.cyberneko.xerces.util;

import java.util.Objects;

import org.htmlunit.cyberneko.xerces.xni.NamespaceContext;

/**
 * Namespace support for XML document handlers. This class doesn't perform any
 * error checking and assumes that all strings passed as arguments to methods
 * are unique symbols. The SymbolTable class can be used for this purpose.
 *
 * @author Andy Clark, IBM
 */
public class NamespaceSupport implements NamespaceContext {

    /**
     * Namespace binding information. This array is composed of a series of tuples
     * containing the namespace binding information: <prefix, uri>. The
     * default size can be set to anything as long as it is a power of 2 greater
     * than 1.
     *
     * @see #fNamespaceSize_
     * @see #fContext_
     */
    private String[] fNamespace_ = new String[16 * 2];

    /** The top of the namespace information array. */
    private int fNamespaceSize_;

    // NOTE: The constructor depends on the initial context size
    // being at least 1. -Ac

    /**
     * Context indexes. This array contains indexes into the namespace information
     * array. The index at the current context is the start index of declared
     * namespace bindings and runs to the size of the namespace information array.
     *
     * @see #fNamespaceSize_
     */
    private int[] fContext_ = new int[8];

    /** The current context. */
    private int fCurrentContext_;

    /** Default constructor. */
    public NamespaceSupport() {
    }

    /**
     * @see org.htmlunit.cyberneko.xerces.xni.NamespaceContext#reset()
     */
    @Override
    public void reset() {

        // reset namespace and context info
        fNamespaceSize_ = 0;
        fCurrentContext_ = 0;
        fContext_[fCurrentContext_] = fNamespaceSize_;

        ++fCurrentContext_;
    }

    /**
     * @see org.htmlunit.cyberneko.xerces.xni.NamespaceContext#pushContext()
     */
    @Override
    public void pushContext() {

        // extend the array, if necessary
        if (fCurrentContext_ + 1 == fContext_.length) {
            final int[] contextarray = new int[fContext_.length * 2];
            System.arraycopy(fContext_, 0, contextarray, 0, fContext_.length);
            fContext_ = contextarray;
        }

        // push context
        fContext_[++fCurrentContext_] = fNamespaceSize_;
    }

    /**
     * @see org.htmlunit.cyberneko.xerces.xni.NamespaceContext#popContext()
     */
    @Override
    public void popContext() {
        fNamespaceSize_ = fContext_[fCurrentContext_--];
    }

    /**
     * @see org.htmlunit.cyberneko.xerces.xni.NamespaceContext#declarePrefix(String,
     *      String)
     */
    @Override
    public boolean declarePrefix(final String prefix, final String uri) {
        // see if prefix already exists in current context
        for (int i = fNamespaceSize_; i > fContext_[fCurrentContext_]; i -= 2) {
            if (Objects.equals(prefix, fNamespace_[i - 2])) {
                // REVISIT: [Q] Should the new binding override the
                // previously declared binding or should it
                // it be ignored? -Ac
                // NOTE: The SAX2 "NamespaceSupport" helper allows
                // re-bindings with the new binding overwriting
                // the previous binding. -Ac
                fNamespace_[i - 1] = uri;
                return true;
            }
        }

        // resize array, if needed
        if (fNamespaceSize_ == fNamespace_.length) {
            final String[] namespacearray = new String[fNamespaceSize_ * 2];
            System.arraycopy(fNamespace_, 0, namespacearray, 0, fNamespaceSize_);
            fNamespace_ = namespacearray;
        }

        // bind prefix to uri in current context
        fNamespace_[fNamespaceSize_++] = prefix;
        fNamespace_[fNamespaceSize_++] = uri;

        return true;
    }

    /**
     * @see org.htmlunit.cyberneko.xerces.xni.NamespaceContext#getURI(String)
     */
    @Override
    public String getURI(final String prefix) {

        // find prefix in current context
        for (int i = fNamespaceSize_; i > 0; i -= 2) {
            if (Objects.equals(prefix, fNamespace_[i - 2])) {
                return fNamespace_[i - 1];
            }
        }

        // prefix not found
        return null;
    }

    /**
     * @see org.htmlunit.cyberneko.xerces.xni.NamespaceContext#getDeclaredPrefixCount()
     */
    @Override
    public int getDeclaredPrefixCount() {
        return (fNamespaceSize_ - fContext_[fCurrentContext_]) / 2;
    }

    /**
     * @see org.htmlunit.cyberneko.xerces.xni.NamespaceContext#getDeclaredPrefixAt(int)
     */
    @Override
    public String getDeclaredPrefixAt(final int index) {
        return fNamespace_[fContext_[fCurrentContext_] + index * 2];
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy