net.sf.juffrou.xml.internal.config.ConfigReader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of juffrou-xml Show documentation
Show all versions of juffrou-xml Show documentation
Juffrou XML is simplified marshaling for java beans into XML and back.
package net.sf.juffrou.xml.internal.config;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import net.sf.juffrou.reflect.JuffrouBeanWrapper;
import net.sf.juffrou.reflect.BeanWrapperContext;
import net.sf.juffrou.xml.error.JuffrouXmlConfigReaderException;
import net.sf.juffrou.xml.error.XmlMappingReaderException;
import net.sf.juffrou.xml.internal.JuffrouBeanMetadata;
import net.sf.juffrou.xml.internal.NodeType;
import net.sf.juffrou.xml.internal.XmlConstants;
import net.sf.juffrou.xml.internal.binding.BeanClassBinding;
import net.sf.juffrou.xml.internal.binding.BeanPropertyBinding;
import net.sf.juffrou.xml.internal.config.protocols.classpath.Handler;
import net.sf.juffrou.xml.serializer.Serializer;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
/**
* Reads the mapping file and sets the metadata values
*
* @author cemartins
*/
public class ConfigReader {
protected static String PREFERENCES_NODENAME = "preferences";
protected static String ROOT_ELEMENT_NODENAME = "root-element";
protected static String ATTRIBUTE_ELEMENT_NODENAME = "attribute";
protected static String TEXT_ELEMENT_NODENAME = "text";
protected static String ELEMENT_ELEMENT_NODENAME = "element";
protected static String SERIALIZER_ELEMENT_NODENAME = "serializer";
protected static String TYPE_ELEMENT_NODENAME = "type";
protected static String XML_ELEMENT_NODENAME = "xml";
protected static String REF_ELEMENT_NODENAME = "ref";
protected static String CLASS_ELEMENT_NODENAME = "class";
protected static String ID_ELEMENT_NODENAME = "id";
protected static String PROPERTY_ELEMENT_NODENAME = "property";
public void readConfigFile(JuffrouBeanMetadata metadata, String urlSpec) {
try {
URL url = new URL(null, urlSpec, new Handler(ClassLoader.getSystemClassLoader()));
InputStream stream = url.openStream();
readConfigFile(metadata, stream);
stream.close();
} catch (UnsupportedEncodingException e) {
throw new JuffrouXmlConfigReaderException("Cannot create a reader of the XML string passed", e);
} catch (FileNotFoundException e) {
throw new JuffrouXmlConfigReaderException("Cannot create a reader of the XML string passed", e);
} catch (IOException e) {
throw new JuffrouXmlConfigReaderException("Cannot create a reader of the XML string passed", e);
}
}
public void readConfigFile(JuffrouBeanMetadata metadata, InputStream stream) {
try {
Document doc;
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
doc = docBuilder.parse(stream);
// normalize text representation
doc.getDocumentElement().normalize();
processMappingElement(metadata, doc.getFirstChild());
} catch (UnsupportedEncodingException e) {
throw new JuffrouXmlConfigReaderException("Cannot create a reader of the XML string passed", e);
} catch (ParserConfigurationException e) {
throw new JuffrouXmlConfigReaderException("Cannot create a reader of the XML string passed", e);
} catch (SAXException e) {
throw new JuffrouXmlConfigReaderException("Cannot create a reader of the XML string passed", e);
} catch (IOException e) {
throw new JuffrouXmlConfigReaderException("Cannot create a reader of the XML string passed", e);
}
}
protected void processMappingElement(JuffrouBeanMetadata metadata, Node currentNode) {
currentNode = currentNode.getFirstChild();
while(currentNode != null) {
if(currentNode.getNodeType() == Node.ELEMENT_NODE) {
if(currentNode.getNodeName().equals(ROOT_ELEMENT_NODENAME))
processRootElement(metadata, currentNode);
else if(currentNode.getNodeName().equals(SERIALIZER_ELEMENT_NODENAME))
processSerializer(metadata, currentNode);
else if(currentNode.getNodeName().equals(PREFERENCES_NODENAME))
processPreferences(metadata, currentNode);
}
currentNode = currentNode.getNextSibling();
}
}
protected void processPreferences(JuffrouBeanMetadata metadata, Node currentNode) {
// read tag attributes
// read tag content
currentNode = currentNode.getFirstChild();
while(currentNode != null) {
if(currentNode.getNodeName().equals(PREFERENCES_NODENAME))
processPreferences(metadata, currentNode);
currentNode = currentNode.getNextSibling();
}
}
/**
* Processes a bean as an XML element root
* @param metadata
* @param currentNode
*/
protected void processRootElement(JuffrouBeanMetadata metadata, Node currentNode) {
// read tag attributes
NamedNodeMap attributes = currentNode.getAttributes();
Node attribute = attributes.getNamedItem(TYPE_ELEMENT_NODENAME);
Class> clazz;
try {
clazz = Class.forName(attribute.getNodeValue());
} catch (ClassNotFoundException e) {
throw new XmlMappingReaderException(e);
}
BeanClassBinding xmlBeanWrapperContext = (BeanClassBinding) metadata.getBeanWrapperFactory().getBeanWrapperContext(clazz);
attribute = attributes.getNamedItem(XML_ELEMENT_NODENAME);
if(attribute != null)
xmlBeanWrapperContext.setXmlElementName(attribute.getNodeValue());
// read tag content
currentNode = currentNode.getFirstChild();
while(currentNode != null) {
if(currentNode.getNodeType() == Node.ELEMENT_NODE) {
if(currentNode.getNodeName().equals(ELEMENT_ELEMENT_NODENAME))
processElement(metadata, xmlBeanWrapperContext, currentNode, NodeType.ELEMENT);
else if(currentNode.getNodeName().equals(ATTRIBUTE_ELEMENT_NODENAME))
processElement(metadata, xmlBeanWrapperContext, currentNode, NodeType.ATTRIBUTE);
else if(currentNode.getNodeName().equals(TEXT_ELEMENT_NODENAME))
processElement(metadata, xmlBeanWrapperContext, currentNode, NodeType.TEXT);
else if(currentNode.getNodeName().equals(XML_ELEMENT_NODENAME))
processRootElementXml(metadata, xmlBeanWrapperContext, currentNode);
else if(currentNode.getNodeName().equals(SERIALIZER_ELEMENT_NODENAME))
xmlBeanWrapperContext.setSerializer(processSerializer(metadata, currentNode));
}
currentNode = currentNode.getNextSibling();
}
metadata.putBeanClassBinding(xmlBeanWrapperContext);
}
protected void processRootElementXml(JuffrouBeanMetadata metadata, BeanClassBinding xmlBeanWrapperContext, Node currentNode) {
NamedNodeMap attributes = currentNode.getAttributes();
Node attribute = attributes.getNamedItem(ID_ELEMENT_NODENAME);
xmlBeanWrapperContext.setXmlElementName(attribute.getNodeValue());
}
/**
* Processes a bean property as a XML element
* @param metadata
* @param xmlBeanWrapperContext
* @param currentNode
*/
protected void processElement(JuffrouBeanMetadata metadata, BeanClassBinding xmlBeanWrapperContext, Node currentNode, NodeType nodeType) {
// read tag attributes
BeanPropertyBinding propertyBinding = new BeanPropertyBinding();
propertyBinding.setNodeType(nodeType);
NamedNodeMap attributes = currentNode.getAttributes();
Node attribute = attributes.getNamedItem(PROPERTY_ELEMENT_NODENAME);
propertyBinding.setBeanPropertyName(attribute.getNodeValue());
// is the property is a node of type TEXT then its xml element name will be CDATA
if(nodeType == NodeType.TEXT)
propertyBinding.setXmlElementName(XmlConstants.CDATA_ELEMENT_NAME);
else {
attribute = attributes.getNamedItem(XML_ELEMENT_NODENAME);
if(attribute != null)
propertyBinding.setXmlElementName(attribute.getNodeValue());
}
attribute = attributes.getNamedItem(TYPE_ELEMENT_NODENAME);
if(attribute != null) {
Class> clazz;
try {
clazz = Class.forName(attribute.getNodeValue());
} catch (ClassNotFoundException e) {
throw new XmlMappingReaderException(e);
}
propertyBinding.setPropertyType(clazz);
}
// read tag content
currentNode = currentNode.getFirstChild();
while(currentNode != null) {
if(currentNode.getNodeType() == Node.ELEMENT_NODE) {
if(currentNode.getNodeName().equals(XML_ELEMENT_NODENAME))
processElementXml(metadata, propertyBinding, currentNode);
else if(currentNode.getNodeName().equals(SERIALIZER_ELEMENT_NODENAME))
propertyBinding.setSerializer(processSerializer(metadata, currentNode));
}
currentNode = currentNode.getNextSibling();
}
// if the XML element name was not defined, use the property name
if(propertyBinding.getXmlElementName() == null)
propertyBinding.setXmlElementName(propertyBinding.getBeanPropertyName());
// if the property type was not defined, use reflection with the help of a bean wrapper
if(propertyBinding.getPropertyType() == null) {
JuffrouBeanWrapper bw = new JuffrouBeanWrapper(xmlBeanWrapperContext);
Class> clazz = bw.getClazz(propertyBinding.getBeanPropertyName());
propertyBinding.setPropertyType(clazz);
}
xmlBeanWrapperContext.addBeanPropertyBinding(propertyBinding);
}
protected void processElementXml(JuffrouBeanMetadata metadata, BeanPropertyBinding propertyBinding, Node currentNode) {
NamedNodeMap attributes = currentNode.getAttributes();
Node attribute = attributes.getNamedItem(ID_ELEMENT_NODENAME);
propertyBinding.setXmlElementName(attribute.getNodeValue());
}
protected Serializer processSerializer(JuffrouBeanMetadata metadata, Node currentNode) {
// read tag attributes
String serializerId = null;
NamedNodeMap attributes = currentNode.getAttributes();
Node attribute = attributes.getNamedItem(REF_ELEMENT_NODENAME);
if(attribute != null)
return metadata.getSerializerWithId(attribute.getNodeValue());
attribute = attributes.getNamedItem(ID_ELEMENT_NODENAME);
if(attribute != null)
serializerId = attribute.getNodeValue();
attribute = attributes.getNamedItem(CLASS_ELEMENT_NODENAME);
if(attribute == null)
throw new XmlMappingReaderException("Serializer must have a 'class' or 'ref' atribute");
Class> clazz;
try {
clazz = Class.forName(attribute.getNodeValue());
} catch (ClassNotFoundException e) {
throw new XmlMappingReaderException("Serializer class not found " + attribute.getNodeValue(), e);
}
BeanWrapperContext bwContext = BeanWrapperContext.create(clazz);
// bwContext.setEagerInstatiation(true);
JuffrouBeanWrapper serializerWrapper = new JuffrouBeanWrapper(bwContext);
// read tag content
currentNode = currentNode.getFirstChild();
while(currentNode != null) {
if(currentNode.getNodeType() == Node.ELEMENT_NODE) {
serializerWrapper.setValueOfString(currentNode.getNodeName(), currentNode.getTextContent());
}
currentNode = currentNode.getNextSibling();
}
Serializer serializer = (Serializer) serializerWrapper.getBean();
if(serializerId != null)
metadata.registerSerializer(serializerId, serializer);
return serializer;
}
}