/*******************************************************************************
 * Copyright (c) 2001, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.xml.ui.internal.wizards;

import java.text.Collator;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.IWizardPage;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.wizards.newresource.BasicNewResourceWizard;
import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMContentBuilder;
import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo;
import org.eclipse.wst.xml.ui.internal.Logger;
import org.eclipse.wst.xml.ui.internal.dialogs.NamespaceInfoErrorHelper;
import org.eclipse.wst.xml.ui.internal.dialogs.SelectFileOrXMLCatalogIdPanel;
import org.eclipse.wst.xml.ui.internal.nsedit.CommonEditNamespacesDialog;

public class NewXMLWizard extends NewModelWizard
{                                  
  protected static final int CREATE_FROM_DTD     = 0;
  protected static final int CREATE_FROM_XSD     = 1;
  protected static final int CREATE_FROM_SCRATCH = 2;

  protected static final String[] createFromRadioButtonLabel
    = {XMLWizardsMessages._UI_RADIO_XML_FROM_DTD,
       XMLWizardsMessages._UI_RADIO_XML_FROM_SCHEMA,
       XMLWizardsMessages._UI_RADIO_XML_FROM_SCRATCH};

  protected static final String[] filePageFilterExtensions = {".xml"}; //$NON-NLS-1$
  protected static final String[] browseXSDFilterExtensions = {".xsd"}; //$NON-NLS-1$
  protected static final String[] browseDTDFilterExtensions = {".dtd"}; //$NON-NLS-1$

  protected NewFilePage newFilePage;
  protected StartPage startPage;
  protected SelectGrammarFilePage selectGrammarFilePage; 
  protected SelectRootElementPage selectRootElementPage;
                 
  protected String cmDocumentErrorMessage;

  protected NewXMLGenerator generator;


  public NewXMLWizard()
  {
    setWindowTitle(XMLWizardsMessages._UI_WIZARD_CREATE_XML_HEADING);
    setDefaultPageImageDescriptor(ImageDescriptor.createFromFile(XMLWizard.class,"icons/generatexml_wiz.gif")); //$NON-NLS-1$
    generator = new NewXMLGenerator();
  }
  

  public NewXMLWizard(IFile file, CMDocument cmDocument)
  {
    this();       

    generator.setGrammarURI(URIHelper.getPlatformURI(file));
    generator.setCMDocument(cmDocument);
  }


  public static void showDialog(Shell shell, IFile file, IStructuredSelection structuredSelection)
  {                             
    String[] errorInfo = new String[2];
    CMDocument cmDocument = NewXMLGenerator.createCMDocument(file.getLocation().toOSString(), errorInfo);
    if (errorInfo[0] == null)
    {
      NewXMLWizard wizard = new NewXMLWizard(file, cmDocument);
      wizard.init(PlatformUI.getWorkbench(), structuredSelection);
      wizard.setNeedsProgressMonitor(true);
      WizardDialog dialog = new WizardDialog(shell, wizard);
      dialog.create();          
      dialog.getShell().setText(XMLWizardsMessages._UI_DIALOG_NEW_TITLE);     
      dialog.setBlockOnOpen(true);
      dialog.open();
    }         
    else
    {
      MessageDialog.openInformation(shell, errorInfo[0], errorInfo[1]);
    }
  }  


  public void addPages()
  {
    String grammarURI = generator.getGrammarURI();

    if (grammarURI == null)
    {
      // start page
      startPage = new StartPage("StartPage", createFromRadioButtonLabel) //$NON-NLS-1$
      {
        public void createControl(Composite parent)
        {
          super.createControl(parent);
        }
                    
        public void setVisible(boolean visible)
        {
          super.setVisible(visible);
          getRadioButtonAtIndex(getCreateMode()).setSelection(true);
          getRadioButtonAtIndex(getCreateMode()).setFocus();

          // Set the help context for each button
          //WorkbenchHelp.setHelp(startPage.getRadioButtonAtIndex(0), XMLBuilderContextIds.XMLC_FROM_DTD_RADIO);
          //WorkbenchHelp.setHelp(startPage.getRadioButtonAtIndex(1), XMLBuilderContextIds.XMLC_XML_SCHEMA_RADIO);
          //WorkbenchHelp.setHelp(startPage.getRadioButtonAtIndex(2), XMLBuilderContextIds.XMLC_SCRATCH_RADIO);
        }
      };


      startPage.setTitle(XMLWizardsMessages._UI_WIZARD_CREATE_XML_HEADING);
      startPage.setDescription(XMLWizardsMessages._UI_WIZARD_CREATE_XML_EXPL);
      addPage(startPage);
    }
                                   
    // new file page                              
    newFilePage = new NewFilePage(selection);
    newFilePage.setTitle(XMLWizardsMessages._UI_WIZARD_CREATE_XML_FILE_HEADING);
    newFilePage.setDescription(XMLWizardsMessages._UI_WIZARD_CREATE_XML_FILE_EXPL); 
    newFilePage.defaultName = (grammarURI != null) ? URIHelper.removeFileExtension(URIHelper.getLastSegment(grammarURI)) : "NewFile"; //$NON-NLS-1$
    newFilePage.defaultFileExtension = ".xml"; //$NON-NLS-1$
    newFilePage.filterExtensions = filePageFilterExtensions;
    addPage(newFilePage);
     
    // selectGrammarFilePage
    selectGrammarFilePage = new SelectGrammarFilePage();   
    addPage(selectGrammarFilePage);                                                                     
            
    // select root element page
    selectRootElementPage = new SelectRootElementPage();
    selectRootElementPage.setTitle(XMLWizardsMessages._UI_WIZARD_SELECT_ROOT_HEADING);
    selectRootElementPage.setDescription(XMLWizardsMessages._UI_WIZARD_SELECT_ROOT_EXPL);
    addPage(selectRootElementPage);
  }
                  

  public IWizardPage getStartingPage()
  {
    WizardPage result = null;
    if (startPage != null)
    {
      result = startPage;
    }
    else
    {
      result = newFilePage;
    }
    return result;
  }


  public int getCreateMode()
  {
    String grammarURI = generator.getGrammarURI();

    int result = CREATE_FROM_SCRATCH;
    if (grammarURI != null)
    {              
      if (grammarURI.endsWith(".dtd")) //$NON-NLS-1$
      {
        result = CREATE_FROM_DTD;
      }
      else if (grammarURI.endsWith(".xsd")) //$NON-NLS-1$
      {
        result = CREATE_FROM_XSD;
      }
    }
    else if (startPage != null)
    {
      int selectedIndex = startPage.getSelectedRadioButtonIndex();
      if (selectedIndex != -1)
      {
        result = selectedIndex;
      }
    }
    return result;
  }
 

  public IWizardPage getNextPage(IWizardPage currentPage)
  {
    WizardPage nextPage = null;
    if (currentPage == startPage)
    {
      nextPage = newFilePage;
    }
    else if (currentPage == newFilePage)
    {                       
      if (getCreateMode() == CREATE_FROM_SCRATCH)
      {
        nextPage = null;
      }
      else if (generator.getGrammarURI() == null)
      {
        nextPage = selectGrammarFilePage;
      }
      else
      {
        nextPage = selectRootElementPage;
      }
    }
    else if (currentPage == selectGrammarFilePage)
    {
      nextPage = selectRootElementPage;
    }                           
    return nextPage;
  }


  public boolean canFinish()
  {
    boolean result = false;

    IWizardPage currentPage = getContainer().getCurrentPage();

    if ((startPage != null && startPage.getSelectedRadioButtonIndex() == CREATE_FROM_SCRATCH && currentPage == newFilePage) ||
        (currentPage == selectRootElementPage))
    {
      result = currentPage.isPageComplete();
    }
    return result;
  }      
  

  public boolean performFinish()
  {       
    boolean result = true;
    super.performFinish();
    String fileName = null;
    try
    {                                                                                   

      String[] namespaceErrors = generator.getNamespaceInfoErrors();
      if (namespaceErrors !=  null) 
      {
        String title = namespaceErrors[0];
        String message = namespaceErrors[1];
        result = MessageDialog.openQuestion(getShell(), title, message);
      }

      if (result)
      {
        fileName = newFilePage.getFileName();
        if ((new Path(fileName)).getFileExtension() == null)
        {
          newFilePage.setFileName(fileName.concat(".xml")); //$NON-NLS-1$
        }

        IFile newFile = newFilePage.createNewFile();
        String xmlFileName = newFile.getLocation().toOSString();

        if (getContainer().getCurrentPage() == selectRootElementPage)
        {

          generator.createXMLDocument(newFile, xmlFileName);
        }           
        else
        {
          generator.createEmptyXMLDocument(newFile);
        }
        
		newFile.refreshLocal(1, null);
		
		IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
		BasicNewResourceWizard.selectAndReveal(newFile, workbenchWindow); 
        openEditor(newFile);
      }
    }
    catch (Exception e)
    {
      Logger.logException("Exception completing New XML wizard " + fileName, e);	//$NON-NLS-1$
    }
    return result;
  }  
  
  public void openEditor(IFile file)
  {  
	// Open editor on new file.
  	String editorId = null;
  	try {
		IEditorDescriptor editor = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(file.getLocation().toOSString(), file.getContentDescription().getContentType());
		if(editor != null){
			editorId = editor.getId();
		}
	} catch (CoreException e1) {
		// editor id could not be retrieved, so we can not open editor
		return;
	}
  	IWorkbenchWindow dw = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
	try {
		if (dw != null) {
			IWorkbenchPage page = dw.getActivePage();
			if (page != null)
				page.openEditor(new FileEditorInput(file), editorId, true);
		}
	} catch (PartInitException e) {
		// editor can not open for some reason
		return;
	}
	
  }
  

  protected String getDefaultSystemId()
  {  
    String relativePath = "platform:/resource/" + newFilePage.getContainerFullPath().toString() + "/dummy";  //$NON-NLS-1$ //$NON-NLS-2$
    return URIHelper.getRelativeURI(generator.getGrammarURI(), relativePath);
  }                          
     

  /**
   * SelectGrammarFilePage
   */
  class SelectGrammarFilePage extends WizardPage
  {
    protected SelectFileOrXMLCatalogIdPanel panel;
  
    SelectGrammarFilePage()
    {
      super("SelectGrammarFilePage"); //$NON-NLS-1$
    }  

    public void createControl(Composite parent)
    {             
      Composite composite = new Composite(parent, SWT.NONE);
      //WorkbenchHelp.setHelp(composite, XMLBuilderContextIds.XMLC_GRAMMAR_PAGE);
      composite.setLayout(new GridLayout());
      composite.setLayoutData(new GridData(GridData.FILL_BOTH));
      setControl(composite);

      panel = new SelectFileOrXMLCatalogIdPanel(composite);
      panel.setLayoutData(new GridData(GridData.FILL_BOTH));

      SelectFileOrXMLCatalogIdPanel.Listener listener = new SelectFileOrXMLCatalogIdPanel.Listener()
      {
        public void completionStateChanged()
        {          
          updateErrorMessage();
        }
      };
      panel.setListener(listener);
    }
   
    public void setVisible(boolean visible)
    {                              
      super.setVisible(visible);                              
      if (visible)
      {                      
        if (getCreateMode() == CREATE_FROM_DTD)
        {                               
          setTitle(XMLWizardsMessages._UI_WIZARD_SELECT_DTD_FILE_TITLE);
          setDescription(XMLWizardsMessages._UI_WIZARD_SELECT_DTD_FILE_DESC);
          panel.setFilterExtensions(browseDTDFilterExtensions);
        }
        else
        { 
          setTitle(XMLWizardsMessages._UI_WIZARD_SELECT_XSD_FILE_TITLE);
          setDescription(XMLWizardsMessages._UI_WIZARD_SELECT_XSD_FILE_DESC);
          panel.setFilterExtensions(browseXSDFilterExtensions);
        } 
        generator.setGrammarURI(null);
        generator.setCMDocument(null); 
        cmDocumentErrorMessage = null;        
      }                             
      panel.setVisibleHelper(visible);
    }  

    public String getURI()
    {                      
      String uri = panel.getXMLCatalogURI();
      if (uri == null)
      {
        IFile file = panel.getFile();
        if (file != null)
        {
          uri = URIHelper.getPlatformURI(file);
        }               
      }
      return uri;
    }  

    public boolean isPageComplete()
    {                            
      return getURI() != null && getErrorMessage() == null;
    }                        

    public String getXMLCatalogId()
    {
      return panel.getXMLCatalogId();
    }                            
    
    public ICatalogEntry getXMLCatalogEntry()
    {
      return panel.getXMLCatalogEntry();   
    }    

    public String computeErrorMessage()
    {           
      String errorMessage = null;
      String uri = getURI();               
      if (uri != null)
      {         
        if (!URIHelper.isReadableURI(uri,false))
        {
          errorMessage = XMLWizardsMessages._UI_LABEL_ERROR_CATALOG_ENTRY_INVALID;                  
        }
      }             
      return errorMessage;
    }


    public void updateErrorMessage()
    {
      String errorMessage = computeErrorMessage();  
      setErrorMessage(errorMessage);
      setPageComplete(isPageComplete());
    }
  }


  /**
   * SelectRootElementPage
   */
  class SelectRootElementPage extends WizardPage implements SelectionListener
  {
    protected Combo combo;
    protected Button[] radioButton;
    protected PageBook pageBook;
    protected XSDOptionsPanel xsdOptionsPanel;
    protected DTDOptionsPanel dtdOptionsPanel;


    SelectRootElementPage()
    {
      super("SelectRootElementPage"); //$NON-NLS-1$
    }

    public void createControl(Composite parent)
    {
      // container group
      Composite containerGroup = new Composite(parent,SWT.NONE);
      //WorkbenchHelp.setHelp(containerGroup, XMLBuilderContextIds.XMLC_ROOT_PAGE);
      containerGroup.setLayout(new GridLayout());
      containerGroup.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      setControl(containerGroup);

      // select root element
      Label containerLabel = new Label(containerGroup, SWT.NONE);
      containerLabel.setText(XMLWizardsMessages._UI_LABEL_ROOT_ELEMENT);
      combo = new Combo(containerGroup, SWT.DROP_DOWN | SWT.READ_ONLY);
      combo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      combo.addSelectionListener(this);
      //WorkbenchHelp.setHelp(combo, XMLBuilderContextIds.XMLC_ROOT_ROOT);

      // Options
      {
        Group group = new Group(containerGroup, SWT.NONE);
        group.setText(XMLWizardsMessages._UI_WIZARD_CONTENT_OPTIONS);
        //WorkbenchHelp.setHelp(group, XMLBuilderContextIds.XMLC_CURRENT_GROUP);
        
        GridLayout layout = new GridLayout();
        layout.numColumns = 1;
        layout.makeColumnsEqualWidth = true;
        layout.marginWidth = 0;
        group.setLayout(layout);
        group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

        radioButton = new Button[4];
                
        radioButton[0] = new Button(group, SWT.CHECK);
        radioButton[0].setText(XMLWizardsMessages._UI_WIZARD_CREATE_OPTIONAL_ATTRIBUTES);
        radioButton[0].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        radioButton[0].setSelection(false);
        //WorkbenchHelp.setHelp(radioButton[0], XMLBuilderContextIds.XMLC_CREATE_OPTIONAL_ATTRIBUTES);
        
        radioButton[1] = new Button(group, SWT.CHECK);
        radioButton[1].setText(XMLWizardsMessages._UI_WIZARD_CREATE_OPTIONAL_ELEMENTS);
        radioButton[1].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        radioButton[1].setSelection(false);
        //WorkbenchHelp.setHelp(radioButton[1], XMLBuilderContextIds.XMLC_CREATE_OPTIONAL_ELEMENTS);
        
        radioButton[2] = new Button(group, SWT.CHECK);
        radioButton[2].setText(XMLWizardsMessages._UI_WIZARD_CREATE_FIRST_CHOICE);
        radioButton[2].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        radioButton[2].setSelection(true);
        //WorkbenchHelp.setHelp(radioButton[2], XMLBuilderContextIds.XMLC_CREATE_FIRST_CHOICE);
        
        radioButton[3] = new Button(group, SWT.CHECK);
        radioButton[3].setText(XMLWizardsMessages._UI_WIZARD_FILL_ELEMENTS_AND_ATTRIBUTES);
        radioButton[3].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        radioButton[3].setSelection(true);                        
        //WorkbenchHelp.setHelp(radioButton[3], XMLBuilderContextIds.XMLC_FILL_ELEMENTS_AND_ATTRIBUTES);
/*
        radioButton = new Button[2];

        radioButton[0] = new Button(group, SWT.RADIO);
        radioButton[0].setText(XMLWizardsMessages.getString("_UI_WIZARD_CREATE_REQUIRED"));
        radioButton[0].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        radioButton[0].setSelection(true);
        WorkbenchHelp.setHelp(radioButton[0], XMLBuilderContextIds.XMLC_CREATE_REQUIRED_ONLY);

        radioButton[1] = new Button(group, SWT.RADIO);
        radioButton[1].setText(XMLWizardsMessages.getString("_UI_WIZARD_CREATE_OPTIONAL"));
        radioButton[1].setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
        WorkbenchHelp.setHelp(radioButton[1], XMLBuilderContextIds.XMLC_CREATE_REQUIRED_AND_OPTION);
*/
      }

      // add the grammar specific generation options
      //
      {
        pageBook = new PageBook(containerGroup, SWT.NONE);
        pageBook.setLayoutData(new GridData(GridData.FILL_BOTH));
        xsdOptionsPanel = new XSDOptionsPanel(this, pageBook);
        dtdOptionsPanel = new DTDOptionsPanel(this, pageBook);
        pageBook.showPage(xsdOptionsPanel); 
      }
    }

    public void widgetSelected(SelectionEvent event)
    {
      int index = combo.getSelectionIndex();
      String rootElementName = (index != -1) ? combo.getItem(index) : null;
      generator.setRootElementName(rootElementName);
    }

    public void widgetDefaultSelected(SelectionEvent event)
    {
    	// do nothing
    }

    public void setVisible(boolean visible)
    {
      super.setVisible(visible);

      if (visible)
      {
        try
        {
          if (generator.getGrammarURI() == null)
          {
            generator.setGrammarURI(selectGrammarFilePage.getURI());
            generator.setXMLCatalogEntry(selectGrammarFilePage.getXMLCatalogEntry());
          }
          Assert.isNotNull(generator.getGrammarURI());    
                
          if (generator.getCMDocument() == null)
          {
            final String[] errorInfo = new String[2];
            final CMDocument[] cmdocs = new CMDocument[1];
            Runnable r = new Runnable()
              {
                public void run()
                {
                  cmdocs[0] = NewXMLGenerator.createCMDocument(generator.getGrammarURI(), errorInfo);
                }
              };
            org.eclipse.swt.custom.BusyIndicator.showWhile(Display.getCurrent(),r);

            generator.setCMDocument(cmdocs[0]);
            cmDocumentErrorMessage = errorInfo[1];     
          }    

          if (generator.getCMDocument() != null && cmDocumentErrorMessage == null)
          {
            CMNamedNodeMap nameNodeMap = generator.getCMDocument().getElements();
            Vector nameNodeVector = new Vector();

            for (int i = 0; i < nameNodeMap.getLength(); i++)
            {
              CMElementDeclaration cmElementDeclaration = (CMElementDeclaration)nameNodeMap.item(i);
              Object value =  cmElementDeclaration.getProperty("Abstract"); //$NON-NLS-1$
              if  (value !=  Boolean.TRUE)
              {
                nameNodeVector.add(cmElementDeclaration.getElementName());
              }
            }

            Object[] nameNodeArray = nameNodeVector.toArray();
            if (nameNodeArray.length > 0 )
            {
              Arrays.sort(nameNodeArray, Collator.getInstance());
            }

            String defaultRootName = (String) (generator.getCMDocument()).getProperty("http://org.eclipse.wst/cm/properties/defaultRootName"); //$NON-NLS-1$
            int defaultRootIndex = -1;
            combo.removeAll();


            for (int i = 0; i < nameNodeArray.length; i++)
            {
              String elementName = (String)nameNodeArray[i];

              combo.add(elementName);
              if (defaultRootName != null && defaultRootName.equals(elementName))
              {
                defaultRootIndex = i;
              }
            }
         
            if (nameNodeArray.length > 0)
            {
              defaultRootIndex = defaultRootIndex != -1 ? defaultRootIndex : 0;
              combo.select(defaultRootIndex);
              generator.setRootElementName(combo.getItem(defaultRootIndex));
            }
          }

          if (generator.getGrammarURI().endsWith("xsd")) //$NON-NLS-1$
          {                                       
            pageBook.showPage(xsdOptionsPanel); 
            generator.setDefaultSystemId(getDefaultSystemId());
            generator.createNamespaceInfoList();

            // Provide default namespace prefix if none
            for (int i=0; i<generator.namespaceInfoList.size(); i++)
            {
              NamespaceInfo nsinfo = 
                (NamespaceInfo)generator.namespaceInfoList.get(i);
              if ((nsinfo.prefix == null || nsinfo.prefix.trim().length() == 0)
                  && (nsinfo.uri != null && nsinfo.uri.trim().length() != 0))
              {
                nsinfo.prefix = getDefaultPrefix(generator.namespaceInfoList);
              }
            }
            xsdOptionsPanel.setNamespaceInfoList(generator.namespaceInfoList);
          }
          else if (generator.getGrammarURI().endsWith("dtd")) //$NON-NLS-1$
          {
            pageBook.showPage(dtdOptionsPanel);
            dtdOptionsPanel.update();
          }
        }   
        catch(Exception e)
        {
           //XMLBuilderPlugin.getPlugin().getMsgLogger().writeCurrentThread();
        }

        /*
        String errorMessage = computeErrorMessage();
        if (errorMessage == null) 
          super.setVisible(visible);
        */
        
        updateErrorMessage();
      }
    }
                            
    private String getDefaultPrefix(List nsInfoList)
    {
      String defaultPrefix = "p"; //$NON-NLS-1$
      if (nsInfoList == null)
        return defaultPrefix;

      Vector v = new Vector();
      for (int i=0; i<nsInfoList.size(); i++)
      {
        NamespaceInfo nsinfo = (NamespaceInfo)nsInfoList.get(i);
        if (nsinfo.prefix != null)
          v.addElement(nsinfo.prefix);
      }

      if (v.contains(defaultPrefix))
      {
        String s = defaultPrefix;
        for (int j=0; v.contains(s); j++)
        {
          s = defaultPrefix + Integer.toString(j);
        }
        return s;
      }
      return defaultPrefix;
    }

    public boolean isPageComplete()
    {
      boolean complete = (generator.getRootElementName() != null && generator.getRootElementName().length() > 0) && getErrorMessage() == null;
      
      if (complete) {
      	/*
        int buildPolicy = radioButton[0].getSelection() ?
                          DOMContentBuilder.BUILD_ONLY_REQUIRED_CONTENT :
                          DOMContentBuilder.BUILD_ALL_CONTENT;
        */
        int buildPolicy = 0;
        if (radioButton[0].getSelection())
          buildPolicy = buildPolicy | DOMContentBuilder.BUILD_OPTIONAL_ATTRIBUTES;
        if (radioButton[1].getSelection())
          buildPolicy = buildPolicy | DOMContentBuilder.BUILD_OPTIONAL_ELEMENTS;
        if (radioButton[2].getSelection())
          buildPolicy = buildPolicy | DOMContentBuilder.BUILD_FIRST_CHOICE | DOMContentBuilder.BUILD_FIRST_SUBSTITUTION;
        if (radioButton[3].getSelection())
          buildPolicy = buildPolicy | DOMContentBuilder.BUILD_TEXT_NODES;
                    
        generator.setBuildPolicy(buildPolicy);
      }

      return complete;
    }

    public String computeErrorMessage()
    {
      String errorMessage = null;
               
      if (cmDocumentErrorMessage != null)
      {
        errorMessage = cmDocumentErrorMessage;                  
      }
      else if (generator.getRootElementName() == null || generator.getRootElementName().length() == 0)
      {
        errorMessage = XMLWizardsMessages._ERROR_ROOT_ELEMENT_MUST_BE_SPECIFIED;
      }                  

      return errorMessage;
    }


    public void updateErrorMessage()
    {
      String errorMessage = computeErrorMessage();
      if (errorMessage == null)
      { 
        if (xsdOptionsPanel.isVisible())
        {
          
          errorMessage = xsdOptionsPanel.computeErrorMessage();
        }
        else if (dtdOptionsPanel.isVisible())
        {
          errorMessage = dtdOptionsPanel.computeErrorMessage();
        }
      }
      setErrorMessage(errorMessage);
      setPageComplete(isPageComplete());
    }
  }
  ////////////////End SelectRootElementPage
  


  public static GridLayout createOptionsPanelLayout()
  {
    GridLayout gridLayout = new GridLayout();
    gridLayout.marginWidth = 0;
    gridLayout.horizontalSpacing = 0;
    return gridLayout;
  }
    

                    
  /**
   * 
   */
  class XSDOptionsPanel extends Composite
  {            
    protected String errorMessage = null;
    protected SelectRootElementPage parentPage;   
    protected CommonEditNamespacesDialog editNamespaces;

    public XSDOptionsPanel(SelectRootElementPage parentPage, Composite parent)
    {
      super(parent, SWT.NONE);
      this.parentPage = parentPage;
                                                                            
      setLayout(createOptionsPanelLayout());                                 
      setLayoutData(new GridData(GridData.FILL_BOTH));             
                                
      Composite co = new Composite(this, SWT.NONE);
      co.setLayout(new GridLayout());
	 
      if (newFilePage != null && newFilePage.getContainerFullPath() != null)
      {
        // todo... this is a nasty mess. I need to revist this code.
        //
        String resourceURI = "platform:/resource" + newFilePage.getContainerFullPath().toString() + "/dummy"; //$NON-NLS-1$ //$NON-NLS-2$
        String resolvedPath = URIHelper.normalize(resourceURI, null, null);
        if (resolvedPath.startsWith("file:/")) //$NON-NLS-1$
        {
          resolvedPath = resolvedPath.substring(6);
        }
        // end nasty messs
        String tableTitle = XMLWizardsMessages._UI_LABEL_NAMESPACE_INFORMATION;
        editNamespaces = new CommonEditNamespacesDialog(co, new Path(resolvedPath), tableTitle, true, true);
      }
    }
    
    public void setNamespaceInfoList(List list)
    {                   
      editNamespaces.setNamespaceInfoList(list);   
      editNamespaces.updateErrorMessage(list);                      
    }    
    
    public void updateErrorMessage(List namespaceInfoList)
    {        
      NamespaceInfoErrorHelper helper = new NamespaceInfoErrorHelper();
      errorMessage = helper.computeErrorMessage(namespaceInfoList, null);
      parentPage.updateErrorMessage();
    }
  
    
    public String computeErrorMessage()
    {             
      return errorMessage;
    }   
  }    


  /**
   * 
   */
  public class DTDOptionsPanel extends Composite implements ModifyListener
  {
    protected Group group;
    protected Text systemIdField;
    protected Text publicIdField;
    protected SelectRootElementPage parentPage;

    public DTDOptionsPanel(SelectRootElementPage parentPage, Composite parent)
    {
      super(parent, SWT.NONE);
      this.parentPage = parentPage;
      setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

      setLayout(createOptionsPanelLayout());
      Group group = new Group(this, SWT.NONE);
      group.setText(XMLWizardsMessages._UI_LABEL_DOCTYPE_INFORMATION);
      //WorkbenchHelp.setHelp(group, XMLBuilderContextIds.XMLC_DOCUMENTATION_GROUP);
      
      GridLayout layout = new GridLayout();
      layout.numColumns = 2;
      group.setLayout(layout);
      group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
                  
      Label publicIdLabel = new Label(group, SWT.NONE);
      publicIdLabel.setText(XMLWizardsMessages._UI_LABEL_PUBLIC_ID);
      publicIdField = new Text(group, SWT.SINGLE | SWT.BORDER);
      publicIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      publicIdField.addModifyListener(this);
      //WorkbenchHelp.setHelp(publicIdField, XMLBuilderContextIds.XMLC_PUBLIC);
      
      Label systemIdLabel = new Label(group, SWT.NONE);
      systemIdLabel.setText(XMLWizardsMessages._UI_LABEL_SYSTEM_ID);
      systemIdField = new Text(group, SWT.SINGLE | SWT.BORDER);
      systemIdField.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
      systemIdField.addModifyListener(this);
      //WorkbenchHelp.setHelp(systemIdField, XMLBuilderContextIds.XMLC_SYSTEM);      
    }
    
    public void update()
    {                           
      String thePublicId = null;                              
      String theSystemId = null;
      ICatalogEntry xmlCatalogEntry = generator.getXMLCatalogEntry();

      if (xmlCatalogEntry != null)
      {
        if (xmlCatalogEntry.getEntryType() == ICatalogEntry.ENTRY_TYPE_PUBLIC)
        {
          thePublicId = xmlCatalogEntry.getKey();
          theSystemId = xmlCatalogEntry.getAttributeValue(ICatalogEntry.ATTR_WEB_URL);
          if (theSystemId == null)
          {
            theSystemId = generator.getGrammarURI().startsWith("http:") ? generator.getGrammarURI() : URIHelper.getLastSegment(generator.getGrammarURI()); //$NON-NLS-1$
          }  
        }                                          
        else
        {
          theSystemId = xmlCatalogEntry.getKey();
        }  
      }                                     
      else
      {
        theSystemId = getDefaultSystemId();
      }                                    
                                                                    
      publicIdField.setText(thePublicId != null ? thePublicId : ""); //$NON-NLS-1$
      systemIdField.setText(theSystemId != null ? theSystemId : ""); //$NON-NLS-1$
    }      

    public void modifyText(ModifyEvent e)
    {
      generator.setSystemId(systemIdField.getText());
      generator.setPublicId(publicIdField.getText());
      parentPage.updateErrorMessage();
    }

    public String computeErrorMessage()
    {
      return null;
    }
  }


}
