001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.xml.wizard;
042:
043: import java.io.File;
044: import java.io.IOException;
045: import java.io.Writer;
046: import java.util.List;
047: import org.netbeans.modules.xml.axi.AXIComponent;
048: import org.netbeans.modules.xml.axi.AXIModel;
049: import org.netbeans.modules.xml.axi.AXIModelFactory;
050: import org.netbeans.modules.xml.axi.AbstractAttribute;
051: import org.netbeans.modules.xml.axi.AnyElement;
052: import org.netbeans.modules.xml.axi.Attribute;
053: import org.netbeans.modules.xml.axi.Element;
054: import org.netbeans.modules.xml.axi.Compositor;
055: import org.netbeans.modules.xml.axi.visitor.DeepAXITreeVisitor;
056: import org.netbeans.modules.xml.retriever.catalog.Utilities;
057: import org.netbeans.modules.xml.schema.model.Attribute.Use;
058: import org.netbeans.modules.xml.schema.model.SchemaModel;
059: import org.netbeans.modules.xml.schema.model.SchemaModelFactory;
060: import org.netbeans.modules.xml.xam.ModelSource;
061: import org.openide.filesystems.FileObject;
062: import org.openide.filesystems.FileUtil;
063:
064: /**
065: *
066: * @author Samaresh (Samaresh.Panda@Sun.Com)
067: */
068: public class XMLGeneratorVisitor extends DeepAXITreeVisitor {
069:
070: /**
071: * Creates a new instance of PrintAXITreeVisitor
072: */
073:
074: private XMLContentAttributes contentAttr;
075: private String prefix;
076: private AXIModel axiModel;
077: private int depth = 0;
078: private String schemaFileName;
079: private String rootElement;
080: private Writer writer;
081:
082: public XMLGeneratorVisitor(String schemaFileName,
083: XMLContentAttributes attr, Writer writer) {
084: super ();
085: this .contentAttr = attr;
086: this .prefix = contentAttr.getPrefix();
087: this .schemaFileName = schemaFileName;
088: this .writer = writer;
089:
090: }
091:
092: public void generateXML(String rootElement) {
093: //TO DO better exception handling
094: if (rootElement == null || schemaFileName == null
095: || schemaFileName.equals("") || rootElement.equals(""))
096: return;
097: this .rootElement = rootElement;
098: File f = new File(schemaFileName);
099: f = FileUtil.normalizeFile(f);
100: FileObject fObj = FileUtil.toFileObject(f);
101: //temp fix to handle http based xsd files
102: if (fObj == null)
103: return;
104: ModelSource ms = null;
105: try {
106: ms = Utilities.createModelSource(fObj, true);
107: } catch (Exception e) {
108: //dont do anything
109: return;
110: }
111: if (ms == null)
112: return;
113: SchemaModel model = SchemaModelFactory.getDefault()
114: .getModel(ms);
115: this .axiModel = AXIModelFactory.getDefault().getModel(model);
116: Element element = findAXIGlobalElement(rootElement);
117: if (element != null) {
118: this .visit(element);
119: }
120:
121: }
122:
123: public void generateXML(Element element) {
124: if (element != null) {
125: this .visit(element);
126: }
127: }
128:
129: public void visit(Element element) {
130: int occurs = getOccurence(element.getMinOccurs(), element
131: .getMaxOccurs());
132:
133: //do we need to generate optional elements
134: if (!contentAttr.generateOptionalElements()) {
135: if (isElementOptional(element))
136: return;
137: }
138: for (int i = 0; i < occurs; i++) {
139: visitChildren(element);
140: }
141: }
142:
143: protected void visitChildren(AXIComponent component) {
144: try {
145: printModel(component);
146: depth++;
147: this .visitChildrenForXML(component);
148: this .postVisitChildren(component);
149: depth--;
150: } catch (Exception e) {
151: //need to figure out how to handle this exception
152: }
153: }
154:
155: private boolean isElementOptional(Element element) {
156: int i = Integer.parseInt(element.getMinOccurs());
157: if (i == 0)
158: return true;
159: else
160: return false;
161: }
162:
163: private void printModel(AXIComponent component) throws IOException {
164: StringBuffer buffer = new StringBuffer();
165: boolean newLine = true;
166: if (component.getChildElements().isEmpty())
167: newLine = false;
168:
169: if (component instanceof Compositor) {
170: Compositor compositor = (Compositor) component;
171: buffer.append((getTab() == null) ? compositor : getTab()
172: + compositor);
173: buffer.append("<min=" + compositor.getMinOccurs() + ":max="
174: + compositor.getMaxOccurs() + ">");
175: return;
176: }
177: if (component instanceof Element) {
178: Element element = (Element) component;
179:
180: //dont print the root element
181: if (element.getName().equals(rootElement))
182: return;
183:
184: buffer.append((getTab() == null) ? element.getName()
185: : getTab() + "<" + contentAttr.getPrefix() + ":"
186: + element.getName());
187: if (element.getAttributes().size() != 0) {
188: buffer.append(" " + getAttributes(element));
189: }
190: if (newLine)
191: writer.write(buffer.toString() + ">" + "\n");
192: else
193: writer.write(buffer.toString() + ">");
194:
195: //write the default/fixed value of the element, if any
196: writer.write(getComponentValue(element));
197: }
198: if (component instanceof AnyElement) {
199: AnyElement element = (AnyElement) component;
200: buffer.append((getTab() == null) ? element : getTab()
201: + element);
202: writer.write(buffer.toString() + "\n");
203: }
204:
205: }
206:
207: private String getAttributes(Element element) {
208: StringBuffer attrs = new StringBuffer();
209: for (AbstractAttribute attr : element.getAttributes()) {
210: if (attr instanceof Attribute) {
211: if (!contentAttr.generateOptionalAttributes()) {
212: if (((Attribute) attr).getUse()
213: .equals(Use.REQUIRED)) {
214: attrs.append(attr + "=\""
215: + getComponentValue((Attribute) attr)
216: + "\" ");
217: }
218: continue;
219: }
220: }
221: if (attr instanceof Attribute)
222: attrs.append(attr + "=\""
223: + getComponentValue((Attribute) attr) + "\" ");
224: else
225: attrs.append(attr + "= \" \" ");
226: }
227: if (attrs.length() > 0)
228: return attrs.toString().substring(0, attrs.length() - 1);
229: else
230: return attrs.toString();
231: }
232:
233: private String getTab() {
234: String tabStr = " ";
235:
236: if (depth == 0) {
237: return null;
238: }
239:
240: StringBuffer tab = new StringBuffer();
241: for (int i = 0; i < depth; i++) {
242: tab.append(tabStr);
243: }
244: return tab.toString();
245: }
246:
247: protected void visitChildrenForXML(AXIComponent component) {
248: if (!super .canVisit(component))
249: return;
250:
251: if (component instanceof Compositor) {
252: Compositor.CompositorType type = ((Compositor) component)
253: .getType();
254: if (type.equals(Compositor.CompositorType.CHOICE)) {
255: List<AXIComponent> children = component.getChildren();
256: if (children != null && children.size() > 0) {
257: component.getChildren().get(0).accept(this );
258: }
259: return;
260: }
261: }
262:
263: for (AXIComponent child : component.getChildren()) {
264: child.accept(this );
265: }
266:
267: }
268:
269: private int getOccurence(String minOccurs, String maxOccurs) {
270: if (maxOccurs.equals("unbounded"))
271: return contentAttr.getPreferredOccurences();
272:
273: int min = Integer.parseInt(minOccurs);
274: int max = Integer.parseInt(maxOccurs);
275:
276: if (contentAttr.getPreferredOccurences() > min
277: && contentAttr.getPreferredOccurences() < max)
278: return contentAttr.getPreferredOccurences();
279:
280: if (contentAttr.getPreferredOccurences() > max)
281: return max;
282:
283: if (contentAttr.getPreferredOccurences() < min)
284: return min;
285:
286: return min;
287: }
288:
289: private void postVisitChildren(AXIComponent component)
290: throws IOException {
291: if (component instanceof Element) {
292: //dont write the closing root element
293: if (((Element) component).getName().equals(rootElement))
294: return;
295:
296: if (component.getChildElements().isEmpty())
297: writer.write("</" + prefix + ":"
298: + ((Element) component).getName() + ">" + "\n");
299: else
300: writer.write(getTab() + "</" + prefix + ":"
301: + ((Element) component).getName() + ">" + "\n");
302: }
303: }
304:
305: private Element findAXIGlobalElement(String name) {
306: if (name == null)
307: return null;
308:
309: for (Element e : axiModel.getRoot().getElements()) {
310: if (e.getName().equals(name)) {
311: return e;
312: }
313: }
314:
315: return null;
316: }
317:
318: private String getComponentValue(AXIComponent component) {
319: String value = null;
320: if (component instanceof Attribute) {
321: Attribute attribute = (Attribute) component;
322: value = attribute.getFixed();
323: if (value == null)
324: value = attribute.getDefault();
325: } else if (component instanceof Element) {
326: Element element = (Element) component;
327: value = element.getFixed();
328: if (value == null)
329: value = element.getDefault();
330: }
331:
332: if (value != null)
333: return value;
334: else
335: return "";
336:
337: }
338:
339: }
|