Method setKeyMethod = getSetMethod(parentCls, getKeyMethodName, setKeyMethodName);
invokeSetter(setKeyMethod, parent, o, setKeyMethodName);
}
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(element.isMapEntryValue())
{
if(parent instanceof MapEntry)
{
MapEntry mapEntry = (MapEntry)parent;
mapEntry.setValue(o);
}
else if(parentElement != null)
{
MapEntryMetaData mapEntryMetaData = getMapEntryMetaData(parentElement, qName);
setMapEntryValue(mapEntryMetaData, parent, o);
}
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)
{
MapEntry mapEntry = (MapEntry)parent;
owner = mapEntry.getValue();
if(owner == null)
{
if(parentElement == 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(parentElement, qName);
String valueType = mapEntryMetaData.getValueType();
if(valueType == null)
{
throw new JBossXBRuntimeException("Element " +
qName +
" of type " +
element.getType() +
" 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(mapEntryMetaData, parent, owner);
}
}
if(owner instanceof GenericValueContainer)
{
((GenericValueContainer)owner).addChild(qName, o);
}
else if(owner instanceof Collection)
{
((Collection)owner).add(o);
}
else
{
PutMethodMetaData putMethodMetaData = element.getPutMethodMetaData();
if(owner instanceof Map || putMethodMetaData != null)
{
MapEntryMetaData mapEntryMetaData = element.getMapEntryMetaData();
if(mapEntryMetaData == null)
{
throw new JBossXBRuntimeException((owner instanceof Map ?
"Parent object is an instance of java.util.Map" :
"putMethod is specified for element " + qName
) +
" but mapEntry is specified for neither element " +
qName +
" nor it's type " +
element.getType().getQName()
);
}
Class oClass = o.getClass();
String getKeyMethodName = mapEntryMetaData.getGetKeyMethod();
if(getKeyMethodName == null)
{
getKeyMethodName = "getKey";
}
Method keyMethod;
try
{
keyMethod = oClass.getMethod(getKeyMethodName, null);
}
catch(NoSuchMethodException e)
{
throw new JBossXBRuntimeException("setParent failed for " +
qName +
"=" +
o +
": getKeyMethod=" +
getKeyMethodName +
" not found in " + oClass
);
}
Object key;
try
{
key = keyMethod.invoke(o, null);
}
catch(Exception e)
{
throw new JBossXBRuntimeException("setParent failed for " +
qName +
"=" +
o +
": getKeyMethod=" +
getKeyMethodName +
" threw an exception: " + e.getMessage(), e
);
}
Class keyType = Object.class;
Class valueType = Object.class;
String putMethodName = "put";
Class ownerClass = owner.getClass();
if(putMethodMetaData != null)
{
if(putMethodMetaData.getKeyType() != null)
{
try
{
keyType =
Thread.currentThread().getContextClassLoader().loadClass(putMethodMetaData.getKeyType());
}
catch(ClassNotFoundException e)
{
throw new JBossXBRuntimeException("setParent failed for " + qName + ": " + e.getMessage(), e);
}
}
if(putMethodMetaData.getValueType() != null)
{
try
{
valueType =
Thread.currentThread().getContextClassLoader().loadClass(putMethodMetaData.getValueType());
}
catch(ClassNotFoundException e)
{
throw new JBossXBRuntimeException("setParent failed for " + qName + ": " + e.getMessage(), e);
}
}
String name = putMethodMetaData.getName();
if(name != null)
{
putMethodName = name;
}
}
Method putMethod;
try
{
putMethod = ownerClass.getMethod(putMethodName, new Class[]{keyType, valueType});
}
catch(NoSuchMethodException e)
{
throw new JBossXBRuntimeException("setParent failed for " +
qName +
"=" +
o +
": putMethod=" +
putMethodName +
"(" + keyType.getName() + " key, " + valueType.getName() + " value) not found in " + ownerClass
);
}
Object value = o;
String valueMethodName = mapEntryMetaData.getGetValueMethod();
if(valueMethodName != null)
{
Method valueMethod;
try
{
valueMethod = oClass.getMethod(valueMethodName, null);
}
catch(NoSuchMethodException e)
{
throw new JBossXBRuntimeException("setParent failed for " +
qName +
"=" +
o +
": getValueMethod=" +
mapEntryMetaData.getGetValueMethod() +
" not found in " + oClass
);
}
try
{
value = valueMethod.invoke(o, null);
}
catch(Exception e)
{
throw new JBossXBRuntimeException("setParent failed for " +
qName +
"=" +
o +
": getValueMethod=" +
mapEntryMetaData.getGetValueMethod() +
" threw an exception: " + e.getMessage(), e
);
}
}
else if(o instanceof MapEntry)
{
value = ((MapEntry)o).getValue();
}
try
{
putMethod.invoke(owner, new Object[]{key, value});
}
catch(Exception e)
{
throw new JBossXBRuntimeException("setParent failed for " +
qName +
"=" +
o +
": putMethod=" +
putMethodName +
" threw an exception for owner=" +
owner +
", key=" +
key +
", value=" +
value +
": " +
e.getMessage(),
e
);
}
}
else
{
AddMethodMetaData addMethodMetaData = element.getAddMethodMetaData();
PropertyMetaData propertyMetaData = null;
if(addMethodMetaData == null)
{
if(parentElement != null && parentElement.getType().isWildcardElement(qName))
{
propertyMetaData = parentElement.getType().getWildcardPropertyMetaData();
}
if(propertyMetaData == null)
{
propertyMetaData = element.getPropertyMetaData();
}
/*
if(propertyMetaData == null)
{
propertyMetaData = element.getType().getPropertyMetaData();
}
*/
}
if(addMethodMetaData != null)
{
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(owner, new Object[]{o});
}
catch(Exception e)
{
throw new JBossXBRuntimeException("setParent failed for " +
qName +
"=" +
o +
": addMethod=" +
addMethodMetaData.getMethodName() +