package com.arondor.common.reflection.parser.spring; import java.io.FileOutputStream; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.log4j.Logger; import org.jdom.Document; import org.jdom.Element; import org.jdom.output.Format; import org.jdom.output.XMLOutputter; import com.arondor.common.reflection.model.config.ElementConfiguration; import com.arondor.common.reflection.model.config.ListConfiguration; import com.arondor.common.reflection.model.config.MapConfiguration; import com.arondor.common.reflection.model.config.ObjectConfiguration; import com.arondor.common.reflection.model.config.ObjectConfigurationMap; import com.arondor.common.reflection.model.config.PrimitiveConfiguration; import com.arondor.common.reflection.model.config.ReferenceConfiguration; /** * Class to serialize {@link ObjectConfigurationMap} and write it to xml file * * @author Caroline Gaudin */ public class XMLBeanDefinitionWriter { private static final Logger LOGGER = Logger.getLogger(XMLBeanDefinitionWriter.class); /** * Serialize objectConfigurationMap and save it on target xml file * * @param objectConfigurationMap * {@link ObjectConfigurationMap} : to serialize and save to * target file * @param path * @throws IOException */ public void write(ObjectConfigurationMap objectConfigurationMap, String path) throws IOException { if (objectConfigurationMap == null || objectConfigurationMap.isEmpty()) { LOGGER.warn("ObjectConfigurationMap is empty, skipping objectConfiguration writting"); return; } Element rootElement = initConfigurationSerializing(); /** * For each objectConfiguration, serialize it */ for (Entry<String, ObjectConfiguration> objectConfEntry : objectConfigurationMap.entrySet()) { LOGGER.debug("Bean defintion name : " + objectConfEntry.getKey()); Element objectConfElement = new Element(XMLBeanTagsConstant.BEAN_TAG, XMLBeanTagsConstant.NAMESPACE); rootElement.addContent(objectConfElement); serializeBeanConfiguration(objectConfElement, objectConfEntry.getKey(), objectConfEntry.getValue(), true); } /** * Xml document construction and save it as target file */ Document document = new Document(rootElement); writeConfigurationFile(path, document); } /** * Write generic header informations for xml file * * @return */ private Element initConfigurationSerializing() { Element rootElement = new Element(XMLBeanTagsConstant.ALL_BEANS_TAG, XMLBeanTagsConstant.NAMESPACE); rootElement.addNamespaceDeclaration(XMLBeanTagsConstant.NAMESPACE_XSI); rootElement.setAttribute(XMLBeanTagsConstant.SCHEMA_LOCATION_NAME, XMLBeanTagsConstant.SCHEMA_LOCATION, XMLBeanTagsConstant.NAMESPACE_XSI); rootElement.addNamespaceDeclaration(XMLBeanTagsConstant.NAMESPACE_CONTEXT); for (Entry<String, String> entry : XMLBeanTagsConstant.HEADER_ATTRIBUTE_MAP.entrySet()) { rootElement.setAttribute(entry.getKey(), entry.getValue()); } return rootElement; } /** * Serialize an element configuration, in function of its * ElementConfigurationType * * @param objectConfElement * @param elementConfiguration * @param isProperty * : no new JDOM element created because it is a property (only * used for PrimitiveConfiguration) */ private void serializeElementConfiguration(Element objectConfElement, ElementConfiguration elementConfiguration, boolean isProperty) { switch (elementConfiguration.getFieldConfigurationType()) { case Map: serializeMapConfiguration(objectConfElement, (MapConfiguration) elementConfiguration); break; case List: serializeListConfiguration(objectConfElement, (ListConfiguration) elementConfiguration); break; case Object: serializeBeanConfiguration(objectConfElement, null, (ObjectConfiguration) elementConfiguration, false); break; case Primitive: serializePrimitiveConfiguration(objectConfElement, (PrimitiveConfiguration) elementConfiguration, isProperty); break; case Reference: serializeReferenceConfiguration(objectConfElement, (ReferenceConfiguration) elementConfiguration); break; } } /** * Serialize bean definition * * @param objectConfElement * @param beanName * @param objectConfiguration * @param isParent * : create a new JDOM element * @return */ private void serializeBeanConfiguration(Element objectConfElement, String beanName, ObjectConfiguration objectConfiguration, boolean isParent) { Element beanDefinitionElement = objectConfElement; if (!isParent) { beanDefinitionElement = new Element(XMLBeanTagsConstant.BEAN_TAG, XMLBeanTagsConstant.NAMESPACE); objectConfElement.addContent(beanDefinitionElement); } String objectName = objectConfiguration.getObjectName(); String className = objectConfiguration.getClassName(); boolean singleton = objectConfiguration.isSingleton(); if (objectName != null) { LOGGER.debug("Bean definition name : " + objectName); beanDefinitionElement.setAttribute(XMLBeanTagsConstant.BEAN_ID_TAG, objectName); } else { // Just use for log message to have contextual value objectName = beanName; } LOGGER.debug("Bean definition name = " + objectName + ", class name = " + className + ", isSingleton = " + singleton); if (className == null) { LOGGER.error("No class name defined for bean definition=" + objectName); throw new RuntimeException("Bean definition=" + objectName + " has no class name defined"); } beanDefinitionElement.setAttribute(XMLBeanTagsConstant.BEAN_CLASS_TAG, className); if (singleton) { beanDefinitionElement.setAttribute(XMLBeanTagsConstant.BEAN_SCOPE_TAG, XMLBeanTagsConstant.SINGLETON); } else { beanDefinitionElement.setAttribute(XMLBeanTagsConstant.BEAN_SCOPE_TAG, XMLBeanTagsConstant.PROTOTYPE); } serializeConstructorArg(beanDefinitionElement, objectName, objectConfiguration.getConstructorArguments()); serializeBeanDefinitionProperties(beanDefinitionElement, objectName, objectConfiguration.getFields()); } /** * Serialize constructor arguments list of bean definition * * @param beanDefinitionElement * @param beanName * @param constructorArguments */ private void serializeConstructorArg(Element beanDefinitionElement, String beanName, List<ElementConfiguration> constructorArguments) { if (constructorArguments == null || constructorArguments.isEmpty()) { LOGGER.debug("No contructor arguments defined for bean definition=" + beanName); return; } Element constructorArg = new Element(XMLBeanTagsConstant.CONSTRUCTOR_ARG_TAG, XMLBeanTagsConstant.NAMESPACE); beanDefinitionElement.addContent(constructorArg); for (ElementConfiguration elementConfiguration : constructorArguments) { serializeElementConfiguration(constructorArg, elementConfiguration, false); } } /** * Serialize properties list of bean definition * * @param beanDefinitionElement * @param beanName * @param fields */ private void serializeBeanDefinitionProperties(Element beanDefinitionElement, String beanName, Map<String, ElementConfiguration> fields) { if (fields == null || fields.isEmpty()) { LOGGER.debug("No properties associated with bean definition=" + beanName); return; } for (Entry<String, ElementConfiguration> fieldEntry : fields.entrySet()) { LOGGER.debug("Add property " + fieldEntry.getKey() + " for bean definition " + beanName); Element propertyElement = new Element(XMLBeanTagsConstant.PROPERTY_TAG, XMLBeanTagsConstant.NAMESPACE); propertyElement.setAttribute(XMLBeanTagsConstant.PROPERTY_NAME_TAG, fieldEntry.getKey()); beanDefinitionElement.addContent(propertyElement); serializeElementConfiguration(propertyElement, fieldEntry.getValue(), true); } } /** * Serialize reference configuration * * @param parentElement * @param elementConfiguration * @return */ private void serializeReferenceConfiguration(Element parentElement, ReferenceConfiguration refConfiguration) { Element refElement = new Element(XMLBeanTagsConstant.REF_TAG, XMLBeanTagsConstant.NAMESPACE); parentElement.addContent(refElement); String reference = refConfiguration.getReferenceName(); if (reference == null) { LOGGER.error("No reference defined"); throw new BeanSerializeException("No reference defined"); } refElement.setAttribute(XMLBeanTagsConstant.BEAN_TAG, reference); } /** * Serialize primitive configuration * * @param parentElement * @param elementConfiguration * @return */ private void serializePrimitiveConfiguration(Element parentElement, PrimitiveConfiguration primitiveConfiguration, boolean isProperty) { String value = primitiveConfiguration.getValue(); if (value == null) { LOGGER.error("No value defined"); throw new BeanSerializeException("No value defined"); } if (!isProperty) { Element valueElement = new Element(XMLBeanTagsConstant.PROPERTY_VALUE_TAG, XMLBeanTagsConstant.NAMESPACE); parentElement.addContent(valueElement); valueElement.addContent(value); } else { parentElement.setAttribute(XMLBeanTagsConstant.PROPERTY_VALUE_TAG, value); } } /** * Serialize list of element configuration * * @param parentElement * @param listConfiguration */ private void serializeListConfiguration(Element parentElement, ListConfiguration listConfiguration) { Element listElement = new Element(XMLBeanTagsConstant.LIST_TAG, XMLBeanTagsConstant.NAMESPACE); parentElement.addContent(listElement); List<ElementConfiguration> elementConfigurationList = listConfiguration.getListConfiguration(); if (elementConfigurationList == null) { LOGGER.error("No list defined"); throw new BeanSerializeException("No list defined"); } for (ElementConfiguration elementConfiguration : elementConfigurationList) { serializeElementConfiguration(listElement, elementConfiguration, false); } } /** * Serialize map of element configuration * * @param parentElement * @param elementConfiguration */ private void serializeMapConfiguration(Element parentElement, MapConfiguration mapConfiguration) { Element mapElement = new Element(XMLBeanTagsConstant.MAP_TAG, XMLBeanTagsConstant.NAMESPACE); parentElement.addContent(mapElement); Map<ElementConfiguration, ElementConfiguration> elementConfMap = mapConfiguration.getMapConfiguration(); if (elementConfMap == null) { LOGGER.error("No map defined"); throw new BeanSerializeException("No map defined"); } for (Entry<ElementConfiguration, ElementConfiguration> elementConfEntry : elementConfMap.entrySet()) { Element entryElement = new Element(XMLBeanTagsConstant.ENTRY_TAG, XMLBeanTagsConstant.NAMESPACE); mapElement.addContent(entryElement); Element keyElement = new Element(XMLBeanTagsConstant.KEY_TAG, XMLBeanTagsConstant.NAMESPACE); entryElement.addContent(keyElement); serializeElementConfiguration(keyElement, elementConfEntry.getKey(), false); ElementConfiguration value = elementConfEntry.getValue(); serializeElementConfiguration(entryElement, value, true); } } /** * Write objectConfigurationMap serialized to the target file * * @param path * @param document * @throws IOException * @throws */ private void writeConfigurationFile(String path, Document document) throws IOException { XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat()); xmlOutputter.output(document, new FileOutputStream(path)); } }