[jbosstools-commits] JBoss Tools SVN: r6674 - in trunk/core: plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/xb and 6 other directories.

jbosstools-commits at lists.jboss.org jbosstools-commits at lists.jboss.org
Mon Mar 3 15:39:41 EST 2008


Author: rob.stryker at jboss.com
Date: 2008-03-03 15:39:41 -0500 (Mon, 03 Mar 2008)
New Revision: 6674

Added:
   trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/xb/StrictXercesXSMarshaller.java
   trunk/core/tests/org.jboss.ide.eclipse.archives.test/expectedOutputs/
   trunk/core/tests/org.jboss.ide.eclipse.archives.test/expectedOutputs/emptyPackages.xml
   trunk/core/tests/org.jboss.ide.eclipse.archives.test/src/org/jboss/ide/eclipse/archives/test/xb/MarshallTest.java
Modified:
   trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/ArchiveNodeImpl.java
   trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/xb/XMLBinding.java
   trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/xml/packages.xsd
   trunk/core/tests/org.jboss.ide.eclipse.archives.test/src/org/jboss/ide/eclipse/archives/test/ArchivesTestSuite.java
   trunk/core/tests/org.jboss.ide.eclipse.archives.test/src/org/jboss/ide/eclipse/archives/test/util/FileIOUtil.java
Log:
Created a modified XercesXSMarshaller to throw an exception if a required attribute (such as name) is missing. 

Modified: trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/ArchiveNodeImpl.java
===================================================================
--- trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/ArchiveNodeImpl.java	2008-03-03 16:46:56 UTC (rev 6673)
+++ trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/ArchiveNodeImpl.java	2008-03-03 20:39:41 UTC (rev 6674)
@@ -37,7 +37,6 @@
 import org.jboss.ide.eclipse.archives.core.model.internal.ArchiveNodeDeltaImpl.NodeDelta;
 import org.jboss.ide.eclipse.archives.core.model.internal.xb.XbPackageNode;
 import org.jboss.ide.eclipse.archives.core.model.internal.xb.XbPackageNodeWithProperties;
-import org.jboss.ide.eclipse.archives.core.model.internal.xb.XbPackages;
 
 /**
  * Abstract superclass implementation for archive node types

Added: trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/xb/StrictXercesXSMarshaller.java
===================================================================
--- trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/xb/StrictXercesXSMarshaller.java	                        (rev 0)
+++ trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/xb/StrictXercesXSMarshaller.java	2008-03-03 20:39:41 UTC (rev 6674)
@@ -0,0 +1,1471 @@
+/*
+  * JBoss, Home of Professional Open Source
+  * Copyright 2005, JBoss Inc., and individual contributors as indicated
+  * by the @authors tag. See the copyright.txt in the distribution for a
+  * full listing of individual contributors.
+  *
+  * This is free software; you can redistribute it and/or modify it
+  * under the terms of the GNU Lesser General Public License as
+  * published by the Free Software Foundation; either version 2.1 of
+  * the License, or (at your option) any later version.
+  *
+  * This software is distributed in the hope that it will be useful,
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  * Lesser General Public License for more details.
+  *
+  * You should have received a copy of the GNU Lesser General Public
+  * License along with this software; if not, write to the Free
+  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  */
+package org.jboss.ide.eclipse.archives.core.model.internal.xb;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.xerces.xs.StringList;
+import org.apache.xerces.xs.XSAttributeDeclaration;
+import org.apache.xerces.xs.XSAttributeUse;
+import org.apache.xerces.xs.XSComplexTypeDefinition;
+import org.apache.xerces.xs.XSConstants;
+import org.apache.xerces.xs.XSElementDeclaration;
+import org.apache.xerces.xs.XSModel;
+import org.apache.xerces.xs.XSModelGroup;
+import org.apache.xerces.xs.XSNamedMap;
+import org.apache.xerces.xs.XSObject;
+import org.apache.xerces.xs.XSObjectList;
+import org.apache.xerces.xs.XSParticle;
+import org.apache.xerces.xs.XSSimpleTypeDefinition;
+import org.apache.xerces.xs.XSTerm;
+import org.apache.xerces.xs.XSTypeDefinition;
+import org.apache.xerces.xs.XSWildcard;
+import org.jboss.xb.binding.AbstractMarshaller;
+import org.jboss.xb.binding.AttributesImpl;
+import org.jboss.xb.binding.Constants;
+import org.jboss.xb.binding.Content;
+import org.jboss.xb.binding.ContentWriter;
+import org.jboss.xb.binding.DelegatingObjectModelProvider;
+import org.jboss.xb.binding.GenericObjectModelProvider;
+import org.jboss.xb.binding.JBossXBRuntimeException;
+import org.jboss.xb.binding.Marshaller;
+import org.jboss.xb.binding.MarshallingContext;
+import org.jboss.xb.binding.NamespaceRegistry;
+import org.jboss.xb.binding.ObjectLocalMarshaller;
+import org.jboss.xb.binding.ObjectModelProvider;
+import org.jboss.xb.binding.SimpleTypeBindings;
+import org.jboss.xb.binding.Util;
+import org.jboss.xb.binding.sunday.unmarshalling.SchemaBindingResolver;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+
+/**
+ * @author <a href="mailto:alex at jboss.org">Alexey Loubyansky</a>
+ * @version <tt>$Revision: 1958 $</tt>
+ */
+public class StrictXercesXSMarshaller
+   extends AbstractMarshaller
+{
+   private Stack stack = new StackImpl();
+
+   /**
+    * ObjectModelProvider for this marshaller
+    */
+   private GenericObjectModelProvider provider;
+
+   private Object root;
+
+   /**
+    * Whether NULL values should be ignored or marshalled as xsi:nil='1'
+    */
+   private boolean supportNil = true;
+
+   private QName rootTypeQName;
+
+   private SchemaBindingResolver schemaResolver;
+
+   private XSModel model;
+
+   private boolean ignoreUnresolvedWildcard;
+
+   private XSAttributeUse currentAttribute;
+   private XSTypeDefinition currentElementType;
+
+   private String simpleContentProperty = "value";
+   
+   private MarshallingContext ctx = new MarshallingContext()
+   {
+      private ContentHandler ch;
+
+      public boolean isAttributeRequired()
+      {
+         if(currentAttribute == null)
+         {
+            throw new JBossXBRuntimeException("There is no current attribute!");
+         }
+         return currentAttribute.getRequired();
+      }
+
+      public boolean isTypeComplex()
+      {
+         if(currentElementType == null)
+         {
+            throw new JBossXBRuntimeException("There is no current element!");
+         }
+         return currentElementType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE;
+      }
+
+      public String getSimpleContentProperty()
+      {
+         return simpleContentProperty;
+      }
+
+      public ContentHandler getContentHandler()
+      {
+         if(ch == null)
+         {
+            ch = new ContentHandlerAdaptor();
+         }
+         return ch;
+      }
+
+      public NamespaceRegistry getNamespaceContext()
+      {
+         return nsRegistry;
+      }
+   };
+
+   public String getSimpleContentProperty()
+   {
+      return simpleContentProperty;
+   }
+
+   public void setSimpleContentProperty(String simpleContentProperty)
+   {
+      this.simpleContentProperty = simpleContentProperty;
+   }
+
+   public boolean isIgnoreUnresolvedWildcard()
+   {
+      return ignoreUnresolvedWildcard;
+   }
+
+   public void setIgnoreUnresolvedWildcard(boolean ignoreUnresolvedWildcard)
+   {
+      this.ignoreUnresolvedWildcard = ignoreUnresolvedWildcard;
+   }
+
+   public SchemaBindingResolver getSchemaResolver()
+   {
+      return schemaResolver;
+   }
+
+   public void setSchemaResolver(SchemaBindingResolver schemaResolver)
+   {
+      this.schemaResolver = schemaResolver;
+   }
+
+   public QName getRootTypeQName()
+   {
+      return rootTypeQName;
+   }
+
+   public void setRootTypeQName(QName rootTypeQName)
+   {
+      this.rootTypeQName = rootTypeQName;
+   }
+
+   public boolean isSupportNil()
+   {
+      return supportNil;
+   }
+
+   public void setSupportNil(boolean supportNil)
+   {
+      this.supportNil = supportNil;
+   }
+
+   /**
+    * Adds an attribute to the top most elements.
+    * First, we check whether there is a namespace associated with the passed in prefix.
+    * If the prefix was not declared, an exception is thrown.
+    *
+    * @param prefix    the prefix of the attribute to be declared
+    * @param localName local name of the attribute
+    * @param type      the type of the attribute
+    * @param value     the value of the attribute
+    */
+   public void addAttribute(String prefix, String localName, String type, String value)
+   {
+      // todo addAttribute(String prefix, String localName, String type, String value)
+   }
+
+   // AbstractMarshaller implementation
+
+   public void marshal(Reader xsdReader, ObjectModelProvider provider, Object root, Writer writer)
+      throws IOException, SAXException, ParserConfigurationException
+   {
+      XSModel model = Util.loadSchema(xsdReader, null, schemaResolver);
+      marshallInternal(provider, root, model, writer);
+   }
+
+   public void marshal(String xsdURL, ObjectModelProvider provider, Object root, Writer writer) throws IOException,
+      SAXException
+   {
+      XSModel model = Util.loadSchema(xsdURL, schemaResolver);
+      marshallInternal(provider, root, model, writer);
+   }
+
+   public void marshal(XSModel model, ObjectModelProvider provider, Object root, Writer writer) throws IOException,
+      SAXException
+   {
+      marshallInternal(provider, root, model, writer);
+   }
+
+   private void marshallInternal(ObjectModelProvider provider, Object root, XSModel model, Writer writer)
+      throws IOException, SAXException
+   {
+      if(model == null)
+      {
+         throw new JBossXBRuntimeException("XSModel is not available!");
+      }
+
+      this.model = model;
+      this.provider = provider instanceof GenericObjectModelProvider ?
+         (GenericObjectModelProvider)provider : new DelegatingObjectModelProvider(provider);
+
+      this.root = root;
+
+      content.startDocument();
+
+      if(rootTypeQName != null)
+      {
+         if(rootQNames.isEmpty())
+         {
+            throw new JBossXBRuntimeException("If type name (" +
+               rootTypeQName +
+               ") for the root element is specified then the name for the root element is required!"
+            );
+         }
+         QName rootQName = (QName)rootQNames.get(0);
+
+         XSTypeDefinition type = model.getTypeDefinition(rootTypeQName.getLocalPart(),
+            rootTypeQName.getNamespaceURI()
+         );
+         if(type == null)
+         {
+            throw new JBossXBRuntimeException("Global type definition is not found: " + rootTypeQName);
+         }
+
+         if(isArrayWrapper(type))
+         {
+            Object o = provider.getRoot(root, null, rootQName.getNamespaceURI(), rootQName.getLocalPart());
+            stack.push(o);
+            marshalComplexType(rootQName.getNamespaceURI(),
+               rootQName.getLocalPart(),
+               (XSComplexTypeDefinition)type,
+               true,
+               false
+            );
+            stack.pop();
+         }
+         else
+         {
+            Object o = provider.getRoot(root, null, rootQName.getNamespaceURI(), rootQName.getLocalPart());
+            marshalElementOccurence(rootQName.getNamespaceURI(),
+               rootQName.getLocalPart(),
+               type,
+               o,
+               false,
+               false,
+               true
+            );
+         }
+      }
+      else if(rootQNames.isEmpty())
+      {
+         XSNamedMap components = model.getComponents(XSConstants.ELEMENT_DECLARATION);
+         if(components.getLength() == 0)
+         {
+            throw new JBossXBRuntimeException("The schema doesn't contain global element declarations.");
+         }
+
+         for(int i = 0; i < components.getLength(); ++i)
+         {
+            XSElementDeclaration element = (XSElementDeclaration)components.item(i);
+            Object o = provider.getRoot(root, null, element.getNamespace(), element.getName());
+            marshalElementOccurence(element.getNamespace(),
+               element.getName(),
+               element.getTypeDefinition(),
+               o,
+               element.getNillable(),
+               false,
+               true
+            );
+         }
+      }
+      else
+      {
+         for(int i = 0; i < rootQNames.size(); ++i)
+         {
+            QName qName = (QName)rootQNames.get(i);
+            XSElementDeclaration element = model.getElementDeclaration(qName.getLocalPart(), qName.getNamespaceURI());
+            if(element == null)
+            {
+               XSNamedMap components = model.getComponents(XSConstants.ELEMENT_DECLARATION);
+               String roots = "";
+               for(int j = 0; j < components.getLength(); ++j)
+               {
+                  XSObject xsObject = components.item(j);
+                  if(j > 0)
+                  {
+                     roots += ", ";
+                  }
+                  roots += "{" + xsObject.getNamespace() + "}" + xsObject.getName();
+               }
+               throw new IllegalStateException("Root element not found: " + qName + " among " + roots);
+            }
+
+            Object o = provider.getRoot(root, null, element.getNamespace(), element.getName());
+            marshalElementOccurence(element.getNamespace(),
+               element.getName(),
+               element.getTypeDefinition(),
+               o,
+               element.getNillable(),
+               false,
+               true
+            );
+         }
+      }
+
+      content.endDocument();
+
+      // version & encoding
+      writeXmlVersion(writer);
+
+      ContentWriter contentWriter = new ContentWriter(writer,
+         propertyIsTrueOrNotSet(Marshaller.PROP_OUTPUT_INDENTATION)
+      );
+      content.handleContent(contentWriter);
+
+      if(log.isTraceEnabled())
+      {
+         java.io.StringWriter traceWriter = new java.io.StringWriter();
+         contentWriter = new ContentWriter(traceWriter,
+            propertyIsTrueOrNotSet(Marshaller.PROP_OUTPUT_INDENTATION)
+         );
+         content.handleContent(contentWriter);
+         log.trace("marshalled:\n" + traceWriter.getBuffer().toString());
+      }
+   }
+
+   private boolean marshalElement(String elementNs, String elementLocal,
+                                  XSTypeDefinition type,
+                                  boolean optional,
+                                  boolean nillable,
+                                  boolean declareNs,
+                                  boolean declareXsiType)
+   {
+      Object value = stack.peek();
+      boolean result = value != null || value == null && (optional || nillable);
+      boolean trace = log.isTraceEnabled() && result;
+      if(trace)
+      {
+         String prefix = getPrefix(elementNs);
+         log.trace("started element ns=" + elementNs + ", local=" + elementLocal + ", prefix=" + prefix);
+      }
+
+      if(value != null)
+      {
+         marshalElementType(elementNs, elementLocal, type, declareNs, nillable, declareXsiType);
+      }
+      else if(nillable)
+      {
+         writeNillable(elementNs, elementLocal, nillable);
+      }
+
+      if(trace)
+      {
+         log.trace("finished element ns=" + elementNs + ", local=" + elementLocal);
+      }
+
+      return result;
+   }
+
+   private void marshalElementType(String elementNs,
+                                   String elementLocal,
+                                   XSTypeDefinition type,
+                                   boolean declareNs,
+                                   boolean nillable,
+                                   boolean declareXsiType)
+   {
+      switch(type.getTypeCategory())
+      {
+         case XSTypeDefinition.SIMPLE_TYPE:
+            marshalSimpleType(elementNs,
+               elementLocal,
+               (XSSimpleTypeDefinition)type,
+               declareNs,
+               nillable,
+               declareXsiType
+            );
+            break;
+         case XSTypeDefinition.COMPLEX_TYPE:
+            marshalComplexType(elementNs, elementLocal, (XSComplexTypeDefinition)type, declareNs, declareXsiType);
+            break;
+         default:
+            throw new IllegalStateException("Unexpected type category: " + type.getTypeCategory());
+      }
+   }
+
+   private void marshalSimpleType(String elementUri,
+                                  String elementLocal,
+                                  XSSimpleTypeDefinition type,
+                                  boolean declareNs,
+                                  boolean nillable,
+                                  boolean declareXsiType)
+   {
+      Object value = stack.peek();
+      if(value != null)
+      {
+         String prefix = getPrefix(elementUri);
+         boolean genPrefix = prefix == null && elementUri != null && elementUri.length() > 0;
+         if(genPrefix)
+         {
+            prefix = "ns_" + elementLocal;
+         }
+
+         AttributesImpl attrs = null;
+         String typeName = type.getName();
+         if(SimpleTypeBindings.XS_QNAME_NAME.equals(typeName) ||
+            SimpleTypeBindings.XS_NOTATION_NAME.equals(typeName) ||
+            type.getItemType() != null &&
+            (SimpleTypeBindings.XS_QNAME_NAME.equals(type.getItemType().getName()) ||
+            SimpleTypeBindings.XS_NOTATION_NAME.equals(type.getItemType().getName())
+            )
+         )
+         {
+            attrs = new AttributesImpl(5);
+         }
+
+         String marshalled = marshalCharacters(elementUri, prefix, type, value, attrs);
+
+         if((declareNs || declareXsiType) && nsRegistry.size() > 0)
+         {
+            if(attrs == null)
+            {
+               attrs = new AttributesImpl(nsRegistry.size() + 1);
+            }
+            declareNs(attrs);
+         }
+
+         if(declareXsiType)
+         {
+            declareXsiType(type, attrs);
+         }
+
+         if(genPrefix)
+         {
+            if(attrs == null)
+            {
+               attrs = new AttributesImpl(1);
+            }
+            attrs.add(null, prefix, "xmlns:" + prefix, null, (String)elementUri);
+         }
+
+         String qName = prefixLocalName(prefix, elementLocal);
+
+         content.startElement(elementUri, elementLocal, qName, attrs);
+         content.characters(marshalled.toCharArray(), 0, marshalled.length());
+         content.endElement(elementUri, elementLocal, qName);
+      }
+      else
+      {
+         writeNillable(elementUri, elementLocal, nillable);
+      }
+   }
+
+   private void marshalComplexType(String elementNsUri,
+                                   String elementLocalName,
+                                   XSComplexTypeDefinition type,
+                                   boolean declareNs,
+                                   boolean declareXsiType)
+   {
+      Object o = stack.peek();
+      XSParticle particle = type.getParticle();
+
+      XSObjectList attributeUses = type.getAttributeUses();
+      int attrsTotal = declareNs || declareXsiType ?
+         nsRegistry.size() + attributeUses.getLength() + 1 :
+         attributeUses.getLength();
+      AttributesImpl attrs = attrsTotal > 0 ? new AttributesImpl(attrsTotal) : null;
+
+      if(declareNs && nsRegistry.size() > 0)
+      {
+         declareNs(attrs);
+      }
+
+      String generatedPrefix = null;
+      if(declareXsiType)
+      {
+         generatedPrefix = declareXsiType(type, attrs);
+         if(generatedPrefix != null)
+         {
+            String typeNsWithGeneratedPrefix = type.getNamespace();
+            declareNs(attrs, generatedPrefix, typeNsWithGeneratedPrefix);
+            declareNamespace(generatedPrefix, typeNsWithGeneratedPrefix);
+         }
+      }
+
+      String prefix = getPrefix(elementNsUri);
+      boolean genPrefix = prefix == null && elementNsUri != null && elementNsUri.length() > 0;
+      if(genPrefix)
+      {
+         // todo: it's possible that the generated prefix already mapped. this should be fixed
+         prefix = "ns_" + elementLocalName;
+         declareNamespace(prefix, elementNsUri);
+         if(attrs == null)
+         {
+            attrs = new AttributesImpl(1);
+         }
+         attrs.add(null, prefix, "xmlns:" + prefix, null, elementNsUri);
+      }
+
+      for(int i = 0; i < attributeUses.getLength(); ++i)
+      {
+         currentAttribute = (XSAttributeUse)attributeUses.item(i);
+         XSAttributeDeclaration attrDec = currentAttribute.getAttrDeclaration();
+         String attrNs = attrDec.getNamespace();
+         String attrLocal = attrDec.getName();
+         Object attrValue = provider.getAttributeValue(o, ctx, attrNs, attrLocal);
+
+         if(attrValue != null)
+         {
+            if(attrs == null)
+            {
+               attrs = new AttributesImpl(5);
+            }
+
+            String attrPrefix = null;
+            if(attrNs != null)
+            {
+               attrPrefix = getPrefix(attrNs);
+               if(attrPrefix == null && attrNs != null && attrNs.length() > 0)
+               {
+                  attrPrefix = "ns_" + attrLocal;
+                  attrs.add(null, attrPrefix, "xmlns:" + attrPrefix, null, attrNs);
+               }
+            }
+
+            String qName = attrPrefix == null || attrPrefix.length() == 0 ? attrLocal : attrPrefix + ":" + attrLocal;
+
+            // todo: this is a quick fix for boolean pattern (0|1 or true|false) should be refactored
+            XSSimpleTypeDefinition attrType = attrDec.getTypeDefinition();
+            if(attrType.getItemType() != null)
+            {
+               XSSimpleTypeDefinition itemType = attrType.getItemType();
+               if(Constants.NS_XML_SCHEMA.equals(itemType.getNamespace()))
+               {
+                  List list;
+                  if(attrValue instanceof List)
+                  {
+                     list = (List)attrValue;
+                  }
+                  else if(attrValue.getClass().isArray())
+                  {
+                     list = Arrays.asList((Object[])attrValue);
+                  }
+                  else
+                  {
+                     throw new JBossXBRuntimeException("Expected value for list type is an array or " +
+                        List.class.getName() +
+                        " but got: " +
+                        attrValue
+                     );
+                  }
+
+                  if(Constants.QNAME_QNAME.getLocalPart().equals(itemType.getName()))
+                  {
+                     for(int listInd = 0; listInd < list.size(); ++listInd)
+                     {
+                        QName item = (QName)list.get(listInd);
+                        String itemNs = item.getNamespaceURI();
+                        if(itemNs != null && itemNs.length() > 0)
+                        {
+                           String itemPrefix;
+                           if(itemNs.equals(elementNsUri))
+                           {
+                              itemPrefix = prefix;
+                           }
+                           else
+                           {
+                              itemPrefix = getPrefix(itemNs);
+                              if(itemPrefix == null)
+                              {
+                                 itemPrefix = attrLocal + listInd;
+                                 declareNs(attrs, itemPrefix, itemNs);
+                              }
+                           }
+                           item = new QName(item.getNamespaceURI(), item.getLocalPart(), itemPrefix);
+                           list.set(listInd, item);
+                        }
+                     }
+                  }
+
+                  attrValue = SimpleTypeBindings.marshalList(itemType.getName(), list, null);
+               }
+               else
+               {
+                  throw new JBossXBRuntimeException("Marshalling of list types with item types not from " +
+                     Constants.NS_XML_SCHEMA + " is not supported."
+                  );
+               }
+            }
+            else if(attrType.getLexicalPattern().item(0) != null
+               &&
+               attrType.derivedFrom(Constants.NS_XML_SCHEMA,
+                  Constants.QNAME_BOOLEAN.getLocalPart(),
+                  XSConstants.DERIVATION_RESTRICTION
+               ))
+            {
+               String item = attrType.getLexicalPattern().item(0);
+               if(item.indexOf('0') != -1 && item.indexOf('1') != -1)
+               {
+                  attrValue = ((Boolean)attrValue).booleanValue() ? "1" : "0";
+               }
+               else
+               {
+                  attrValue = ((Boolean)attrValue).booleanValue() ? "true" : "false";
+               }
+            }
+            else if(Constants.QNAME_QNAME.getNamespaceURI().equals(attrType.getNamespace()) &&
+               Constants.QNAME_QNAME.getLocalPart().equals(attrType.getName()))
+            {
+               QName qNameValue = (QName)attrValue;
+
+               String qNamePrefix = null;
+               boolean declarePrefix = false;
+               String ns = qNameValue.getNamespaceURI();
+               if(ns != null && ns.length() > 0)
+               {
+                  qNamePrefix = getPrefix(ns);
+                  if(qNamePrefix == null)
+                  {
+                     qNamePrefix = qNameValue.getPrefix();
+                     if(qNamePrefix == null || qNamePrefix.length() == 0)
+                     {
+                        qNamePrefix = "ns_" + qNameValue.getLocalPart();
+                     }
+                     declareNs(attrs, qNamePrefix, ns);
+                     nsRegistry.addPrefixMapping(qNamePrefix, ns);
+                     declarePrefix = true;
+                  }
+               }
+
+               attrValue = SimpleTypeBindings.marshalQName(qNameValue, nsRegistry);
+
+               if(declarePrefix)
+               {
+                  nsRegistry.removePrefixMapping(qNamePrefix);
+               }
+            }
+            else
+            {
+               attrValue = attrValue.toString();
+            }
+
+            attrs.add(attrNs,
+               attrLocal,
+               qName,
+               attrDec.getTypeDefinition().getName(),
+               attrValue.toString()
+            );
+         } // end if attrValue != null 
+         else if( currentAttribute.getRequired()){
+        	 // its required and is not present. Must throw exception
+        	 String name = currentAttribute.getAttrDeclaration().getName();
+        	 throw new JBossXBRuntimeException("Required Attribute " + name + " is not present");
+         }
+      }
+      currentAttribute = null;
+
+      String characters = null;
+      if(type.getSimpleType() != null)
+      {
+         Object value = getSimpleContentValue(elementNsUri, elementLocalName, type);
+         if(value != null)
+         {
+            XSSimpleTypeDefinition simpleType = type.getSimpleType();
+            String typeName = simpleType.getName();
+            if(attrs == null && (SimpleTypeBindings.XS_QNAME_NAME.equals(typeName) ||
+               SimpleTypeBindings.XS_NOTATION_NAME.equals(typeName) ||
+               simpleType.getItemType() != null &&
+               (SimpleTypeBindings.XS_QNAME_NAME.equals(simpleType.getItemType().getName()) ||
+               SimpleTypeBindings.XS_NOTATION_NAME.equals(simpleType.getItemType().getName())
+               )
+               )
+            )
+            {
+               attrs = new AttributesImpl(5);
+            }
+
+            characters = marshalCharacters(elementNsUri, prefix, simpleType, value, attrs);
+         }
+      }
+
+      String qName = prefixLocalName(prefix, elementLocalName);
+      content.startElement(elementNsUri, elementLocalName, qName, attrs);
+
+      if(particle != null)
+      {
+         marshalParticle(particle, false);
+      }
+
+      if(characters != null)
+      {
+         content.characters(characters.toCharArray(), 0, characters.length());
+      }
+      content.endElement(elementNsUri, elementLocalName, qName);
+
+      if(genPrefix)
+      {
+         removePrefixMapping(prefix);
+      }
+
+      if(generatedPrefix != null)
+      {
+         removePrefixMapping(generatedPrefix);
+      }
+   }
+
+   private boolean marshalParticle(XSParticle particle, boolean declareNs)
+   {
+      boolean marshalled;
+      XSTerm term = particle.getTerm();
+      Object o;
+      Iterator i;
+      switch(term.getType())
+      {
+         case XSConstants.MODEL_GROUP:
+            o = stack.peek();
+            i = o != null && isRepeatable(particle) ? getIterator(o) : null;
+            if(i != null)
+            {
+               marshalled = true;
+               while(i.hasNext() && marshalled)
+               {
+                  Object value = i.next();
+                  stack.push(value);
+                  marshalled = marshalModelGroup(particle, declareNs);
+                  stack.pop();
+               }
+            }
+            else
+            {
+               marshalled = marshalModelGroup(particle, declareNs);
+            }
+            break;
+         case XSConstants.WILDCARD:
+            o = stack.peek();
+
+            boolean popWildcardValue = false;
+            ObjectLocalMarshaller marshaller = null;
+            FieldToWildcardMapping mapping = (FieldToWildcardMapping)field2WildcardMap.get(o.getClass());
+            if(mapping != null)
+            {
+               marshaller = mapping.marshaller;
+               o = mapping.fieldInfo.getValue(o);
+               stack.push(o);
+               popWildcardValue = true;
+            }
+
+            i = o != null && isRepeatable(particle) ? getIterator(o) : null;
+            if(i != null)
+            {
+               marshalled = true;
+               while(i.hasNext() && marshalled)
+               {
+                  Object value = i.next();
+                  marshalled = marshalWildcardOccurence(particle, marshaller, value, declareNs);
+               }
+            }
+            else
+            {
+               marshalled = marshalWildcardOccurence(particle, marshaller, o, declareNs);
+            }
+
+            if(popWildcardValue)
+            {
+               stack.pop();
+            }
+
+            break;
+         case XSConstants.ELEMENT_DECLARATION:
+            XSElementDeclaration element = (XSElementDeclaration)term;
+            XSTypeDefinition type = element.getTypeDefinition();
+            o = getElementValue(element.getNamespace(), element.getName(), type);
+
+            i = o != null && isRepeatable(particle) ? getIterator(o) : null;
+            if(i != null)
+            {
+               marshalled = true;
+               while(i.hasNext() && marshalled)
+               {
+                  Object value = i.next();
+                  marshalled =
+                     marshalElementOccurence(element.getNamespace(),
+                        element.getName(),
+                        type,
+                        value,
+                        element.getNillable(),
+                        particle.getMinOccurs() == 0,
+                        declareNs
+                     );
+               }
+            }
+            else
+            {
+               marshalled =
+                  marshalElementOccurence(element.getNamespace(),
+                     element.getName(),
+                     type,
+                     o,
+                     element.getNillable(),
+                     particle.getMinOccurs() == 0,
+                     declareNs
+                  );
+            }
+            break;
+         default:
+            throw new IllegalStateException("Unexpected term type: " + term.getType());
+      }
+      return marshalled;
+   }
+
+   private boolean marshalElementOccurence(String elementNs,
+                                           String elementLocal,
+                                           XSTypeDefinition type,
+                                           Object value,
+                                           boolean nillable,
+                                           boolean optional,
+                                           boolean declareNs)
+   {
+      boolean declareXsiType = false;
+      QName xsiTypeQName = null;
+      if(value != null)
+      {
+         xsiTypeQName = (QName)cls2TypeMap.get(value.getClass());
+         if(xsiTypeQName != null &&
+            !(type.getName().equals(xsiTypeQName.getLocalPart()) &&
+            type.getNamespace().equals(xsiTypeQName.getNamespaceURI())
+            ))
+         {
+            declareXsiType = true;
+            if(log.isTraceEnabled())
+            {
+               log.trace(value.getClass() + " is mapped to xsi:type " + xsiTypeQName);
+            }
+
+            XSTypeDefinition xsiType = model.getTypeDefinition(xsiTypeQName.getLocalPart(),
+               xsiTypeQName.getNamespaceURI()
+            );
+
+            if(xsiType == null)
+            {
+               log.warn("Class " +
+                  value.getClass() +
+                  " is mapped to type " +
+                  xsiTypeQName +
+                  " but the type is not found in schema."
+               );
+            }
+            // todo should check derivation also, i.e. if(xsiType.derivedFrom())
+            else
+            {
+               type = xsiType;
+            }
+         }
+      }
+
+      stack.push(value);
+      boolean marshalled = marshalElement(elementNs,
+         elementLocal,
+         type,
+         optional,
+         nillable,
+         declareNs,
+         declareXsiType
+      );
+      stack.pop();
+
+      return marshalled;
+   }
+
+   private boolean marshalWildcardOccurence(XSParticle particle,
+                                            ObjectLocalMarshaller marshaller,
+                                            Object value,
+                                            boolean declareNs)
+   {
+      boolean marshalled = true;
+      if(marshaller != null)
+      {
+         marshaller.marshal(ctx, value);
+      }
+      else
+      {
+         stack.push(value);
+         marshalled = marshalWildcard(particle, declareNs);
+         stack.pop();
+      }
+      return marshalled;
+   }
+
+   private boolean marshalWildcard(XSParticle particle, boolean declareNs)
+   {
+      XSWildcard wildcard = (XSWildcard)particle.getTerm();
+      Object o = stack.peek();
+      ClassMapping mapping = getClassMapping(o.getClass());
+      if(mapping == null)
+      {
+         // todo: YAH (yet another hack)
+         QName autoType = SimpleTypeBindings.typeQName(o.getClass());
+         if(autoType != null)
+         {
+            String marshalled = SimpleTypeBindings.marshal(autoType.getLocalPart(), o, null);
+            content.characters(marshalled.toCharArray(), 0, marshalled.length());
+            return true;
+         }
+         else
+         {
+            if(ignoreUnresolvedWildcard)
+            {
+               log.warn("Failed to marshal wildcard. Class mapping not found for " +
+                  o.getClass() +
+                  "@" +
+                  o.hashCode() +
+                  ": " + o
+               );
+               return true;
+            }
+            else
+            {
+               throw new IllegalStateException("Failed to marshal wildcard. Class mapping not found for " +
+                  o.getClass() +
+                  "@" +
+                  o.hashCode() +
+                  ": " + o
+               );
+            }
+         }
+      }
+
+      GenericObjectModelProvider parentProvider = this.provider;
+      Object parentRoot = this.root;
+      Stack parentStack = this.stack;
+      XSModel parentModel = this.model;
+
+      this.root = o;
+      this.stack = new StackImpl();
+      this.model = mapping.schemaUrl == null ? this.model : Util.loadSchema(mapping.schemaUrl, schemaResolver);
+      if(mapping.provider != null)
+      {
+         this.provider = mapping.provider;
+      }
+
+      boolean marshalled;
+      if(mapping.elementName != null)
+      {
+         XSElementDeclaration elDec = model.getElementDeclaration(mapping.elementName.getLocalPart(),
+            mapping.elementName.getNamespaceURI()
+         );
+
+         if(elDec == null)
+         {
+            throw new JBossXBRuntimeException("Element " + mapping.elementName + " is not declared in the schema.");
+         }
+
+         Object elementValue = provider.getRoot(root, null, elDec.getNamespace(), elDec.getName());
+         marshalled = marshalElementOccurence(elDec.getNamespace(),
+            elDec.getName(),
+            elDec.getTypeDefinition(),
+            elementValue,
+            elDec.getNillable(),
+            particle.getMinOccurs() == 0,
+            declareNs
+         );
+      }
+      else if(mapping.typeName != null)
+      {
+         XSTypeDefinition typeDef = model.getTypeDefinition(mapping.typeName.getLocalPart(),
+            mapping.typeName.getNamespaceURI()
+         );
+
+         if(typeDef == null)
+         {
+            List typeNames = new ArrayList();
+            XSNamedMap types = model.getComponents(XSConstants.TYPE_DEFINITION);
+            for(int i = 0; i < types.getLength(); ++i)
+            {
+               XSObject type = types.item(i);
+               if(!Constants.NS_XML_SCHEMA.equals(type.getNamespace()))
+               {
+                  typeNames.add(new QName(type.getNamespace(), type.getName()));
+               }
+            }
+            throw new JBossXBRuntimeException("Type " +
+               mapping.typeName +
+               " is not defined in the schema." +
+               " Defined types are: " + typeNames
+            );
+         }
+
+         Object elementValue = provider.getRoot(root, null, wildcard.getNamespace(), wildcard.getName());
+         marshalled =
+            marshalElementOccurence(wildcard.getNamespace(),
+               wildcard.getName(),
+               typeDef,
+               elementValue,
+               true,
+               particle.getMinOccurs() == 0,
+               declareNs
+            );
+      }
+      else
+      {
+         throw new JBossXBRuntimeException("Class mapping for " +
+            mapping.cls +
+            " is associated with neither global element name nor global type name."
+         );
+      }
+
+      this.root = parentRoot;
+      this.provider = parentProvider;
+      this.stack = parentStack;
+      this.model = parentModel;
+
+      return marshalled;
+   }
+
+   private boolean marshalModelGroup(XSParticle particle, boolean declareNs)
+   {
+      XSModelGroup modelGroup = (XSModelGroup)particle.getTerm();
+      boolean marshalled;
+      switch(modelGroup.getCompositor())
+      {
+         case XSModelGroup.COMPOSITOR_ALL:
+            marshalled = marshalModelGroupAll(modelGroup.getParticles(), declareNs);
+            break;
+         case XSModelGroup.COMPOSITOR_CHOICE:
+            marshalled = marshalModelGroupChoice(modelGroup.getParticles(), declareNs);
+            break;
+         case XSModelGroup.COMPOSITOR_SEQUENCE:
+            marshalled = marshalModelGroupSequence(modelGroup.getParticles(), declareNs);
+            break;
+         default:
+            throw new IllegalStateException("Unexpected compsitor: " + modelGroup.getCompositor());
+      }
+      return marshalled;
+   }
+
+   private boolean marshalModelGroupAll(XSObjectList particles, boolean declareNs)
+   {
+      boolean marshalled = false;
+      for(int i = 0; i < particles.getLength(); ++i)
+      {
+         XSParticle particle = (XSParticle)particles.item(i);
+         marshalled |= marshalParticle(particle, declareNs);
+      }
+      return marshalled;
+   }
+
+   private boolean marshalModelGroupChoice(XSObjectList particles, boolean declareNs)
+   {
+      boolean marshalled = false;
+      Content mainContent = this.content;
+      for(int i = 0; i < particles.getLength() && !marshalled; ++i)
+      {
+         XSParticle particle = (XSParticle)particles.item(i);
+         this.content = new Content();
+         marshalled = marshalParticle(particle, declareNs);
+      }
+
+      if(marshalled)
+      {
+         mainContent.append(this.content);
+      }
+      this.content = mainContent;
+
+      return marshalled;
+   }
+
+   private boolean marshalModelGroupSequence(XSObjectList particles, boolean declareNs)
+   {
+      boolean marshalled = true;
+      for(int i = 0; i < particles.getLength(); ++i)
+      {
+         XSParticle particle = (XSParticle)particles.item(i);
+         marshalled &= marshalParticle(particle, declareNs);
+      }
+      return marshalled;
+   }
+
+   private String marshalCharacters(String elementUri,
+                                    String elementPrefix,
+                                    XSSimpleTypeDefinition type,
+                                    Object value,
+                                    AttributesImpl attrs)
+   {
+      String marshalled;
+      if(type.getItemType() != null)
+      {
+         XSSimpleTypeDefinition itemType = type.getItemType();
+         if(Constants.NS_XML_SCHEMA.equals(itemType.getNamespace()))
+         {
+            List list;
+            if(value instanceof List)
+            {
+               list = (List)value;
+            }
+            else if(value.getClass().isArray())
+            {
+               list = asList(value);
+            }
+            else
+            {
+               // todo: qname are also not yet supported
+               throw new JBossXBRuntimeException(
+                  "Expected value for list type is an array or " + List.class.getName() + " but got: " + value
+               );
+            }
+
+            marshalled = SimpleTypeBindings.marshalList(itemType.getName(), list, null);
+         }
+         else
+         {
+            throw new JBossXBRuntimeException("Marshalling of list types with item types not from " +
+               Constants.NS_XML_SCHEMA + " is not supported."
+            );
+         }
+      }
+      else if(Constants.NS_XML_SCHEMA.equals(type.getNamespace()))
+      {
+         String typeName = type.getName();
+
+         String prefix = null;
+         boolean removePrefix = false;
+         if(SimpleTypeBindings.XS_QNAME_NAME.equals(typeName) ||
+            SimpleTypeBindings.XS_NOTATION_NAME.equals(typeName))
+         {
+            QName qName = (QName)value;
+            if(qName.getNamespaceURI() != null && qName.getNamespaceURI().length() > 0)
+            {
+               prefix = nsRegistry.getPrefix(qName.getNamespaceURI());
+               if(prefix == null)
+               {
+                  prefix = qName.getPrefix();
+                  if(prefix == null || prefix.length() == 0)
+                  {
+                     prefix = qName.getLocalPart() + "_ns";
+                  }
+                  nsRegistry.addPrefixMapping(prefix, qName.getNamespaceURI());
+                  declareNs(attrs, prefix, qName.getNamespaceURI());
+
+                  removePrefix = true;
+               }
+            }
+         }
+         marshalled = SimpleTypeBindings.marshal(typeName, value, nsRegistry);
+
+         if(removePrefix)
+         {
+            nsRegistry.removePrefixMapping(prefix);
+         }
+      }
+      // todo: this is a quick fix for boolean pattern (0|1 or true|false) should be refactored
+      else if(type.getLexicalPattern().item(0) != null
+         &&
+         type.derivedFrom(Constants.NS_XML_SCHEMA,
+            Constants.QNAME_BOOLEAN.getLocalPart(),
+            XSConstants.DERIVATION_RESTRICTION
+         ))
+      {
+         String item = type.getLexicalPattern().item(0);
+         if(item.indexOf('0') != -1 && item.indexOf('1') != -1)
+         {
+            marshalled = ((Boolean)value).booleanValue() ? "1" : "0";
+         }
+         else
+         {
+            marshalled = ((Boolean)value).booleanValue() ? "true" : "false";
+         }
+      }
+      else
+      {
+         StringList lexicalEnumeration = type.getLexicalEnumeration();
+         if(lexicalEnumeration != null && lexicalEnumeration.getLength() > 0)
+         {
+            Method getValue;
+            try
+            {
+               getValue = value.getClass().getMethod("value", null);
+            }
+            catch(NoSuchMethodException e)
+            {
+               try
+               {
+                  getValue = value.getClass().getMethod("getValue", null);
+               }
+               catch(NoSuchMethodException e1)
+               {
+                  List values = new ArrayList(lexicalEnumeration.getLength());
+                  for(int i = 0; i < lexicalEnumeration.getLength(); ++i)
+                  {
+                     values.add(lexicalEnumeration.item(i));
+                  }
+
+                  throw new JBossXBRuntimeException("Failed to find neither value() nor getValue() in " +
+                     value.getClass() +
+                     " which is bound to enumeration type (" +
+                     type.getNamespace() +
+                     ", " +
+                     type.getName() + "): " + values
+                  );
+               }
+            }
+
+            try
+            {
+               value = getValue.invoke(value, null);
+            }
+            catch(Exception e)
+            {
+               throw new JBossXBRuntimeException(
+                  "Failed to invoke getValue() on " + value + " to get the enumeration value", e
+               );
+            }
+         }
+
+         marshalled = marshalCharacters(elementUri,
+            elementPrefix,
+            (XSSimpleTypeDefinition)type.getBaseType(),
+            value, attrs
+         );
+      }
+      return marshalled;
+   }
+
+   /**
+    * Adds xsi:type attribute and optionally declares namespaces for xsi and type's namespace.
+    * @param type  the type to declare xsi:type attribute for
+    * @param attrs  the attributes to add xsi:type attribute to
+    * @return  prefix for the type's ns if it was generated
+    */
+   private String declareXsiType(XSTypeDefinition type, AttributesImpl attrs)
+   {
+      String result = null;
+      String xsiPrefix = nsRegistry.getPrefix(Constants.NS_XML_SCHEMA_INSTANCE);
+      if(xsiPrefix == null)
+      {
+         attrs.add(Constants.NS_XML_SCHEMA, "xmlns", "xmlns:xsi", null, Constants.NS_XML_SCHEMA_INSTANCE);
+         xsiPrefix = "xsi";
+      }
+
+      String pref = getPrefix(type.getNamespace());
+      if(pref == null)
+      {
+         // the ns is not declared
+         result = pref = type.getName() + "_ns";
+      }
+
+      String typeQName = pref == null ? type.getName() : pref + ':' + type.getName();
+      attrs.add(Constants.NS_XML_SCHEMA_INSTANCE, "type", xsiPrefix + ":type", null, typeQName);
+      return result;
+   }
+
+   private Object getElementValue(String elementNs, String elementLocal, XSTypeDefinition type)
+   {
+      Object value;
+      Object peeked = stack.isEmpty() ? root : stack.peek();
+      if(peeked == null)
+      {
+         value = null;
+      }
+      else if(peeked instanceof Collection || peeked.getClass().isArray())
+      {
+         // collection is the provider
+         value = peeked;
+      }
+      else
+      {
+         XSTypeDefinition parentType = currentElementType;
+         currentElementType = type;
+
+         value = provider.getChildren(peeked, ctx, elementNs, elementLocal);
+         if(value == null)
+         {
+            value = provider.getElementValue(peeked, ctx, elementNs, elementLocal);
+         }
+
+         currentElementType = parentType;
+      }
+      return value;
+   }
+
+   private Object getSimpleContentValue(String elementNs, String elementLocal, XSTypeDefinition type)
+   {
+      Object value;
+      Object peeked = stack.isEmpty() ? root : stack.peek();
+      if(peeked == null)
+      {
+         value = null;
+      }
+      else
+      {
+         XSTypeDefinition parentType = currentElementType;
+         currentElementType = type;
+         value = provider.getElementValue(peeked, ctx, elementNs, elementLocal);
+         currentElementType = parentType;
+      }
+      return value;
+   }
+
+   private void writeNillable(String elementNs, String elementLocal, boolean nillable)
+   {
+      if(!supportNil)
+      {
+         return;
+      }
+
+      if(!nillable)
+      {
+         throw new JBossXBRuntimeException("Failed to marshal " +
+            new QName(elementNs, elementLocal) +
+            ": Java value is null but the element is not nillable."
+         );
+      }
+
+      AttributesImpl attrs;
+      String prefix = getPrefix(elementNs);
+      if(prefix == null && elementNs != null && elementNs.length() > 0)
+      {
+         prefix = "ns_" + elementLocal;
+         attrs = new AttributesImpl(2);
+         attrs.add(null, prefix, "xmlns:" + prefix, null, elementNs);
+      }
+      else
+      {
+         attrs = new AttributesImpl(1);
+      }
+
+      String xsiPrefix = getPrefix(Constants.NS_XML_SCHEMA_INSTANCE);
+      if(xsiPrefix == null)
+      {
+         xsiPrefix = "xsi";
+         attrs.add(null,
+            xsiPrefix,
+            "xmlns:xsi",
+            null,
+            Constants.NS_XML_SCHEMA_INSTANCE
+         );
+      }
+
+      String nilQName = xsiPrefix + ":nil";
+      attrs.add(Constants.NS_XML_SCHEMA_INSTANCE, "nil", nilQName, null, "1");
+
+      String qName = prefixLocalName(prefix, elementLocal);
+      content.startElement(elementNs, elementLocal, qName, attrs);
+      content.endElement(elementNs, elementLocal, qName);
+   }
+
+   private static boolean isArrayWrapper(XSTypeDefinition type)
+   {
+      boolean is = false;
+      if(XSTypeDefinition.COMPLEX_TYPE == type.getTypeCategory())
+      {
+         XSComplexTypeDefinition cType = (XSComplexTypeDefinition)type;
+         XSParticle particle = cType.getParticle();
+         if(particle != null)
+         {
+            is = particle.getMaxOccursUnbounded() || particle.getMaxOccurs() > 1;
+         }
+      }
+      return is;
+   }
+
+   private Iterator getIterator(Object value)
+   {
+      Iterator i = null;
+      if(value instanceof Collection)
+      {
+         i = ((Collection)value).iterator();
+      }
+      else if(value.getClass().isArray())
+      {
+         final Object arr = value;
+         i = new Iterator()
+         {
+            private int curInd = 0;
+            private int length = Array.getLength(arr);
+
+            public boolean hasNext()
+            {
+               return curInd < length;
+            }
+
+            public Object next()
+            {
+               return Array.get(arr, curInd++);
+            }
+
+            public void remove()
+            {
+               throw new UnsupportedOperationException("remove is not implemented.");
+            }
+         };
+      }
+      else if(value instanceof Iterator)
+      {
+         i = (Iterator)value;
+      }
+      else
+      {
+         //throw new JBossXBRuntimeException("Unexpected type for children: " + value.getClass());
+      }
+      return i;
+   }
+
+   private static boolean isRepeatable(XSParticle particle)
+   {
+      return particle.getMaxOccursUnbounded() || particle.getMaxOccurs() > 1 || particle.getMinOccurs() > 1;
+   }
+
+   private static final List asList(final Object arr)
+   {
+      return new AbstractList()
+      {
+         private final Object array = arr;
+
+         public Object get(int index)
+         {
+            return Array.get(array, index);
+         }
+
+         public int size()
+         {
+            return Array.getLength(array);
+         }
+      };
+   }
+}

Modified: trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/xb/XMLBinding.java
===================================================================
--- trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/xb/XMLBinding.java	2008-03-03 16:46:56 UTC (rev 6673)
+++ trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/main/org/jboss/ide/eclipse/archives/core/model/internal/xb/XMLBinding.java	2008-03-03 20:39:41 UTC (rev 6674)
@@ -22,7 +22,6 @@
 package org.jboss.ide.eclipse.archives.core.model.internal.xb;
 
 import java.io.ByteArrayInputStream;
-import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -41,7 +40,9 @@
 import org.jboss.ide.eclipse.archives.core.model.IArchivesLogger;
 import org.jboss.ide.eclipse.archives.core.model.internal.ArchiveImpl;
 import org.jboss.xb.binding.JBossXBException;
+import org.jboss.xb.binding.JBossXBRuntimeException;
 import org.jboss.xb.binding.XercesXsMarshaller;
+import org.jboss.xb.binding.sunday.unmarshalling.DefaultSchemaResolver;
 import org.jboss.xb.binding.sunday.unmarshalling.SchemaBinding;
 import org.jboss.xb.binding.sunday.unmarshalling.XsdBinder;
 import org.xml.sax.SAXException;
@@ -166,7 +167,7 @@
 					stream = schema.openStream();
 					monitor.worked(1);
 					
-					XercesXsMarshaller marshaller = new XercesXsMarshaller();
+					StrictXercesXSMarshaller marshaller = new StrictXercesXSMarshaller();
 					marshaller.marshal(new InputStreamReader(stream), new XbPackagesObjectProvider(), element, writer);
 					monitor.worked(1);
 				} catch (IOException e) {
@@ -175,7 +176,7 @@
 					f = e;
 				} catch (ParserConfigurationException e) {
 					f = e;
-				} catch (Exception e ) {
+				} catch (JBossXBRuntimeException e ) {
 					f = e;
 				} finally {
 					if( stream != null ) {

Modified: trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/xml/packages.xsd
===================================================================
--- trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/xml/packages.xsd	2008-03-03 16:46:56 UTC (rev 6673)
+++ trunk/core/plugins/org.jboss.ide.eclipse.archives.core/src/xml/packages.xsd	2008-03-03 20:39:41 UTC (rev 6674)
@@ -60,7 +60,7 @@
     	</xsd:sequence>
 
     	<xsd:attribute name="name" type="xsd:string" use="required" />
-    	<xsd:attribute name="type" type="xsd:string" use="optional">
+    	<xsd:attribute name="type" type="xsd:string" use="optional" >
     		<xsd:annotation>
     			<xsd:appinfo>
     				<jbxb:property name="packageType" />
@@ -88,7 +88,7 @@
         </xsd:annotation>
         
         <xsd:sequence>
-            <xsd:element maxOccurs="unbounded" minOccurs="1" name="property" type="property-type"/>
+            <xsd:element maxOccurs="unbounded" minOccurs="0" name="property" type="property-type"/>
         </xsd:sequence>
     </xsd:complexType>
     

Added: trunk/core/tests/org.jboss.ide.eclipse.archives.test/expectedOutputs/emptyPackages.xml
===================================================================
--- trunk/core/tests/org.jboss.ide.eclipse.archives.test/expectedOutputs/emptyPackages.xml	                        (rev 0)
+++ trunk/core/tests/org.jboss.ide.eclipse.archives.test/expectedOutputs/emptyPackages.xml	2008-03-03 20:39:41 UTC (rev 6674)
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<packages>
+   <properties></properties>
+</packages>
\ No newline at end of file

Modified: trunk/core/tests/org.jboss.ide.eclipse.archives.test/src/org/jboss/ide/eclipse/archives/test/ArchivesTestSuite.java
===================================================================
--- trunk/core/tests/org.jboss.ide.eclipse.archives.test/src/org/jboss/ide/eclipse/archives/test/ArchivesTestSuite.java	2008-03-03 16:46:56 UTC (rev 6673)
+++ trunk/core/tests/org.jboss.ide.eclipse.archives.test/src/org/jboss/ide/eclipse/archives/test/ArchivesTestSuite.java	2008-03-03 20:39:41 UTC (rev 6674)
@@ -5,6 +5,7 @@
 
 import org.jboss.ide.eclipse.archives.test.core.ArchivesCoreTest;
 import org.jboss.ide.eclipse.archives.test.util.TruezipUtilTest;
+import org.jboss.ide.eclipse.archives.test.xb.MarshallTest;
 import org.jboss.ide.eclipse.archives.test.xb.MarshallUnmarshallTest;
 import org.jboss.ide.eclipse.archives.test.xb.ValidationTest;
 
@@ -12,6 +13,7 @@
     public static Test suite() { 
         TestSuite suite = new TestSuite("Archives Tests");
         suite.addTestSuite(ArchivesCoreTest.class);
+        suite.addTestSuite(MarshallTest.class);
         suite.addTestSuite(MarshallUnmarshallTest.class);
         suite.addTestSuite(ValidationTest.class);
         suite.addTestSuite(TruezipUtilTest.class);

Modified: trunk/core/tests/org.jboss.ide.eclipse.archives.test/src/org/jboss/ide/eclipse/archives/test/util/FileIOUtil.java
===================================================================
--- trunk/core/tests/org.jboss.ide.eclipse.archives.test/src/org/jboss/ide/eclipse/archives/test/util/FileIOUtil.java	2008-03-03 16:46:56 UTC (rev 6673)
+++ trunk/core/tests/org.jboss.ide.eclipse.archives.test/src/org/jboss/ide/eclipse/archives/test/util/FileIOUtil.java	2008-03-03 20:39:41 UTC (rev 6674)
@@ -1,15 +1,34 @@
 package org.jboss.ide.eclipse.archives.test.util;
 
+import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
 
 public class FileIOUtil {
 
 	public static void clearFolder(File[] children) {
-		for( int i = 0; i < children.length; i++ ) {
+		for (int i = 0; i < children.length; i++) {
 			File[] second = children[i].listFiles();
-			if( second != null && second.length > 0 )
+			if (second != null && second.length > 0)
 				clearFolder(second);
 			children[i].delete();
 		}
 	}
+
+	public static String getFileContents(File f) {
+		try {
+			BufferedReader r = new BufferedReader(new FileReader(f));
+			StringBuffer contents = new StringBuffer();
+			int c = r.read();
+			while (c != -1) {
+				contents.append((char)c);
+				c=r.read();
+			}
+			r.close();
+			return contents.toString();
+		} catch (IOException ioe) {
+			return null;
+		}
+	}
 }

Added: trunk/core/tests/org.jboss.ide.eclipse.archives.test/src/org/jboss/ide/eclipse/archives/test/xb/MarshallTest.java
===================================================================
--- trunk/core/tests/org.jboss.ide.eclipse.archives.test/src/org/jboss/ide/eclipse/archives/test/xb/MarshallTest.java	                        (rev 0)
+++ trunk/core/tests/org.jboss.ide.eclipse.archives.test/src/org/jboss/ide/eclipse/archives/test/xb/MarshallTest.java	2008-03-03 20:39:41 UTC (rev 6674)
@@ -0,0 +1,118 @@
+/**
+ * JBoss, a Division of Red Hat
+ * Copyright 2006, Red Hat Middleware, LLC, and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+* This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.ide.eclipse.archives.test.xb;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+
+import junit.framework.TestCase;
+
+import org.eclipse.core.runtime.FileLocator;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.jboss.ide.eclipse.archives.core.model.internal.xb.XMLBinding;
+import org.jboss.ide.eclipse.archives.core.model.internal.xb.XbPackage;
+import org.jboss.ide.eclipse.archives.core.model.internal.xb.XbPackages;
+import org.jboss.ide.eclipse.archives.core.model.internal.xb.XMLBinding.XbException;
+import org.jboss.ide.eclipse.archives.test.ArchivesTest;
+import org.jboss.ide.eclipse.archives.test.util.FileIOUtil;
+import org.osgi.framework.Bundle;
+
+/**
+ * @author rob.stryker <rob.stryker at redhat.com>
+ *
+ */
+public class MarshallTest extends TestCase {
+	private Bundle bundle;
+	private IPath bundlePath;
+	private IPath expectedOutputs;
+	private IPath outputs;
+	protected void setUp() {
+		if( bundlePath == null ) {
+			try {
+				bundle = ArchivesTest.getDefault().getBundle();
+				URL bundleURL = FileLocator.toFileURL(bundle.getEntry(""));
+				bundlePath = new Path(bundleURL.getFile());
+				expectedOutputs = bundlePath.append("expectedOutputs");
+				outputs = bundlePath.append("output");
+			} catch( IOException ioe) {
+				fail("Failed to set up " + getClass().getName());
+			}
+		}
+	}
+
+	public void tearDown() {
+		FileIOUtil.clearFolder(outputs.toFile().listFiles());
+	}
+		
+	public void testStringWriter() {
+		XbPackages packs = new XbPackages();
+		try {
+			File expected = expectedOutputs.append("emptyPackages.xml").toFile();
+			String expectedContents = FileIOUtil.getFileContents(expected);
+			String asString = XMLBinding.serializePackages(packs, new NullProgressMonitor());
+			assertEquals(asString, expectedContents);
+		} catch( XbException xbe ) {
+			fail(xbe.getMessage());
+		}
+	}
+	
+	public void testFileWriter() {
+		XbPackages packs = new XbPackages();
+		IPath out = outputs.append("test.xml");
+		try {
+			File expected = expectedOutputs.append("emptyPackages.xml").toFile();
+			String expectedContents = FileIOUtil.getFileContents(expected);
+
+			XMLBinding.marshallToFile(packs, out, new NullProgressMonitor());
+			String actualContents = FileIOUtil.getFileContents(out.toFile());
+			
+			assertEquals(expectedContents, actualContents);
+		} catch( XbException xbe ) {
+			xbe.printStackTrace();
+			fail(xbe.getMessage());
+		} catch( IOException ioe ) {
+			fail(ioe.getMessage());
+		}
+	}
+	
+	public void testWriteFailingPackage() {
+		XbException e = null;
+		XbPackages packs = new XbPackages();
+		XbPackage pack = new XbPackage();
+		packs.addChild(pack);
+		try {
+			IPath out = outputs.append("test.xml");
+			XMLBinding.marshallToFile(packs, out, new NullProgressMonitor());
+		} catch( IOException ioe ) {
+			fail("IOException during testWritePackage operation");
+		}catch( XbException xbe ) {
+			e = xbe;
+		} finally {
+			if( e == null ) {
+				fail("Incomplete Model saved when it should not have been.");
+			}
+		}
+	}
+}




More information about the jbosstools-commits mailing list