Package org.jboss.xb.binding.sunday.unmarshalling

Source Code of org.jboss.xb.binding.sunday.unmarshalling.SundayContentHandler$StackImpl

/*
* 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.xb.binding.sunday.unmarshalling;

import java.util.LinkedList;
import java.util.List;
import javax.xml.namespace.QName;

import org.jboss.xb.binding.JBossXBRuntimeException;
import org.jboss.xb.binding.NamespaceRegistry;
import org.jboss.xb.binding.Util;
import org.jboss.xb.binding.metadata.CharactersMetaData;
import org.jboss.xb.binding.metadata.ValueMetaData;
import org.jboss.xb.binding.parser.JBossXBParser;
import org.jboss.logging.Logger;
import org.jboss.util.StringPropertyReplacer;
import org.xml.sax.Attributes;
import org.apache.xerces.xs.XSTypeDefinition;

/**
* todo: to improve performance, consider gathering all the necessary binding metadata in startElement and
* pushing it instead of ElementBinding into elementStack to free the endElement implementation from
* re-gathering this same metadata again.
*
* @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
* @version <tt>$Revision: 1455 $</tt>
*/
public class SundayContentHandler
   implements JBossXBParser.ContentHandler
{
   private final static Logger log = Logger.getLogger(SundayContentHandler.class);

   private final static Object NIL = new Object();

   private final SchemaBinding schema;
   private final SchemaBindingResolver schemaResolver;
   private final StackImpl elementStack = new StackImpl();
   private final StackImpl objectStack = new StackImpl();
   private StringBuffer textContent = new StringBuffer();
   private Object root;
   private NamespaceRegistry nsRegistry = new NamespaceRegistry();

   public SundayContentHandler(SchemaBinding schema)
   {
      this.schema = schema;
      this.schemaResolver = null;
   }

   public SundayContentHandler(SchemaBindingResolver schemaResolver)
   {
      this.schemaResolver = schemaResolver;
      this.schema = null;
   }

   public void characters(char[] ch, int start, int length)
   {
      if(elementStack.peek() != null)
      {
         textContent.append(ch, start, length);
      }
   }

   public void endElement(String namespaceURI, String localName, String qName)
   {
      ElementBinding elementBinding = (ElementBinding)elementStack.pop();
      if(elementBinding != null)
      {
         QName endName = localName.length() == 0 ? new QName(qName) : new QName(namespaceURI, localName);
         Object o = objectStack.pop();

         TypeBinding typeBinding = elementBinding.getType();
         List elementHandlers = elementBinding.getInterceptors();

         if(o != NIL)
         {
            //
            // characters
            //

            CharactersHandler simpleType = typeBinding.getSimpleType();
            if(textContent.length() > 0 || simpleType != null)
            {
               String dataContent;
               SchemaBinding schema = elementBinding.getSchema();
               if(textContent.length() == 0)
               {
                  dataContent = null;
               }
               else
               {
                 
                  dataContent = textContent.toString();
                  if(schema != null && schema.isReplacePropertyRefs())
                  {
                     dataContent = StringPropertyReplacer.replaceProperties(dataContent);
                  }
                  textContent.delete(0, textContent.length());
               }

               Object unmarshalled;

               if(simpleType == null)
               {
                  if(schema != null && schema.isStrictSchema())
                  {
                     throw new JBossXBRuntimeException("Element " +
                        endName +
                        " type binding " +
                        typeBinding.getQName() +
                        " does not include text content binding ('" + dataContent
                     );
                  }
                  unmarshalled = dataContent;
               }
               else
               {
                  ValueMetaData valueMetaData = elementBinding.getValueMetaData();
                  if(valueMetaData == null)
                  {
                     CharactersMetaData charactersMetaData = typeBinding.getCharactersMetaData();
                     if(charactersMetaData != null)
                     {
                        valueMetaData = charactersMetaData.getValue();
                     }
                  }

                  // todo valueMetaData is available from typeBinding
                  unmarshalled = dataContent == null ?
                     simpleType.unmarshalEmpty(endName, typeBinding, nsRegistry, valueMetaData) :
                     simpleType.unmarshal(endName, typeBinding, nsRegistry, valueMetaData, dataContent);
               }

               if(unmarshalled != null)
               {
                  // if startElement returned null, we use characters as the object for this element
                  // todo subject to refactoring
                  if(o == null)
                  {
                     o = unmarshalled;
                  }
                  else if(simpleType != null)
                  {
                     simpleType.setValue(endName, elementBinding, o, unmarshalled);
                  }
               }
              
               // todo interceptors get dataContent?
               int i = elementHandlers.size();
               while(i-- > 0)
               {
                  ElementInterceptor interceptor = (ElementInterceptor)elementHandlers.get(i);
                  interceptor.characters(objectStack.peek(elementHandlers.size() - 1 - i),
                     endName, typeBinding, nsRegistry, dataContent
                  );
               }
            }
         }
         else
         {
            o = null;
         }

         //
         // endElement
         //

         Object parent = objectStack.isEmpty() ? null : objectStack.peek();
         o = typeBinding.endElement(parent, o, elementBinding, endName);

         int i = elementHandlers.size();
         while(i-- > 0)
         {
            ElementInterceptor interceptor = (ElementInterceptor)elementHandlers.get(i);
            interceptor.endElement(objectStack.peek(elementHandlers.size() - 1 - i), endName, typeBinding);
         }

         //
         // setParent
         //

         i = elementHandlers.size();
         // todo yack...
         if(i == 0)
         {
            ElementBinding parentElement = elementStack.isEmpty() ? null : (ElementBinding)elementStack.peek();
            if(parent != null)
            {
               typeBinding.getHandler().setParent(parent, o, endName, elementBinding, parentElement);
            }
            else if(parentElement != null)
            {
               // todo: review this> the parent has anyType, so it gets the value of its child
               if(!objectStack.isEmpty())
               {
                  objectStack.pop();
                  objectStack.push(o);
                  if(log.isTraceEnabled())
                  {
                     log.trace("Value of " + endName + " " + o + " is promoted as the value of its parent element.");
                  }
               }
            }
         }
         else
         {
            while(i-- > 0)
            {
               ElementInterceptor interceptor = (ElementInterceptor)elementHandlers.get(i);
               parent = objectStack.pop();
               interceptor.add(parent, o, endName);
               o = parent;
            }
         }

         if(objectStack.isEmpty())
         {
            root = o;
         }
      }
   }

   public void startElement(String namespaceURI,
                            String localName,
                            String qName,
                            Attributes atts,
                            XSTypeDefinition type)
   {
      QName startName = localName.length() == 0 ? new QName(qName) : new QName(namespaceURI, localName);
      ElementBinding binding = null;

      ElementBinding parentBinding = null;
      SchemaBinding schemaBinding = schema;
      if(elementStack.isEmpty())
      {
         if(schemaBinding != null)
         {
            binding = schemaBinding.getElement(startName);
         }
         else if(schemaResolver != null)
         {
            String schemaLocation = atts == null ? null : Util.getSchemaLocation(atts, namespaceURI);
            schemaBinding = schemaResolver.resolve(namespaceURI, localName, null, schemaLocation);
            if(schemaBinding != null)
            {
               binding = schemaBinding.getElement(startName);
            }
         }
         else
         {
            throw new JBossXBRuntimeException("Neither schema binding nor schema binding resolver is not available!");
         }
      }
      else
      {
         parentBinding = (ElementBinding)elementStack.peek();
         if(parentBinding != null)
         {
            binding = parentBinding.getType().getElement(startName, atts);
            schemaBinding = parentBinding.getSchema();
         }
      }

      elementStack.push(binding);

      if(binding != null)
      {
         TypeBinding typeBinding = binding.getType();
         Object o = objectStack.isEmpty() ? null : objectStack.peek();

         List elementHandlers = binding.getInterceptors();
         for(int i = 0; i < elementHandlers.size(); ++i)
         {
            ElementInterceptor interceptor = (ElementInterceptor)elementHandlers.get(i);
            o = interceptor.startElement(o, startName, typeBinding);
            objectStack.push(o);
            interceptor.attributes(o, startName, typeBinding, atts, nsRegistry);
         }

         // todo xsi:nil handling
         String nil = atts.getValue("xsi:nil");
         if(nil == null || !("1".equals(nil) || "true".equals(nil)))
         {
            o = typeBinding.startElement(o, startName, binding);
         }
         else
         {
            o = NIL;
         }
         objectStack.push(o);

         if(o != null && o != NIL)
         {
            // Expand the attributes list with any missing attrs with defaults
            atts = typeBinding.expandWithDefaultAttributes(atts);
            typeBinding.attributes(o, startName, binding, atts, nsRegistry);
         }
      }
      else if(schemaBinding != null && schemaBinding.isStrictSchema())
      {
         throw new JBossXBRuntimeException("Element " +
            startName +
            " is not bound " +
            (parentBinding == null ? "as a global element." : "in type " + parentBinding.getType().getQName())
         );
      }
      else if(log.isTraceEnabled())
      {
         log.trace("Element " +
            startName +
            " is not bound " +
            (parentBinding == null ? "as a global element." : "in type " + parentBinding.getType().getQName())
         );
      }
   }

   public void startPrefixMapping(String prefix, String uri)
   {
      nsRegistry.addPrefixMapping(prefix, uri);
   }

   public void endPrefixMapping(String prefix)
   {
      nsRegistry.removePrefixMapping(prefix);
   }

   public void processingInstruction(String target, String data)
   {
   }

   public Object getRoot()
   {
      return root;
   }

   // Inner

   static class StackImpl
   {
      private LinkedList list = new LinkedList();

      public void clear()
      {
         list.clear();
      }

      public void push(Object o)
      {
         list.addLast(o);
      }

      public Object pop()
      {
         return list.removeLast();
      }

      public Object peek()
      {
         return list.getLast();
      }

      public Object peek(int i)
      {
         return list.get(list.size() - 1 - i);
      }

      public boolean isEmpty()
      {
         return list.isEmpty();
      }

      public int size()
      {
         return list.size();
      }
   }
}
TOP

Related Classes of org.jboss.xb.binding.sunday.unmarshalling.SundayContentHandler$StackImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.