alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (StartTag.java)

This example Java source code file (StartTag.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

attribute, containerelement, content, document, illegalargumentexception, illegalstateexception, namespacedecl, namespaceresolver, object, prefix, starttag, string, the

The StartTag.java Java example source code

/*
 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.sun.xml.internal.txw2;

import javax.xml.namespace.QName;


/**
 * Start tag.
 *
 * <p>
 * This object implements {@link NamespaceResolver} for attribute values.
 *
 * @author Kohsuke Kawaguchi
 */
class StartTag extends Content implements NamespaceResolver {
    /**
     * Tag name of the element.
     *
     * <p>
     * This field is also used as a flag to indicate
     * whether the start tag has been written.
     * This field is initially set to non-null, and
     * then reset to null when it's written.
     */
    private String uri;
    // but we keep the local name non-null so that
    // we can diagnose an error
    private final String localName;

    private Attribute firstAtt;
    private Attribute lastAtt;

    /**
     * If this {@link StartTag} has the parent {@link ContainerElement},
     * that value. Otherwise null.
     */
    private ContainerElement owner;

    /**
     * Explicitly given namespace declarations on this element.
     *
     * <p>
     * Additional namespace declarations might be necessary to
     * generate child {@link QName}s and attributes.
     */
    private NamespaceDecl firstNs;
    private NamespaceDecl lastNs;

    final Document document;

    public StartTag(ContainerElement owner, String uri, String localName) {
        this(owner.document,uri,localName);
        this.owner = owner;
    }

    public StartTag(Document document, String uri, String localName) {
        assert uri!=null;
        assert localName!=null;

        this.uri = uri;
        this.localName = localName;
        this.document = document;

        // TODO: think about a better way to maintain namespace decls.
        // this requires at least one NamespaceDecl per start tag,
        // which is rather expensive.
        addNamespaceDecl(uri,null,false);
    }

    public void addAttribute(String nsUri, String localName, Object arg) {
        checkWritable();

        // look for the existing ones
        Attribute a;
        for(a=firstAtt; a!=null; a=a.next) {
            if(a.hasName(nsUri,localName)) {
                break;
            }
        }

        // if not found, declare a new one
        if(a==null) {
            a = new Attribute(nsUri,localName);
            if(lastAtt==null) {
                assert firstAtt==null;
                firstAtt = lastAtt = a;
            } else {
                assert firstAtt!=null;
                lastAtt.next = a;
                lastAtt = a;
            }
            if(nsUri.length()>0)
                addNamespaceDecl(nsUri,null,true);
        }

        document.writeValue(arg,this,a.value);
    }

    /**
     * Declares a new namespace URI on this tag.
     *
     * @param uri
     *      namespace URI to be bound. Can be empty, but must not be null.
     * @param prefix
     *      If non-null and non-empty, this prefix is bound to the URI
     *      on this element. If empty, then the runtime will still try to
     *      use the URI as the default namespace, but it may fail to do so
     *      because of the constraints in the XML.
     *      <p>
     *      If this parameter is null, the runtime will allocate an unique prefix.
     * @param requirePrefix
     *      Used only when the prefix parameter is null. If true, this indicates
     *      that the non-empty prefix must be assigned to this URI. If false,
     *      then this URI might be used as the default namespace.
     *      <p>
     *      Normally you just need to set it to false.
     */
    public NamespaceDecl addNamespaceDecl(String uri, String prefix,boolean requirePrefix) {
        checkWritable();

        if(uri==null)
            throw new IllegalArgumentException();
        if(uri.length()==0) {
            if(requirePrefix)
                throw new IllegalArgumentException("The empty namespace cannot have a non-empty prefix");
            if(prefix!=null && prefix.length()>0)
                throw new IllegalArgumentException("The empty namespace can be only bound to the empty prefix");
            prefix = "";
        }

        // check for the duplicate
        for(NamespaceDecl n=firstNs; n!=null; n=n.next) {
            if(uri.equals(n.uri)) {
                if(prefix==null) {
                    // reuse this binding
                    n.requirePrefix |= requirePrefix;
                    return n;
                }
                if(n.prefix==null) {
                    // reuse this binding
                    n.prefix = prefix;
                    n.requirePrefix |= requirePrefix;
                    return n;
                }
                if(prefix.equals(n.prefix)) {
                    // reuse this binding
                    n.requirePrefix |= requirePrefix;
                    return n;
                }
            }
            if(prefix!=null && n.prefix!=null && n.prefix.equals(prefix))
                throw new IllegalArgumentException(
                    "Prefix '"+prefix+"' is already bound to '"+n.uri+'\'');
        }

        NamespaceDecl ns = new NamespaceDecl(document.assignNewId(),uri,prefix,requirePrefix);
        if(lastNs==null) {
            assert firstNs==null;
            firstNs = lastNs = ns;
        } else {
            assert firstNs!=null;
            lastNs.next = ns;
            lastNs = ns;
        }
        return ns;
    }

    /**
     * Throws an error if the start tag has already been committed.
     */
    private void checkWritable() {
        if(isWritten())
            throw new IllegalStateException(
                "The start tag of "+this.localName+" has already been written. " +
                "If you need out of order writing, see the TypedXmlWriter.block method");
    }

    /**
     * Returns true if this start tag has already been written.
     */
    boolean isWritten() {
        return uri==null;
    }

    /**
     * A {@link StartTag} can be only written after
     * we are sure that all the necessary namespace declarations are given.
     */
    boolean isReadyToCommit() {
        if(owner!=null && owner.isBlocked())
            return false;

        for( Content c=getNext(); c!=null; c=c.getNext() )
            if(c.concludesPendingStartTag())
                return true;

        return false;
    }

    public void written() {
        firstAtt = lastAtt = null;
        uri = null;
        if(owner!=null) {
            assert owner.startTag==this;
            owner.startTag = null;
        }
    }

    boolean concludesPendingStartTag() {
        return true;
    }

    void accept(ContentVisitor visitor) {
        visitor.onStartTag(uri,localName,firstAtt,firstNs);
    }

    public String getPrefix(String nsUri) {
        NamespaceDecl ns = addNamespaceDecl(nsUri,null,false);
        if(ns.prefix!=null)
            // if the prefix has already been declared, use it.
            return ns.prefix;
        return ns.dummyPrefix;
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java StartTag.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.