Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 321851

Summary: [editor] BaseCommand.ensureSchemaElement() fires unnecessary DOM events and breaks Undo/Redo of EMF commands
Product: [WebTools] WTP Source Editing Reporter: Stanislav Nichev <stanislav.nichev>
Component: wst.xsdAssignee: wst.xsd <wst.xsd-inbox>
Status: NEW --- QA Contact: Keith Chong <keith.chong.ca>
Severity: normal    
Priority: P3 CC: stanislav.nichev
Version: 3.1   
Target Milestone: ---   
Hardware: PC   
OS: Windows Vista   
Whiteboard:

Description Stanislav Nichev CLA 2010-08-05 07:33:13 EDT
Build Identifier: M20100211-1343

Hi Colleagues,

When calling the BaseCommand.ensureSchemaElement(XsdSchema) (package org.eclipse.wst.xsd.ui.internal.common.commands) on an empty file, first the <schema...> tags are added, then - the xml directive.

This updates the underlying DOM several times: once for <schema> with ADD eventType, second - ADD for <?xml ..> and third - CHANGE for the <schema> attributes. The reason for those DOM changes is in the following method call:

protected static void ensureSchemaElement(XSDSchema schema)
  {
    Document document = schema.getDocument();
    Element schemaElement = document.getDocumentElement();

    if (schemaElement == null)
    {
      String targetNamespace = getDefaultNamespace(schema);
      schema.setTargetNamespace(targetNamespace);
      Map qNamePrefixToNamespaceMap = schema.getQNamePrefixToNamespaceMap();
      qNamePrefixToNamespaceMap.put("tns", targetNamespace);      
      if (XSDEditorPlugin.getDefault().isQualifyXMLSchemaLanguage())
      {
        String prefix = XSDEditorPlugin.getDefault().getXMLSchemaPrefix();
        schema.setSchemaForSchemaQNamePrefix(prefix);
        qNamePrefixToNamespaceMap.put(prefix, XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001);      
      }
      else
      {
        qNamePrefixToNamespaceMap.put(null, XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001);      
      }
      
      schema.updateElement();


HERE-->     ensureXMLDirective(document);
    }
  }

If we move the ensureXMLDirective() method call just after the "if (schemaElement == null)" if, the DOM model is notified with the correct sequence of events.

Another possible solution of the problem is changing the ensureXMLDirective() visibility to protected. That way - ensureXmlDirective() can be explicitly called before the ensureSchemaElement() method call.

Reproducible: Always

Steps to Reproduce:
1. Execute the BaseCommand.ensureSchemaElement() method on an empty file through an AbstractEMFCommand subclass.
2. xml directive and <schema> element tags are added to the document
3. Execute undo of the AbstractEMFCommand subclass command.
4. The file contents are not empty as before, but only <schema></schema> tags remain.
Comment 1 Stanislav Nichev CLA 2010-08-05 07:51:20 EDT
The same problem exists in the org.eclipse.wst.wsdl.ui.internal.adapters.commands.W11TopLevelElementCommand#ensureDefinition() method. The ensureXMLDirective(document) is private and again - after the <definition...> tags addition to the DOM/document
Comment 2 David Williams CLA 2010-09-27 10:24:13 EDT
(I'm not quite sure of right sub-project/component ... so, assigning based on initial guess).