001: /*
002: * To change this template, choose Tools | Templates
003: * and open the template in the editor.
004: */
005: package org.netbeans.modules.xml.schema.wizard;
006:
007: import java.awt.Component;
008: import java.awt.Dialog;
009: import java.io.BufferedOutputStream;
010: import java.io.File;
011: import java.io.IOException;
012: import java.io.OutputStream;
013: import java.io.OutputStreamWriter;
014: import java.io.Writer;
015: import java.net.URI;
016: import java.net.URISyntaxException;
017: import java.net.URL;
018: import java.text.DateFormat;
019: import java.text.MessageFormat;
020: import java.util.Collections;
021: import java.util.Date;
022: import java.util.HashSet;
023: import java.util.NoSuchElementException;
024: import java.util.Set;
025: import javax.swing.JComponent;
026: import javax.swing.event.ChangeListener;
027: import org.netbeans.api.project.FileOwnerQuery;
028: import org.netbeans.api.project.Project;
029: import org.netbeans.api.project.ProjectUtils;
030: import org.netbeans.api.project.SourceGroup;
031: import org.netbeans.api.project.Sources;
032: import org.netbeans.modules.xml.api.EncodingUtil;
033: import org.netbeans.modules.xml.schema.SchemaDataObject;
034: import org.netbeans.modules.xml.wizard.AbstractPanel;
035: import org.netbeans.modules.xml.wizard.DocumentModel;
036: import org.netbeans.modules.xml.wizard.Util;
037: import org.netbeans.modules.xml.wizard.XMLContentPanel;
038: import org.netbeans.modules.xml.wizard.XMLGeneratorVisitor;
039: import org.netbeans.modules.xml.xam.ui.ProjectConstants;
040: import org.openide.DialogDisplayer;
041: import org.openide.WizardDescriptor;
042: import org.openide.filesystems.FileObject;
043: import org.openide.loaders.DataFolder;
044: import org.netbeans.spi.project.ui.templates.support.Templates;
045: import org.openide.filesystems.FileLock;
046: import org.openide.filesystems.FileSystem;
047: import org.openide.filesystems.FileUtil;
048: import org.openide.loaders.DataObject;
049: import org.openide.util.NbBundle;
050:
051: public final class SampleXMLGeneratorWizardIterator implements
052: WizardDescriptor.InstantiatingIterator {
053:
054: private int index;
055: private WizardDescriptor wizard;
056: private WizardDescriptor.Panel[] panels;
057: private Project srcProject;
058: private DataFolder df;
059: private FileObject schemaFileObject;
060: private DocumentModel model;
061: private XMLContentPanel xmlPanel;
062: private static String PREFIX = "ns0";
063: private static final String XML_EXT = "xml";
064:
065: public SampleXMLGeneratorWizardIterator(SchemaDataObject dobj) {
066: schemaFileObject = dobj.getPrimaryFile();
067: this .srcProject = FileOwnerQuery.getOwner(schemaFileObject);
068: }
069:
070: public void show() {
071: WizardDescriptor wizardDescriptor = new WizardDescriptor(
072: getPanels());
073: initialize(wizardDescriptor);
074: wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
075: wizardDescriptor.setTitle(NbBundle.getMessage(
076: SampleXMLGeneratorWizardIterator.class,
077: "TITLE_XML_WIZARD"));
078: Dialog dialog = DialogDisplayer.getDefault().createDialog(
079: wizardDescriptor);
080: dialog.setVisible(true);
081: dialog.toFront();
082: boolean cancelled = wizardDescriptor.getValue() != WizardDescriptor.FINISH_OPTION;
083:
084: if (!cancelled) {
085: try {
086: instantiate();
087: } catch (Exception e) {
088: e.printStackTrace();
089: }
090: }
091:
092: }
093:
094: /**
095: * Initialize panels representing individual wizard's steps and sets
096: * various properties for them influencing wizard appearance.
097: */
098: private WizardDescriptor.Panel[] getPanels() {
099:
100: xmlPanel = new XMLContentPanel(true);
101:
102: if (panels == null) {
103: panels = new WizardDescriptor.Panel[] {
104: //Templates.createSimpleTargetChooser(srcProject, folders)
105: new AbstractPanel.WizardStep(xmlPanel) };
106: String[] steps = new String[panels.length];
107: for (int i = 0; i < panels.length; i++) {
108: Component c = panels[i].getComponent();
109: if (steps[i] == null) {
110: // Default step name to component name of panel. Mainly
111: // useful for getting the name of the target chooser to
112: // appear in the list of steps.
113: steps[i] = c.getName();
114: }
115: if (c instanceof JComponent) { // assume Swing components
116: JComponent jc = (JComponent) c;
117: // Sets step number of a component
118: jc.putClientProperty(
119: "WizardPanel_contentSelectedIndex",
120: new Integer(i));
121: // Sets steps names for a panel
122: jc.putClientProperty("WizardPanel_contentData",
123: steps);
124: // Turn on subtitle creation on each step
125: jc.putClientProperty("WizardPanel_autoWizardStyle",
126: Boolean.TRUE);
127: // Show steps on the left side with the image on the background
128: jc.putClientProperty(
129: "WizardPanel_contentDisplayed",
130: Boolean.TRUE);
131: // Turn on numbering of all steps
132: jc.putClientProperty("WizardPanel_contentNumbered",
133: Boolean.TRUE);
134: }
135: }
136: }
137: return panels;
138: }
139:
140: public Set instantiate() throws IOException {
141: final String extension = XML_EXT;
142:
143: String targetName = schemaFileObject.getName();
144: if (targetName == null || "null".equals(targetName)) { // NOI18N
145: targetName = "XMLDocument"; // NOI18N
146: }
147:
148: final FileObject targetFolder = schemaFileObject.getParent();
149: String uniqueTargetName = targetName;
150: int i = 2;
151: while (targetFolder.getFileObject(uniqueTargetName, extension) != null) {
152: uniqueTargetName = targetName + i;
153: i++;
154: }
155:
156: final String name = uniqueTargetName;
157:
158: // in atomic action create data object and return it
159:
160: FileSystem filesystem = targetFolder.getFileSystem();
161: final FileObject[] fileObject = new FileObject[1];
162: FileSystem.AtomicAction fsAction = new FileSystem.AtomicAction() {
163: public void run() throws IOException {
164: //use the project's encoding if there is one
165: String encoding = EncodingUtil
166: .getProjectEncoding(targetFolder);
167: if (!EncodingUtil.isValidEncoding(encoding))
168: encoding = "UTF-8"; //NOI18N
169: FileObject fo = targetFolder
170: .createData(name, extension);
171: FileLock lock = null;
172: try {
173: lock = fo.lock();
174: OutputStream out = fo.getOutputStream(lock);
175: out = new BufferedOutputStream(out, 999);
176: Writer writer = new OutputStreamWriter(out,
177: encoding); // NOI18N
178:
179: String root = model.getRoot();
180: if (root == null)
181: root = "root";
182: String prefix = model.getPrefix();
183:
184: // generate file content
185: // header
186: writer.write("<?xml version=\"1.0\" encoding=\""
187: + encoding + "\"?>\n"); // NOI18N
188: writer.write("\n"); // NOI18N
189: // comment
190: String nameExt = name + "." + extension; // NOI18N
191: Date now = new Date();
192: String currentDate = DateFormat.getDateInstance(
193: DateFormat.LONG).format(now);
194: String currentTime = DateFormat.getTimeInstance(
195: DateFormat.SHORT).format(now);
196: String userName = System.getProperty("user.name");
197: writer.write("<!--\n"); // NOI18N
198: writer.write(" Document : " + nameExt + "\n"); // NOI18N
199: writer.write(" Created on : " + currentDate
200: + ", " + currentTime + "\n"); // NOI18N
201: writer.write(" Author : " + userName + "\n"); // NOI18N
202: writer.write(" Description:\n"); // NOI18N
203: writer
204: .write(" Purpose of the document follows.\n"); // NOI18N
205: writer.write("-->\n"); // NOI18N
206: writer.write("\n"); // NOI18N
207:
208: String namespace = model.getNamespace();
209:
210: if (prefix == null || "".equals(prefix)) {
211: writer
212: .write("<"
213: + root
214: + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n");
215: } else {
216: writer
217: .write("<"
218: + prefix
219: + ":"
220: + root
221: + " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n");
222: }
223:
224: if (prefix == null || "".equals(prefix)) {
225: writer.write(" xmlns='" + namespace + "'\n");
226: } else {
227: writer.write(" xmlns:" + prefix + "='"
228: + namespace + "'\n");
229: }
230:
231: writer.write(" xsi:schemaLocation='" + namespace
232: + " " + schemaFileObject.getNameExt()
233: + "'>\n");
234: generateXMLBody(model, root, writer);
235:
236: if (prefix == null || "".equals(prefix)) {
237: writer.write("\n"); // NOI18N
238: writer.write("</" + root + ">\n"); // NOI18N
239: } else {
240: writer.write("\n"); // NOI18N
241: writer
242: .write("</" + prefix + ":" + root
243: + ">\n");
244: }
245:
246: writer.flush();
247: writer.close();
248:
249: // return DataObject
250: lock.releaseLock();
251: lock = null;
252:
253: fileObject[0] = fo;
254:
255: } finally {
256: if (lock != null)
257: lock.releaseLock();
258: }
259: }
260: };
261:
262: filesystem.runAtomicAction(fsAction);
263:
264: // perform default action and return
265:
266: Set set = new HashSet(1);
267: DataObject createdObject = DataObject.find(fileObject[0]);
268: Util.performDefaultAction(createdObject);
269: set.add(createdObject);
270:
271: return set;
272: }
273:
274: public void initialize(WizardDescriptor wiz) {
275: index = 0;
276: wizard = wiz;
277: URL targetFolderURL = null;
278: try {
279: FileObject folder = schemaFileObject.getParent();
280: targetFolderURL = folder.getURL();
281: //#25604 workaround
282: if (targetFolderURL.toExternalForm().endsWith("/") == false) {
283: targetFolderURL = new URL(targetFolderURL
284: .toExternalForm()
285: + "/");
286: }
287: } catch (IOException ignore) {
288: }
289:
290: model = new DocumentModel(targetFolderURL);
291: File file = FileUtil.toFile(schemaFileObject);
292: String uri = file.getPath();
293: if (uri != null) {
294: try {
295: // escape the non-ASCII characters
296: uri = new URI(uri).toASCIIString();
297: } catch (URISyntaxException e) {
298: // the specified uri is not valid, it is too late to fix it now
299: }
300: }
301: model.setPrimarySchema(uri);
302:
303: xmlPanel.setObject(model);
304: model.setPrefix(PREFIX);
305: String ns = Util.getNamespace(schemaFileObject);
306: model.setNamespace(ns);
307: }
308:
309: public void uninitialize(WizardDescriptor wizard) {
310: panels = null;
311: wizard = null;
312: }
313:
314: public WizardDescriptor.Panel current() {
315: return getPanels()[index];
316: }
317:
318: public String name() {
319: return index + 1 + ". from " + getPanels().length;
320: }
321:
322: public boolean hasNext() {
323: return index < getPanels().length - 1;
324: }
325:
326: public boolean hasPrevious() {
327: return index > 0;
328: }
329:
330: public void nextPanel() {
331: if (!hasNext()) {
332: throw new NoSuchElementException();
333: }
334: index++;
335: }
336:
337: public void previousPanel() {
338: if (!hasPrevious()) {
339: throw new NoSuchElementException();
340: }
341: index--;
342: }
343:
344: // If nothing unusual changes in the middle of the wizard, simply:
345: public void addChangeListener(ChangeListener l) {
346: }
347:
348: public void removeChangeListener(ChangeListener l) {
349: }
350:
351: private void generateXMLBody(DocumentModel model, String root,
352: Writer writer) {
353: XMLGeneratorVisitor visitor = new XMLGeneratorVisitor(model
354: .getPrimarySchema(), model.getXMLContentAttributes(),
355: writer);
356: visitor.generateXML(root);
357:
358: }
359:
360: // If something changes dynamically (besides moving between panels), e.g.
361: // the number of panels changes in response to user input, then uncomment
362: // the following and call when needed: fireChangeEvent();
363: /*
364: private Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
365: public final void addChangeListener(ChangeListener l) {
366: synchronized (listeners) {
367: listeners.add(l);
368: }
369: }
370: public final void removeChangeListener(ChangeListener l) {
371: synchronized (listeners) {
372: listeners.remove(l);
373: }
374: }
375: protected final void fireChangeEvent() {
376: Iterator<ChangeListener> it;
377: synchronized (listeners) {
378: it = new HashSet<ChangeListener>(listeners).iterator();
379: }
380: ChangeEvent ev = new ChangeEvent(this);
381: while (it.hasNext()) {
382: it.next().stateChanged(ev);
383: }
384: }
385: */
386:
387: }
|