package de.vksi.c4j.internal.configuration;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.List;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;
public class JaxbUnmarshaller {
public <T> T unmarshal(InputStream xmlStream, Class<T> xmlClass) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(xmlClass);
Unmarshaller unmarshaller = context.createUnmarshaller();
@SuppressWarnings("unchecked")
T unmarshal = (T) unmarshaller.unmarshal(xmlStream);
setDefaultValues(unmarshal);
return unmarshal;
}
public <T> void setDefaultValues(T xmlObject) throws JAXBException {
try {
for (Field field : xmlObject.getClass().getDeclaredFields())
setDefaultValueForField(xmlObject, field);
} catch (Exception e) {
throw new JAXBException("Error handling default values", e);
}
}
private <T> void setDefaultValueForField(T xmlObject, Field field) throws JAXBException, IllegalAccessException,
InstantiationException {
if (field.getAnnotation(XmlElement.class) == null)
return;
field.setAccessible(true);
Object fieldValue = field.get(xmlObject);
if (field.getType().equals(List.class)) {
setDefaultValueForList(fieldValue);
return;
}
if (fieldValue == null)
handleFieldDefaultValue(xmlObject, field);
}
private <T> void handleFieldDefaultValue(T xmlObject, Field field) throws IllegalAccessException,
InstantiationException {
if (handleFieldDefaultValueAsXmlType(xmlObject, field))
return;
String defaultValue = field.getAnnotation(XmlElement.class).defaultValue();
if ("\u0000".equals(defaultValue))
return;
if (handleFieldDefaultValueAsBoolean(xmlObject, field, defaultValue))
return;
if (handleFieldDefaultValueAsEnum(xmlObject, field, defaultValue))
return;
}
private <T> boolean handleFieldDefaultValueAsXmlType(T xmlObject, Field field) throws IllegalAccessException,
InstantiationException {
if (field.getType().isEnum() || field.getType().getAnnotation(XmlType.class) == null)
return false;
field.set(xmlObject, field.getType().newInstance());
return true;
}
private <T> boolean handleFieldDefaultValueAsEnum(T xmlObject, Field field, String defaultValue)
throws IllegalAccessException {
if (!field.getType().isEnum())
return false;
@SuppressWarnings({ "unchecked", "rawtypes" })
Enum<?> enumValue = Enum.valueOf((Class<? extends Enum>) field.getType(), defaultValue.toUpperCase());
field.set(xmlObject, enumValue);
return true;
}
private <T> boolean handleFieldDefaultValueAsBoolean(T xmlObject, Field field, String defaultValue)
throws IllegalAccessException {
if (!field.getType().equals(Boolean.class))
return false;
field.set(xmlObject, Boolean.valueOf(defaultValue));
return true;
}
private void setDefaultValueForList(Object fieldValue) throws JAXBException {
if (fieldValue == null) {
return;
}
List<?> listValues = (List<?>) fieldValue;
for (Object value : listValues) {
setDefaultValues(value);
}
}
}