/* */ package org.jboss.xb.binding;
/* */
/* */ import com.wutka.dtd.DTD;
/* */ import com.wutka.dtd.DTDAttribute;
/* */ import com.wutka.dtd.DTDCardinal;
/* */ import com.wutka.dtd.DTDContainer;
/* */ import com.wutka.dtd.DTDElement;
/* */ import com.wutka.dtd.DTDEmpty;
/* */ import com.wutka.dtd.DTDItem;
/* */ import com.wutka.dtd.DTDMixed;
/* */ import com.wutka.dtd.DTDName;
/* */ import com.wutka.dtd.DTDPCData;
/* */ import com.wutka.dtd.DTDParser;
/* */ import java.io.IOException;
/* */ import java.io.InputStream;
/* */ import java.io.InputStreamReader;
/* */ import java.io.Reader;
/* */ import java.io.Writer;
/* */ import java.net.MalformedURLException;
/* */ import java.net.URL;
/* */ import java.util.ArrayList;
/* */ import java.util.Collection;
/* */ import java.util.Collections;
/* */ import java.util.Enumeration;
/* */ import java.util.HashMap;
/* */ import java.util.Hashtable;
/* */ import java.util.Iterator;
/* */ import java.util.List;
/* */ import java.util.Map;
/* */ import java.util.Vector;
/* */ import javax.xml.parsers.ParserConfigurationException;
/* */ import org.jboss.logging.Logger;
/* */ import org.xml.sax.Attributes;
/* */ import org.xml.sax.SAXException;
/* */
/* */ public class DtdMarshaller extends AbstractMarshaller
/* */ {
/* 67 */ private static final Logger log = Logger.getLogger(DtdMarshaller.class);
/* */ private String publicId;
/* */ private String systemId;
/* */ private final AbstractMarshaller.Stack stack;
/* */ private DTD dtd;
/* */ private GenericObjectModelProvider provider;
/* */ private Content content;
/* */ private final List elementStack;
/* */ private final Map simpleTypeBindings;
/* */
/* */ public DtdMarshaller()
/* */ {
/* 72 */ this.stack = new AbstractMarshaller.StackImpl();
/* */
/* 75 */ this.content = new Content();
/* */
/* 77 */ this.elementStack = new ArrayList();
/* */
/* 79 */ this.simpleTypeBindings = new HashMap();
/* */ }
/* */
/* */ public void addBinding(String elementName, TypeBinding binding) {
/* 83 */ this.simpleTypeBindings.put(elementName, binding);
/* */ }
/* */
/* */ public void mapPublicIdToSystemId(String publicId, String systemId)
/* */ {
/* 88 */ this.publicId = publicId;
/* 89 */ this.systemId = systemId;
/* */ }
/* */
/* */ public void declareNamespace(String prefix, String uri)
/* */ {
/* 94 */ throw new UnsupportedOperationException("declareNamespace is not implemented.");
/* */ }
/* */
/* */ public void addAttribute(String prefix, String localName, String type, String value)
/* */ {
/* 99 */ throw new UnsupportedOperationException("addAttribute is not implemented.");
/* */ }
/* */
/* */ public void marshal(String schemaUri, ObjectModelProvider provider, Object root, Writer writer)
/* */ throws IOException, ParserConfigurationException, SAXException
/* */ {
/* */ URL url;
/* */ try
/* */ {
/* 109 */ url = new URL(schemaUri);
/* */ }
/* */ catch (MalformedURLException e)
/* */ {
/* 113 */ throw new IllegalArgumentException("Malformed schema URI " + schemaUri + ": " + e.getMessage());
/* */ }
/* */ InputStream is;
/* */ try
/* */ {
/* 119 */ is = url.openStream();
/* */ }
/* */ catch (IOException e)
/* */ {
/* 123 */ throw new IllegalStateException("Failed to open input stream for schema " + schemaUri + ": " + e.getMessage());
/* */ }
/* */
/* */ try
/* */ {
/* 128 */ InputStreamReader reader = new InputStreamReader(is);
/* 129 */ marshal(reader, provider, root, writer);
/* */ }
/* */ finally
/* */ {
/* 133 */ is.close();
/* */ }
/* */ }
/* */
/* */ public void marshal(Reader dtdReader, ObjectModelProvider provider, Object document, Writer writer)
/* */ throws IOException, SAXException
/* */ {
/* 140 */ DTDParser parser = new DTDParser(dtdReader);
/* 141 */ this.dtd = parser.parse(true);
/* */
/* 143 */ this.provider = ((provider instanceof GenericObjectModelProvider) ? (GenericObjectModelProvider)provider : new DelegatingObjectModelProvider(provider));
/* */
/* 147 */ DTDElement[] roots = null;
/* 148 */ if (this.dtd.rootElement != null)
/* */ {
/* 150 */ handleRootElement(document, this.dtd.rootElement);
/* */ }
/* */ else
/* */ {
/* 154 */ roots = getRootList(this.dtd);
/* 155 */ for (int i = 0; i < roots.length; i++)
/* */ {
/* 157 */ handleRootElement(document, roots[i]);
/* */ }
/* */
/* */ }
/* */
/* 164 */ writeXmlVersion(writer);
/* */
/* 167 */ writer.write("<!DOCTYPE ");
/* */
/* 169 */ if (this.dtd.rootElement != null)
/* */ {
/* 171 */ writer.write(this.dtd.rootElement.getName());
/* */ }
/* */ else
/* */ {
/* 175 */ for (int i = 0; i < roots.length; i++)
/* */ {
/* 177 */ writer.write(", ");
/* 178 */ writer.write(roots[i].getName());
/* */ }
/* */ }
/* */
/* 182 */ writer.write(" PUBLIC \"");
/* 183 */ writer.write(this.publicId);
/* 184 */ writer.write("\" \"");
/* 185 */ writer.write(this.systemId);
/* 186 */ writer.write("\">\n");
/* */
/* 188 */ ContentWriter contentWriter = new ContentWriter(writer, propertyIsTrueOrNotSet("org.jboss.xml.binding.marshalling.indent"));
/* 189 */ this.content.handleContent(contentWriter);
/* */ }
/* */
/* */ private void handleRootElement(Object o, DTDElement dtdRoot)
/* */ {
/* 194 */ Element el = new Element(dtdRoot, true);
/* 195 */ this.elementStack.add(el);
/* 196 */ this.content.startDocument();
/* */
/* 198 */ Object root = this.provider.getRoot(o, null, this.systemId, dtdRoot.getName());
/* 199 */ if (root == null)
/* */ {
/* 201 */ return;
/* */ }
/* 203 */ this.stack.push(root);
/* */
/* 205 */ Attributes attrs = provideAttributes(dtdRoot, root);
/* 206 */ this.content.startElement("", dtdRoot.getName(), dtdRoot.getName(), attrs);
/* 207 */ handleElement(this.dtd, dtdRoot, attrs);
/* 208 */ this.content.endElement("", dtdRoot.getName(), dtdRoot.getName());
/* */
/* 210 */ this.stack.pop();
/* 211 */ this.content.endDocument();
/* 212 */ this.elementStack.remove(this.elementStack.size() - 1);
/* */ }
/* */
/* */ private final void handleElement(DTD dtd, DTDElement element, Attributes attrs)
/* */ {
/* 217 */ DTDItem item = element.content;
/* 218 */ if ((item instanceof DTDMixed))
/* */ {
/* 220 */ handleMixedElement(element, attrs);
/* */ }
/* 222 */ else if ((item instanceof DTDEmpty))
/* */ {
/* 224 */ Object value = this.provider.getElementValue(this.stack.peek(), null, this.systemId, element.getName());
/* 225 */ if (Boolean.TRUE.equals(value))
/* */ {
/* 227 */ writeSkippedElements();
/* 228 */ this.content.startElement("", element.getName(), element.getName(), attrs);
/* 229 */ this.content.endElement("", element.getName(), element.getName());
/* */ }
/* */ }
/* 232 */ else if ((item instanceof DTDContainer))
/* */ {
/* 234 */ processContainer(dtd, (DTDContainer)item);
/* */ }
/* */ else
/* */ {
/* 238 */ throw new IllegalStateException("Unexpected element: " + element.getName());
/* */ }
/* */ }
/* */
/* */ private final void handleMixedElement(DTDElement element, Attributes attrs)
/* */ {
/* 244 */ boolean startElement = false;
/* 245 */ if (!this.elementStack.isEmpty())
/* */ {
/* 247 */ Element e = (Element)this.elementStack.get(this.elementStack.size() - 1);
/* 248 */ startElement = element != e.element;
/* */ }
/* */
/* 251 */ DTDMixed mixed = (DTDMixed)element.content;
/* 252 */ String elementName = element.getName();
/* 253 */ Object parent = this.stack.peek();
/* 254 */ DTDItem[] items = mixed.getItems();
/* 255 */ for (int i = 0; i < items.length; i++)
/* */ {
/* 257 */ DTDItem item = items[i];
/* 258 */ if (!(item instanceof DTDPCData))
/* */ continue;
/* 260 */ Object value = this.provider.getElementValue(parent, null, this.systemId, elementName);
/* 261 */ if (value == null)
/* */ continue;
/* 263 */ writeSkippedElements();
/* */
/* 266 */ TypeBinding binding = (TypeBinding)this.simpleTypeBindings.get(elementName);
/* */ String marshalled;
/* */ String marshalled;
/* 267 */ if (binding != null)
/* */ {
/* 269 */ marshalled = binding.marshal(value);
/* */ }
/* */ else
/* */ {
/* 273 */ marshalled = value.toString();
/* */ }
/* */
/* 276 */ char[] ch = marshalled.toCharArray();
/* 277 */ if (startElement)
/* */ {
/* 279 */ this.content.startElement("", elementName, elementName, attrs);
/* */ }
/* */
/* 282 */ this.content.characters(ch, 0, ch.length);
/* */
/* 284 */ if (!startElement)
/* */ continue;
/* 286 */ this.content.endElement("", elementName, elementName);
/* */ }
/* */ }
/* */
/* */ private final void handleChildren(DTD dtd, DTDElement element, DTDCardinal elementCardinal)
/* */ {
/* 295 */ Object parent = this.stack.peek();
/* 296 */ Object children = this.provider.getChildren(parent, null, this.systemId, element.getName());
/* */
/* 298 */ if (children != null)
/* */ {
/* */ Iterator iter;
/* */ Iterator iter;
/* 301 */ if ((children instanceof Iterator))
/* */ {
/* 303 */ iter = (Iterator)children;
/* */ }
/* */ else
/* */ {
/* */ Iterator iter;
/* 305 */ if ((children instanceof Collection))
/* */ {
/* 307 */ iter = ((Collection)children).iterator();
/* */ }
/* */ else
/* */ {
/* 311 */ iter = Collections.singletonList(children).iterator();
/* */ }
/* */ }
/* 314 */ writeSkippedElements();
/* */
/* 316 */ Element el = new Element(element, true);
/* 317 */ this.elementStack.add(el);
/* */
/* 319 */ boolean singleValued = (elementCardinal == DTDCardinal.NONE) || (elementCardinal == DTDCardinal.OPTIONAL);
/* 320 */ if (singleValued)
/* */ {
/* 323 */ this.content.startElement("", element.getName(), element.getName(), null);
/* */ }
/* */
/* 326 */ while (iter.hasNext())
/* */ {
/* 328 */ Object child = iter.next();
/* 329 */ this.stack.push(child);
/* */
/* 331 */ AttributesImpl attrs = element.attributes.isEmpty() ? null : provideAttributes(element, child);
/* 332 */ if (!singleValued)
/* */ {
/* 334 */ this.content.startElement("", element.getName(), element.getName(), attrs);
/* */ }
/* */
/* 337 */ handleElement(dtd, element, attrs);
/* */
/* 339 */ if (!singleValued)
/* */ {
/* 341 */ this.content.endElement(this.systemId, element.getName(), element.getName());
/* */ }
/* */
/* 344 */ this.stack.pop();
/* */ }
/* */
/* 347 */ if (singleValued)
/* */ {
/* 349 */ this.content.endElement(this.systemId, element.getName(), element.getName());
/* */ }
/* */
/* 352 */ this.elementStack.remove(this.elementStack.size() - 1);
/* */ }
/* */ else
/* */ {
/* 356 */ boolean removeLast = false;
/* 357 */ if ((!(element.getContent() instanceof DTDMixed)) && (!(element.getContent() instanceof DTDEmpty)))
/* */ {
/* 359 */ Element el = new Element(element);
/* 360 */ this.elementStack.add(el);
/* 361 */ removeLast = true;
/* */ }
/* */
/* 364 */ AttributesImpl attrs = element.attributes.isEmpty() ? null : provideAttributes(element, parent);
/* 365 */ handleElement(dtd, element, attrs);
/* */
/* 367 */ if (removeLast)
/* */ {
/* 369 */ Element el = (Element)this.elementStack.remove(this.elementStack.size() - 1);
/* 370 */ if (el.started)
/* */ {
/* 372 */ DTDElement started = el.element;
/* 373 */ this.content.endElement("", started.getName(), started.getName());
/* */ }
/* */ }
/* */ }
/* */ }
/* */
/* */ private final void processContainer(DTD dtd, DTDContainer container)
/* */ {
/* 381 */ DTDItem[] items = container.getItems();
/* 382 */ for (int i = 0; i < items.length; i++)
/* */ {
/* 384 */ DTDItem item = items[i];
/* 385 */ if ((item instanceof DTDContainer))
/* */ {
/* 387 */ processContainer(dtd, (DTDContainer)item);
/* */ } else {
/* 389 */ if (!(item instanceof DTDName))
/* */ continue;
/* 391 */ DTDName name = (DTDName)item;
/* 392 */ DTDElement element = (DTDElement)dtd.elements.get(name.value);
/* 393 */ handleChildren(dtd, element, name.getCardinal());
/* */ }
/* */ }
/* */ }
/* */
/* */ private void writeSkippedElements()
/* */ {
/* 400 */ Element el = (Element)this.elementStack.get(this.elementStack.size() - 1);
/* 401 */ if (!el.started)
/* */ {
/* 403 */ int firstNotStarted = this.elementStack.size() - 1;
/* */ do
/* */ {
/* 406 */ firstNotStarted--; el = (Element)this.elementStack.get(firstNotStarted);
/* */ }
/* 408 */ while (!el.started);
/* */
/* 410 */ firstNotStarted++;
/* */
/* 412 */ while (firstNotStarted < this.elementStack.size())
/* */ {
/* 414 */ el = (Element)this.elementStack.get(firstNotStarted++);
/* 415 */ DTDElement notStarted = el.element;
/* */
/* 417 */ if (log.isTraceEnabled())
/* */ {
/* 419 */ log.trace("starting skipped> " + notStarted.getName());
/* */ }
/* */
/* 422 */ this.content.startElement("", notStarted.getName(), notStarted.getName(), null);
/* 423 */ el.started = true;
/* */ }
/* */ }
/* */ }
/* */
/* */ private AttributesImpl provideAttributes(DTDElement element, Object container)
/* */ {
/* 430 */ Hashtable attributes = element.attributes;
/* 431 */ AttributesImpl attrs = new AttributesImpl(attributes.size());
/* */
/* 433 */ for (Iterator attrIter = attributes.values().iterator(); attrIter.hasNext(); )
/* */ {
/* 435 */ DTDAttribute attr = (DTDAttribute)attrIter.next();
/* 436 */ Object attrValue = this.provider.getAttributeValue(container, null, this.systemId, attr.getName());
/* */
/* 438 */ if (attrValue != null)
/* */ {
/* 440 */ attrs.add(this.systemId, attr.getName(), attr.getName(), attr.getType().toString(), attrValue.toString());
/* */ }
/* */
/* */ }
/* */
/* 449 */ return attrs;
/* */ }
/* */
/* */ protected static DTDElement[] getRootList(DTD dtd)
/* */ {
/* 458 */ Hashtable roots = new Hashtable();
/* 459 */ Enumeration e = dtd.elements.elements();
/* 460 */ while (e.hasMoreElements())
/* */ {
/* 462 */ DTDElement element = (DTDElement)e.nextElement();
/* 463 */ roots.put(element.name, element);
/* */ }
/* */
/* 466 */ e = dtd.elements.elements();
/* 467 */ while (e.hasMoreElements())
/* */ {
/* 469 */ DTDElement element = (DTDElement)e.nextElement();
/* 470 */ if (!(element.content instanceof DTDContainer))
/* */ {
/* */ continue;
/* */ }
/* */
/* 475 */ Enumeration items = ((DTDContainer)element.content).getItemsVec().elements();
/* 476 */ while (items.hasMoreElements())
/* */ {
/* 478 */ removeElements(roots, dtd, (DTDItem)items.nextElement());
/* */ }
/* */ }
/* */
/* 482 */ Collection rootCol = roots.values();
/* 483 */ return (DTDElement[])(DTDElement[])rootCol.toArray(new DTDElement[rootCol.size()]);
/* */ }
/* */
/* */ protected static void removeElements(Hashtable h, DTD dtd, DTDItem item)
/* */ {
/* 488 */ if ((item instanceof DTDName))
/* */ {
/* 490 */ h.remove(((DTDName)item).value);
/* */ }
/* 492 */ else if ((item instanceof DTDContainer))
/* */ {
/* 494 */ Enumeration e = ((DTDContainer)item).getItemsVec().elements();
/* 495 */ while (e.hasMoreElements())
/* */ {
/* 497 */ removeElements(h, dtd, (DTDItem)e.nextElement());
/* */ }
/* */ }
/* */ }
/* */
/* */ private static final class Element
/* */ {
/* */ public final DTDElement element;
/* */ public boolean started;
/* */
/* */ public Element(DTDElement element, boolean started)
/* */ {
/* 511 */ this.element = element;
/* 512 */ this.started = started;
/* */ }
/* */
/* */ public Element(DTDElement element)
/* */ {
/* 517 */ this.element = element;
/* */ }
/* */
/* */ public String toString()
/* */ {
/* 522 */ return "[element=" + this.element.getName() + ", started=" + this.started + "]";
/* */ }
/* */ }
/* */ }
/* Location: /home/mnovotny/projects/EMBEDDED_JBOSS_BETA3_COMMUNITY/embedded/output/lib/embedded-jboss/lib/jboss-embedded-all.jar
* Qualified Name: org.jboss.xb.binding.DtdMarshaller
* JD-Core Version: 0.6.0
*/