xml.schema/src/org/netbeans/modules/xml/schema/wizard/SampleXMLGeneratorWizardIterator.java
author Milutin Kristofic <mkristofic@netbeans.org>
Mon, 30 Jan 2017 14:30:54 +0100
changeset 1583 fe20f672a61a
parent 1138 0b115953d06c
permissions -rw-r--r--
Added Missing copyright information in source files
     1 /*
     2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3  *
     4  * Copyright 2009-2017 Oracle and/or its affiliates. All rights reserved.
     5  *
     6  * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
     7  * Other names may be trademarks of their respective owners.
     8  *
     9  * The contents of this file are subject to the terms of either the GNU
    10  * General Public License Version 2 only ("GPL") or the Common
    11  * Development and Distribution License("CDDL") (collectively, the
    12  * "License"). You may not use this file except in compliance with the
    13  * License. You can obtain a copy of the License at
    14  * http://www.netbeans.org/cddl-gplv2.html
    15  * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    16  * specific language governing permissions and limitations under the
    17  * License.  When distributing the software, include this License Header
    18  * Notice in each file and include the License file at
    19  * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    20  * particular file as subject to the "Classpath" exception as provided
    21  * by Oracle in the GPL Version 2 section of the License file that
    22  * accompanied this code. If applicable, add the following below the
    23  * License Header, with the fields enclosed by brackets [] replaced by
    24  * your own identifying information:
    25  * "Portions Copyrighted [year] [name of copyright owner]"
    26  *
    27  * Contributor(s):
    28  *
    29  * The Original Software is NetBeans. The Initial Developer of the Original
    30  * Software is Sun Microsystems, Inc. Portions Copyright 2009-2010 Sun
    31  * Microsystems, Inc. All Rights Reserved.
    32  *
    33  * If you wish your version of this file to be governed by only the CDDL
    34  * or only the GPL Version 2, indicate your decision by adding
    35  * "[Contributor] elects to include this software in this distribution
    36  * under the [CDDL or GPL Version 2] license." If you do not indicate a
    37  * single choice of license, a recipient has the option to distribute
    38  * your version of this file under either the CDDL, the GPL Version 2 or
    39  * to extend the choice of license to its licensees as provided above.
    40  * However, if you add GPL Version 2 code and therefore, elected the GPL
    41  * Version 2 license, then the option applies only if the new code is
    42  * made subject to such option by the copyright holder.
    43  */
    44 /*
    45  * To change this template, choose Tools | Templates
    46  * and open the template in the editor.
    47  */
    48 package org.netbeans.modules.xml.schema.wizard;
    49 
    50 import java.awt.Component;
    51 import java.awt.Dialog;
    52 import java.io.BufferedOutputStream;
    53 import java.io.File;
    54 import java.io.IOException;
    55 import java.io.OutputStream;
    56 import java.io.OutputStreamWriter;
    57 import java.io.Writer;
    58 import java.net.URI;
    59 import java.net.URISyntaxException;
    60 import java.net.URL;
    61 import java.text.DateFormat;
    62 import java.text.MessageFormat;
    63 import java.util.Date;
    64 import java.util.HashSet;
    65 import java.util.Map;
    66 import java.util.NoSuchElementException;
    67 import java.util.Set;
    68 import javax.swing.JComponent;
    69 import javax.swing.event.ChangeListener;
    70 import javax.xml.parsers.DocumentBuilder;
    71 import javax.xml.parsers.DocumentBuilderFactory;
    72 import javax.xml.transform.OutputKeys;
    73 import javax.xml.transform.Result;
    74 import javax.xml.transform.Transformer;
    75 import javax.xml.transform.TransformerFactory;
    76 import javax.xml.transform.dom.DOMSource;
    77 import javax.xml.transform.stream.StreamResult;
    78 import org.netbeans.api.project.FileOwnerQuery;
    79 import org.netbeans.api.project.Project;
    80 import org.netbeans.editor.BaseDocument;
    81 import org.netbeans.modules.xml.api.EncodingUtil;
    82 import org.netbeans.modules.xml.lib.GuiUtil;
    83 import org.netbeans.modules.xml.schema.SchemaDataObject;
    84 import org.netbeans.modules.xml.text.TextEditorSupport;
    85 import org.netbeans.modules.xml.wizard.AbstractPanel;
    86 import org.netbeans.modules.xml.wizard.DocumentModel;
    87 import org.netbeans.modules.xml.wizard.SchemaParser;
    88 import org.netbeans.modules.xml.wizard.XMLContentPanel;
    89 import org.netbeans.modules.xml.wizard.XMLGeneratorVisitor;
    90 import org.openide.DialogDisplayer;
    91 import org.openide.WizardDescriptor;
    92 import org.openide.cookies.EditCookie;
    93 import org.openide.cookies.EditorCookie;
    94 import org.openide.filesystems.FileObject;
    95 import org.openide.filesystems.FileLock;
    96 import org.openide.filesystems.FileSystem;
    97 import org.openide.filesystems.FileUtil;
    98 import org.openide.loaders.DataObject;
    99 import org.openide.util.NbBundle;
   100 import org.w3c.dom.Attr;
   101 import org.w3c.dom.Document;
   102 import org.w3c.dom.NamedNodeMap;
   103 
   104 public final class SampleXMLGeneratorWizardIterator implements WizardDescriptor.InstantiatingIterator {
   105 
   106     private int index;
   107     private WizardDescriptor.Panel[] panels;
   108     private Project srcProject;
   109     private FileObject schemaFileObject;
   110     private DocumentModel model;
   111     private XMLContentPanel xmlPanel;
   112     private static String PREFIX = "ns0";
   113     private static final String XML_EXT = "xml";  
   114     
   115     public SampleXMLGeneratorWizardIterator(SchemaDataObject dobj) {
   116          schemaFileObject = dobj.getPrimaryFile();
   117          this.srcProject = FileOwnerQuery.getOwner(schemaFileObject);
   118     }
   119 
   120     public void show() {
   121         WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels());
   122         initialize(wizardDescriptor);
   123         wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
   124         wizardDescriptor.setTitle(NbBundle.getMessage(SampleXMLGeneratorWizardIterator.class,"TITLE_XML_WIZARD"));        
   125         Dialog dialog = DialogDisplayer.getDefault().createDialog(wizardDescriptor);
   126         dialog.getAccessibleContext().setAccessibleName(
   127                 NbBundle.getMessage(SampleXMLGeneratorWizardIterator.class,"TITLE_XML_WIZARD"));
   128         dialog.getAccessibleContext().setAccessibleDescription(
   129                 NbBundle.getMessage(SampleXMLGeneratorWizardIterator.class,"TITLE_XML_WIZARD"));
   130         dialog.setVisible(true);
   131         dialog.toFront();
   132         boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION;
   133         
   134         if (!cancelled) {
   135             try {
   136                 instantiate();
   137             }catch (Exception e){
   138                 e.printStackTrace();
   139             }
   140         }
   141         
   142     }
   143 
   144     /**
   145      * Initialize panels representing individual wizard's steps and sets
   146      * various properties for them influencing wizard appearance.
   147      */
   148     private WizardDescriptor.Panel[] getPanels() {
   149                
   150         xmlPanel = new XMLContentPanel(true);
   151         
   152         if (panels == null) {
   153             panels = new WizardDescriptor.Panel[]{
   154                //Templates.createSimpleTargetChooser(srcProject, folders)
   155                 new AbstractPanel.WizardStep(xmlPanel)
   156             };
   157             String[] steps = new String[panels.length];
   158             for (int i = 0; i < panels.length; i++) {
   159                 Component c = panels[i].getComponent();
   160                 if (steps[i] == null) {
   161                     // Default step name to component name of panel. Mainly
   162                     // useful for getting the name of the target chooser to
   163                     // appear in the list of steps.
   164                     steps[i] = c.getName();
   165                 }
   166                 if (c instanceof JComponent) { // assume Swing components
   167                     JComponent jc = (JComponent) c;
   168                     // Sets step number of a component
   169                     jc.putClientProperty(WizardDescriptor.PROP_CONTENT_SELECTED_INDEX, new Integer(i));
   170                     // Sets steps names for a panel
   171                     jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DATA, steps);
   172                     // Turn on subtitle creation on each step
   173                     jc.putClientProperty(WizardDescriptor.PROP_AUTO_WIZARD_STYLE, Boolean.TRUE);
   174                     // Show steps on the left side with the image on the background
   175                     jc.putClientProperty(WizardDescriptor.PROP_CONTENT_DISPLAYED, Boolean.TRUE);
   176                     // Turn on numbering of all steps
   177                     jc.putClientProperty(WizardDescriptor.PROP_CONTENT_NUMBERED, Boolean.TRUE);
   178                 }
   179             }
   180         }
   181         return panels;
   182     }
   183 
   184     public Set instantiate() throws IOException {
   185         final String extension = XML_EXT;
   186         
   187         String targetName = schemaFileObject.getName();
   188         if (targetName == null || "null".equals(targetName)) {                  // NOI18N
   189             targetName = "XMLDocument";                                         // NOI18N
   190         }
   191         
   192         final FileObject targetFolder = schemaFileObject.getParent();
   193         String uniqueTargetName = targetName;
   194         int i = 1;        
   195         while (targetFolder.getFileObject(uniqueTargetName, extension) != null) {
   196             uniqueTargetName = targetName + i;
   197             i++;
   198         }
   199 
   200         final String name = uniqueTargetName;
   201         
   202            // in atomic action create data object and return it
   203         
   204         FileSystem filesystem = targetFolder.getFileSystem();        
   205         final FileObject[] fileObject = new FileObject[1];
   206         String encoding = EncodingUtil.getProjectEncoding(targetFolder);
   207         if (!EncodingUtil.isValidEncoding(encoding)) {
   208             encoding = "UTF-8"; //NOI18N
   209         }
   210         String nameExt = name + "." + extension;
   211         FileSystem.AtomicAction fsAction = new FileSystem.AtomicAction() {
   212             public void run() throws IOException {
   213                
   214                 FileObject fo = targetFolder.createData(name, extension);
   215                 fileObject[0] = fo;
   216             }
   217         };
   218          
   219         filesystem.runAtomicAction(fsAction);
   220         StringBuffer sb = new StringBuffer();
   221         //write the comment
   222         writeXMLComment(sb, nameExt, encoding);
   223         //write the body
   224         writeXMLFile(sb);
   225                 
   226         FileLock lock = null;
   227         try {
   228             lock = fileObject[0].lock();
   229             OutputStream out = fileObject[0].getOutputStream(lock);
   230             out = new BufferedOutputStream(out, 999);
   231             Writer writer = new OutputStreamWriter(out, encoding); 
   232             writer.write(sb.toString());
   233             writer.flush();
   234             writer.close();
   235             lock.releaseLock();
   236             lock = null;
   237 
   238         } finally {
   239             if (lock != null) {
   240                 lock.releaseLock();
   241             }
   242         }
   243         // perform default action and return
   244                
   245         Set set = new HashSet(1);                
   246         DataObject createdObject = DataObject.find(fileObject[0]);        
   247         GuiUtil.performDefaultAction(createdObject);
   248         set.add(createdObject); 
   249         
   250         formatXML(fileObject[0]);
   251         return set;
   252     }
   253 
   254     public void initialize(WizardDescriptor wiz) {
   255         index=0;
   256         URL targetFolderURL = null;
   257         try {
   258             FileObject folder = schemaFileObject.getParent();
   259             targetFolderURL = folder.getURL();
   260             //#25604 workaround
   261             if (targetFolderURL.toExternalForm().endsWith("/") == false) {
   262                 targetFolderURL = new URL(targetFolderURL.toExternalForm() + "/");
   263             }
   264         } catch (IOException ignore) {
   265         }
   266         
   267         model = new DocumentModel(targetFolderURL);
   268         File file = FileUtil.toFile(schemaFileObject);
   269         String uri = file.getPath();
   270         if (uri != null) {
   271                try {
   272                     // escape the non-ASCII characters
   273                     uri = new URI(uri).toASCIIString();
   274                 } catch (URISyntaxException e) {
   275                   // the specified uri is not valid, it is too late to fix it now
   276                 }
   277              }
   278         model.setPrimarySchema(uri);
   279         
   280         xmlPanel.setObject(model);
   281         model.setPrefix(PREFIX);
   282         String ns = SchemaParser.getNamespace(schemaFileObject);
   283         model.setNamespace(ns);   
   284     }
   285 
   286     public void uninitialize(WizardDescriptor wizard) {
   287         panels = null;
   288     }
   289 
   290     public WizardDescriptor.Panel current() {
   291         return panels[index];
   292     }
   293 
   294     public String name() {
   295         return NbBundle.getMessage(SchemaWizardIterator.class, "TITLE_x_of_y",
   296             Integer.valueOf(index + 1), Integer.valueOf(panels.length));
   297     }
   298 
   299     public boolean hasNext() {
   300         return index < getPanels().length - 1;
   301     }
   302 
   303     public boolean hasPrevious() {
   304         return index > 0;
   305     }
   306 
   307     public void nextPanel() {
   308         if (!hasNext()) {
   309             throw new NoSuchElementException();
   310         }
   311         index++;
   312     }
   313 
   314     public void previousPanel() {
   315         if (!hasPrevious()) {
   316             throw new NoSuchElementException();
   317         }
   318         index--;
   319     }
   320 
   321     // If nothing unusual changes in the middle of the wizard, simply:
   322     public void addChangeListener(ChangeListener l) {
   323     }
   324 
   325     public void removeChangeListener(ChangeListener l) {
   326     }
   327 
   328       
   329     private void generateXMLBody(DocumentModel model, String root, StringBuffer writer){
   330         XMLGeneratorVisitor visitor = new XMLGeneratorVisitor(model.getPrimarySchema(), model.getXMLContentAttributes(), writer);
   331         visitor.generateXML(root);
   332        
   333     }
   334     
   335     private void modifyRootElementAttrs(FileObject fobj) {
   336         try {
   337             File file = new File(fobj.getPath());
   338             DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
   339             DocumentBuilder db = dbf.newDocumentBuilder();
   340             Document doc = db.parse(file);
   341             doc.getDocumentElement().normalize();
   342             
   343             NamedNodeMap rootAttributes = doc.getDocumentElement().getAttributes();
   344             Map<String, String> nsAttrs = model.getXMLContentAttributes().getNamespaceToPrefixMap();
   345             
   346             if(nsAttrs == null || nsAttrs.size() == 0)
   347                 return;
   348             for(String ns:nsAttrs.keySet()) {
   349                 Attr galaxy = doc.createAttribute("xmlns:" + nsAttrs.get(ns));
   350                 galaxy.setValue(ns);
   351                 rootAttributes.setNamedItem(galaxy);
   352             }
   353 
   354             //write to oputput file
   355             Transformer transformer = TransformerFactory.newInstance().newTransformer();
   356             transformer.setOutputProperty(OutputKeys.INDENT, "yes");
   357 
   358             DOMSource source = new DOMSource(doc);
   359             Result result = new StreamResult(file);
   360             transformer.transform(source, result);
   361  
   362        } catch(Exception e) {
   363           
   364        }
   365     }
   366     
   367     private void writeXMLComment(StringBuffer writer, String filename, String encoding) throws IOException {
   368         writer.append("<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n");  // NOI18N
   369         writer.append("\n");                                         // NOI18N
   370         // comment
   371         Date now = new Date();
   372         String currentDate = DateFormat.getDateInstance(DateFormat.LONG).format(now);
   373         String currentTime = DateFormat.getTimeInstance(DateFormat.SHORT).format(now);
   374         String userName = System.getProperty("user.name");
   375         writer.append("<!--\n"); // NOI18N
   376         writer.append("    Document   : " + filename + "\n"); // NOI18N
   377         writer.append("    Created on : " + currentDate + ", " + currentTime + "\n"); // NOI18N
   378         writer.append("    Author     : " + userName + "\n"); // NOI18N
   379         writer.append("    Description:\n"); // NOI18N
   380         writer.append("        Purpose of the document follows.\n"); // NOI18N
   381         writer.append("-->\n"); // NOI18N
   382         writer.append("\n");
   383     }
   384     
   385     
   386     
   387     private void formatXML(FileObject fobj){
   388         try {
   389             DataObject dobj = DataObject.find(fobj);
   390             EditorCookie ec = dobj.getCookie(EditorCookie.class);
   391             if (ec == null) {
   392                 return;
   393             }
   394             BaseDocument doc = (BaseDocument) ec.getDocument();
   395             org.netbeans.modules.xml.text.api.XMLFormatUtil.reformat(doc, 0, doc.getLength());
   396             EditCookie cookie = dobj.getCookie(EditCookie.class);
   397             if (cookie instanceof TextEditorSupport) {
   398                 if (cookie != null) {
   399                     ((TextEditorSupport) cookie).saveDocument();
   400                 } 
   401             }
   402 
   403         } catch (Exception e) {
   404             //if exception , then the file will be informatted
   405         }
   406                  
   407         
   408     }
   409     
   410     private void modifyRootElementAttrs(StringBuffer xmlBuffer) {
   411          Map<String, String> nsAttrs = model.getXMLContentAttributes().getNamespaceToPrefixMap();
   412            
   413          if (nsAttrs == null || nsAttrs.size() == 0) {
   414              return;
   415          }
   416          int firstOccur = xmlBuffer.indexOf("xmlns");
   417          int insertLoc = xmlBuffer.indexOf("xmlns", firstOccur + 1);
   418 
   419          StringBuffer sb = new StringBuffer();
   420          for (String ns : nsAttrs.keySet()) {
   421              String xmlnsString = "xmlns:" + nsAttrs.get(ns) + "='" + ns + "'";
   422              if (xmlBuffer.indexOf(xmlnsString) == -1) {
   423                  xmlBuffer.insert(insertLoc, xmlnsString + "\n   ");
   424              }
   425          }
   426          xmlBuffer.insert(insertLoc, sb.toString());            
   427             
   428      }
   429 
   430      
   431     private void writeXMLFile(StringBuffer writer) throws IOException {
   432         String root = model.getRoot();
   433         if (root == null) {
   434             root = "root";
   435         }
   436         String prefix = model.getPrefix();
   437         String namespace = model.getNamespace();
   438         if (prefix == null || "".equals(prefix)) {
   439             writer.append("<" + root + "  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n");
   440         } else {
   441             writer.append("<" + prefix + ":" + root + "  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n");
   442         }
   443 
   444         if (prefix == null || "".equals(prefix)) {
   445             writer.append("   xmlns='" + namespace + "'\n");
   446         } else {
   447             writer.append("   xmlns:" + prefix + "='" + namespace + "'\n");
   448         }
   449         writer.append("   xsi:schemaLocation='" + namespace + " " + schemaFileObject.getNameExt() + "'>\n");
   450         generateXMLBody(model, root, writer);
   451         modifyRootElementAttrs(writer);
   452         if (prefix == null || "".equals(prefix)) {
   453             writer.append("\n");                                         // NOI18N
   454             writer.append("</" + root + ">\n");                          // NOI18N
   455         } else {
   456             writer.append("\n");                                         // NOI18N
   457             writer.append("</" + prefix + ":" + root + ">\n");
   458         }
   459 
   460       //  writer.flush();
   461      //   writer.close();
   462 
   463     }
   464     
   465 
   466     // If something changes dynamically (besides moving between panels), e.g.
   467     // the number of panels changes in response to user input, then uncomment
   468     // the following and call when needed: fireChangeEvent();
   469     /*
   470     private Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
   471     public final void addChangeListener(ChangeListener l) {
   472     synchronized (listeners) {
   473     listeners.add(l);
   474     }
   475     }
   476     public final void removeChangeListener(ChangeListener l) {
   477     synchronized (listeners) {
   478     listeners.remove(l);
   479     }
   480     }
   481     protected final void fireChangeEvent() {
   482     Iterator<ChangeListener> it;
   483     synchronized (listeners) {
   484     it = new HashSet<ChangeListener>(listeners).iterator();
   485     }
   486     ChangeEvent ev = new ChangeEvent(this);
   487     while (it.hasNext()) {
   488     it.next().stateChanged(ev);
   489     }
   490     }
   491      */
   492 
   493     }