de.xwic.appkit.core.transport.xml.XmlBeanSerializer.java Source code

Java tutorial

Introduction

Here is the source code for de.xwic.appkit.core.transport.xml.XmlBeanSerializer.java

Source

/*******************************************************************************
 * Copyright 2015 xWic group (http://www.xwic.de)
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 *  
 *******************************************************************************/
/**
 * 
 */
package de.xwic.appkit.core.transport.xml;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dom4j.Document;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

import de.xwic.appkit.core.config.ConfigurationException;
import de.xwic.appkit.core.config.ConfigurationManager;
import de.xwic.appkit.core.config.Language;
import de.xwic.appkit.core.config.model.EntityDescriptor;
import de.xwic.appkit.core.dao.DAO;
import de.xwic.appkit.core.dao.DAOSystem;
import de.xwic.appkit.core.dao.EntityKey;
import de.xwic.appkit.core.dao.IEntity;
import de.xwic.appkit.core.dao.util.Entities;
import de.xwic.appkit.core.export.XmlExport;
import de.xwic.appkit.core.model.daos.IPicklisteDAO;
import de.xwic.appkit.core.model.entities.IPicklistEntry;
import de.xwic.appkit.core.model.entities.IPickliste;
import de.xwic.appkit.core.remote.client.EntityProxyFactory;
import de.xwic.appkit.core.transfer.EntityTransferObject;
import de.xwic.appkit.core.transfer.PropertyValue;

/**
 * @author Florian Lippisch
 */
public class XmlBeanSerializer {

    /**
     * 
     */
    public static final String ATTRVALUE_TRUE = "1";
    /**
     * 
     */
    public static final String ELM_NULL = "null";
    /**
     * 
     */
    public static final String ELM_ELEMENT = "element";
    /**
     * 
     */
    public static final String ELM_SET = "set";
    /**
     * 
     */
    public static final String ELM_LIST = "list";
    /**
     *
     */
    private static final String ELM_MAP = "map";
    /**
     *
     */
    private static final String ELM_MAP_ENTRY = "entry";
    /**
     *
     */
    private static final String ELM_MAP_KEY = "key";
    /**
     *
     */
    private static final String ELM_MAP_VALUE = "value";
    /**
     * 
     */
    public static final String ELM_BEAN = "bean";

    /**
     *
     */
    public static final String ELM_ENUM = "enum-name";

    /**
     * 
     */
    private static final String NEW_LINE_PLACEHOLDER = "<nl_ph>";

    private final static Object[] NO_ARGS = new Object[0];
    protected static final Log log = LogFactory.getLog(XmlBeanSerializer.class);

    private List<ICustomObjectSerializer> customSerializer = new ArrayList<ICustomObjectSerializer>();
    private Set<String> skipPropertyNames = new HashSet<String>();

    private boolean serializeEntity = false;

    private XmlEntityTransport transport;

    public XmlBeanSerializer(XmlEntityTransport transport) {
        this.transport = transport;
    }

    /**
     * For no caching
     */
    public XmlBeanSerializer() {
        this(new HashMap<EntityKey, EntityTransferObject>());
    }

    public XmlBeanSerializer(Map<EntityKey, EntityTransferObject> sessionCache) {
        this(new XmlEntityTransport(sessionCache));
    }

    /**
     * Add a custom serializer
     * 
     * @param serializer
     */
    public void addCustomObjectSerializer(ICustomObjectSerializer serializer) {
        customSerializer.add(serializer);
    }

    /**
     * Add a property name to skip.
     * 
     * @param name
     */
    public void addSkipPropertyName(String name) {
        skipPropertyNames.add(name);
    }

    /**
     * @param rootElement
     * @param bean
     * @return
     * @throws TransportException
     */
    public static String serializeToXML(String rootElement, Object bean) throws TransportException {
        return serializeToXML(rootElement, bean, false);
    }

    /**
     * @param rootElement
     * @param bean
     * @return
     * @throws TransportException
     */
    public static String serializeToXML(String rootElement, Object bean, boolean serializeEntity)
            throws TransportException {
        return serializeCollectionToXML(rootElement, Arrays.asList(bean), serializeEntity);
    }

    /**
     * @param rootElement
     * @param beans
     * @return
     * @throws TransportException
     */
    public static String serializeCollectionToXML(String rootElement, Collection<?> beans, boolean serializeEntity)
            throws TransportException {
        ByteArrayOutputStream baOut = new ByteArrayOutputStream();
        OutputStreamWriter writer = new OutputStreamWriter(baOut);

        try {
            Document doc = DocumentFactory.getInstance().createDocument();
            Element root = doc.addElement(rootElement);

            XmlEntityTransport transport = new XmlEntityTransport(new HashMap<EntityKey, EntityTransferObject>());
            XmlBeanSerializer xml = new XmlBeanSerializer(transport);
            xml.setSerializeEntity(serializeEntity);

            for (Object bean : beans) {
                xml.addValue(root, bean, true);
            }

            OutputFormat prettyFormat = OutputFormat.createCompactFormat();// CompactFormat();//PrettyPrint();
            // this "hack" is required to preserve the LBCR's in strings...
            XMLWriter xmlWriter = new XMLWriter(writer, prettyFormat) {
                @Override
                public void write(Document arg0) throws IOException {
                    // this.preserve = true;
                    super.write(arg0);
                }
            };
            xmlWriter.write(doc);
            xmlWriter.flush();

        } catch (IOException e) {
            throw new TransportException("Unexpected IOException while serializing query.", e);
        }

        return baOut.toString();
    }

    /**
     * @param doc
     * @param string
     * @param query
     * @throws IntrospectionException
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     */
    public void serializeBean(Element elm, String elementName, Object bean) throws TransportException {

        Element root = elm.addElement(elementName);

        root.addAttribute("type", bean.getClass().getName());

        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(bean.getClass());
            for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {

                if (!"class".equals(pd.getName())) {
                    Element pElm = root.addElement(pd.getName());
                    Method mRead = pd.getReadMethod();
                    if (mRead == null) {
                        log.debug(String.format("No '%s' property on '%s'.", pd.getName(), bean.getClass()));
                        continue;
                    }
                    Object value = mRead.invoke(bean, NO_ARGS);

                    boolean addType = true;
                    addType = value != null && !value.getClass().equals(pd.getPropertyType())
                            && !pd.getPropertyType().isPrimitive();
                    addValue(pElm, value, addType);
                }

            }
        } catch (Exception e) {
            throw new TransportException("Error serializing bean: " + e, e);
        }

    }

    public void addValue(Element elm, Object value, boolean addTypeInfo) throws TransportException {
        addValue(elm, value, addTypeInfo, true);
    }

    /**
     * @param value
     * @param value2
     * @throws TransportException
     */
    public void addValue(Element elm, Object value, boolean addTypeInfo, boolean lazy) throws TransportException {

        // check custom object serializers first.
        for (ICustomObjectSerializer cos : customSerializer) {
            if (cos.handlesObject(value)) {
                cos.serialize(elm, value);
                return; // early exit
            }
        }

        String typeInfo = null;

        if (value instanceof PropertyValue) {
            PropertyValue pv = (PropertyValue) value;
            if (pv.isEntityType()) {
                if (pv.isLoaded() && pv.getValue() == null) {
                    value = null;
                } else {
                    elm.addAttribute("id", Integer.toString(pv.getEntityId()));
                    elm.addAttribute("entityType", ATTRVALUE_TRUE);
                    if (pv.isLoaded()) {
                        value = pv.getValue();
                    } else {
                        value = "";
                        typeInfo = pv.getType().getName();
                    }
                }
            } else if (pv.isLoaded()) {
                value = pv.getValue();
            } else {
                // non loaded value
                value = null;
                elm.addAttribute("lazy", ATTRVALUE_TRUE);
                return; // BREAK
            }

            if (pv.isModified()) {
                elm.addAttribute("modified", ATTRVALUE_TRUE);
            }
        }

        if (typeInfo == null) {
            typeInfo = value != null ? value.getClass().getName() : null;
        }

        if (value instanceof Enum<?>) {
            serializeEnum(elm, (Enum<?>) value);
            return;
        }

        if (value == null) {
            elm.addAttribute(ELM_NULL, ATTRVALUE_TRUE);
        } else if (value instanceof String) {
            String newValue = ((String) value).replaceAll("(\n\r)|\n", NEW_LINE_PLACEHOLDER);
            elm.setText(newValue);
        } else if (value instanceof Integer) {
            elm.setText(value.toString());
        } else if (value instanceof Boolean) {
            Boolean bo = (Boolean) value;
            elm.setText(bo.booleanValue() ? "true" : "false");
        } else if (value instanceof Long) {
            elm.setText(value.toString());
        } else if (value instanceof Double) {
            elm.setText(value.toString());
        } else if (value instanceof Date) {
            Date date = (Date) value;
            elm.setText(Long.toString(date.getTime()));

        } else if (value instanceof IPicklistEntry) {
            IPicklistEntry entry = (IPicklistEntry) value;
            typeInfo = entry.type().getName();
            if (entry.getKey() != null) {
                elm.addAttribute("key", entry.getKey());
            }
            elm.addAttribute("picklistid", entry.getPickliste().getKey());
            elm.addAttribute("entryid", Integer.toString(entry.getId()));
            elm.addAttribute("langid", "de");
            elm.setText(entry.getBezeichnung("de")); // use german language in export, as it is most
            // common

        } else if (value instanceof IEntity) {
            IEntity entity = (IEntity) value;
            typeInfo = entity.type().getName();
            if (entity.getId() == Entities.NEW_ENTITY_ID || serializeEntity || !lazy) {
                EntityDescriptor descr;
                try {
                    descr = DAOSystem.getEntityDescriptor(typeInfo);
                    transport.addEntity(elm, descr, entity);
                } catch (ConfigurationException e) {
                    throw new TransportException(e);
                }

            }
            elm.addAttribute("id", Integer.toString(entity.getId()));

        } else if (value instanceof EntityTransferObject) {
            EntityTransferObject eto = (EntityTransferObject) value;
            DAO<?> dao = DAOSystem.findDAOforEntity(eto.getEntityClass());
            typeInfo = dao.getEntityClass().getName();
            EntityDescriptor descr;
            try {
                descr = DAOSystem.getEntityDescriptor(typeInfo);
                transport.addEntity(elm, descr, eto, lazy);
            } catch (ConfigurationException e) {
                throw new TransportException(e);
            }
            elm.addAttribute("id", Integer.toString(eto.getEntityId()));

        } else if (value instanceof Set) {
            Set<?> set = (Set<?>) value;
            Element elmSet = elm.addElement(ELM_SET);
            if (lazy) {
                elm.addAttribute("lazy", ATTRVALUE_TRUE);
            }
            for (Object o : set) {
                Element entry = elmSet.addElement(ELM_ELEMENT);
                addValue(entry, o, true);
            }
        } else if (value instanceof List) {
            List<?> list = (List<?>) value;
            Element elmSet = elm.addElement(ELM_LIST);
            if (lazy) {
                elm.addAttribute("lazy", ATTRVALUE_TRUE);
            }
            for (Object o : list) {
                Element entry = elmSet.addElement(ELM_ELEMENT);
                addValue(entry, o, true);
            }
        } else if (value instanceof Map<?, ?>) {
            serializeMap(elm, (Map<?, ?>) value);
        } else {
            serializeBean(elm, ELM_BEAN, value);
            addTypeInfo = false;
        }

        if (addTypeInfo && typeInfo != null) {
            elm.addAttribute("type", typeInfo);
        }

    }

    /**
     * @param root
     * @param string
     * @return
     */
    public Object deserializeBean(Element elm, boolean forceLoadCollection) throws TransportException {
        Map<EntityKey, Integer> context = new HashMap<EntityKey, Integer>();
        return deserializeBean(elm, context, forceLoadCollection);
    }

    /**
     * 
     * @param elm
     * @return
     * @throws TransportException
     */
    public Object deserializeBean(Element elm) throws TransportException {
        return deserializeBean(elm, false);
    }

    /**
     * @param elm
     * @param context
     * @return
     * @throws TransportException
     */
    public void deserializeBean(Object bean, Element elm, Map<EntityKey, Integer> context)
            throws TransportException {
        deserializeBean(bean, elm, context, false);
    }

    /**
     * Deserializes a bean.
     * 
     * @param elm
     * @param context
     * @return
     * @throws TransportException
     */
    public Object deserializeBean(Element elm, Map<EntityKey, Integer> context, boolean forceLoadCollection)
            throws TransportException {
        Element firstElem = (Element) elm.elementIterator().next();
        if (firstElem != null && (ELM_LIST.equals(firstElem.getName()) || ELM_SET.equals(firstElem.getName()))) {
            return readValue(context, elm, null, forceLoadCollection);
        }

        String strTypeClass = elm.attributeValue("type");
        if (strTypeClass == null || strTypeClass.length() == 0) {
            throw new TransportException("Missing type attribute in bean element (" + elm.getName() + ")");
        }

        // instanciate bean
        Class<?> beanType;
        Object bean;
        try {
            beanType = Class.forName(strTypeClass);
            bean = beanType.newInstance();
        } catch (InstantiationException e) {
            throw new TransportException("Can not instantiate bean class " + strTypeClass, e);
        } catch (IllegalAccessException e) {
            throw new TransportException("IllegalAccessException instantiating bean class " + strTypeClass);
        } catch (ClassNotFoundException e) {
            throw new TransportException(
                    "The bean '" + strTypeClass + "' can not be deserialized because the class can not be found.",
                    e);
        }

        deserializeBean(bean, elm, context, forceLoadCollection);

        return bean;
    }

    /**
     * Deserializes an element into a bean.
     * 
     * @param elm
     * @param context
     * @return
     * @throws TransportException
     */
    public void deserializeBean(Object bean, Element elm, Map<EntityKey, Integer> context,
            boolean forceLoadCollection) throws TransportException {
        // now read the properties
        try {
            BeanInfo bi = Introspector.getBeanInfo(bean.getClass());
            for (PropertyDescriptor pd : bi.getPropertyDescriptors()) {
                Method mWrite = pd.getWriteMethod();
                if (!"class".equals(pd.getName()) && mWrite != null && !skipPropertyNames.contains(pd.getName())) {
                    Element elmProp = elm.element(pd.getName());
                    if (elmProp != null) {
                        Object value = readValue(context, elmProp, pd, forceLoadCollection);
                        mWrite.invoke(bean, new Object[] { value });
                    } else {
                        log.warn("The property " + pd.getName()
                                + " is not specified in the xml document. The bean may not be restored completly");
                    }
                }
            }
        } catch (Exception e) {
            throw new TransportException("Error deserializing bean: " + e, e);
        }
    }

    /**
     * @param context
     * @param elmProp
     * @param pd
     * @return
     * @throws TransportException
     */
    @SuppressWarnings("unchecked")
    public Object readValue(Map<EntityKey, Integer> context, Element elProp, PropertyDescriptor pd,
            boolean forceLoadCollection) throws TransportException {

        // check if value is null
        if (elProp.element(XmlExport.ELM_NULL) != null || ATTRVALUE_TRUE.equals(elProp.attributeValue("null"))) {
            return null;
        }

        Class<?> type = getType(elProp.attributeValue("type"));

        if (type == null) {
            if (pd != null) {
                type = pd.getPropertyType();
            } else {
                // is it a bean?
                Element elBean = elProp.element(ELM_BEAN);
                if (elBean != null) {
                    return deserializeBean(elBean, context, forceLoadCollection);
                }
                throw new TransportException(
                        "Can't deserialize element '" + elProp.getName() + "' - no type informations available.");
            }
        }

        // check custom object serializers first.
        for (ICustomObjectSerializer cos : customSerializer) {
            if (cos.handlesType(type)) {
                // found a custom serializer, directly return the value, even if null
                return cos.deserialize(elProp);
            }
        }

        Object value = null;

        if (Enum.class.isAssignableFrom(type)) {
            return deserializeEnum(type, elProp);
        }

        if (Set.class.isAssignableFrom(type)) {
            // a set.
            Element elSet = elProp.element(ELM_SET);
            if (elSet != null) {
                Set<Object> set = new HashSet<Object>();
                for (Iterator<?> itSet = elSet.elementIterator(ELM_ELEMENT); itSet.hasNext();) {
                    Element elSetElement = (Element) itSet.next();
                    set.add(readValue(context, elSetElement, null, forceLoadCollection));
                }
                value = set;
            }
        } else if (List.class.isAssignableFrom(type)) {
            Element elSet = elProp.element(ELM_LIST);
            if (elSet != null) {
                List<Object> list = new ArrayList<Object>();
                for (Iterator<?> itSet = elSet.elementIterator(ELM_ELEMENT); itSet.hasNext();) {
                    Element elSetElement = (Element) itSet.next();
                    list.add(readValue(context, elSetElement, null, forceLoadCollection));
                }
                value = list;
            }
        } else if (Map.class.isAssignableFrom(type)) {
            value = deserializeMap(context, elProp, forceLoadCollection);
        } else if (IPicklistEntry.class.isAssignableFrom(type)) {

            IPicklisteDAO plDAO = DAOSystem.getDAO(IPicklisteDAO.class);
            IPicklistEntry entry = null;

            String picklistId = elProp.attributeValue("picklistid");
            String key = elProp.attributeValue("key");
            String text = elProp.getText();

            if ((picklistId == null || picklistId.trim().isEmpty()) || (key == null || key.trim().isEmpty())) {
                // maybe it was sent with the ID?

                String strId = elProp.attributeValue("id");

                if (strId != null && !strId.isEmpty()) {
                    int id = Integer.parseInt(strId);
                    entry = plDAO.getPickListEntryByID(id);
                }

            } else {

                String langid = elProp.attributeValue("langid");
                if (langid == null || langid.length() == 0) {
                    langid = "en";
                }

                // try to find by key
                if (key != null && key.length() != 0 && picklistId != null && picklistId.length() != 0) {
                    entry = plDAO.getPickListEntryByKey(picklistId, key); // try to find by key
                }

                // not found, try by title
                if (entry == null && picklistId != null && picklistId.length() != 0 && text != null
                        && text.length() != 0) {
                    List<IPicklistEntry> lst = plDAO.getAllEntriesToList(picklistId);
                    for (IPicklistEntry pe : lst) {
                        if (text.equals(pe.getBezeichnung(langid))) {
                            entry = pe;
                            break;
                        }
                    }
                }
            }

            if (entry == null && picklistId != null && text != null) {
                // create??
                IPickliste plist = plDAO.getPicklisteByKey(picklistId);
                if (plist != null) {
                    entry = plDAO.createPicklistEntry();
                    entry.setKey(key);
                    entry.setPickliste(plist);
                    plDAO.update(entry);

                    for (Language lang : ConfigurationManager.getSetup().getLanguages()) {
                        plDAO.createBezeichnung(entry, lang.getId(), text);
                    }
                }
            }
            value = entry;

        } else if (IEntity.class.isAssignableFrom(type)) {
            // entity type
            int refId = Integer.parseInt(elProp.attributeValue("id"));
            if (context != null) {
                Integer newId = context.get(new EntityKey(type.getName(), refId));
                if (newId != null) {
                    // its an imported object
                    refId = newId.intValue();
                }
            }
            DAO<?> refDAO = DAOSystem.findDAOforEntity((Class<? extends IEntity>) type);
            IEntity refEntity;

            if (refId == Entities.NEW_ENTITY_ID && elProp.attributeValue(EtoSerializer.ETO_PROPERTY) != null) {
                refEntity = EtoSerializer.newEntity(elProp.attributeValue(EtoSerializer.ETO_PROPERTY),
                        forceLoadCollection);
            } else if (elProp.element(XmlEntityTransport.ELM_ENTITY) != null) {

                EtoEntityNodeParser parser = new EtoEntityNodeParser();
                EntityTransferObject refEto = (EntityTransferObject) parser.parseElement(
                        elProp.element(XmlEntityTransport.ELM_ENTITY), context, type, refDAO.getEntityDescriptor(),
                        this, transport.getSessionCache(), forceLoadCollection);
                refEntity = EntityProxyFactory.createEntityProxy(refEto);
            } else {
                refEntity = refDAO.getEntity(refId);
            }

            if (refEntity == null) {
                throw new TransportException(String.format("No entity of type %s with id %s.", type, refId));
            }
            value = refEntity;

        } else {

            Element elBean = elProp.element(ELM_BEAN);
            if (elBean != null) {
                value = deserializeBean(elBean, context, forceLoadCollection);
            } else {
                // basic type
                String text = elProp.getText();
                if (String.class.equals(type)) {
                    if (text != null) {
                        value = text.replaceAll(NEW_LINE_PLACEHOLDER, "\n");
                    }
                } else if (int.class.equals(type) || Integer.class.equals(type)) {
                    value = new Integer(text);
                } else if (long.class.equals(type) || Long.class.equals(type)) {
                    value = new Long(text);
                } else if (boolean.class.equals(type) || Boolean.class.equals(type)) {
                    value = new Boolean(text.equals("true"));
                } else if (Date.class.equals(type) || java.sql.Timestamp.class.equals(type)) {
                    // entities coming from the DB have the Date field as java.sql.Timestamp
                    // the serialized value is the ms timestamp, so we can instantiate a Date from
                    // it
                    value = new Date(Long.parseLong(text));
                } else if (double.class.equals(type) || Double.class.equals(type)) {
                    value = new Double(text);
                }
            }
        }

        return value;
    }

    /**
     * @param elm
     * @param value
     * @param addTypeInfo
     * @throws TransportException
     */
    private void serializeMap(final Element elm, final Map<?, ?> map) throws TransportException {
        final Element elmMap = elm.addElement(ELM_MAP);
        for (final Entry<?, ?> entry : map.entrySet()) {
            final Element element = elmMap.addElement(ELM_MAP_ENTRY);
            final Element key = element.addElement(ELM_MAP_KEY);
            addValue(key, entry.getKey(), true);
            final Element mapValue = element.addElement(ELM_MAP_VALUE);
            addValue(mapValue, entry.getValue(), true);
        }
    }

    /**
     * @param context
     * @param elProp
     * @param value
     * @return
     * @throws TransportException
     */
    private Map<?, ?> deserializeMap(final Map<EntityKey, Integer> context, final Element elProp,
            boolean forceLoadCollection) throws TransportException {
        final Element element = elProp.element(ELM_MAP);
        if (element == null) {
            return null;
        }
        final Map<Object, Object> map = new HashMap<Object, Object>();
        final Iterator<Element> it = element.elementIterator(ELM_MAP_ENTRY);
        while (it.hasNext()) {
            final Element entry = it.next();

            final Object key = readValue(context, entry.element(ELM_MAP_KEY), null, forceLoadCollection);
            final Object value = readValue(context, entry.element(ELM_MAP_VALUE), null, forceLoadCollection);

            map.put(key, value);
        }
        return map;
    }

    /**
     * @param typeName
     * @return
     * @throws TransportException if the class is not found
     */
    private static Class<?> getType(final String typeName) throws TransportException {
        if (typeName != null) {
            try {
                return Class.forName(typeName);
            } catch (ClassNotFoundException e) {
                throw new TransportException("Can not create class: " + e, e);
            }
        }
        return null;
    }

    /**
     * If true, entity object would be serialized as well
     * 
     * @return the serializeEntity
     */
    public boolean isSerializeEntity() {
        return serializeEntity;
    }

    /**
     * @param serializeEntity the serializeEntity to set
     */
    public void setSerializeEntity(boolean serializeEntity) {
        this.serializeEntity = serializeEntity;
    }

    /**
     * @param element
     * @param value
     */
    private static <T extends Enum<T>> void serializeEnum(final Element element, final Enum<T> value) {
        element.addElement(ELM_ENUM).setText(value.name());
    }

    /**
     * @param beanType
     * @param element
     * @return
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static Object deserializeEnum(final Class beanType, final Element element) {
        return Enum.valueOf(beanType, element.elementText(ELM_ENUM));
    }

}