Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
     * 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.impl.runtime;
  
  import java.util.Map;

Author(s):
Alexey Loubyansky
Version:
$Revision: 2478 $
  
  public class RtElementHandler
     implements ParticleHandler
  {
     private static final Logger log = Logger.getLogger(RtElementHandler.class);
  
     public static final RtElementHandler INSTANCE = new RtElementHandler();
     
     // ParticleHandler impl
  
   
TODO: it seems like for correct type resolution in startParticle I should take into account the way the object is going to be added to the parent in setParent (and, hence, do some steps that are done in setParticle). In setParent then I should reuse the results of what has been done in startParticle.
  
     public Object startParticle(Object parent,
                                 QName elementName,
                                 ParticleBinding particle,
                                 Attributes attrs,
                                 NamespaceContext nsCtx)
     {
        TermBinding term = particle.getTerm();
        Object o = startElement(parentelementNameparticle);
        if(!term.isModelGroup())
        {
           ElementBinding element = (ElementBinding)term;
           if(o != null)
           {
              attrs = element.getType().expandWithDefaultAttributes(attrs);
              attributes(oelementNameelementattrsnsCtx);
           }
        }
        return o;
    }
 
    public void setParent(Object parent,
                          Object o,
                          QName qName,
                          ParticleBinding particle,
                          ParticleBinding parentParticle)
    {
       TermBinding term = particle.getTerm();
       if(term.isSkip())
       {
          return;
       }
 
       boolean trace = .isTraceEnabled();
       if(trace)
       {
          .trace("setParent " + qName + " parent=" + parent + " object=" + o + " term=" + term);
       }
 
       TermBinding parentTerm = parentParticle.getTerm();
 
       if(term.isMapEntryKey())
       {
          if(trace)
          {
             .trace("setParent " + qName + " mapKey");
          }
 
          if(parent instanceof MapEntry)
          {
             MapEntry mapEntry = (MapEntry)parent;
             mapEntry.setKey(o);
          }
          else if(parentTerm != null)
          {
             MapEntryMetaData mapEntryMetaData = getMapEntryMetaData(parentTermqName);
 
             String getKeyMethodName = mapEntryMetaData.getGetKeyMethod();
             if(getKeyMethodName == null)
             {
                getKeyMethodName = "getKey";
             }
 
             String setKeyMethodName = mapEntryMetaData.getSetKeyMethod();
             if(setKeyMethodName == null)
             {
                setKeyMethodName = "setKey";
             }
 
             Class parentCls = parent.getClass();
             Method setKeyMethod = getSetMethod(parentClsgetKeyMethodNamesetKeyMethodName);
             invokeSetter(setKeyMethodparentosetKeyMethodName);
          }
          else
          {
             throw new JBossXBRuntimeException(
                "Element " +
                qName +
                " bound as map entry key but parent element is not recognized as map entry and its metadata is not available."
             );
          }
       }
       else if(term.isMapEntryValue())
       {
          if(trace)
          {
             .trace("setParent " + qName + " mapValue");
          }
 
          if(parent instanceof MapEntry)
          {
             MapEntry mapEntry = (MapEntry)parent;
             mapEntry.setValue(o);
          }
          else if(parentTerm != null)
          {
             MapEntryMetaData mapEntryMetaData = getMapEntryMetaData(parentTermqName);
             setMapEntryValue(mapEntryMetaDataparento);
          }
          else
          {
             throw new JBossXBRuntimeException(
                "Element " +
                qName +
                " bound as map entry key but parent element is not recognized as map entry and its metadata is not available."
             );
          }
       }
       else
       {
          Object owner = parent;
          if(parent instanceof MapEntry)
          {
             if(trace)
             {
                .trace("setParent " + qName + " mapEntry");
             }
 
             MapEntry mapEntry = (MapEntry)parent;
             owner = mapEntry.getValue();
             if(owner == null)
             {
                if(parentTerm == null)
                {
                   throw new JBossXBRuntimeException("Binding metadata needed for lazy map entry value instantiation is not available " +
                      "for parent element of element " +
                      qName
                   );
                }
 
                MapEntryMetaData mapEntryMetaData = getMapEntryMetaData(parentTermqName);
                String valueType = mapEntryMetaData.getValueType();
                if(valueType == null)
                {
                   throw new JBossXBRuntimeException("Element " +
                      qName +
                      " is supposed to be bound as map entry value with lazy value instantiation " +
                      "but value type is not specified in its map entry metadata."
                   );
                }
 
                Class valueCls;
                try
                {
                   valueCls = Thread.currentThread().getContextClassLoader().loadClass(valueType);
                }
                catch(ClassNotFoundException e)
                {
                   throw new JBossXBRuntimeException(
                      "Failed to load value type specified in the map entry metadata: " + valueType
                   );
                }
 
                try
                {
                   owner = valueCls.newInstance();
                }
                catch(Exception e)
                {
                   throw new JBossXBRuntimeException(
                      "Failed to create an instance of value type " + valueType + ": " + e.getMessage()
                   );
                }
 
                setMapEntryValue(mapEntryMetaDataparentowner);
             }
          }
 
          // the wildcard this element is a content of
          WildcardBinding wildcard = null;
          if(parentTerm != null && !parentTerm.isModelGroup())
          {
             ElementBinding parentElement = (ElementBinding)parentTerm;
             TypeBinding parentType = parentElement.getType();
             wildcard = parentType.getWildcard();
             // there should be a better way of checking this
             if(wildcard != null && parentType.getElement(qName) != null)
             {
                wildcard = null;
             }
          }
 
          if(tryPut(owneroqNametermtrace))
          {
          }
          else if(tryAdd(owneroqNametermwildcardtrace))
          {
          }
          else if (owner instanceof GenericValueContainer)
          {
             if (trace)
             {
                .trace("setParent " + qName + " addChild");
             }
             ((GenericValueContainerowner).addChild(qNameo);
          }
          else if (owner instanceof Collection)
          {
             if (trace)
             {
                .trace("setParent " + qName + " collection.add()");
             }
             ((Collectionowner).add(o);
          }
          else
          {
             PropertyMetaData propertyMetaData = wildcard == null ? null : wildcard.getPropertyMetaData();
             if (propertyMetaData == null)
             {
                propertyMetaData = term.getPropertyMetaData();
             }
 
             String propName = null;
             String colType = null;
             if (propertyMetaData != null)
             {
                propName = propertyMetaData.getName();
                colType = propertyMetaData.getCollectionType();
             }
 
             if (propName == null)
             {
                propName = Util.xmlNameToFieldName(qName.getLocalPart(), term.getSchema().isIgnoreLowLine());
             }
 
             if (trace)
             {
                .trace("setParent " + qName + " metadata set " + propName);
             }
 
             /*if(particle.isRepeatable())
             {
                RtUtil.add(owner, o, propName, colType,
                   term.getSchema().isIgnoreUnresolvedFieldOrClass(),
                   term.getValueAdapter()
                );
             }
             else
             {*/
                RtUtil.set(owneropropNamecolType,
                      term.getSchema().isIgnoreUnresolvedFieldOrClass(),
                      term.getValueAdapter());
             //}
          }
       }
    }
 
    public Object endParticle(Object oQName elementNameParticleBinding particle)
    {
       TermBinding term = particle.getTerm();
       if(term.isSkip())
       {
          return o;
       }
 
       boolean trace = .isTraceEnabled();
       if(trace)
       {
          .trace("endParticle " + elementName + " object=" + o + " term=" + term);
       }
 
       if(o instanceof GenericValueContainer)
       {
          try
          {
             if(trace)
             {
                .trace("endParticle " + elementName + " instantiate()");
             }
             o = ((GenericValueContainer)o).instantiate();
          }
          catch(JBossXBRuntimeException e)
          {
             throw e;
          }
          catch(RuntimeException e)
          {
             throw new JBossXBRuntimeException("Container failed to create an instance for " +
                elementName +
                ": " + e.getMessage(), e
             );
          }
       }
 
       return o;
    }
 
    // Private
 
    private Object startElement(Object parentQName elementNameParticleBinding particle)
    {
       TermBinding term = particle.getTerm();
       if(term.isSkip())
       {
          return parent;
       }
 
       boolean trace = .isTraceEnabled();
       if(trace)
       {
          .trace("startElement " + elementName + " parent=" + parent + " term=" + term);
       }
 
       ClassMetaData classMetaData = term.getClassMetaData();
       MapEntryMetaData mapEntryMetaData = term.getMapEntryMetaData();
 
       if(!term.isModelGroup())
       {
          TypeBinding type = ((ElementBinding)term).getType();
          if(type.isSimple() ||
                classMetaData == null && mapEntryMetaData == null &&
                (!type.isStartElementCreatesObject() ||
                      ..equals(type.getQName())))
          {
             if(trace)
             {
                .trace("startElement " + elementName + " does not create an object");
             }
             return null;
          }
       }
 
       // if addMethod is specified, it's probably some collection field
       // but should not be set as a property. Instead, items are added to it using the addMethod
       ElementBinding arrayItem = null;
       if(!term.isModelGroup())
       {
          TypeBinding type = ((ElementBinding)term).getType();
          if(type.getAttributes().isEmpty())
          {
             ParticleBinding typeParticle = type.getParticle();
             ModelGroupBinding modelGroup = (ModelGroupBinding)(typeParticle == null ? null : typeParticle.getTerm());
             arrayItem = modelGroup == null ? null : modelGroup.getArrayItem();
 
             // todo refactor later (move it to modelGroup.getArrayItem()?)
             if(arrayItem != null &&
                (arrayItem.isSkip() ||
                arrayItem.getMapEntryMetaData() != null ||
                arrayItem.getPutMethodMetaData() != null ||
                arrayItem.getAddMethodMetaData() != null
                ))
             {
                arrayItem = null;
             }
          }
       }
 
       if(arrayItem != null)
       {
          Class wrapperType = null;
          if(classMetaData != null)
          {
             wrapperType = loadClassForTerm(classMetaData.getImpl(),
                term.getSchema().isIgnoreUnresolvedFieldOrClass(),
                elementName
             );
 
             if(GenericValueContainer.class.isAssignableFrom(wrapperType) ||
                Collection.class.isAssignableFrom(wrapperType) ||
                Map.class.isAssignableFrom(wrapperType))
             {
                return newInstance(wrapperTypeelementNameterm.getSchema().isUseNoArgCtorIfFound());
             }
          }
 
          if(wrapperType == null && parent == null)
          {
             Class itemType = classForElement(arrayItemnull);
             if(itemType != null)
             {
                if(trace)
                {
                   .trace("startElement " + elementName + " new array " + itemType.getName());
                }
                return GenericValueContainer.FACTORY.array(itemType);
             }
          }
          else
          {
             PropertyMetaData propertyMetaData = wrapperType == null ?
                term.getPropertyMetaData() : arrayItem.getPropertyMetaData();
 
             String propName;
             if(propertyMetaData == null)
             {
                propName = Util.xmlNameToFieldName(
                   wrapperType == null ? elementName.getLocalPart() : arrayItem.getQName().getLocalPart(),
                   term.getSchema().isIgnoreLowLine()
                );
             }
             else
             {
                propName = propertyMetaData.getName();
             }
 
             if(trace)
             {
                .trace("startElement " + elementName + " property=" + propName + " wrapper=" + wrapperType);
             }
 
             Class parentClass = wrapperType;
             if(wrapperType == null)
             {
                if(parent instanceof GenericValueContainer)
                {
                   parentClass = ((GenericValueContainer)parent).getTargetClass();
                }
                else if(parent instanceof ValueList)
                {
                   parentClass = ((ValueList)parent).getTargetClass();
                }
                else
                {
                   parentClass = parent.getClass();
                }
             }
 
             Class fieldType = null;
             if(parentClass.isArray())
             {
                fieldType = parentClass.getComponentType();
             }
             else
             {
                //fieldType = FieldInfo.getFieldInfo(parentClass, propName, true).getType();
                // this was changed to false because allow overriding of handler.setParent()
                // with an interceptor.add(). See CollectionOverridePropertyUnitTestCase
                // In other words, don't treat it as an array wrapper.
                FieldInfo fieldInfo = FieldInfo.getFieldInfo(parentClasspropNamefalse);
                if(fieldInfo != null)
                {
                   fieldType = fieldInfo.getType();
                   if (particle.isRepeatable() && fieldType.isArray())
                   {
                      fieldType = fieldType.getComponentType();
                   }
                }
                else if(((ElementBinding)term).getType().getInterceptors(arrayItem.getQName()).isEmpty() &&
                      arrayItem.getInterceptors().isEmpty())
                {
                   QName typeName = ((ElementBinding)term).getType().getQName();
                   throw new JBossXBRuntimeException(
                         "Couldn't apply 'array wrapper' pattern for element " +
                         elementName + " of type " +
                         (typeName == null ? "anonymous" : typeName.toString()) +
                         ": failed to resolve property " + propName +
                         " and no interceptors applied to override handler.setParent(...)");
                }
             }
 
             if(fieldType != null)
             {
                // TODO: review the logic for cases when wrapperType == null
                if (fieldType.isArray())
                {
                   return GenericValueContainer.FACTORY.array(wrapperTypepropNamefieldType.getComponentType());
                }
                else if (Collection.class.isAssignableFrom(fieldType))
                {
                   if (wrapperType == null)
                   {
                      return new ValueListInitializer().newValueList(ValueListHandler.FACTORY.child(), Collection.class);
                      //o = new ArrayList();
                   }
                }
                else
                {
                   return GenericValueContainer.FACTORY.array(wrapperTypepropNamefieldType);
                }
             }
          }
       }
 
       Object o = null;
       if (mapEntryMetaData != null)
       {
          if (mapEntryMetaData.getImpl() != null)
          {
             Class cls = loadClassForTerm(mapEntryMetaData.getImpl(), term.getSchema().isIgnoreUnresolvedFieldOrClass(), elementName);
 
             if (trace)
             {
                .trace("startElement " + elementName + " new map entry " + cls.getName());
             }
 
             o = newInstance(clselementNameterm.getSchema().isUseNoArgCtorIfFound());
          }
          else
          {
             o = new MapEntry();
             if (trace)
             {
                .trace("startElement " + elementName + " new map entry");
             }
          }
 
          if (mapEntryMetaData.isNonNullValue() && mapEntryMetaData.getValueType() != null)
          {
             Class mapValueType;
             try
             {
                mapValueType = Thread.currentThread().getContextClassLoader().loadClass(mapEntryMetaData.getValueType());
             }
             catch (ClassNotFoundException e)
             {
                throw new JBossXBRuntimeException("startElement failed for " + elementName + ": failed to load class "
                      + mapEntryMetaData.getValueType() + " for map entry value.");
             }
 
             Object value;
             try
             {
                if (trace)
                {
                   .trace("startElement " + elementName + " map value type " + mapEntryMetaData.getValueType());
                }
                value = mapValueType.newInstance();
             }
             catch (Exception e)
             {
                throw new JBossXBRuntimeException("startElement failed for " + elementName
                      + ": failed to create an instance of " + mapValueType + " for map entry value.");
             }
 
             if (o instanceof MapEntry)
             {
                ((MapEntryo).setValue(value);
             }
             else
             {
                String getValueMethodName = mapEntryMetaData.getGetValueMethod();
                if (getValueMethodName == null)
                {
                   getValueMethodName = "getValue";
                }
 
                String setValueMethodName = mapEntryMetaData.getSetValueMethod();
                if (setValueMethodName == null)
                {
                   setValueMethodName = "setValue";
                }
 
                Method getValueMethod;
                try
                {
                   getValueMethod = o.getClass().getMethod(getValueMethodNamenull);
                }
                catch (NoSuchMethodException e)
                {
                   throw new JBossXBRuntimeException("getValueMethod=" + getValueMethodName
                         + " is not found in map entry " + o.getClass());
                }
 
                Method setValueMethod;
                try
                {
                   setValueMethod = o.getClass().getMethod(setValueMethodNamenew Class[]{getValueMethod.getReturnType()});
                }
                catch (NoSuchMethodException e)
                {
                   throw new JBossXBRuntimeException("setValueMethod=" + setValueMethodName + "("
                         + getValueMethod.getReturnType().getName() + " value) is not found in map entry "
                         + o.getClass());
                }
 
                try
                {
                   setValueMethod.invoke(onew Object[]
                   {value});
                }
                catch (Exception e)
                {
                   throw new JBossXBRuntimeException("setValueMethod=" + setValueMethodName + " failed: owner=" + o
                         + ", value=" + value + ", msg=" + e.getMessage(), e);
                }
             }
          }
       }
       else
       {
          // todo: for now we require metadata for model groups to be bound
          // todo 2: parent.getClass() is not going to work for containers
          Class parentClass = null;
          if (parent != null)
          {
             if (parent instanceof GenericValueContainer)
             {
                parentClass = ((GenericValueContainerparent).getTargetClass();
             }
             else if (parent instanceof ValueList)
             {
                parentClass = ((ValueListparent).getTargetClass();
             }
             else
             {
                parentClass = parent.getClass();
             }
          }
 
          Class cls;
          if (term.isModelGroup())
          {
             if (classMetaData == null)
             {
                throw new JBossXBRuntimeException(
                      "Model groups should be annotated with 'class' annotation to be bound.");
             }
             cls = loadClassForTerm(classMetaData.getImpl(), term.getSchema().isIgnoreUnresolvedFieldOrClass(), elementName);
          }
          else
          {
             ElementBinding element = (ElementBindingterm;
             cls = classForNonArrayItem(elementparentClass);
             if (cls != null)
             {
                // todo: before that, the type should be checked for required attributes and elements
                TypeBinding simpleType = element.getType().getSimpleType();
                if (simpleType != null)
                {
                   Class simpleCls = classForSimpleType(simpleTypeelement.isNillable());
                   if (cls.equals(simpleCls) || cls.isPrimitive() && Classes.getPrimitiveWrapper(cls) == simpleCls
                         || simpleCls.isPrimitive() && Classes.getPrimitiveWrapper(simpleCls) == cls)
                   {
                      cls = null;
                   }
                }
             }
          }
 
          if (cls != null)
          {
             boolean noArgCtor;
             if (classMetaData == null)
             {
                noArgCtor = term.getSchema().isUseNoArgCtorIfFound();
             }
             else
             {
                Boolean termUsesNoArgCtor = classMetaData.isUseNoArgCtor();
                noArgCtor = termUsesNoArgCtor == null ?
                      term.getSchema().isUseNoArgCtorIfFound() : termUsesNoArgCtor.booleanValue();
             }
 
             if (trace)
             {
                .trace("startElement " + elementName + " new " + cls.getName() + ", noArgCtor=" + noArgCtor);
             }
             o = newInstance(clselementNamenoArgCtor);
          }
       }
 
       return o;
    }
 
    private void attributes(Object o,
                            QName elementName,
                            ElementBinding element,
                            Attributes attrs,
                            NamespaceContext nsCtx)
    {
       TypeBinding type = element.getType();
       for(int i = 0; i < attrs.getLength(); ++i)
       {
          QName attrName = new QName(attrs.getURI(i), attrs.getLocalName(i));
          AttributeBinding binding = type.getAttribute(attrName);
          if(binding != null)
          {
             AttributeHandler handler = binding.getHandler();
             if(handler != null)
             {
                Object value = handler.unmarshal(elementNameattrNamebindingnsCtxattrs.getValue(i));
                handler.attribute(elementNameattrNamebindingovalue);
             }
             else
             {
                throw new JBossXBRuntimeException(
                   "Attribute binding present but has no handler: element=" + elementName + ", attrinute=" + attrName
                );
             }
          }
          else
          {
             if(!..equals(attrs.getURI(i)))
             {
                CharactersHandler simpleType = type.getCharactersHandler();
                Object value;
                if(simpleType == null)
                {
                   value = attrs.getValue(i);
                   RtUtil.set(oattrNamevalueelement.getSchema().isIgnoreLowLine());
                }
             }
          }
       }
    }
 
    private boolean tryAdd(Object owner,
                           Object o,
                           QName qName,
                           TermBinding term,
                           WildcardBinding wildcard,
                           boolean trace)
    {
       AddMethodMetaData addMetaData = wildcard == null ? null : wildcard.getAddMethodMetaData();
       if(addMetaData == null)
       {
          addMetaData = term.getAddMethodMetaData();
       }
 
       if(addMetaData == null)
       {
          return false;
       }
 
       if(trace)
       {
          .trace("setParent " + qName + " add");
       }
       invokeAdd(qNameaddMetaDataownero);
       return true;
    }
 
    private boolean tryPut(Object ownerObject oQName qNameTermBinding termboolean trace)
    {
       if(term.getPutMethodMetaData() != null ||
          term.getMapEntryMetaData() != null && owner instanceof Map)
       {
          if(trace)
          {
             .trace("setParent " + qName + " mapPut");
          }
          invokePut(qNametermownero);
          return true;
       }
       return false;
    }
 
    private Class classForElement(ElementBinding elementClass parentClass)
    {
       Class cls;
       TypeBinding type = element.getType();
       QName typeQName = type.getQName();
       if(typeQName != null && ..equals(typeQName.getNamespaceURI()))
       {
          cls = SimpleTypeBindings.classForType(type.getQName().getLocalPart(), element.isNillable());
       }
       else
       {
          ElementBinding arrayItem = null;
          if(!type.isSimple() && type.getAttributes().isEmpty())
          {
             ParticleBinding typeParticle = type.getParticle();
             ModelGroupBinding modelGroup = (ModelGroupBinding)(typeParticle == null ? null : typeParticle.getTerm());
             arrayItem = modelGroup == null ? null : modelGroup.getArrayItem();
          }
 
          if(arrayItem != null)
          {
             cls = classForElement(arrayItemparentClass);
             // todo: what's the best way to get an array class having the item class
             cls = Array.newInstance(cls, 0).getClass();
          }
          else
          {
             cls = classForNonArrayItem(elementparentClass);
          }
       }
       return cls;
    }
 
    private static void setMapEntryValue(MapEntryMetaData mapEntryMetaDataObject parentObject o)
    {
       String getValueMethodName = mapEntryMetaData.getGetValueMethod();
       if(getValueMethodName == null)
       {
          getValueMethodName = "getValue";
       }
 
       String setValueMethodName = mapEntryMetaData.getSetValueMethod();
       if(setValueMethodName == null)
       {
          setValueMethodName = "setValue";
       }
 
       Class parentCls = parent.getClass();
       Method setValueMethod = getSetMethod(parentClsgetValueMethodNamesetValueMethodName);
       invokeSetter(setValueMethodparentosetValueMethodName);
    }
 
    private static void invokeSetter(Method setValueMethodObject parentObject oString setValueMethodName)
    {
       try
       {
          setValueMethod.invoke(parentnew Object[]{o});
       }
       catch(Exception e)
       {
          throw new JBossXBRuntimeException("Failed to invoke " +
             setValueMethodName +
             " on " +
             parent +
             " with parameter " +
             o +
             ": " +
             e.getMessage()
          );
       }
    }
 
    private static Method getSetMethod(Class clsString getMethodNameString setMethodName)
    {
       Method getKeyMethod;
       try
       {
          getKeyMethod = cls.getMethod(getMethodNamenull);
       }
       catch(NoSuchMethodException e)
       {
          throw new JBossXBRuntimeException("Method " + getMethodName + " not found in " + cls);
       }
 
       Method setKeyMethod;
       try
       {
          setKeyMethod = cls.getMethod(setMethodNamenew Class[]{getKeyMethod.getReturnType()});
       }
       catch(NoSuchMethodException e)
       {
          throw new JBossXBRuntimeException("Method " +
             setMethodName +
             "(" +
             getKeyMethod.getReturnType().getName() +
             " p) not found in " +
             cls
          );
       }
       return setKeyMethod;
    }
 
    private static MapEntryMetaData getMapEntryMetaData(TermBinding termQName qName)
    {
       MapEntryMetaData mapEntryMetaData = term.getMapEntryMetaData();
       if(mapEntryMetaData == null)
       {
          String msg;
          if(term.isModelGroup())
          {
             msg = "Term " +
                qName +
                " bound as map entry key or value but map entry metadata is not available for its parent term.";
          }
          else
          {
             ElementBinding element = (ElementBinding)term;
             msg = "Element " +
                qName +
                " bound as map entry key or value but map entry metadata is not available for its parent element nor its " +
                (element.getType().getQName() == null ?
                "annonymous" :
                element.getType().getQName().toString()
                ) +
                " type.";
          }
          throw new JBossXBRuntimeException(msg);
       }
       return mapEntryMetaData;
    }
 
    private static Object newInstance(Class clsQName elementNameboolean useNoArgCtorIfFound)
    {
       Object o;
       if(cls.isArray())
       {
          o = GenericValueContainer.FACTORY.array(cls.getComponentType());
       }
       else
       {
          Constructor[] ctors = cls.getConstructors();
          if(ctors.length == 0)
          {
             throw new JBossXBRuntimeException(
                "Class " + cls.getName() + " has no public constructors or the class reflects a primitive type or void"
             );
          }
 
          if(useNoArgCtorIfFound)
          {
             try
             {
                Constructor ctor = cls.getConstructor(null);
                o = ctor.newInstance(null);
             }
             catch(NoSuchMethodException e)
             {
                o = new ValueListInitializer().newValueList(.cls);
             }
             catch(Exception e)
             {
                throw new JBossXBRuntimeException("Failed to create an instance of " +
                   cls +
                   " using default constructor for element " +
                   elementName + ": " + e.getMessage(), e
                );
             }
          }
          else if(ctors.length > 1 || ctors[0].getParameterTypes().length > 0)
          {
             o = new ValueListInitializer().newValueList(.cls);
          }
          else
          {
             try
             {
                o = ctors[0].newInstance(null);
             }
             catch(Exception e)
             {
                throw new JBossXBRuntimeException("Failed to create an instance of " +
                   cls +
                  " using default constructor for element " +
                  elementName + ": " + e.getMessage(), e
               );
            }
         }
      }
      return o;
   }
   private static Class loadClassForTerm(String className,
                                         boolean ignoreCNFE,
                                         QName elementName)
   {
      if(className == null)
      {
         throw new JBossXBRuntimeException("No class for " + elementName);
      }
      Class cls = null;
      try
      {
         cls = Thread.currentThread().getContextClassLoader().loadClass(className);
      }
      catch(ClassNotFoundException e)
      {
         if(ignoreCNFE)
         {
            if(.isTraceEnabled())
            {
               .trace("Failed to resolve class for element " +
                  elementName +
                  ": " +
                  className
               );
            }
         }
         else
         {
            throw new JBossXBRuntimeException("Failed to resolve class name for " +
               elementName +
               ": " +
               e.getMessage()
            );
         }
      }
      return cls;
   }
   private void invokeAdd(QName qNameAddMethodMetaData addMethodMetaDataObject ownerObject o)
   {
      Class valueType = Object.class;
      if(addMethodMetaData.getValueType() != null)
      {
         try
         {
            valueType = Thread.currentThread().getContextClassLoader().
               loadClass(addMethodMetaData.getValueType());
         }
         catch(ClassNotFoundException e)
         {
            throw new JBossXBRuntimeException("Failed to load value type for addMethod.name=" +
               addMethodMetaData.getMethodName() +
               ", valueType=" +
               addMethodMetaData.getValueType() +
               ": " + e.getMessage(), e
            );
         }
      }
      else if(addMethodMetaData.isChildType())
      {
         if(o == null)
         {
            throw new JBossXBRuntimeException("addMethod=" +
               addMethodMetaData.getMethodName() +
               " for element " +
               qName +
               " is configured with valueType='child'. The valueType cannot be determined because" +
               " the child is null"
            );
         }
         valueType = o.getClass();
      }
      Class ownerClass = owner.getClass();
      Method addMethod;
      try
      {
         addMethod = ownerClass.getMethod(addMethodMetaData.getMethodName(), new Class[]{valueType});
      }
      catch(NoSuchMethodException e)
      {
         throw new JBossXBRuntimeException("Failed to find addMethod.name=" +
            addMethodMetaData.getMethodName() +
            ", addMethod.valueType=" +
            valueType.getName() +
            " in class " +
            ownerClass.getName() +
            ": " +
            e.getMessage(), e
         );
      }
      try
      {
         addMethod.invoke(ownernew Object[]{o});
      }
      catch(Exception e)
      {
         throw new JBossXBRuntimeException("setParent failed for " +
            qName +
            "=" +
            o +
            ": addMethod=" +
            addMethodMetaData.getMethodName() +
            " threw an exception for owner=" +
            owner +
            ", value=" +
            o +
            ": " +
            e.getMessage(),
            e
         );
      }
   }
   private void invokePut(QName qNameTermBinding termObject ownerObject o)
   {
      PutMethodMetaData putMethodMetaData = term.getPutMethodMetaData();
      MapEntryMetaData mapEntryMetaData =