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

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.netbeans.modules.schema2beansdev;

import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

import org.netbeans.modules.schema2beans.*;

/**
 * @see GraphNode
 *
 * Roughtly, a GraphLink is used to hold attribute definitions or groupings.
 */
public class GraphLink {
    /*
     *	The element that this link is associated to. This element might
     *	be referenced by more than one GraphLink object.
     */
    GraphNode	element;
    
    /*
     *	Where this object is coming from.
     */
    private GraphLink	parent;
    
    /*
     *	Point to the next link holding information about the element
     *	in the sequence.
     *
     *	For example 
     *
     *	If this link element references a, the sibling references a link
     *	object defining the element b.
     *
     */
    private GraphLink	sibling;
    
    /*
     *	Point to a subnode link defining information about an element
     *	defined in a "one-more level of parenthese".
     *
     *	For example 
     *
     *	If this link element references a, the sibling references a link
     *	object defining the element d and the child link element references
     *	a link defining the element b (this link has itself a sibling link
     *	on a link object defining c). Note that the prop of the child link
     *	element will be: SEQUENCE_OR | INSTANCE_1N.
     *
     */
    private GraphLink	child;

    private transient GraphLink lastChild;  // cache
    
    /*
     *	The prop integers define some properties on the link or element.
     *	The link might either start to define a list of nodes as
     *	a sequence of nodes: a and b and c, or it might define
     *	a list of node choices: a or b or c.
     *
     *	For example      -> sequence
     *	               -> choice
     *
     *
     *	Also, the set of nodes defined by the link might have some
     *	rules as they should be instanciated (as defined by the ?, * and +
     *	DTD characters).
     *
     *	propElement applies to the element of this link (one element of the
     *	DTD represented by a unique GraphNode might have different
     *	property values depending where and how the element is referenced
     *	by other elements).
     *	propChildren applies to the set of children of this GraphLink.
     *
     *	For example, 
     *
     *	The link associated to the element a has the propElement set to the
     *	? value and the propChildren set to the + value.
     */
    int			propElement;
    int			propChildren;

    /**
     * Name of the java bean property (java class attribute) that we're
     * defining.  If it's null, then we're used for grouping.
     */
    String name;
    private String schemaName = null;
    private String namespace = null;
    private String defaultValue;
    private boolean nillable;
    
    private Object			object;

    List extraData = new ArrayList();

    GraphLink(String name) {
        //  Those are the default values
        this.propElement = Common.SEQUENCE_AND | Common.TYPE_1;
        this.propChildren = Common.SEQUENCE_AND | Common.TYPE_1;
        this.name = name;
        this.schemaName = name;
    }

    GraphLink(String name, String namespace) {
        //  Those are the default values
        this.propElement = Common.SEQUENCE_AND | Common.TYPE_1;
        this.propChildren = Common.SEQUENCE_AND | Common.TYPE_1;
        this.name = name;
        this.namespace = namespace;
        this.schemaName = name;
    }

    public String getNamespace() {
        return namespace;
    }

    public List getChildren() {	// List
        List result = new ArrayList();
        for (GraphLink l = child; l != null; l = l.sibling)
            result.add(l);
        return result;
    }

    /**
     * Return our parents children minus this.
     */
    public List getSiblings() {	// List
        List result = new ArrayList();
        if (parent == null) {
            // The graph isn't well connected, assume I'm first child.
            for (GraphLink l = this; l != null; l = l.sibling)
                result.add(l);
            return result;
        }
        for (GraphLink l = parent.child; l != null; l = l.sibling) {
            if (l == this)
                continue;
            result.add(l);
        }
        return result;
    }

    /**
     * Return our parents children.
     */
    public List getSiblingsAndMe() {	// List
        if (parent == null) {
            // The graph isn't well connected, assume I'm first child.
            List result = new ArrayList();
            for (GraphLink l = this; l != null; l = l.sibling)
                result.add(l);
            return result;
        }
        return parent.getChildren();
    }

    /**
     * Get next sibling.  This might return null.
     */
    public GraphLink getSibling() {
        return sibling;
    }

    public GraphLink getLastSibling() {
        // Check if our parent has kept track of it.
        if (parent != null && parent.lastChild != null)
            return parent.getLastChild();
        if (sibling == null)
            return this;
        else
            return sibling.getLastSibling();
    }

    /**
     * This might return null.
     */
    public GraphLink getFirstChild() {
        return child;
    }

    /**
     * This might return null.
     */
    public GraphLink getLastChild() {
        if (lastChild == null) {
            if (child != null)
                lastChild = child.getLastSibling();
        }
        return lastChild;
    }

    /**
     * Replaces child list.
     */
    public void setChild(GraphLink l) {
        child = l;
        child.parent = this;
        lastChild = null;
    }

    private void addSibling(GraphLink l) {
        if (sibling != null)
            throw new RuntimeException("I am not the last sibling!");
        sibling = l;
        // Siblings share the same parent
        l.parent = parent;
        if (parent != null)
            parent.lastChild = l;
    }

    /**
     * Adds child to end of child list.
     */
    public void addChild(GraphLink l) {
        if (child == null)
            setChild(l);
        else
            child.getLastSibling().addSibling(l);
    }
    
    /**
     * This might return null.
     */
    public GraphLink getParent() {
        return parent;
    }

    private void setParent(GraphLink l) {
        parent = l;
    }

    boolean isSequenceAnd() {
	//  Apply only to the set of children
	return ((this.propChildren & Common.SEQUENCE_AND) ==
	    Common.SEQUENCE_AND);
    }
    
    boolean isSequenceOr() {
	//  Apply only to the set of children
	return ((this.propChildren & Common.SEQUENCE_OR) ==
	    Common.SEQUENCE_OR);
    }
    
    void setSequence(int prop) {
	this.propChildren = (this.propChildren & Common.MASK_TYPE) | prop;
    }
    
    void setElementInstance(int instance) {
	this.propElement =
	    (this.propElement & Common.MASK_SEQUENCE) | instance;
    }
    
    int getElementInstance() {
	return (this.propElement & Common.MASK_INSTANCE);
    }
    
    void setGroupInstance(int instance) {
        this.propChildren =
            (this.propChildren & Common.MASK_SEQUENCE) | instance;
    }
    
    int getGroupInstance() {
        return (this.propChildren & Common.MASK_INSTANCE);
    }

    /**
     * Fill links with GraphLink's that we're mutually exclusive with.
     */
    public void getMutuallyExclusiveLinks(List links) {	// List
        if (parent == null)
            return;
        //
        // Mutual exclusion is caused by xsd:choice or '|': (a|b|c)
        // From b's perspective, it's mutually exclusive with a and c.
        // From a's perspective, it's mutually exclusive with b and c, etc.
        // However, if the groupInstance can be more than 1, then
        // we're not mutually exclusive: (a|b|c)*
        //
        if (parent.isSequenceOr() &&
            (parent.getGroupInstance() == Common.TYPE_1 ||
             parent.getGroupInstance() == Common.TYPE_0_1)) {
            for (Iterator it = getSiblings().iterator(); it.hasNext(); ) {
                GraphLink l = (GraphLink) it.next();
                l.findAllBelowBranch(links);
            }
        }
        parent.getMutuallyExclusiveLinks(links);
    }

    /**
     * Starting from this GraphLink, fill in all links below it, including
     * this one.
     */
    public void findAllBelowBranch(List links) { // List
        links.add(this);
        if (child != null)
            child.findAllBelowBranchAndSiblings(links);
    }

    public void findAllBelowBranchAndSiblings(List links) { // List
        GraphLink l = this;
        for (; l != null; l = l.sibling) {
            links.add(l);
            if (l.child != null)
                l.child.findAllBelowBranchAndSiblings(links);
        }
    }
    
    String getDefaultValue() {
        return defaultValue;
    }

    void setDefaultValue(String d) {
        defaultValue = d;
    }

    void setObject(Object obj) {
        this.object = obj;
    }
    
    Object getObject() {
        return this.object;
    }

    boolean isNillable() {
        return nillable;
    }

    void setNillable(boolean value) {
        nillable = value;
    }

    String getSchemaName() {
        return schemaName;
    }
    
    public XPathIterator xPathIterator(String xpath) {
        return new XPathIterator(this, xpath);
    }

    public static class XPathIterator implements java.util.Iterator {
        private String xpath;
        private String step;
        private GraphLink curLink;
        private int position;
        
        public XPathIterator(GraphLink startingLink, String xpath) {
            this.xpath = xpath;
            curLink = startingLink;
            findNextStep();
        }

        // Figure out the next step, and advance the state.
        private void findNextStep() {
            if (position >= xpath.length()) {
                step = null;
                return;
            }
            int startingPos = position;
            for (; position < xpath.length(); ++position) {
                if (xpath.charAt(position) == '/') {
                    step = xpath.substring(startingPos, position);
                    ++position;
                    if (".".equals(step)) {
                        // skip over intermediate '.'s
                        startingPos = position;
                    } else {
                        return;
                    }
                }
            }
            step = xpath.substring(startingPos, position);
            if (startingPos > 0 && ".".equals(step)) {
                step = null;
            }
        }

        public boolean hasNext() {
            if (step == null)
                return false;
            return true;
        }

        /**
         * Returns GraphLink's
         */
        public Object next() {
            if (step == null)
                throw new java.util.NoSuchElementException();
            GraphLink result = curLink;
            while (".".equals(step)) {
                findNextStep();
                if (step == null)
                    return result;
            }
            // Don't deal with namespaces
            int colonPos = step.indexOf(':');
            if (colonPos >= 0)
                step = step.substring(colonPos+1, step.length());
            //System.out.println("step="+step);
            // Now go look for step
            result = result.lookForChild(step);
            if (result == null) {
                // Not found.
                step = null;
                position = xpath.length();
                return null;
            }
            if (result.element == null) {
                curLink = null;
            } else {
                curLink = result.element.getGraphLink();
            }

            findNextStep();
            return result;
        }

        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    /**
     * Look amongst out children to see if we have one where
     * searchName.equals(getSchemaName())
     */
    GraphLink lookForChild(String searchName) {
        /*
        System.out.println("this="+this);
        System.out.println("this.element="+this.element);
        System.out.println("this.schemaName="+this.getSchemaName());
        System.out.println("this.sibling="+this.sibling);
        System.out.println("this.child="+this.child);
        */
        
        if (searchName.equals(getSchemaName()))
            return this;
        if (name == null) {
            //System.out.println("Grouping");
            if (child != null) {
                GraphLink childResult = child.lookForChild(searchName);
                if (childResult != null)
                    return childResult;
            }
        }
        if (sibling != null)
            return sibling.lookForChild(searchName);
        if (child != null)
            return child.lookForChild(searchName);
        return null;
    }
}
... 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.