nddelima    2004/10/21 14:51:05

  Modified:    java/src/org/apache/xerces/dom CoreDocumentImpl.java
                        LCount.java DocumentImpl.java
                        CharacterDataImpl.java
  Log:
  Patch that fixes some DOM Level 2 events problems such as:
  - Dispatching of events to a subtree was being stopped from reaching descendants 
when a higher node in the tree did not have a registered listener.
  - Sibling of the target node and its descendants were receiving events during 
dispatch to the target node's subtree.
  - During replaceData, only one event to mark the replacement rather than two for 
insert and delete is fired.
  - DOMAttrModified was not being fired when the text node child of an attribute was 
modified.
  - Adds a total field to LCount to tell whether any listeners are registered rather 
than checking captures + bubbles + default
  
  Thanks to Nalea for her contribution [1].
  
  [1] http://nagoya.apache.org/eyebrowse/[EMAIL PROTECTED]&msgNo=4662
  
  Revision  Changes    Path
  1.81      +17 -4     xml-xerces/java/src/org/apache/xerces/dom/CoreDocumentImpl.java
  
  Index: CoreDocumentImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/CoreDocumentImpl.java,v
  retrieving revision 1.80
  retrieving revision 1.81
  diff -u -r1.80 -r1.81
  --- CoreDocumentImpl.java     5 Oct 2004 17:12:50 -0000       1.80
  +++ CoreDocumentImpl.java     21 Oct 2004 21:51:05 -0000      1.81
  @@ -2599,15 +2599,15 @@
       }
   
       /**
  -     * A method to be called when a character data node has been modified
  +     * A method to be called when a character data node is about to be modified
        */
  -    void modifyingCharacterData(NodeImpl node) {
  +    void modifyingCharacterData(NodeImpl node, boolean replace) {
       }
   
       /**
        * A method to be called when a character data node has been modified
        */
  -    void modifiedCharacterData(NodeImpl node, String oldvalue, String value) {
  +    void modifiedCharacterData(NodeImpl node, String oldvalue, String value, 
boolean replace) {
       }
   
       /**
  @@ -2646,6 +2646,19 @@
       void replacedNode(NodeImpl node) {
       }
   
  +    /**
  +     * A method to be called when a character data node is about to be replaced
  +     */
  +    void replacingData(NodeImpl node) {
  +    }
  +
  +    /**
  +     *  method to be called when a character data node has been replaced.
  +     */
  +    void replacedCharacterData(NodeImpl node, String oldvalue, String value) {
  +    }
  +
  +    
       /**
        * A method to be called when an attribute value has been modified
        */
  
  
  
  1.9       +2 -7      xml-xerces/java/src/org/apache/xerces/dom/LCount.java
  
  Index: LCount.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/LCount.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- LCount.java       5 Oct 2004 17:12:51 -0000       1.8
  +++ LCount.java       21 Oct 2004 21:51:05 -0000      1.9
  @@ -26,11 +26,6 @@
       Move it when we have a chance to do so. Sorry; we were
       rushed.
       
  -    ***** Also, I'm currently asking "are there any listeners"
  -    by testing captures+bubbles+defaults =? 0. It would probably
  -    make sense to have a separate "total" field, calculated at
  -    add/remove, to save a few cycles during dispatch. Fix.
  -    
       ???? CONCERN: Hashtables are known to be "overserialized" in
       current versions of Java. That may impact performance.
       
  @@ -47,7 +42,7 @@
   class LCount 
   { 
       static java.util.Hashtable lCounts=new java.util.Hashtable();
  -    public int captures=0,bubbles=0,defaults=0;
  +    public int captures=0,bubbles=0,defaults, total=0;
   
       static LCount lookup(String evtName)
       {
  
  
  
  1.82      +105 -48   xml-xerces/java/src/org/apache/xerces/dom/DocumentImpl.java
  
  Index: DocumentImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xerces/java/src/org/apache/xerces/dom/DocumentImpl.java,v
  retrieving revision 1.81
  retrieving revision 1.82
  diff -u -r1.81 -r1.82
  --- DocumentImpl.java 5 Oct 2004 17:12:50 -0000       1.81
  +++ DocumentImpl.java 21 Oct 2004 21:51:05 -0000      1.82
  @@ -517,7 +517,7 @@
           // a listener to dispatch to
           if (type == null || type.equals("") || listener == null)
               return;
  -
  +      
           // Each listener may be registered only once per type per phase.
           // Simplest way to code that is to zap the previous entry, if any.
           removeEventListener(node, type, listener, useCapture);
  @@ -531,10 +531,14 @@
            
           // Record active listener
           LCount lc = LCount.lookup(type);
  -        if (useCapture)
  +        if (useCapture) {
               ++lc.captures;
  -        else
  +            ++lc.total;
  +        }
  +        else {
               ++lc.bubbles;
  +            ++lc.total;
  +        }
   
       } // addEventListener(NodeImpl,String,EventListener,boolean) :void
        
  @@ -574,10 +578,14 @@
   
                   // Remove active listener
                   LCount lc = LCount.lookup(type);
  -                if (useCapture)
  +                if (useCapture) {
                       --lc.captures;
  -                else
  +                    --lc.total;
  +                }
  +                else {
                       --lc.bubbles;
  +                    --lc.total;
  +                }
   
                   break;  // Found it; no need to loop farther.
               }
  @@ -658,7 +666,7 @@
           
           // If nobody is listening for this event, discard immediately
           LCount lc = LCount.lookup(evt.getType());
  -        if (lc.captures + lc.bubbles + lc.defaults == 0)
  +        if (lc.total == 0)
               return evt.preventDefault;
   
           // INITIALIZE THE EVENT'S DISPATCH STATUS
  @@ -720,6 +728,7 @@
               }
           }
           
  +        
           // Both AT_TARGET and BUBBLE use non-capturing listeners.
           if (lc.bubbles > 0) {
               // AT_TARGET PHASE: Event is dispatched to NON-CAPTURING listeners
  @@ -802,32 +811,52 @@
        * are dispatched to an entire subtree. This is the distribution code
        * therefor. They DO NOT bubble, thanks be, but may be captured.
        * <p>
  +     * Similar to code in dispatchingEventToSubtree however this method
  +     * is only used on the target node and does not start a dispatching chain
  +     * on the sibling of the target node as this is not part of the subtree 
        * ***** At the moment I'm being sloppy and using the normal
        * capture dispatcher on every node. This could be optimized hugely
        * by writing a capture engine that tracks our position in the tree to
        * update the capture chain without repeated chases up to root.
  -     * @param node node to dispatch to
  -     * @param n node which was directly inserted or removed
  +     * @param n target node (that was directly inserted or removed)
        * @param e event to be sent to that node and its subtree
        */
  -    protected void dispatchEventToSubtree(NodeImpl node, Node n, Event e) {
  -        Vector nodeListeners = getEventListeners(node);
  -        if (nodeListeners == null || n == null)
  -            return;
  -
  -        // ***** Recursive implementation. This is excessively expensive,
  -        // and should be replaced in conjunction with optimization
  -        // mentioned above.
  +    protected void dispatchEventToSubtree(Node n, Event e) {
  +        
           ((NodeImpl) n).dispatchEvent(e);
           if (n.getNodeType() == Node.ELEMENT_NODE) {
               NamedNodeMap a = n.getAttributes();
               for (int i = a.getLength() - 1; i >= 0; --i)
  -                dispatchEventToSubtree(node, a.item(i), e);
  +                dispatchingEventToSubtree(a.item(i), e);
           }
  -        dispatchEventToSubtree(node, n.getFirstChild(), e);
  -        dispatchEventToSubtree(node, n.getNextSibling(), e);
  +        dispatchingEventToSubtree(n.getFirstChild(), e);
  +        
       } // dispatchEventToSubtree(NodeImpl,Node,Event) :void
   
  +
  +    /**
  +     * Dispatches event to the target node's descendents recursively
  +     * 
  +     * @param n node to dispatch to
  +     * @param e event to be sent to that node and its subtree
  +     */
  +    protected void dispatchingEventToSubtree(Node n, Event e) {
  +     if (n==null) 
  +             return;
  +     
  +     // ***** Recursive implementation. This is excessively expensive,
  +        // and should be replaced in conjunction with optimization
  +        // mentioned above.
  +     ((NodeImpl) n).dispatchEvent(e);
  +        if (n.getNodeType() == Node.ELEMENT_NODE) {
  +            NamedNodeMap a = n.getAttributes();
  +            for (int i = a.getLength() - 1; i >= 0; --i)
  +                dispatchingEventToSubtree(a.item(i), e);
  +        }
  +        dispatchingEventToSubtree(n.getFirstChild(), e);   
  +        dispatchingEventToSubtree(n.getNextSibling(), e);
  +    }
  +    
       /**
        * NON-DOM INTERNAL: Return object for getEnclosingAttr. Carries
        * (two values, the Attr node affected (if any) and its previous 
  @@ -889,7 +918,7 @@
           if (enclosingAttr != null) {
               LCount lc = LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
               owner = (NodeImpl) enclosingAttr.getOwnerElement();
  -            if (lc.captures + lc.bubbles + lc.defaults > 0) {
  +            if (lc.total > 0) {
                   if (owner != null) {
                       MutationEventImpl me =  new MutationEventImpl();
                       me.initMutationEvent(MutationEventImpl.DOM_ATTR_MODIFIED,
  @@ -907,7 +936,7 @@
           // "This event is dispatched after all other events caused by the
           // mutation have been fired."
           LCount lc = LCount.lookup(MutationEventImpl.DOM_SUBTREE_MODIFIED);
  -        if (lc.captures + lc.bubbles + lc.defaults > 0) {
  +        if (lc.total > 0) {
               MutationEvent me =  new MutationEventImpl();
               me.initMutationEvent(MutationEventImpl.DOM_SUBTREE_MODIFIED,
                                    true, false, null, null,
  @@ -940,7 +969,7 @@
           // was requested, we need to preserve its previous value for
           // that event.
           LCount lc = LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
  -        if (lc.captures + lc.bubbles + lc.defaults > 0) {
  +        if (lc.total > 0) {
               NodeImpl eventAncestor = node;
               while (true) {
                   if (eventAncestor == null)
  @@ -955,6 +984,8 @@
                   }
                   else if (type == Node.ENTITY_REFERENCE_NODE)
                       eventAncestor = eventAncestor.parentNode();
  +                else if (type == Node.TEXT_NODE)
  +                    eventAncestor = eventAncestor.parentNode();
                   else
                       return;
                   // Any other parent means we're not in an Attr
  @@ -965,34 +996,51 @@
       /**
        * A method to be called when a character data node has been modified
        */
  -    void modifyingCharacterData(NodeImpl node) {
  +    void modifyingCharacterData(NodeImpl node, boolean replace) {
           if (mutationEvents) {
  -            saveEnclosingAttr(node);
  +             if (!replace) {
  +                     saveEnclosingAttr(node);
  +             }
           }
       }
   
       /**
        * A method to be called when a character data node has been modified
        */
  -    void modifiedCharacterData(NodeImpl node, String oldvalue, String value) {
  +    void modifiedCharacterData(NodeImpl node, String oldvalue, String value, 
boolean replace) {
           if (mutationEvents) {
  -            // MUTATION POST-EVENTS:
  -            LCount lc =
  -                LCount.lookup(MutationEventImpl.DOM_CHARACTER_DATA_MODIFIED);
  -            if (lc.captures + lc.bubbles + lc.defaults > 0) {
  -                MutationEvent me = new MutationEventImpl();
  -                me.initMutationEvent(
  -                                 MutationEventImpl.DOM_CHARACTER_DATA_MODIFIED,
  -                                     true, false, null,
  -                                     oldvalue, value, null, (short) 0);
  -                dispatchEvent(node, me);
  -            }
  +             if (!replace) {
  +                     // MUTATION POST-EVENTS:
  +                     LCount lc =
  +                             
LCount.lookup(MutationEventImpl.DOM_CHARACTER_DATA_MODIFIED);
  +                     if (lc.total > 0) {
  +                             MutationEvent me = new MutationEventImpl();
  +                             me.initMutationEvent(
  +                                     MutationEventImpl.DOM_CHARACTER_DATA_MODIFIED,
  +                                             true, false, null,
  +                                                                             
oldvalue, value, null, (short) 0);
  +                             dispatchEvent(node, me);
  +                     }
               
  -            // Subroutine: Transmit DOMAttrModified and DOMSubtreeModified,
  -            // if required. (Common to most kinds of mutation)
  -            dispatchAggregateEvents(node, savedEnclosingAttr);
  -        } // End mutation postprocessing
  +                     // Subroutine: Transmit DOMAttrModified and DOMSubtreeModified,
  +                     // if required. (Common to most kinds of mutation)
  +                     dispatchAggregateEvents(node, savedEnclosingAttr);
  +             } // End mutation postprocessing
  +        }
  +    }
  +    
  +    /**
  +     * A method to be called when a character data node has been replaced
  +     */
  +    void replacedCharacterData(NodeImpl node, String oldvalue, String value) {
  +     //now that we have finished replacing data, we need to perform the same actions
  +     //that are required after a character data node has been modified
  +     //send the value of false for replace parameter so that mutation
  +     //events if appropriate will be initiated
  +     modifiedCharacterData(node, oldvalue, value, false);
       }
  +    
  +    
   
       /**
        * A method to be called when a node is about to be inserted in the tree.
  @@ -1014,7 +1062,7 @@
               // "Local" events (non-aggregated)
               // New child is told it was inserted, and where
               LCount lc = LCount.lookup(MutationEventImpl.DOM_NODE_INSERTED);
  -            if (lc.captures + lc.bubbles + lc.defaults > 0) {
  +            if (lc.total > 0) {
                   MutationEventImpl me = new MutationEventImpl();
                   me.initMutationEvent(MutationEventImpl.DOM_NODE_INSERTED,
                                        true, false, node,
  @@ -1026,7 +1074,7 @@
               // to the Doc.
               lc = LCount.lookup(
                               MutationEventImpl.DOM_NODE_INSERTED_INTO_DOCUMENT);
  -            if (lc.captures + lc.bubbles + lc.defaults > 0) {
  +            if (lc.total > 0) {
                   NodeImpl eventAncestor = node;
                   if (savedEnclosingAttr != null)
                       eventAncestor = (NodeImpl)
  @@ -1050,7 +1098,7 @@
                                                .DOM_NODE_INSERTED_INTO_DOCUMENT,
                                                false,false,null,null,
                                                null,null,(short)0);
  -                        dispatchEventToSubtree(node, newInternal, me);
  +                        dispatchEventToSubtree(newInternal, me);
                       }
                   }
               }
  @@ -1102,7 +1150,7 @@
               }
               // Child is told that it is about to be removed
               LCount lc = LCount.lookup(MutationEventImpl.DOM_NODE_REMOVED);
  -            if (lc.captures + lc.bubbles + lc.defaults > 0) {
  +            if (lc.total > 0) {
                   MutationEventImpl me= new MutationEventImpl();
                   me.initMutationEvent(MutationEventImpl.DOM_NODE_REMOVED,
                                        true, false, node, null,
  @@ -1114,7 +1162,7 @@
               // losing that status
               lc = LCount.lookup(
                                MutationEventImpl.DOM_NODE_REMOVED_FROM_DOCUMENT);
  -            if (lc.captures + lc.bubbles + lc.defaults > 0) {
  +            if (lc.total > 0) {
                   NodeImpl eventAncestor = this;
                   if(savedEnclosingAttr != null)
                       eventAncestor = (NodeImpl)
  @@ -1130,7 +1178,7 @@
                                 MutationEventImpl.DOM_NODE_REMOVED_FROM_DOCUMENT,
                                                false, false, null,
                                                null, null, null, (short) 0);
  -                        dispatchEventToSubtree(node, oldChild, me);
  +                        dispatchEventToSubtree(oldChild, me);
                       }
                   }
               }
  @@ -1159,6 +1207,15 @@
               saveEnclosingAttr(node);
           }
       }
  +    
  +    /**
  +     * A method to be called when character data is about to be replaced in the 
tree.
  +     */
  +    void replacingData (NodeImpl node) {
  +     if (mutationEvents) {
  +                     saveEnclosingAttr(node);
  +     }
  +    }
   
       /**
        * A method to be called when a node has been replaced in the tree.
  @@ -1209,7 +1266,7 @@
            // If we have to send DOMAttrModified (determined earlier),
               // do so.
               LCount lc = LCount.lookup(MutationEventImpl.DOM_ATTR_MODIFIED);
  -            if (lc.captures + lc.bubbles + lc.defaults > 0) {
  +            if (lc.total > 0) {
                   MutationEventImpl me= new MutationEventImpl();
                   me.initMutationEvent(MutationEventImpl.DOM_ATTR_MODIFIED,
                                        true, false, attr,
  
  
  
  1.23      +111 -54   xml-xerces/java/src/org/apache/xerces/dom/CharacterDataImpl.java
  
  Index: CharacterDataImpl.java
  ===================================================================
  RCS file: 
/home/cvs/xml-xerces/java/src/org/apache/xerces/dom/CharacterDataImpl.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- CharacterDataImpl.java    5 Oct 2004 17:12:50 -0000       1.22
  +++ CharacterDataImpl.java    21 Oct 2004 21:51:05 -0000      1.23
  @@ -90,6 +90,13 @@
           return data;
       }
   
  +   /** Convenience wrapper for calling setNodeValueInternal when 
  +     * we are not performing a replacement operation  
  +     */
  +    protected void setNodeValueInternal (String value) {
  +     setNodeValueInternal(value, false);
  +    }
  +    
       /** This function added so that we can distinguish whether
        *  setNodeValue has been called from some other DOM functions.
        *  or by the client.<p>
  @@ -97,7 +104,7 @@
        *  from the high-level functions in CharacterData, and another
        *  type if the client simply calls setNodeValue(value).
        */
  -    protected void setNodeValueInternal(String value) {
  +    protected void setNodeValueInternal(String value, boolean replace) {
        if (isReadOnly()) {
               String msg = 
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, 
"NO_MODIFICATION_ALLOWED_ERR", null);
               throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
  @@ -114,12 +121,12 @@
           CoreDocumentImpl ownerDocument = ownerDocument();
   
           // notify document
  -        ownerDocument.modifyingCharacterData(this);
  +        ownerDocument.modifyingCharacterData(this, replace);
   
        this.data = value;
   
           // notify document
  -        ownerDocument.modifiedCharacterData(this, oldvalue, value);
  +        ownerDocument.modifiedCharacterData(this, oldvalue, value, replace);
       }
   
       /**
  @@ -203,38 +210,54 @@
        */
       public void deleteData(int offset, int count) 
           throws DOMException {
  +     
  +     internalDeleteData(offset, count, false);
  +    } // deleteData(int,int)
   
  +    
  +    /** NON-DOM INTERNAL: Within DOM actions, we sometimes need to be able
  +     * to control which mutation events are spawned. This version of the
  +     * deleteData operation allows us to do so. It is not intended
  +     * for use by application programs.
  +     */
  +    void internalDeleteData (int offset, int count, boolean replace)
  +     throws DOMException {
  +     
        if (isReadOnly()) {
  -            String msg = 
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, 
"NO_MODIFICATION_ALLOWED_ERR", null);
  -            throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
  -        }
  +             String msg = 
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, 
"NO_MODIFICATION_ALLOWED_ERR", null);
  +             throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
  +     }
  +
  +     if (count < 0) {
  +             String msg = 
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", 
null);
  +             throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
  +     }
  +
  +     if (needsSyncData()) {
  +             synchronizeData();
  +     }
  +     int tailLength = Math.max(data.length() - count - offset, 0);
  +     try {
  +             String value = data.substring(0, offset) +
  +             (tailLength > 0
  +                             ? data.substring(offset + count, offset + count + 
tailLength) 
  +                             : "");
   
  -        if (count < 0) {
  -            String msg = 
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", 
null);
  -            throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
  -        }
  +        
  +             setNodeValueInternal(value, replace);      
   
  -        if (needsSyncData()) {
  -            synchronizeData();
  -        }
  -        int tailLength = Math.max(data.length() - count - offset, 0);
  -        try {
  -            String value = data.substring(0, offset) +
  -                (tailLength > 0
  -                 ? data.substring(offset + count, offset + count + tailLength) 
  -                 : "");
  -
  -            setNodeValueInternal(value);
  -
  -            // notify document
  -            ownerDocument().deletedText(this, offset, count);
  -        }
  -        catch (StringIndexOutOfBoundsException e) {
  -            String msg = 
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", 
null);
  -            throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
  -        }
  +             // notify document
  +             ownerDocument().deletedText(this, offset, count);
  +     }
  +     catch (StringIndexOutOfBoundsException e) {
  +             String msg = 
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", 
null);
  +             throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
  +     }
  +     
  +    } // internalDeleteData(int,int,boolean)
  +     
   
  -    } // deleteData(int,int)
  +    
   
       /**
        * Insert additional characters into the data stored in this node,
  @@ -248,30 +271,47 @@
       public void insertData(int offset, String data) 
           throws DOMException {
   
  -        if (isReadOnly()) {
  -            String msg = 
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, 
"NO_MODIFICATION_ALLOWED_ERR", null);
  -            throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
  -        }
  +     internalInsertData(offset, data, false);
  +        
  +    } // insertData(int,int)
  +    
  +    
  +    
  +    /** NON-DOM INTERNAL: Within DOM actions, we sometimes need to be able
  +     * to control which mutation events are spawned. This version of the
  +     * insertData operation allows us to do so. It is not intended
  +     * for use by application programs.
  +     */
  +    void internalInsertData (int offset, String data, boolean replace)
  +     throws DOMException {
  +     
  +     if (isReadOnly()) {
  +             String msg = 
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, 
"NO_MODIFICATION_ALLOWED_ERR", null);
  +             throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
  +     }
  +
  +     if (needsSyncData()) {
  +             synchronizeData();
  +     }
  +     try {
  +             String value =
  +                     new StringBuffer(this.data).insert(offset, data).toString();
   
  -        if (needsSyncData()) {
  -            synchronizeData();
  -        }
  -        try {
  -            String value =
  -                new StringBuffer(this.data).insert(offset, data).toString();
  -
  -            setNodeValueInternal(value);
  -
  -            // notify document
  -            ownerDocument().insertedText(this, offset, data.length());
  -        }
  -        catch (StringIndexOutOfBoundsException e) {
  -            String msg = 
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", 
null);
  -            throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
  -        }
  +        
  +             setNodeValueInternal(value, replace);
  +      
  +             // notify document
  +             ownerDocument().insertedText(this, offset, data.length());
  +     }
  +     catch (StringIndexOutOfBoundsException e) {
  +             String msg = 
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "INDEX_SIZE_ERR", 
null);
  +             throw new DOMException(DOMException.INDEX_SIZE_ERR, msg);
  +     }
   
  -    } // insertData(int,int)
  +    } // internalInsertData(int,String,boolean)
   
  +    
  +    
       /**
        * Replace a series of characters at the specified (zero-based)
        * offset with a new string, NOT necessarily of the same
  @@ -305,8 +345,25 @@
           // DOMSubtreeModified. But mutation events are 
           // underspecified; I don't feel compelled
           // to deal with it right now.
  -        deleteData(offset, count);
  -        insertData(offset, data);
  +        if (isReadOnly()) {
  +            String msg = 
DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, 
"NO_MODIFICATION_ALLOWED_ERR", null);
  +                throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR, 
msg);
  +        }
  +        
  +        if (needsSyncData()) {
  +            synchronizeData();
  +        }
  +       
  +        //notify document
  +        ownerDocument().replacingData(this);
  +
  +        // keep old value for document notification
  +        String oldvalue = this.data;
  +               
  +        internalDeleteData(offset, count, true);
  +        internalInsertData(offset, data, true);
  +                
  +        ownerDocument().replacedCharacterData(this, oldvalue, this.data);
   
       } // replaceData(int,int,String)
   
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to