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.schema2beans;

import java.util.*;
import java.io.*;
import java.beans.*;

//  To dynamically build an array of the bean clastype (class[] getter method)
import java.lang.reflect.*;

import org.w3c.dom.*;


/**
 *  The BeanProp class is the internal representation of a schema2beans property.
 *  The three main classes that make the schema2beans architecture are: BaseBean,
 *  BeanProp and DOMBinding. BaseBean is the schema2beans java beans that maps
 *  a tag DTD element (BaseBean is the class extended by the generated code,
 *  specific to the DTD names). BaseBean contains as much as BeanProp object
 *  instances as it containes properties (element tags). A BeanProp handle
 *  both single and array properties. A single property is represented
 *  by one BeanProp instance that will be of type 'single' (TYPE_0_1 or TYPE_1).
 *  An array property is represented also by one BeanProp instance, 
 *  but of type 'array' (TYPE_0_N or TYPE_1_N).
 *  
 *  The BeanProp class is handling properties, and is acting between 
 *  the BaseBean (user view) and the DOMBinding (access to the DOM tree).
 *  The events, add/change/remove code and logic is on the BeanProp class.
 */
public class BeanProp implements BaseProperty {
    
    
    //
    //	The goal of the GroupProp class is to provide a common container
    //	for DTD or'd elements. Each or'd element of a same group references
    //	the same GroupProp instance.
    //	For example, (a | b | c) in a DTD generates 3 properties A, B, C. For
    //	each property, a BeanProp is created. One GroupProp is created
    //	for these 3 properties, and each BeanProp reference this GroupProp.
    //
    static class GroupProp {
        ArrayList group;
	
        public GroupProp(BeanProp prop) {
            this.group = new ArrayList();
            this.add(prop);
        }
	
        void add(BeanProp prop) {
            this.group.add(prop);
        }
	
        BeanProp[] list() {
            int size = this.group.size();
            BeanProp[] ret = new BeanProp[size];
            for (int i=0; i 0);
        }
	
        void delay() {
            if (useEvents())
                this.delayed++;
        }
	
        void addEvent(PropertyChangeEvent e, boolean propagate) {
            if (useEvents()) {
                if (this.isDelayed()) {
                    this.events.add(new Evt(e, propagate));
                } else {
                    this.bp.notifyInternal(e, propagate);
                }
            }
        }
	
        void fireEvents() {
            if (useEvents()) {
                if (this.delayed == 0)
                    return;
		
                this.delayed--;
		
                if (this.delayed == 0) {
                    int size = this.events.size();
                    if (size > 0) {
                        for (int i=0; i, then the order
    //	values for the properties b, c and d are: 1, 2 and 3.
    //	If we need to insert the property c, we know that is should
    //	be inserted before the property d, simply looking at its order
    //	number (see the BaseBean.createProperty for comment on the order
    //	value)
    //
    private int				order;
    
    //
    //	If this property is defined as or'd (char |) in the DTD file,
    //	the following GroupProp instance holds references to the other
    //	BeanProp sharing the same or'd definition (a | b | c ...)
    //	The following group reference should be null if the property
    //	is simply defined as an 'and sequence' (a, b, c ...)
    //
    GroupProp		group;
    
    
    public BeanProp(BaseBean bean, String dtdName, String beanName,
		    int type, Class propClass) {
        this(bean, dtdName, beanName, type, propClass, 10);
    }
    
    public BeanProp(BaseBean bean, String dtdName, String beanName,
		    int type, Class propClass, int initialCapacity) {
        //System.out.println("intitialCapacity="+initialCapacity);
	this.dtdName = dtdName;
	this.beanName = beanName;
	this.type = type;
	this.propClass = propClass;
	this.bean = bean;
    if (initialCapacity >= 0) {
        this.bindings = new ArrayList(initialCapacity);
        this.attributes = new ArrayList(initialCapacity);
    }
	this.changeListeners = null;
	this.vetoableListeners = null;
	this.knownValues = null;
	this.isRoot = false;
	this.order = 0;
	this.eventMgr = new EventMgr(this);
	this.group = null;
    }
    
    public BeanProp(BaseBean bean, String dtdName, String beanName,
		    int type, Class propClass, boolean isRoot) {
        this(bean, dtdName, beanName, type, propClass, isRoot, 10);
    }

    public BeanProp(BaseBean bean, String dtdName, String beanName,
		    int type, Class propClass, boolean isRoot, int initialCapacity) {
	this(bean, dtdName, beanName, type, propClass, initialCapacity);
	this.isRoot = isRoot;
    }

    /**
     *	Called by the BaseBean class when the property is fully created.
     *	(no more creation work needs to be done in the BaseBean for this
     *	property.). This is where any extra initialization work should take
     * 	place if this couldn't be done in the constructor.
     */
    public void initialize() {
	//
	//  If the property us or'd with others, group these properties
	//  together. The following assumes that the property are created
	//  through the BaseBean in the DTD order (which is how the GenBeans
	//  works), and also assumes that two sets of or'd properties never
	//  follow each others. (for example: (a | b) (c | d)).
	//
	if (Common.isSequenceOr(this.type)) {
	    //	Try to get the previous reference, else create a new one
	    //	(first element in the list of or'd elements)
	    BeanProp previousProp = null;
	    
	    if (this.order > 1) {
		previousProp = this.bean.beanProp(this.order-1);
	    }
	    
	    if ((previousProp != null) && (previousProp.group != null)) {
		//  The previous property already have one - use it
		previousProp.group.add(this);
		this.group = previousProp.group;
	    }
	    
	    if (this.group == null) {
		this.group = new GroupProp(this);
	    }
	}
    }
    
    boolean useEvents() {
	return handleEvents;
    }
    
    boolean useVetoEvents() {
	return handleVetoEvents;
    }
    
    void setOrder(int order) {
	this.order = order;
    }
    
    public Class getPropClass() {
	return this.propClass;
    }
    
    public int getType() {
	return this.type;
    }
    
    public String getBeanName() {
	return this.beanName;
    }
    
    public BaseBean getBean() {
	return this.bean;
    }
    
    public BaseBean getParent() {
	return this.getBean();
    }

    NodeFactory getNodeFactory() {
	return this.bean.graphManager().getNodeFactory();
    }
    
    Node getParentNode() {
	//  If we are the root, there is no parent node
	if (this.isRoot) {
	    return null;
	}
	
	Node	    n = null;
	DOMBinding  b = this.bean.domBinding();
	
	if (b != null) {
	    n = b.getNode();
	}
	
	if (n == null) {
	    throw new IllegalStateException(Common.getMessage("ParentNodeCantBeNull_msg"));
	} else {
	    return n;
	}
    }
    
    //
    //	This method is called by the DOMBinding class when a DOM object
    //	needs to be inserted into the DOM graph. The goal of this method
    //	is to find out the next property (using the order value of the
    //	BeanProp) that has a DOM node, and if this is an indexed property,
    //	which DOM Node is the first of the list. This method makes sure that
    //	the new elements are inserted in the right property order (as specified
    //	by the DTD)
    //
    Node getFollowingSibling(DOMBinding binding) {
	BeanProp bp = null;
	int	 next = this.order+1;
	
	bp = this.bean.beanProp(next++);
	
    //System.out.println("getFollowingSibling next="+next+" bp="+bp);
	while (bp != null) {
	    boolean	found = false;
	    int 	size = bp.size();
	    
	    //	Find out if there is any DOM Node
	    for (int i=0; i 0) || (this.bindingsSize() == 0))
                return null;
        }
        if (bindingsSize() == 0) {
            // Ok no value set so far. return null.
            return null;
        } // end of if (this.bindingsSize() == 0)

        DOMBinding b = (DOMBinding)this.bindings.get(index);

        if (b != null)
            return b.getValue(this);
        else
            return null;
    }
    
    
    /**
     *	Return the element which as the unique DOMBinding identifier id
     *	(Every DOMBinding has a unique identifier which identifies uniquely
     *	the DOM element referenced by the DOMBinding object. This id is,
     *	for example, used to build the absolute name of an elt of the graph)
     */
    public Object getValueById(int id) {
        int size = this.bindingsSize();
        for (int i=0; i=0 && index=0)?(size+extraElements):size));
	
	//	If we have enough space
		int i=0;
		try {
            if (extraElements >= 0) {
                for (i=0; i= this.bindingsSize() && 
	    Common.isVetoable(this.type) && useVetoEvents()) {

	    DOMBinding b = (DOMBinding)this.bindings.get(index);
	    if (b != null) {
		Object value = b.getValue(this);

		//	Check before doing any change if this is ok
		this.raiseVetoableEvent(value, 0, OP_SETTER_REMOVE);
	    }
	    
	    //	If we reach this point, no exception has been raised,
	    //	and the change can happen.
	}

	this.removeElement(index, true);
    }
    
    //	Common sanity check on the parameters
    private void checkParams(int index, Object value, boolean add) {
	if (add) {
	    if (value == null)
		throw new IllegalArgumentException(Common.
		    getMessage("CannotAddNullValue_msg"));
	}
	else {
	    if (!Common.isArray(this.type)) {
		if (index > 0)
		    throw new IllegalArgumentException(Common.
			getMessage("InvalidIndexForTypeProperty_msg"));
	    }
	    else {
		if ((index < 0) || (index >= this.bindingsSize()))
		    throw new IndexOutOfBoundsException();
	    }
	}
    }
    
    /**
     *	Different cases might happen in this method, depending on the
     *	type of the property, if the property is an array or not,
     *	and also depending on the type of the value parameter.
     *
     *	If the property is a single property, the value replaces the
     *	previous value.
     *
     *	If the property is an indexed value, the operation is not allowed.
     *
     *	If the propery didn't have any value (no DOM node yet), a DOMBinding
     *	is created and takes care of setting the new value.
     *
     */
    protected int setElement(int index, Object value, boolean add) {
	this.checkParams(index, value, add);
	
	if ((value != null) && Common.isBean(this.type)
	    && ((BaseBean)value).hasDomNode()) {
        Document doc1 = null;
        Document doc2 = null;
        DOMBinding domBinding1 = ((BaseBean)value).domBinding();
        DOMBinding domBinding2 = bean.domBinding();
        //System.out.println("domBinding1="+domBinding1);
        //System.out.println("domBinding2="+domBinding2);
        if (domBinding1 != null && domBinding2 != null) {
            Node node1 = domBinding1.getNode();
            Node node2 = domBinding2.getNode();
            //System.out.println("node1="+node1);
            //System.out.println("node2="+node2);
            if (node1 != null && node2 != null) {
                doc1 = node1.getOwnerDocument();
                doc2 = node2.getOwnerDocument();
            }
        }
        //System.out.println("doc1="+doc1);
        //System.out.println("doc2="+doc2);
        //System.out.println("doc1==doc2="+(doc1==doc2));
        if (doc1 != null && doc1 == doc2) {
            //
            //	For now, reject any attempt to insert an element which
            //	is already part of the DOM graph.
            //	We could clone the element automatically, but for now,
            //	we just reject it.
            //
            throw new IllegalArgumentException(Common.
                                               getMessage("CannotInsertElementAlreadyInGraph_msg"));
        }
	}

    /*
	//  If String, store a copy of the string
	if (value instanceof java.lang.String) {
	    
	    //	An empty optional String is equivalement to a null string
	    if (!this.isBean()
	        && ((this.type & Common.MASK_INSTANCE) == Common.TYPE_0_1)
            && value.equals("")) { // NOI18N    
		    
            value = null;
	    } else {
            value = new String((String)value);
	    }
	}
    */
	
	if (DDLogFlags.debug) {
	    TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
	    DDLogFlags.DBG_BLD, 1, DDLogFlags.SETVALUE,
	    this.dtdName + "[" + index + "] - " +
	    (value==null?"null":value.toString()));
	}
	
	//
	//  If the object is null, the setValue call is equivalent to a remove
	//  Otherwise, the object might be a bean or a wrapper object (String,
	//  Boolean, Date, ...)
	//
	//  If the object is a bean, we have to remove first the previous bean.
	//  Then, we affect the new bean to the DOMBinding object.
	//  (See the comment in the delete() operation to see how this
	//  involves the BeanProp and DOMBinding data structure).
	//
	//  If the object is a wrapper, simply call the DomBinding to change
	//  the DOM node value (there is no change in the internal structure).
	//
	
	//  Do not send any event while updating
	this.eventMgr.delay();
	
	if (value != null) {
	    //	Before adding the new value, remove the previous one
	    if (Common.isBean(this.type) && !add)
            this.removeElement(index, false);
	    
	    DOMBinding b = null;
	    boolean empty = true;
	    Object	oldValue = null;
	    
	    if (!add) {
            empty = (this.bindingsSize() == 0);
            if (!empty)
                b = (DOMBinding)this.bindings.get(index);
	    }
	    
	    if (b == null) {
            //
            //  This is a brand new property - create the DOMBinding
            //  for this object. The DOMBinding will take care
            //  later on to create the proper DOM tree structures.
            //
            b = new DOMBinding();
            b.register(this, value);
            b.setDefaultAttributeValues(this);
	    }
	    
	    if (add)
            index = this.bindingsSize();
	    
	    if (empty)
            this.bindings.add(b);
	    else
            this.bindings.set(index, b);
	    
	    if (DDLogFlags.debug) {
            TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
                            DDLogFlags.DBG_BLD, 1, DDLogFlags.NEWBIND,
                            this.dtdName + "[" + (empty?0:index) + "]");
	    }
	    
	    oldValue = b.setValue(this, value);
	    
	    //
	    //	If the parent bean is attached to a DOM Node, this new
	    //	value has to be attached to the DOM Node. Otherwise,
	    //	the new value stays cached in the DOMBinding.
	    //	The algorithm is: if the parent is not anchored to the DOM
	    //	tree, cache the value. If the parent is attached,
	    //	flush into the DOM tree all the cached values.
	    //
	    if (this.bean.hasDomNode()) {
            b.syncNodes(this, new Action(Action.ADD));
	    }
	    else {
            if (DDLogFlags.debug) {
                TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
                                DDLogFlags.DBG_BLD, 1, DDLogFlags.CACHING,
                                this.dtdName);
            }
	    }
	    
	    //
	    //	Now that the setValue is done, ask the DOMBinding to signal
	    //	all the properties bound to this Node (including ourself).
	    //
	    b.notifyBeansForChange(oldValue, value, null);
	    
	    //	Attribute values might have been cached in the bean
	    if (Common.isBean(this.type) && (value != null)) {
            BaseBean bb = (BaseBean)value;
            String[] names = bb.cachedAttributeNames();
            for (int i=0; i= this.bindingsSize()) {
	    // There is nothing here so do nothing.
	    return;
	}
	
	b = (DOMBinding)this.bindings.get(index);
	if (b != null) {
	    Object oldValue = b.getValue(this);
	    b.setLastKnownIndex(this, index);
	    
	    PropertyChangeEvent e = this.createEvent(b, oldValue, null, null);
	    
	    if (DDLogFlags.debug) {
		TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
		DDLogFlags.DBG_EVT, 1, DDLogFlags.CREATEREM,
		(e==null?"no-event":e.getPropertyName()) +
		" - source " + this.beanName +
		"\n\t\toldValue is " +
		(oldValue==null?"":"<"+
		oldValue.toString()+">") +
		"\n\t\tnewValue is null");
	    }
	    
	    if (remove)
		this.bindings.remove(index);
	    else
		this.bindings.set(index, null);
	    
	    //	Remove and notify the subtree included ourself
	    b.syncNodes(this, new Action(Action.REMOVE, e));
	    
	    //	Notify the parents
	    this.notifyInternal(e, true);
	}
    }
    
    //	Return the list of well known values
    public Object[] knownValues() {
	if (this.knownValues == null)
	    return null;
	
	int size = this.knownValues.size();
	Object a = Array.newInstance(this.propClass, size);
	
	for (int i=0; i 0) || (this.bindingsSize() == 0))
		return null;
	}
	
	DOMBinding b = (DOMBinding)this.bindings.get(index);
	
	if (b != null)
	    ret = b.getAttributeValue(this, ap.getDtdName());
	
	if (DDLogFlags.debug) {
	    TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
	    DDLogFlags.DBG_BLD, 10, DDLogFlags.GETATTR,
	    this.beanName + "[" + index + "]." +
	    ap.getDtdName() + ": " + ret + " " +
	    ((b==null)?"":("B("+b.hashCode()+")"))+
	    " BP(" + this.hashCode() + ")");
	}
	
	return ret;
    }
    
    //
    //	Attributes methods
    //
    ///////////////////////
    
    
    
    /**
     *	Called back by the DOMBinding when another bean removed the binding.
     *	This allows an automatic update of all the bean trees sharing the
     *	same DOM nodes.
     */
    void removeBinding(DOMBinding binding) {
	throw new UnsupportedOperationException(Common.
	    getMessage("NotImplementedYet_msg"));
    }
    
    
    /**
     *	Create the DOM Nodes for all the properties previously cached.
     *	(Cached because no beans/values created could be attached
     *	to the real DOM tree: no element was attached to the DOM tree
     *	at the time of their creation - see the setElement() method)
     */
    void syncNodes(Action a) {
	int 		size = this.bindingsSize();
	
	for (int i=0; i":"<"+
	    oldValue.toString()+">") +
	    "\n\t\tnewValue is " +
	    (newValue==null?"":"<"+
	    newValue.toString()+">"));
	}
	return e;
    }
    
    //	Helper method
    void notifyInternal(PropertyChangeEvent e, boolean propagate) {
	this.notifyInternal(new InternalEvent(InternalEvent.CHANGED, e),
	propagate);
    }
    
    //	Mechanism used to propagate an event through the tree up to the root
    void notifyInternal(InternalEvent ie, boolean propagate) {
	if (ie.type == InternalEvent.CHANGED) {
	    if (!useEvents())
		return;
	    
	    if (this.eventMgr.isDelayed()) {
		this.eventMgr.addEvent(ie.getPropertyChangeEvent(), propagate);
		return;
	    }
	    
	    if (DDLogFlags.debug) {
		TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
		DDLogFlags.DBG_EVT, 1, DDLogFlags.NOTIFYCHG,
		ie.getPropertyChangeEvent().getPropertyName()+
		(propagate?"(P)":"") +
		" in " + this.beanName + " - " +
		(this.changeListeners==null?"null listener":
		    (this.changeListeners.hasListeners(null)?
		    "has listeners":"no listener")) );
	    }
	    
	    if (this.changeListeners != null)
		//  Notify the object listening on this property
		this.changeListeners.firePropertyChange(
		    ie.getPropertyChangeEvent());
	}
	else
	    if (ie.type == InternalEvent.VETOABLE) {
		if( !useVetoEvents())
		    return;
		
		if (DDLogFlags.debug) {
		    TraceLogger.put(TraceLogger.DEBUG, TraceLogger.SVC_DD,
		    DDLogFlags.DBG_EVT, 1, DDLogFlags.NOTIFYVETO,
		    ie.getPropertyChangeEvent().getPropertyName()+
		    (propagate?"(P)":"") +
		    " in " + this.beanName + " - " +
		    (this.vetoableListeners==null?"null listener":
			(this.vetoableListeners.hasListeners(null)?
			"has listeners":"no listener")) );
		}
		
		try {
		    if (this.vetoableListeners != null)
			//  Notify the object listening on this property
			this.vetoableListeners.fireVetoableChange(
			    ie.getPropertyChangeEvent());
		}
		catch(PropertyVetoException ve) {
		    //	This has been vetoed, raise our internal runtime exception
		    //	holding this ve. We'll rethrow it later on, from the
		    //	generated beans.
		    throw new BaseProperty.VetoException(ve,
			Common.getMessage("ChangeForPropertyVetoed_msg",
					  this.beanName));
		}
	    }
	
	//  Notify the parent (this will go up to the root)
	if (!this.isRoot && (this.bean != null) && propagate)
	    this.bean.notifyInternal(ie);
    }
    
    private void raiseVetoableEvent(Object value, int index, int op) {
	Object curValue = null;
	Object newValue = null;
	
	//  Get the current and new value
	if (Common.isArray(this.type)) {
	    Object []arrValue;
	    
	    curValue = this.getValues();
	    switch(op) {
		case OP_SETTER_SETARRAY:
		    //	The new value is the new array
		    newValue = value;
		    break;
		case OP_SETTER_SETELT:
		    //	One element only will change
		    arrValue = this.getObjectArray(0);
		    arrValue[index] = value;
		    newValue = arrValue;
		    break;
		case OP_SETTER_ADD:
		    //	Add the new element at the end of the array
		    arrValue = this.getObjectArray(1);
		    arrValue[this.bindingsSize()] = value;
		    newValue = arrValue;
		    break;
		case OP_SETTER_REMOVE:
		    //	One element removed
		    
		    //	This call only allocate the array (no values)
		    int i, j;
		    Object[] curValues = (Object[])curValue;
		    arrValue = this.getObjectArray(-1);
		    
		    for (i=0; i":"<"+
		curValue.toString()+">") +
		"\n\t\tnewValue is " +
		(newValue==null?"":"<"+
		newValue.toString()+">"));
	}
	
	//  Propagate this vetoable event up to the root
	this.notifyInternal(new InternalEvent(InternalEvent.VETOABLE, e),
			    true);
    }
    
    
    /**
     *	Book-keeping of the listeners
     */
    public void addPCListener(PropertyChangeListener l) {
	handleEvents = true;
	if (this.changeListeners == null) {
	    Object obj = (this.bean==null)?(Object)this:(Object)this.bean;
	    this.changeListeners = new PropertyChangeSupport(obj);
	}
	this.changeListeners.addPropertyChangeListener(l);
    }
    
    public void removePCListener(PropertyChangeListener l) {
	if (this.changeListeners != null)
	    this.changeListeners.removePropertyChangeListener(l);
    }
    
    public void addVCListener(VetoableChangeListener l) {
	if (this.checkVetoable(true)) {
	    handleVetoEvents = true;
	    if (this.vetoableListeners == null) {
		Object obj = (this.bean==null)?(Object)this:(Object)this.bean;
		this.vetoableListeners = new VetoableChangeSupport(obj);
	    }
	    this.vetoableListeners.addVetoableChangeListener(l);
	}
    }
    
    public void removeVCListener(VetoableChangeListener l) {
	if (this.checkVetoable(false))
	    this.vetoableListeners.removeVetoableChangeListener(l);
    }
    
    
    //
    //	A property might not support the veto mechanism either because
    //	it has not been generated to support it, or because it is a bean.
    //
    private boolean checkVetoable(boolean raise) {
	if (Common.isVetoable(this.type) || Common.isBean(this.type))
	    return true;
	
	if (raise) {
	    if (!Common.isBean(this.type)) {
		throw new Schema2BeansRuntimeException(Common.
		    getMessage("PropertyDoesntSupportVeto_msg", this.beanName));
	    }
	}
	
	return false;
    }
    
    /**
     *	If the current property is a bean, returns an instance of the bean
     */
    BaseBean newBeanInstance() {
	if (Common.isBean(this.type)) {
	    try {
		Constructor c = null;
		
		try {
		    Class[] cc = new Class[] {int.class};
		    c = this.propClass.getDeclaredConstructor(cc);
		}
		catch(NoSuchMethodException me) {
		    return (BaseBean)this.propClass.newInstance();
		}
		
		//  Do not initialize the default values
		Object[] p =
		    new Object[] {new Integer(Common.NO_DEFAULT_VALUES)};
		
		return (BaseBean)c.newInstance(p);
	    }
	    catch(Exception e) {
		TraceLogger.error(e);
		throw new Schema2BeansRuntimeException(Common.
		    getMessage("CantInstantiateBean_msg", e.getMessage()));
	    }
	}
	return null;
    }
    
    /**
     *	This method is called to associate this bean property to a DOM Node.
     *	When the bean graph is built from the DOM graph, the DOM graph is
     *	parsed while trying to match the element names of the DOM graph
     *	with the property names of the bean graph.
     *
     *	When a match is found between a bean property name and a DOM element
     *	name, this method is called to associate the DOM node to the bean.
     *
     *	The bean property might be a simple String (#PCDATA in DTD) as the
     *	leaf of the bean graph, or a bean object, containing other beans.
     *	(One node of the bean graph). Whatever the case is, there is a DOM Node
     *	that correspond to this property.
     *
     *	Also, the propery might be either a single value property or an
     *	array. In the first case, only one Node of the DOM graph can match
     *	the property (if not, this is fatal error in building the bean graph).
     *	In the second case, this property contains an array referencing the
     *	DOM graph.
     *
     *	Note that the property might be of type: optional, mandatory,
     *	an array possibly empty or an array with at least one element.
     *	The verify() method	might be called to check the consistency of the
     *	type of the property, especially after the bean graph is built or
     *	before a modified bean graph has to be saved.
     *
     *	See also the DOMBinding class comments.
     */
    public DOMBinding registerDomNode(Node node, DOMBinding binding,
				      BaseBean bean) throws Schema2BeansException {
	int 		count = 0;
	int 		size = this.bindingsSize();
	
	//	Check that we don't already know this node
	for (int i=0; i 0) || (this.bindingsSize() == 0))
                return null;
        }
	
        DOMBinding b = (DOMBinding)this.bindings.get(index);
	
        if (b != null) {
            if (attr != null) {
                name.append(":");	// NOI18N
                name.append(attr);
            }
            this.buildPathName(b, name);
        }
        else
            return null;
	
        return name.toString();
    }
    
    public int getInstanceType() {
	return (this.type & Common.MASK_INSTANCE);
    }
    
    public boolean isChoiceProperty() {
	return (this.group != null);
    }
    
    public BaseProperty[] getChoiceProperties() {
	if (this.isChoiceProperty()) {
	    return this.group.list();
	}
	return null;
    }
    
    //	true if the name is either the mangled name or the dtd name
    public boolean hasName(String name) {
	if (name.equals(this.beanName) || name.equals(this.dtdName))
	    return true;
	else
	    return false;
    }

    public boolean isKey() {
	return Common.isKey(this.type);
    }
}


... 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.