0001: /*
0002: * GeoTools - OpenSource mapping toolkit
0003: * http://geotools.org
0004: * (C) 2004-2006, GeoTools Project Managment Committee (PMC)
0005: *
0006: * This library is free software; you can redistribute it and/or
0007: * modify it under the terms of the GNU Lesser General Public
0008: * License as published by the Free Software Foundation;
0009: * version 2.1 of the License.
0010: *
0011: * This library is distributed in the hope that it will be useful,
0012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0014: * Lesser General Public License for more details.
0015: */
0016: package org.geotools.xml;
0017:
0018: import java.io.File;
0019: import java.io.FileWriter;
0020: import java.io.IOException;
0021: import java.io.Writer;
0022: import java.net.URI;
0023: import java.net.URISyntaxException;
0024: import java.util.HashMap;
0025: import java.util.Iterator;
0026: import java.util.LinkedList;
0027: import java.util.List;
0028: import java.util.Map;
0029: import java.util.logging.Level;
0030: import java.util.logging.Logger;
0031:
0032: import javax.naming.OperationNotSupportedException;
0033:
0034: import org.geotools.xml.handlers.xsi.AttributeHandler;
0035: import org.geotools.xml.handlers.xsi.ComplexTypeHandler;
0036: import org.geotools.xml.schema.All;
0037: import org.geotools.xml.schema.Any;
0038: import org.geotools.xml.schema.Attribute;
0039: import org.geotools.xml.schema.AttributeGroup;
0040: import org.geotools.xml.schema.Choice;
0041: import org.geotools.xml.schema.ComplexType;
0042: import org.geotools.xml.schema.Element;
0043: import org.geotools.xml.schema.ElementGrouping;
0044: import org.geotools.xml.schema.Facet;
0045: import org.geotools.xml.schema.Group;
0046: import org.geotools.xml.schema.Schema;
0047: import org.geotools.xml.schema.Sequence;
0048: import org.geotools.xml.schema.SimpleType;
0049: import org.geotools.xml.schema.Type;
0050: import org.geotools.xml.xsi.XSISimpleTypes;
0051: import org.xml.sax.Attributes;
0052: import org.xml.sax.helpers.AttributesImpl;
0053:
0054: /**
0055: * This is the thing that writes documents.
0056: *
0057: * <p>
0058: * This will create valid XML documents, given an object and a schema.
0059: * </p>
0060: *
0061: * @author dzwiers
0062: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/xml/src/main/java/org/geotools/xml/DocumentWriter.java $
0063: */
0064: public class DocumentWriter {
0065: /** DOCUMENT ME! */
0066: public static final Logger logger = org.geotools.util.logging.Logging
0067: .getLogger("net.refractions.xml.write");
0068: private static Level level = Level.WARNING;
0069:
0070: /**
0071: * Writer ... include the key to represent true when writing to files,
0072: * include a Writer to write to otherwise.
0073: */
0074: public static final String WRITE_SCHEMA = "DocumentWriter_WRITE_SCHEMA";
0075:
0076: /**
0077: * Element or String ... include a ref to an Element to be used, or a
0078: * string representing the name of the element
0079: */
0080: public static final String BASE_ELEMENT = "DocumentWriter_BASE_ELEMENT";
0081:
0082: /**
0083: * Schema[] or String[]... The order to search the schemas for a valid
0084: * element, either an array of ref to Schema instances or an Array or
0085: * TargetNamespaces
0086: */
0087: public static final String SCHEMA_ORDER = "DocumentWriter_SCHEMA_ORDER";
0088:
0089: /**
0090: * The Encoding which should be used for the Document which should be created.
0091: */
0092: public static final String ENCODING = "DocumentWriter_ENCODING";
0093:
0094: // TODO implement this searchOrder
0095:
0096: /**
0097: * boolean ... include the key to use the "nearest" strategy for searching
0098: * schemas. This will be ignored if a schema order was set. When not
0099: * included the schema order as they appear in the orginal schema will be
0100: * used.
0101: */
0102: public static final String USE_NEAREST = "DocumentWriter_USE_NEAREST";
0103:
0104: /** a map of URI->URI representing targetNamespace->Location */
0105: public static final String SCHEMA_LOCATION_HINT = "DocumentWriter_SCHEMA_LOCATION_HINT";
0106:
0107: /**
0108: * Sets the logger level
0109: *
0110: * @param l Level
0111: */
0112: public static void setLevel(Level l) {
0113: level = l;
0114: logger.setLevel(l);
0115: }
0116:
0117: /**
0118: * Write value to file using provided schema.
0119: *
0120: * <p>
0121: * Hints:
0122: *
0123: * <ul>
0124: * <li>
0125: * WRITE_SCHEMA - (non null) write to outputfilename.xsd
0126: * </li>
0127: * <li>
0128: * BASE_ELEMENT - (Element) mapping of value to element instance
0129: * </li>
0130: * <li>
0131: * USE_NEAREST - (Boolean) not implemented
0132: * </li>
0133: * <li>
0134: * SCHEMA_ORDER - (String[] or Schema[]) resolve ambiguity & import
0135: * </li>
0136: * </ul>
0137: * </p>
0138: *
0139: * @param value
0140: * @param schema
0141: * @param f
0142: * @param hints
0143: *
0144: * @throws OperationNotSupportedException
0145: * @throws IOException
0146: *
0147: */
0148: public static void writeDocument(Object value, Schema schema,
0149: File f, Map hints) throws OperationNotSupportedException,
0150: IOException {
0151: if ((f == null) || (!f.canWrite())) {
0152: throw new IOException("Cannot write to " + f);
0153: }
0154:
0155: if ((hints != null) && hints.containsKey(WRITE_SCHEMA)) {
0156: Map hints2 = new HashMap(hints);
0157: hints2.remove(WRITE_SCHEMA);
0158:
0159: File f2 = new File(f.getParentFile(), f.getName()
0160: .substring(0, f.getName().indexOf("."))
0161: + ".xsd");
0162: FileWriter wf = new FileWriter(f2);
0163: writeSchema(schema, wf, hints2);
0164: wf.close();
0165: }
0166:
0167: FileWriter wf = new FileWriter(f);
0168: writeDocument(value, schema, wf, hints);
0169: wf.close();
0170: }
0171:
0172: /**
0173: * Entry Point to Document writer.
0174: *
0175: * <p>
0176: * Hints:
0177: *
0178: * <ul>
0179: * <li>
0180: * WRITE_SCHEMA - (Writer) will be used to write the schema
0181: * </li>
0182: * <li>
0183: * BASE_ELEMENT - (Element) mapping of value to element instance
0184: * </li>
0185: * <li>
0186: * USE_NEAREST - (Boolean) not implemented
0187: * </li>
0188: * <li>
0189: * SCHEMA_ORDER - (String[] or Schema[]) resolve ambiguity & import
0190: * </li>
0191: * </ul>
0192: * </p>
0193: *
0194: * @param value
0195: * @param schema
0196: * @param w
0197: * @param hints optional hints for writing
0198: *
0199: * @throws OperationNotSupportedException
0200: * @throws IOException
0201: *
0202: */
0203: public static void writeDocument(Object value, Schema schema,
0204: Writer w, Map hints) throws OperationNotSupportedException,
0205: IOException {
0206: if ((hints != null) && hints.containsKey(WRITE_SCHEMA)) {
0207: Writer w2 = (Writer) hints.get(WRITE_SCHEMA);
0208: writeSchema(schema, w2, hints);
0209:
0210: }
0211:
0212: WriterContentHandler wch = new WriterContentHandler(schema, w,
0213: hints); // should deal with xmlns declarations
0214: wch.startDocument();
0215:
0216: writeFragment(value, wch);
0217:
0218: wch.endDocument();
0219: w.flush();
0220: }
0221:
0222: /**
0223: * Write value to file using provided schema.
0224: *
0225: * <p>
0226: * Hints:
0227: *
0228: * <ul>
0229: * <li>
0230: * BASE_ELEMENT - (Element) mapping of value to element instance
0231: * </li>
0232: * <li>
0233: * USE_NEAREST - (Boolean) not implemented
0234: * </li>
0235: * <li>
0236: * SCHEMA_ORDER - (String[] or Schema[]) resolve ambiguity & import
0237: * </li>
0238: * </ul>
0239: * </p>
0240: *
0241: * @param value
0242: * @param schema
0243: * @param f
0244: * @param hints
0245: *
0246: * @throws OperationNotSupportedException
0247: * @throws IOException
0248: *
0249: */
0250: public static void writeFragment(Object value, Schema schema,
0251: File f, Map hints) throws OperationNotSupportedException,
0252: IOException {
0253: if ((f == null) || (!f.canWrite())) {
0254: throw new IOException("Cannot write to " + f);
0255: }
0256:
0257: FileWriter wf = new FileWriter(f);
0258: writeFragment(value, schema, wf, hints);
0259: wf.close();
0260: }
0261:
0262: /**
0263: * Entry Point to Document writer.
0264: *
0265: * <p>
0266: * Hints:
0267: *
0268: * <ul>
0269: * <li>
0270: * BASE_ELEMENT - (Element) mapping of value to element instance
0271: * </li>
0272: * <li>
0273: * USE_NEAREST - (Boolean) not implemented
0274: * </li>
0275: * <li>
0276: * SCHEMA_ORDER - (String[] or Schema[]) resolve ambiguity & import
0277: * </li>
0278: * </ul>
0279: * </p>
0280: *
0281: * @param value
0282: * @param schema
0283: * @param w
0284: * @param hints optional hints for writing
0285: *
0286: * @throws OperationNotSupportedException
0287: * @throws IOException
0288: *
0289: */
0290: public static void writeFragment(Object value, Schema schema,
0291: Writer w, Map hints) throws OperationNotSupportedException,
0292: IOException {
0293: WriterContentHandler wch = new WriterContentHandler(schema, w,
0294: hints); // should deal with xmlns declarations
0295:
0296: writeFragment(value, wch);
0297:
0298: w.flush();
0299: }
0300:
0301: private static void writeFragment(Object value,
0302: WriterContentHandler wch)
0303: throws OperationNotSupportedException, IOException {
0304:
0305: Element e = null;
0306: logger.setLevel(level);
0307:
0308: if ((wch.hints != null) && wch.hints.containsKey(BASE_ELEMENT)) {
0309: e = (Element) wch.hints.get(BASE_ELEMENT);
0310:
0311: if ((e != null) && (e.getType() != null)) {
0312: e = e.getType().canEncode(e, value, wch.hints) ? e
0313: : null;
0314: }
0315: }
0316:
0317: if (e == null) {
0318: e = wch.findElement(value);
0319: }
0320:
0321: if (e != null) {
0322: Type type = e.getType();
0323: type.encode(e, value, wch, wch.hints);
0324: } else {
0325: throw new OperationNotSupportedException(
0326: "Could not find an appropriate Element to use for encoding of a "
0327: + ((value == null) ? null : value
0328: .getClass().getName()));
0329: }
0330: }
0331:
0332: /**
0333: * DOCUMENT ME!
0334: *
0335: * @param schema DOCUMENT ME!
0336: * @param w DOCUMENT ME!
0337: * @param hints DOCUMENT ME!
0338: *
0339: * @throws IOException
0340: */
0341: public static void writeSchema(Schema schema, Writer w, Map hints)
0342: throws IOException {
0343: WriterContentHandler wch = new WriterContentHandler(schema, w,
0344: hints); // should deal with xmlns declarations
0345: Element[] elems = schema.getElements();
0346:
0347: if (elems == null) {
0348: throw new IOException("Cannot write for Schema "
0349: + schema.getTargetNamespace());
0350: }
0351:
0352: wch.startDocument();
0353:
0354: writeSchema(schema, wch, hints);
0355:
0356: wch.endDocument();
0357: }
0358:
0359: private static void writeSchema(Schema schema, PrintHandler ph,
0360: Map hints) throws IOException {
0361: if (schema == null) {
0362: return;
0363: }
0364:
0365: AttributesImpl ai = new AttributesImpl();
0366:
0367: ai.addAttribute("", "targetNamespace", "", "anyUri", schema
0368: .getTargetNamespace().toString());
0369: ai.addAttribute("", "xmlns", "", "anyUri",
0370: XSISimpleTypes.NAMESPACE.toString());
0371: ai.addAttribute("", "xmlns:" + schema.getPrefix(), "",
0372: "anyUri", schema.getTargetNamespace().toString());
0373:
0374: Schema[] imports = schema.getImports();
0375:
0376: for (int i = 0; i < imports.length; i++) {
0377: ai.addAttribute("", "xmlns:" + imports[i].getPrefix(), "",
0378: "anyUri", imports[i].getTargetNamespace()
0379: .toString());
0380: }
0381:
0382: if ((schema.getId() != null) && (schema.getId() != "")) {
0383: ai.addAttribute("", "id", "", "ID", schema.getId());
0384: }
0385:
0386: if ((schema.getVersion() != null)
0387: && (schema.getVersion() != "")) {
0388: ai.addAttribute("", "version", "", "String", schema
0389: .getVersion());
0390: }
0391:
0392: if (schema.isAttributeFormDefault()) {
0393: ai.addAttribute("", "attributeFormDefault", "", "NMTOKEN",
0394: "qualified");
0395: }
0396:
0397: if (schema.isElementFormDefault()) {
0398: ai.addAttribute("", "elementFormDefault", "", "NMTOKEN",
0399: "qualified");
0400: }
0401:
0402: if (schema.getBlockDefault() != Schema.NONE) {
0403: ai.addAttribute("", "blockDefault", "", "NMTOKENS",
0404: ComplexTypeHandler.writeBlock(schema
0405: .getBlockDefault()));
0406: }
0407:
0408: if (schema.getFinalDefault() != Schema.NONE) {
0409: ai.addAttribute("", "finalDefault", "", "NMTOKENS",
0410: ComplexTypeHandler.writeFinal(schema
0411: .getFinalDefault()));
0412: }
0413:
0414: ph.startElement(XSISimpleTypes.NAMESPACE, "schema", ai);
0415:
0416: for (int i = 0; i < imports.length; i++)
0417: writeImport(imports[i], ph);
0418:
0419: Element[] elems = schema.getElements();
0420:
0421: if (elems != null) {
0422: for (int i = 0; i < elems.length; i++)
0423: writeElement(elems[i], schema, ph, hints);
0424: }
0425:
0426: ComplexType[] cts = schema.getComplexTypes();
0427:
0428: if (elems != null) {
0429: for (int i = 0; i < cts.length; i++)
0430: writeComplexType(cts[i], schema, ph, hints);
0431: }
0432:
0433: SimpleType[] sts = schema.getSimpleTypes();
0434:
0435: if (elems != null) {
0436: for (int i = 0; i < sts.length; i++)
0437: writeSimpleType(sts[i], schema, ph, hints);
0438: }
0439:
0440: Group[] groups = schema.getGroups();
0441:
0442: if (elems != null) {
0443: for (int i = 0; i < groups.length; i++)
0444: writeGroup(groups[i], schema, ph, hints);
0445: }
0446:
0447: Attribute[] attrs = schema.getAttributes();
0448:
0449: if (elems != null) {
0450: for (int i = 0; i < attrs.length; i++)
0451: writeAttribute(attrs[i], schema, ph, hints);
0452: }
0453:
0454: AttributeGroup[] attrgrps = schema.getAttributeGroups();
0455:
0456: if (elems != null) {
0457: for (int i = 0; i < attrgrps.length; i++)
0458: writeAttributeGroup(attrgrps[i], schema, ph, hints);
0459: }
0460:
0461: ph.endElement(XSISimpleTypes.NAMESPACE, "schema");
0462: }
0463:
0464: private static void writeImport(Schema schema, PrintHandler ph)
0465: throws IOException {
0466: AttributesImpl ai = new AttributesImpl();
0467:
0468: if ((schema.getId() != null) && (schema.getId() != "")) {
0469: ai.addAttribute("", "id", "", "ID", schema.getId());
0470: }
0471:
0472: ai.addAttribute("", "namespace", "", "anyUri", schema
0473: .getTargetNamespace().toString());
0474:
0475: if (schema.getURI() != null) {
0476: ai.addAttribute("", "schemaLocation", "", "anyUri", schema
0477: .getURI().toString());
0478: }
0479:
0480: ph.element(XSISimpleTypes.NAMESPACE, "import", ai);
0481: }
0482:
0483: private static void writeElement(Element element, Schema schema,
0484: PrintHandler ph, Map hints) throws IOException {
0485: AttributesImpl ai = new AttributesImpl();
0486:
0487: if ((element.getId() != null) && (element.getId() != "")) {
0488: ai.addAttribute("", "id", "", "ID", element.getId());
0489: }
0490:
0491: if (element.getMaxOccurs() != 1) {
0492: ai
0493: .addAttribute(
0494: "",
0495: "maxOccurs",
0496: "",
0497: "Union",
0498: (element.getMaxOccurs() == ElementGrouping.UNBOUNDED) ? "unbounded"
0499: : ("" + element.getMaxOccurs()));
0500: }
0501:
0502: if (element.getMinOccurs() != 1) {
0503: ai.addAttribute("", "minOccurs", "", "ID", ""
0504: + element.getMinOccurs());
0505: }
0506:
0507: boolean nested = false;
0508:
0509: if (element.getNamespace().equals(schema.getTargetNamespace())) {
0510: // search schema for element, then it's a ref
0511: Element[] elems = schema.getElements();
0512: boolean found = false;
0513:
0514: for (int i = 0; (i < elems.length) && !found; i++)
0515: if (element.getName().equals(elems[i].getName())) {
0516: found = true;
0517: ai.addAttribute("", "ref", "", "QName", element
0518: .getName());
0519: }
0520:
0521: if (!found) {
0522: // type in other NS
0523: if (!element.getType().getNamespace().equals(
0524: schema.getTargetNamespace())) {
0525: found = true;
0526: XSISAXHandler.setLogLevel(logger.getLevel());
0527: Schema s = SchemaFactory.getInstance(element
0528: .getNamespace());
0529:
0530: if ((element.getName() != null)
0531: && (element.getName() != "")) {
0532: ai.addAttribute("", "name", "", "QName",
0533: element.getName());
0534: }
0535:
0536: ai.addAttribute("", "type", "", "QName", s
0537: .getPrefix()
0538: + ":" + element.getType().getName());
0539: }
0540:
0541: // search schema for type, then type can be a qName
0542: Type[] types = schema.getComplexTypes();
0543:
0544: for (int i = 0; (i < types.length) && !found; i++)
0545:
0546: // TODO use equals here
0547: if (element.getType().getName().equals(
0548: types[i].getName())) {
0549: found = true;
0550:
0551: if ((element.getName() != null)
0552: && (element.getName() != "")) {
0553: ai.addAttribute("", "name", "", "QName",
0554: element.getName());
0555: }
0556:
0557: ai.addAttribute("", "type", "", "QName",
0558: element.getType().getName());
0559: }
0560:
0561: types = schema.getSimpleTypes();
0562:
0563: for (int i = 0; (i < types.length) && !found; i++)
0564:
0565: // TODO use equals here
0566: if (element.getType().getName().equals(
0567: types[i].getName())) {
0568: found = true;
0569:
0570: if ((element.getName() != null)
0571: && (element.getName() != "")) {
0572: ai.addAttribute("", "name", "", "QName",
0573: element.getName());
0574: }
0575:
0576: ai.addAttribute("", "type", "", "QName",
0577: element.getType().getName());
0578: }
0579:
0580: if (!found) {
0581: // we are nested ... log this
0582: nested = true;
0583:
0584: if ((element.getName() != null)
0585: && (element.getName() != "")) {
0586: ai.addAttribute("", "name", "", "QName",
0587: element.getName());
0588: }
0589: }
0590: }
0591: } else {
0592: // use a ref
0593: Schema s = SchemaFactory
0594: .getInstance(element.getNamespace());
0595: ai.addAttribute("", "ref", "", "QName", s.getPrefix() + ":"
0596: + element.getName());
0597: }
0598:
0599: if (element.isNillable()) {
0600: ai.addAttribute("", "nillable", "", "boolean", "true");
0601: }
0602:
0603: if ((element.getDefault() != null)
0604: && (element.getDefault() != "")) {
0605: ai.addAttribute("", "default", "", "String", element
0606: .getDefault());
0607: } else {
0608: if ((element.getFixed() != null)
0609: && (element.getFixed() != "")) {
0610: ai.addAttribute("", "fixed", "", "String", element
0611: .getFixed());
0612: }
0613: }
0614:
0615: if (element.getSubstitutionGroup() != null) {
0616: String s = "";
0617:
0618: if (!element.getSubstitutionGroup().getNamespace().equals(
0619: schema.getTargetNamespace())) {
0620: Schema sss = SchemaFactory.getInstance(element
0621: .getSubstitutionGroup().getNamespace());
0622: s = sss.getPrefix() + ":";
0623: }
0624:
0625: s += element.getSubstitutionGroup().getName();
0626: ai.addAttribute("", "substitutionGroup", "", "QName", s);
0627: }
0628:
0629: if (element.isForm()) {
0630: ai.addAttribute("", "form", "", "NMTOKEN", "qualified");
0631: }
0632:
0633: if (element.getFinal() != Schema.NONE) {
0634: ai.addAttribute("", "final", "", "NMTOKENS",
0635: ComplexTypeHandler.writeFinal(element.getFinal()));
0636: }
0637:
0638: if (element.getBlock() != Schema.NONE) {
0639: ai.addAttribute("", "block", "", "NMTOKENS",
0640: ComplexTypeHandler.writeBlock(element.getBlock()));
0641: }
0642:
0643: if (element.isAbstract()) {
0644: ai.addAttribute("", "abstract", "", "boolean", "true");
0645: }
0646:
0647: ph.startElement(XSISimpleTypes.NAMESPACE, "element", ai);
0648:
0649: if (nested) {
0650: if (element.getType() instanceof ComplexType) {
0651: writeComplexType((ComplexType) element.getType(),
0652: schema, ph, hints);
0653: } else {
0654: writeSimpleType((SimpleType) element.getType(), schema,
0655: ph, hints);
0656: }
0657: }
0658:
0659: ph.endElement(XSISimpleTypes.NAMESPACE, "element");
0660: }
0661:
0662: private static void writeAttribute(Attribute attribute,
0663: Schema schema, PrintHandler ph, Map hints)
0664: throws IOException {
0665: AttributesImpl ai = new AttributesImpl();
0666:
0667: if ((attribute.getId() != null) && (attribute.getId() != "")) {
0668: ai.addAttribute("", "id", "", "ID", attribute.getId());
0669: }
0670:
0671: boolean nested = false;
0672:
0673: if (attribute.getNamespace()
0674: .equals(schema.getTargetNamespace())) {
0675: // search schema for element, then it's a ref
0676: Attribute[] elems = schema.getAttributes();
0677: boolean found = false;
0678:
0679: for (int i = 0; (i < elems.length) && !found; i++)
0680: if (attribute.getName().equals(elems[i].getName())) {
0681: found = true;
0682: ai.addAttribute("", "ref", "", "QName", attribute
0683: .getName());
0684: }
0685:
0686: if (!found) {
0687: // type in other NS
0688: if (!attribute.getSimpleType().getNamespace().equals(
0689: schema.getTargetNamespace())) {
0690: found = true;
0691: XSISAXHandler.setLogLevel(logger.getLevel());
0692: Schema s = SchemaFactory.getInstance(attribute
0693: .getNamespace());
0694:
0695: if ((attribute.getName() != null)
0696: && (attribute.getName() != "")) {
0697: ai.addAttribute("", "name", "", "QName",
0698: attribute.getName());
0699: }
0700:
0701: ai
0702: .addAttribute("", "type", "", "QName", s
0703: .getPrefix()
0704: + ":"
0705: + attribute.getSimpleType()
0706: .getName());
0707: }
0708:
0709: // search schema for type, then type can be a qName
0710: SimpleType[] types = schema.getSimpleTypes();
0711:
0712: for (int i = 0; (i < types.length) && !found; i++)
0713:
0714: // TODO use equals here
0715: if (attribute.getSimpleType().getName().equals(
0716: types[i].getName())) {
0717: found = true;
0718:
0719: if ((attribute.getName() != null)
0720: && (attribute.getName() != "")) {
0721: ai.addAttribute("", "name", "", "QName",
0722: attribute.getName());
0723: }
0724:
0725: ai.addAttribute("", "type", "", "QName",
0726: attribute.getSimpleType().getName());
0727: }
0728:
0729: if (!found) {
0730: // we are nested ... log this
0731: nested = true;
0732:
0733: if ((attribute.getName() != null)
0734: && (attribute.getName() != "")) {
0735: ai.addAttribute("", "name", "", "QName",
0736: attribute.getName());
0737: }
0738: }
0739: }
0740: } else {
0741: // use a ref
0742: Schema s = SchemaFactory.getInstance(attribute
0743: .getNamespace());
0744: ai.addAttribute("", "ref", "", "QName", s.getPrefix() + ":"
0745: + attribute.getName());
0746: }
0747:
0748: if (attribute.getUse() != Attribute.OPTIONAL) {
0749: ai.addAttribute("", "use", "", "NMTOKEN", AttributeHandler
0750: .writeUse(attribute.getUse()));
0751: }
0752:
0753: if ((attribute.getDefault() != null)
0754: && (attribute.getDefault() != "")) {
0755: ai.addAttribute("", "default", "", "String", attribute
0756: .getDefault());
0757: } else {
0758: if ((attribute.getFixed() != null)
0759: && (attribute.getFixed() != "")) {
0760: ai.addAttribute("", "fixed", "", "String", attribute
0761: .getFixed());
0762: }
0763: }
0764:
0765: if (attribute.isForm()) {
0766: ai.addAttribute("", "form", "", "NMTOKEN", "qualified");
0767: }
0768:
0769: ph.startElement(XSISimpleTypes.NAMESPACE, "attribute", ai);
0770:
0771: if (nested) {
0772: writeSimpleType(attribute.getSimpleType(), schema, ph,
0773: hints);
0774: }
0775:
0776: ph.endElement(XSISimpleTypes.NAMESPACE, "attribute");
0777: }
0778:
0779: private static void writeGroup(Group group, Schema schema,
0780: PrintHandler ph, Map hints) throws IOException {
0781: AttributesImpl ai = new AttributesImpl();
0782:
0783: if ((group.getId() != null) && (group.getId() != "")) {
0784: ai.addAttribute("", "id", "", "ID", group.getId());
0785: }
0786:
0787: boolean nested = false;
0788:
0789: if (group.getNamespace().equals(schema.getTargetNamespace())) {
0790: // search schema for element, then it's a ref
0791: Group[] groups = schema.getGroups();
0792: boolean found = false;
0793:
0794: for (int i = 0; (i < groups.length) && !found; i++)
0795: if (group.getName().equals(groups[i].getName())) {
0796: found = true;
0797: ai.addAttribute("", "ref", "", "QName", group
0798: .getName());
0799: }
0800:
0801: if (!found) {
0802: ai.addAttribute("", "name", "", "QName", group
0803: .getName());
0804: nested = true;
0805: }
0806: } else {
0807: // use a ref
0808: XSISAXHandler.setLogLevel(logger.getLevel());
0809: Schema s = SchemaFactory.getInstance(group.getNamespace());
0810: ai.addAttribute("", "ref", "", "QName", s.getPrefix() + ":"
0811: + group.getName());
0812: }
0813:
0814: if (group.getMaxOccurs() != 1) {
0815: ai
0816: .addAttribute(
0817: "",
0818: "maxOccurs",
0819: "",
0820: "Union",
0821: (group.getMaxOccurs() == ElementGrouping.UNBOUNDED) ? "unbounded"
0822: : ("" + group.getMaxOccurs()));
0823: }
0824:
0825: if (group.getMinOccurs() != 1) {
0826: ai.addAttribute("", "minOccurs", "", "ID", ""
0827: + group.getMinOccurs());
0828: }
0829:
0830: ph.startElement(XSISimpleTypes.NAMESPACE, "group", ai);
0831:
0832: if (nested) {
0833: if (group.getChild().getGrouping() == ElementGrouping.CHOICE) {
0834: writeChoice((Choice) group.getChild(), schema, ph,
0835: hints);
0836: } else {
0837: writeSequence((Sequence) group.getChild(), schema, ph,
0838: hints);
0839: }
0840: }
0841:
0842: ph.endElement(XSISimpleTypes.NAMESPACE, "group");
0843: }
0844:
0845: private static void writeAttributeGroup(
0846: AttributeGroup attributeGroup, Schema schema,
0847: PrintHandler ph, Map hints) throws IOException {
0848: AttributesImpl ai = new AttributesImpl();
0849:
0850: if ((attributeGroup.getId() != null)
0851: && (attributeGroup.getId() != "")) {
0852: ai.addAttribute("", "id", "", "ID", attributeGroup.getId());
0853: }
0854:
0855: boolean nested = false;
0856:
0857: if (attributeGroup.getNamespace().equals(
0858: schema.getTargetNamespace())) {
0859: // search schema for element, then it's a ref
0860: Group[] groups = schema.getGroups();
0861: boolean found = false;
0862:
0863: for (int i = 0; (i < groups.length) && !found; i++)
0864: if (attributeGroup.getName()
0865: .equals(groups[i].getName())) {
0866: found = true;
0867: ai.addAttribute("", "ref", "", "QName",
0868: attributeGroup.getName());
0869: }
0870:
0871: if (!found) {
0872: ai.addAttribute("", "name", "", "QName", attributeGroup
0873: .getName());
0874: nested = true;
0875: }
0876: } else {
0877: // use a ref
0878: XSISAXHandler.setLogLevel(logger.getLevel());
0879: Schema s = SchemaFactory.getInstance(attributeGroup
0880: .getNamespace());
0881: ai.addAttribute("", "ref", "", "QName", s.getPrefix() + ":"
0882: + attributeGroup.getName());
0883: }
0884:
0885: ph.startElement(XSISimpleTypes.NAMESPACE, "group", ai);
0886:
0887: if (nested) {
0888: if (attributeGroup.getAnyAttributeNameSpace() != null) {
0889: ai = new AttributesImpl();
0890: ai.addAttribute("", "namespace", "", "special",
0891: attributeGroup.getAnyAttributeNameSpace());
0892: ph
0893: .element(XSISimpleTypes.NAMESPACE,
0894: "anyAttribute", ai);
0895: }
0896:
0897: if (attributeGroup.getAttributes() != null) {
0898: Attribute[] attrs = attributeGroup.getAttributes();
0899:
0900: for (int i = 0; i < attrs.length; i++)
0901: writeAttribute(attrs[i], schema, ph, hints);
0902: }
0903: }
0904:
0905: ph.endElement(XSISimpleTypes.NAMESPACE, "group");
0906: }
0907:
0908: private static void writeSimpleType(SimpleType simpleType,
0909: Schema schema, PrintHandler ph, Map hints)
0910: throws IOException {
0911: if (XSISimpleTypes.NAMESPACE.equals(simpleType.getNamespace())) {
0912: //error - not sure what to do
0913: // TODO log the type error - throw an exception?
0914: }
0915:
0916: AttributesImpl ai = new AttributesImpl();
0917:
0918: if ((simpleType.getId() != null) && (simpleType.getId() != "")) {
0919: ai.addAttribute("", "id", "", "ID", simpleType.getId());
0920: }
0921:
0922: if ((simpleType.getName() != null)
0923: && (simpleType.getName() != "")) {
0924: ai.addAttribute("", "name", "", "NCName", simpleType
0925: .getName());
0926: }
0927:
0928: if (simpleType.getFinal() != Schema.NONE) {
0929: ai.addAttribute("", "final", "", "NMTOKENS",
0930: ComplexTypeHandler
0931: .writeFinal(simpleType.getFinal()));
0932: }
0933:
0934: ph.startElement(XSISimpleTypes.NAMESPACE, "simpleType", ai);
0935:
0936: switch (simpleType.getChildType()) {
0937: case SimpleType.RESTRICTION:
0938:
0939: // determine whether to print or reference the child st
0940: SimpleType st = simpleType.getParents()[0];
0941: ai = null;
0942:
0943: if (schema.getTargetNamespace().equals(st.getNamespace())) {
0944: if ((st.getName() != null) && (st.getName() != "")) {
0945: SimpleType[] sts = schema.getSimpleTypes();
0946:
0947: if (sts != null) {
0948: for (int i = 0; i < sts.length; i++)
0949: if (st.getName().equals(sts[i].getName())) {
0950: ai = new AttributesImpl();
0951: ai.addAttribute("", "base", "",
0952: "QName", st.getName());
0953: }
0954: }
0955: }
0956: } else {
0957: ai = new AttributesImpl();
0958: XSISAXHandler.setLogLevel(logger.getLevel());
0959: Schema s = SchemaFactory.getInstance(st.getNamespace());
0960: ai.addAttribute("", "base", "", "QName", s.getPrefix()
0961: + ":" + st.getName());
0962: }
0963:
0964: ph
0965: .startElement(XSISimpleTypes.NAMESPACE,
0966: "restriction", ai);
0967:
0968: if (ai == null) {
0969: writeSimpleType(st, schema, ph, hints);
0970: }
0971:
0972: Facet[] facets = simpleType.getFacets();
0973:
0974: if (facets != null) {
0975: for (int i = 0; i < facets.length; i++)
0976: writeFacet(facets[i], ph);
0977: }
0978:
0979: ph.endElement(XSISimpleTypes.NAMESPACE, "restriction");
0980:
0981: break;
0982:
0983: case SimpleType.LIST:
0984:
0985: // determine whether to print or reference the child st
0986: st = simpleType.getParents()[0];
0987: ai = null;
0988:
0989: if (schema.getTargetNamespace().equals(st.getNamespace())) {
0990: if ((st.getName() != null) && (st.getName() != "")) {
0991: SimpleType[] sts = schema.getSimpleTypes();
0992:
0993: if (sts != null) {
0994: for (int i = 0; i < sts.length; i++)
0995: if (st.getName().equals(sts[i].getName())) {
0996: ai = new AttributesImpl();
0997: ai.addAttribute("", "itemType", "",
0998: "QName", st.getName());
0999: }
1000: }
1001: }
1002: } else {
1003: ai = new AttributesImpl();
1004:
1005: Schema s = SchemaFactory.getInstance(st.getNamespace());
1006: ai.addAttribute("", "itemType", "", "QName", s
1007: .getPrefix()
1008: + ":" + st.getName());
1009: }
1010:
1011: ph.startElement(XSISimpleTypes.NAMESPACE, "list", ai);
1012:
1013: if (ai == null) {
1014: writeSimpleType(st, schema, ph, hints);
1015: }
1016:
1017: ph.endElement(XSISimpleTypes.NAMESPACE, "list");
1018:
1019: break;
1020:
1021: case SimpleType.UNION:
1022:
1023: // determine whether to print or reference the child st
1024: SimpleType[] sts = simpleType.getParents();
1025: String memberTypes = null;
1026: List childTs = new LinkedList();
1027:
1028: if (sts != null) {
1029: for (int j = 0; j < sts.length; j++) {
1030: st = sts[j];
1031:
1032: if (schema.getTargetNamespace().equals(
1033: st.getNamespace())) {
1034: boolean found = false;
1035:
1036: if ((st.getName() != null)
1037: && (st.getName() != "")) {
1038: SimpleType[] sts2 = schema.getSimpleTypes();
1039:
1040: if (sts2 != null) {
1041: for (int i = 0; i < sts2.length; i++)
1042: if (st.getName().equals(
1043: sts2[i].getName())) {
1044: found = true;
1045:
1046: if (memberTypes == null) {
1047: memberTypes = st.getName();
1048: } else {
1049: memberTypes += (" " + st
1050: .getName());
1051: }
1052: }
1053: }
1054: }
1055:
1056: if (!found) {
1057: childTs.add(st);
1058: }
1059: } else {
1060: ai = new AttributesImpl();
1061:
1062: Schema s = SchemaFactory.getInstance(st
1063: .getNamespace());
1064:
1065: if (memberTypes == null) {
1066: memberTypes = s.getPrefix() + ":"
1067: + st.getName();
1068: } else {
1069: memberTypes += (" " + s.getPrefix() + ":" + st
1070: .getName());
1071: }
1072: }
1073: }
1074: }
1075:
1076: if (memberTypes != null) {
1077: ai = new AttributesImpl();
1078: ai.addAttribute("", "memberTypes", "", "QName",
1079: memberTypes);
1080: }
1081:
1082: ph.startElement(XSISimpleTypes.NAMESPACE, "union", ai);
1083:
1084: if (childTs.size() > 0) {
1085: Iterator i = childTs.iterator();
1086:
1087: while (i.hasNext())
1088: writeSimpleType((SimpleType) i.next(), schema, ph,
1089: hints);
1090: }
1091:
1092: ph.endElement(XSISimpleTypes.NAMESPACE, "union");
1093:
1094: break;
1095: }
1096:
1097: ph.endElement(XSISimpleTypes.NAMESPACE, "simpleType");
1098: }
1099:
1100: private static void writeChoice(Choice choice, Schema schema,
1101: PrintHandler ph, Map hints) throws IOException {
1102: AttributesImpl ai = new AttributesImpl();
1103:
1104: if ((choice.getId() != null) && (choice.getId() != "")) {
1105: ai.addAttribute("", "id", "", "ID", choice.getId());
1106: }
1107:
1108: if (choice.getMaxOccurs() != 1) {
1109: ai
1110: .addAttribute(
1111: "",
1112: "maxOccurs",
1113: "",
1114: "Union",
1115: (choice.getMaxOccurs() == ElementGrouping.UNBOUNDED) ? "unbounded"
1116: : ("" + choice.getMaxOccurs()));
1117: }
1118:
1119: if (choice.getMinOccurs() != 1) {
1120: ai.addAttribute("", "minOccurs", "", "ID", ""
1121: + choice.getMinOccurs());
1122: }
1123:
1124: ph.startElement(XSISimpleTypes.NAMESPACE, "choice", ai);
1125:
1126: ElementGrouping[] egs = choice.getChildren();
1127:
1128: if (egs != null) {
1129: for (int i = 0; i < egs.length; i++)
1130: if (egs[i] != null) {
1131: switch (egs[i].getGrouping()) {
1132: case ElementGrouping.ALL:
1133: writeAll((All) egs[i], schema, ph, hints);
1134:
1135: break;
1136:
1137: case ElementGrouping.ANY:
1138: writeAny((Any) egs[i], ph);
1139:
1140: break;
1141:
1142: case ElementGrouping.CHOICE:
1143: writeChoice((Choice) egs[i], schema, ph, hints);
1144:
1145: break;
1146:
1147: case ElementGrouping.ELEMENT:
1148: writeElement((Element) egs[i], schema, ph,
1149: hints);
1150:
1151: break;
1152:
1153: case ElementGrouping.GROUP:
1154: writeGroup((Group) egs[i], schema, ph, hints);
1155:
1156: break;
1157:
1158: case ElementGrouping.SEQUENCE:
1159: writeSequence((Sequence) egs[i], schema, ph,
1160: hints);
1161:
1162: break;
1163: }
1164: }
1165: }
1166:
1167: ph.endElement(XSISimpleTypes.NAMESPACE, "choice");
1168: }
1169:
1170: private static void writeSequence(Sequence sequence, Schema schema,
1171: PrintHandler ph, Map hints) throws IOException {
1172: AttributesImpl ai = new AttributesImpl();
1173:
1174: if ((sequence.getId() != null) && (sequence.getId() != "")) {
1175: ai.addAttribute("", "id", "", "ID", sequence.getId());
1176: }
1177:
1178: if (sequence.getMaxOccurs() != 1) {
1179: ai
1180: .addAttribute(
1181: "",
1182: "maxOccurs",
1183: "",
1184: "Union",
1185: (sequence.getMaxOccurs() == ElementGrouping.UNBOUNDED) ? "unbounded"
1186: : ("" + sequence.getMaxOccurs()));
1187: }
1188:
1189: if (sequence.getMinOccurs() != 1) {
1190: ai.addAttribute("", "minOccurs", "", "ID", ""
1191: + sequence.getMinOccurs());
1192: }
1193:
1194: ph.startElement(XSISimpleTypes.NAMESPACE, "sequence", ai);
1195:
1196: ElementGrouping[] egs = sequence.getChildren();
1197:
1198: if (egs != null) {
1199: for (int i = 0; i < egs.length; i++)
1200: if (egs[i] != null) {
1201: switch (egs[i].getGrouping()) {
1202: case ElementGrouping.ANY:
1203: writeAny((Any) egs[i], ph);
1204:
1205: break;
1206:
1207: case ElementGrouping.CHOICE:
1208: writeChoice((Choice) egs[i], schema, ph, hints);
1209:
1210: break;
1211:
1212: case ElementGrouping.ELEMENT:
1213: writeElement((Element) egs[i], schema, ph,
1214: hints);
1215:
1216: break;
1217:
1218: case ElementGrouping.GROUP:
1219: writeGroup((Group) egs[i], schema, ph, hints);
1220:
1221: break;
1222:
1223: case ElementGrouping.SEQUENCE:
1224: writeSequence((Sequence) egs[i], schema, ph,
1225: hints);
1226:
1227: break;
1228: }
1229: }
1230: }
1231:
1232: ph.endElement(XSISimpleTypes.NAMESPACE, "sequence");
1233: }
1234:
1235: private static void writeAll(All all, Schema schema,
1236: PrintHandler ph, Map hints) throws IOException {
1237: AttributesImpl ai = new AttributesImpl();
1238:
1239: if ((all.getId() != null) && (all.getId() != "")) {
1240: ai.addAttribute("", "id", "", "ID", all.getId());
1241: }
1242:
1243: if (all.getMaxOccurs() != 1) {
1244: ai
1245: .addAttribute(
1246: "",
1247: "maxOccurs",
1248: "",
1249: "Union",
1250: (all.getMaxOccurs() == ElementGrouping.UNBOUNDED) ? "unbounded"
1251: : ("" + all.getMaxOccurs()));
1252: }
1253:
1254: if (all.getMinOccurs() != 1) {
1255: ai.addAttribute("", "minOccurs", "", "ID", ""
1256: + all.getMinOccurs());
1257: }
1258:
1259: ph.startElement(XSISimpleTypes.NAMESPACE, "all", ai);
1260:
1261: Element[] egs = all.getElements();
1262:
1263: if (egs != null) {
1264: for (int i = 0; i < egs.length; i++)
1265: if (egs[i] != null) {
1266: writeElement(egs[i], schema, ph, hints);
1267: }
1268: }
1269:
1270: ph.endElement(XSISimpleTypes.NAMESPACE, "all");
1271: }
1272:
1273: private static void writeAny(Any any, PrintHandler ph)
1274: throws IOException {
1275: AttributesImpl ai = new AttributesImpl();
1276:
1277: if ((any.getId() != null) && (any.getId() != "")) {
1278: ai.addAttribute("", "id", "", "ID", any.getId());
1279: }
1280:
1281: if (any.getMaxOccurs() != 1) {
1282: ai
1283: .addAttribute(
1284: "",
1285: "maxOccurs",
1286: "",
1287: "Union",
1288: (any.getMaxOccurs() == ElementGrouping.UNBOUNDED) ? "unbounded"
1289: : ("" + any.getMaxOccurs()));
1290: }
1291:
1292: if (any.getMinOccurs() != 1) {
1293: ai.addAttribute("", "minOccurs", "", "ID", ""
1294: + any.getMinOccurs());
1295: }
1296:
1297: if (any.getNamespace() != null) {
1298: ai.addAttribute("", "namespace", "", "special", ""
1299: + any.getNamespace());
1300: }
1301:
1302: ph.element(XSISimpleTypes.NAMESPACE, "any", ai);
1303: }
1304:
1305: private static void writeComplexType(ComplexType complexType,
1306: Schema schema, PrintHandler ph, Map hints)
1307: throws IOException {
1308: AttributesImpl ai = new AttributesImpl();
1309:
1310: if ((complexType.getId() != null)
1311: && (complexType.getId() != "")) {
1312: ai.addAttribute("", "id", "", "ID", complexType.getId());
1313: }
1314:
1315: if ((complexType.getName() != null)
1316: && (complexType.getName() != "")) {
1317: ai.addAttribute("", "name", "", "NCName", complexType
1318: .getName());
1319: }
1320:
1321: if (complexType.isAbstract()) {
1322: ai.addAttribute("", "abstract", "", "boolean", "true");
1323: }
1324:
1325: if (complexType.getFinal() != Schema.NONE) {
1326: ai.addAttribute("", "final", "", "NMTOKENS",
1327: ComplexTypeHandler.writeFinal(complexType
1328: .getFinal()));
1329: }
1330:
1331: if (complexType.getBlock() != Schema.NONE) {
1332: ai.addAttribute("", "block", "", "NMTOKENS",
1333: ComplexTypeHandler.writeBlock(complexType
1334: .getBlock()));
1335: }
1336:
1337: if (complexType.isMixed()) {
1338: ai.addAttribute("", "mixed", "", "boolean", "true");
1339: }
1340:
1341: ph.startElement(XSISimpleTypes.NAMESPACE, "complexType", ai);
1342:
1343: ElementGrouping egs = complexType.getChild();
1344: complexType.getChild();
1345:
1346: // TODO determine if this complexType isDerived ... and make a complexContent or Simplecontent to match
1347: if (egs != null) {
1348: switch (egs.getGrouping()) {
1349: // TODO determine if this will work
1350: // case ElementGrouping.COMPLEXCONTENT:
1351: // writeAny((ComplexContent)egs,schema,ph,hints);
1352: // break;
1353: // case ElementGrouping.SIMPLECONTENT:
1354: // writeAny((SimpleContent)egs,schema,ph,hints);
1355: // break;
1356: case ElementGrouping.ALL:
1357: writeAll((All) egs, schema, ph, hints);
1358:
1359: break;
1360:
1361: case ElementGrouping.CHOICE:
1362: writeChoice((Choice) egs, schema, ph, hints);
1363:
1364: break;
1365:
1366: case ElementGrouping.GROUP:
1367: writeGroup((Group) egs, schema, ph, hints);
1368:
1369: break;
1370:
1371: case ElementGrouping.SEQUENCE:
1372: writeSequence((Sequence) egs, schema, ph, hints);
1373:
1374: break;
1375: }
1376: }
1377:
1378: if (complexType.getAnyAttributeNameSpace() != null) {
1379: ai = new AttributesImpl();
1380: ai.addAttribute("", "namespace", "", "special", complexType
1381: .getAnyAttributeNameSpace());
1382: ph.element(XSISimpleTypes.NAMESPACE, "anyAttribute", ai);
1383: }
1384:
1385: // TODO think about checking for attribute groupings?
1386: // add a Attribute.getParentGroup() ... null or Group
1387: if (complexType.getAttributes() != null) {
1388: Attribute[] attrs = complexType.getAttributes();
1389:
1390: for (int i = 0; i < attrs.length; i++)
1391: writeAttribute(attrs[i], schema, ph, hints);
1392: }
1393:
1394: ph.endElement(XSISimpleTypes.NAMESPACE, "complexType");
1395: }
1396:
1397: private static void writeFacet(Facet facet, PrintHandler ph)
1398: throws IOException {
1399: if (facet == null) {
1400: return;
1401: }
1402:
1403: AttributesImpl ai = new AttributesImpl();
1404: ai.addAttribute("", "value", "", "ID", facet.getValue());
1405:
1406: switch (facet.getFacetType()) {
1407: case Facet.ENUMERATION:
1408: ph.element(XSISimpleTypes.NAMESPACE, "enumeration", ai);
1409:
1410: break;
1411:
1412: case Facet.FRACTIONDIGITS:
1413: ph.element(XSISimpleTypes.NAMESPACE, "fractionDigits", ai);
1414:
1415: break;
1416:
1417: case Facet.LENGTH:
1418: ph.element(XSISimpleTypes.NAMESPACE, "length", ai);
1419:
1420: break;
1421:
1422: case Facet.MAXEXCLUSIVE:
1423: ph.element(XSISimpleTypes.NAMESPACE, "maxExclusive", ai);
1424:
1425: break;
1426:
1427: case Facet.MAXINCLUSIVE:
1428: ph.element(XSISimpleTypes.NAMESPACE, "maxInclusive", ai);
1429:
1430: break;
1431:
1432: case Facet.MAXLENGTH:
1433: ph.element(XSISimpleTypes.NAMESPACE, "maxLength", ai);
1434:
1435: break;
1436:
1437: case Facet.MINEXCLUSIVE:
1438: ph.element(XSISimpleTypes.NAMESPACE, "minExclusive", ai);
1439:
1440: break;
1441:
1442: case Facet.MININCLUSIVE:
1443: ph.element(XSISimpleTypes.NAMESPACE, "minInclusive", ai);
1444:
1445: break;
1446:
1447: case Facet.MINLENGTH:
1448: ph.element(XSISimpleTypes.NAMESPACE, "minLength", ai);
1449:
1450: break;
1451:
1452: case Facet.PATTERN:
1453: ph.element(XSISimpleTypes.NAMESPACE, "pattern", ai);
1454:
1455: break;
1456:
1457: case Facet.TOTALDIGITS:
1458: ph.element(XSISimpleTypes.NAMESPACE, "totalDigits", ai);
1459:
1460: break;
1461:
1462: case Facet.WHITESPACE:
1463: ph.element(XSISimpleTypes.NAMESPACE, "whiteSpace", ai);
1464:
1465: break;
1466: }
1467: }
1468:
1469: private static class WriterContentHandler implements PrintHandler {
1470: private boolean firstElement = true; // needed for NS declarations
1471: private Writer writer;
1472: private Map prefixMappings; // when the value is null it has not been included yet into the document ...
1473: private Schema schema;
1474: protected Map hints;
1475: private Schema[] searchOrder = null;
1476: private String encoding = "UTF-8";
1477:
1478: WriterContentHandler(Schema schema, Writer writer, Map hints) {
1479: this .writer = writer;
1480: this .schema = schema;
1481: this .hints = hints;
1482: if (this .hints != null) {
1483: Object encodingValue = this
1484: .getHint(DocumentWriter.ENCODING);
1485: if (encodingValue != null) {
1486: this .encoding = encodingValue.toString();
1487: }
1488: }
1489:
1490: prefixMappings = new HashMap();
1491: prefixMappings.put(schema.getTargetNamespace(), "");
1492:
1493: Schema[] imports = schema.getImports();
1494:
1495: if (imports != null) {
1496: for (int i = 0; i < imports.length; i++)
1497: prefixMappings.put(imports[i].getTargetNamespace(),
1498: imports[i].getPrefix());
1499: }
1500: }
1501:
1502: private void printXMLNSDecs(Map arg0) throws IOException {
1503: Schema[] imports = getSchemaOrdering();
1504: String s = "";
1505: Map schemaLocs = (Map) ((arg0 == null) ? null : arg0
1506: .get(SCHEMA_LOCATION_HINT));
1507: schemaLocs = (schemaLocs == null) ? new HashMap()
1508: : schemaLocs;
1509:
1510: for (int i = 0; i < imports.length; i++) {
1511: if (imports[i] != null) {
1512: if (imports[i] == schema) {
1513: writer.write(" xmlns=\""
1514: + schema.getTargetNamespace() + "\"");
1515:
1516: if ((schema.getURI() != null)
1517: && !schema.getTargetNamespace().equals(
1518: schema.getURI())) {
1519:
1520: String endResult = schema.getURI()
1521: .toString();
1522: endResult = endResult.replaceAll("&",
1523: "&");
1524: s = schema.getTargetNamespace() + " "
1525: + endResult;
1526: }
1527: } else {
1528: writer.write(" xmlns:" + imports[i].getPrefix()
1529: + "=\""
1530: + imports[i].getTargetNamespace()
1531: + "\"");
1532: }
1533:
1534: URI location = imports[i].getURI();
1535: boolean forced = false;
1536:
1537: if (schemaLocs.containsKey(imports[i]
1538: .getTargetNamespace())) {
1539: location = (URI) schemaLocs.get(imports[i]
1540: .getTargetNamespace());
1541: forced = true;
1542: }
1543:
1544: if ((location != null) && location.isAbsolute()) {
1545: if (imports[i].includesURI(location) || forced) {
1546: if ((location != null)
1547: && !location.equals(imports[i]
1548: .getTargetNamespace())) {
1549: String endResult = location.toString();
1550: endResult = endResult.replaceAll("&",
1551: "&");
1552: s += (" "
1553: + imports[i]
1554: .getTargetNamespace()
1555: + " " + endResult);
1556: }
1557: }
1558: }
1559: }
1560: }
1561:
1562: s = s.trim();
1563:
1564: if (!"".equals(s)) {
1565: writer
1566: .write(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
1567: writer.write(" xsi:schemaLocation=\"" + s + "\"");
1568: }
1569: }
1570:
1571: /**
1572: * @see PrintHandler#startElement(URI, String, Attributes)
1573: *
1574: * @param namespaceURI URI
1575: * @param localName String
1576: * @param attributes Attributes
1577: */
1578: public void startElement(URI namespaceURI, String localName,
1579: Attributes attributes) throws IOException {
1580: String prefix = (String) prefixMappings.get(namespaceURI);
1581:
1582: if (prefix != null) {
1583: if (!prefix.equals("")) {
1584: prefix = prefix + ":";
1585: }
1586: } else {
1587: if (namespaceURI.equals(schema.getTargetNamespace())) {
1588: prefix = "";
1589: } else {
1590: XSISAXHandler.setLogLevel(logger.getLevel());
1591: prefix = SchemaFactory.getInstance(namespaceURI)
1592: .getPrefix();
1593:
1594: if (prefix == null) {
1595: prefix = "";
1596: }
1597:
1598: if (prefix != "") {
1599: prefix += ":";
1600: }
1601: }
1602: }
1603:
1604: writer.write("<");
1605: writer.write(prefix + localName);
1606:
1607: if (firstElement) {
1608: printXMLNSDecs(hints);
1609: firstElement = false;
1610: }
1611:
1612: if (attributes != null) {
1613: for (int i = 0; i < attributes.getLength(); i++) {
1614: String name = attributes.getLocalName(i);
1615: String value = attributes.getValue(i);
1616: writer.write(" ");
1617: writer.write(name);
1618: writer.write("=\"");
1619: writer.write(value);
1620: writer.write("\"");
1621: }
1622: }
1623:
1624: writer.write(">");
1625:
1626: // TODO format here
1627: // writer.write("\n");
1628: }
1629:
1630: /**
1631: * @see PrintHandler#element(URI, String, Attributes)
1632: *
1633: * @param namespaceURI URI
1634: * @param localName String
1635: * @param attributes Attributes
1636: */
1637: public void element(URI namespaceURI, String localName,
1638: Attributes attributes) throws IOException {
1639: String prefix = (String) prefixMappings.get(namespaceURI);
1640:
1641: if (prefix != null) {
1642: if (!prefix.equals("")) {
1643: prefix = prefix + ":";
1644: }
1645: } else {
1646: if (namespaceURI.equals(schema.getTargetNamespace())) {
1647: prefix = "";
1648: } else {
1649: XSISAXHandler.setLogLevel(logger.getLevel());
1650: prefix = SchemaFactory.getInstance(namespaceURI)
1651: .getPrefix();
1652:
1653: if (prefix == null) {
1654: prefix = "";
1655: }
1656:
1657: if (prefix != "") {
1658: prefix += ":";
1659: }
1660: }
1661: }
1662:
1663: writer.write("<");
1664: writer.write(prefix + localName);
1665:
1666: if (firstElement) {
1667: printXMLNSDecs(hints);
1668: firstElement = false;
1669: }
1670:
1671: if (attributes != null) {
1672: for (int i = 0; i < attributes.getLength(); i++) {
1673: String name = attributes.getLocalName(i);
1674: String value = attributes.getValue(i);
1675: writer.write(" ");
1676: writer.write(name);
1677: writer.write("=\"");
1678: writer.write(value);
1679: writer.write("\"");
1680: }
1681: }
1682:
1683: writer.write("/>");
1684:
1685: // TODO format here
1686: writer.write("\n");
1687: }
1688:
1689: /**
1690: * @see PrintHandler#endElement(URI, String)
1691: * @param namespaceURI URI
1692: * @param localName String
1693: */
1694: public void endElement(URI namespaceURI, String localName)
1695: throws IOException {
1696: String prefix = (String) prefixMappings.get(namespaceURI);
1697:
1698: if (prefix != null) {
1699: if (!prefix.equals("")) {
1700: prefix = prefix + ":";
1701: }
1702: } else {
1703: if (namespaceURI.equals(schema.getTargetNamespace())) {
1704: prefix = "";
1705: } else {
1706: XSISAXHandler.setLogLevel(logger.getLevel());
1707: prefix = SchemaFactory.getInstance(namespaceURI)
1708: .getPrefix();
1709:
1710: if (prefix == null) {
1711: prefix = "";
1712: }
1713:
1714: if (prefix != "") {
1715: prefix += ":";
1716: }
1717: }
1718: }
1719:
1720: writer.write("</");
1721: writer.write(prefix + localName);
1722: writer.write(">");
1723:
1724: // TODO format here
1725: writer.write("\n");
1726: }
1727:
1728: /**
1729: * @see PrintHandler#characters(char[], int, int)
1730: * @see Writer#write(char[], int, int)
1731: * @param arg0
1732: * @param arg1
1733: * @param arg2
1734: */
1735: public void characters(char[] arg0, int arg1, int arg2)
1736: throws IOException {
1737: writer.write(arg0, arg1, arg2);
1738: }
1739:
1740: /**
1741: * @see PrintHandler#characters(String)
1742: * @see Writer#write(java.lang.String)
1743: * @param s String
1744: */
1745: public void characters(String s) throws IOException {
1746: writer.write(s);
1747: }
1748:
1749: /**
1750: * @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int,
1751: * int)
1752: * @see Writer#write(char[], int, int)
1753: * @param arg0
1754: * @param arg1
1755: * @param arg2
1756: * @throws IOException
1757: */
1758: public void ignorableWhitespace(char[] arg0, int arg1, int arg2)
1759: throws IOException {
1760: writer.write(arg0, arg1, arg2);
1761: }
1762:
1763: /**
1764: * @see PrintHandler#startDocument()
1765: */
1766: public void startDocument() throws IOException {
1767: writer.write("<?xml version=\"1.0\" encoding=\"" + encoding
1768: + "\"?>");
1769:
1770: // TODO format here
1771: writer.write("\n");
1772: }
1773:
1774: /**
1775: * @see PrintHandler#endDocument()
1776: */
1777: public void endDocument() throws IOException {
1778: // TODO format here
1779: writer.write("\n");
1780: writer.flush();
1781: }
1782:
1783: /**
1784: * @see PrintHandler#getDocumentSchema()
1785: */
1786: public Schema getDocumentSchema() {
1787: return schema;
1788: }
1789:
1790: /**
1791: * @see PrintHandler#getHint(Object)
1792: */
1793: public Object getHint(Object key) {
1794: return hints.get(key);
1795: }
1796:
1797: /**
1798: * @see PrintHandler#findElement(Object)
1799: */
1800: public Element findElement(Object value) {
1801: Schema[] searchOrder1;
1802:
1803: try {
1804: searchOrder1 = getSchemaOrdering();
1805: } catch (IOException e) {
1806: logger.warning(e.toString());
1807:
1808: return null;
1809: }
1810:
1811: for (int i = 0; i < searchOrder1.length; i++) {
1812: Element[] elems = searchOrder1[i].getElements();
1813:
1814: if (elems != null) {
1815: for (int j = 0; j < elems.length; j++)
1816: if ((elems[j].getType() != null)
1817: && elems[j].getType().canEncode(
1818: elems[j], value, hints)) {
1819: return elems[j];
1820: }
1821: }
1822: }
1823:
1824: return null;
1825: }
1826:
1827: /**
1828: * @see PrintHandler#findElement(String)
1829: */
1830: public Element findElement(String name) {
1831: Schema[] searchOrder1;
1832:
1833: try {
1834: searchOrder1 = getSchemaOrdering();
1835: } catch (IOException e) {
1836: logger.warning(e.toString());
1837:
1838: return null;
1839: }
1840:
1841: for (int i = 0; i < searchOrder1.length; i++) {
1842: Element[] elems = searchOrder1[i].getElements();
1843:
1844: if (elems != null) {
1845: for (int j = 0; j < elems.length; j++)
1846: if ((elems[j].getName() != null)
1847: && elems[j].getName().equals(name)) {
1848: return elems[j];
1849: }
1850: }
1851: }
1852:
1853: return null;
1854: }
1855:
1856: private Schema[] getSchemaOrdering() throws IOException {
1857: if (searchOrder != null) {
1858: return searchOrder;
1859: }
1860:
1861: if (((hints == null) || (hints.get(SCHEMA_ORDER) == null))
1862: && ((schema.getImports() == null) || (schema
1863: .getImports().length == 0))) {
1864: searchOrder = new Schema[] { schema, };
1865: } else {
1866: List so = new LinkedList();
1867:
1868: if ((hints != null) && hints.containsKey(SCHEMA_ORDER)) {
1869: Object order = hints.get(SCHEMA_ORDER);
1870: List targNS = new LinkedList();
1871: targNS.add(schema.getTargetNamespace());
1872:
1873: if (schema.getImports() != null) {
1874: for (int i = 0; i < schema.getImports().length; i++)
1875: if (!targNS.contains(schema.getImports()[i]
1876: .getTargetNamespace())) {
1877: targNS.add(schema.getImports()[i]
1878: .getTargetNamespace());
1879: }
1880: }
1881:
1882: if (order instanceof Schema[]) {
1883: Schema[] sOrder = (Schema[]) order;
1884:
1885: for (int i = 0; i < sOrder.length; i++) {
1886: int nsIndex = targNS.indexOf(sOrder[i]
1887: .getTargetNamespace());
1888:
1889: if (nsIndex >= 0) { // found
1890: so.add(sOrder[i]);
1891: targNS.remove(nsIndex);
1892: }
1893: }
1894: } else {
1895: String[] stringOrder = (String[]) order;
1896:
1897: for (int i = 0; i < stringOrder.length; i++) {
1898: int nsIndex = targNS
1899: .indexOf(stringOrder[i]);
1900:
1901: try {
1902: if (nsIndex >= 0) { // found
1903:
1904: URI uri = new URI(stringOrder[i]);
1905: XSISAXHandler.setLogLevel(logger
1906: .getLevel());
1907: so.add(SchemaFactory
1908: .getInstance(uri));
1909: targNS.remove(nsIndex);
1910: } else {
1911: URI uri = new URI(stringOrder[i]);
1912: so.add(SchemaFactory
1913: .getInstance(uri));
1914: }
1915: } catch (URISyntaxException e) {
1916: logger.warning(e.toString());
1917: IOException t = new IOException(e
1918: .toString());
1919: t.initCause(e);
1920: throw t;
1921: }
1922: }
1923: }
1924:
1925: if (!targNS.contains(schema.getTargetNamespace())) {
1926: so.add(schema);
1927: }
1928:
1929: for (int i = 0; i < schema.getImports().length; i++) {
1930: int nsIndex = targNS.indexOf(schema
1931: .getImports()[i].getTargetNamespace());
1932:
1933: if (nsIndex >= 0) { // found
1934: so.add(schema.getImports()[i]);
1935: targNS.remove(nsIndex);
1936: }
1937: }
1938: } else {
1939: if ((hints != null)
1940: && hints.containsKey(USE_NEAREST)) {
1941: // TODO fill this in
1942: so.add(schema);
1943:
1944: for (int i = 0; i < schema.getImports().length; i++)
1945: so.add(schema.getImports()[i]);
1946: } else {
1947: so.add(schema);
1948:
1949: for (int i = 0; i < schema.getImports().length; i++)
1950: so.add(schema.getImports()[i]);
1951: }
1952: }
1953:
1954: searchOrder = (Schema[]) so.toArray(new Schema[so
1955: .size()]);
1956: }
1957:
1958: return searchOrder;
1959: }
1960: }
1961: }
|