Package javolution.xml.internal

Source Code of javolution.xml.internal.XMLContextImpl

/*
* Javolution - Java(TM) Solution for Real-Time and Embedded Systems
* Copyright (C) 2012 - Javolution (http://javolution.org/)
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software is
* freely granted, provided that this notice is preserved.
*/
package javolution.xml.internal;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import javolution.context.LogContext;
import javolution.text.CharArray;
import javolution.text.TextBuilder;
import javolution.text.TextContext;
import javolution.text.TextFormat;
import javolution.util.FastMap;
import javolution.xml.DefaultXMLFormat;
import javolution.xml.XMLContext;
import javolution.xml.XMLFormat;
import javolution.xml.stream.XMLStreamException;

/**
* Holds the default implementation of XMLContext.
*
* @author  <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
* @version 6.0, July 21, 2013
*/
@SuppressWarnings("rawtypes")
public final class XMLContextImpl extends XMLContext {

    // Holds class->format mapping.
    private final FastMap<Class<?>, XMLFormat<?>> classToFormat = new FastMap<Class<?>, XMLFormat<?>>()
            .shared();

    // Holds parent (null if root).
    private final XMLContextImpl parent;

    /** Default constructor for root */
    public XMLContextImpl() {
        parent = null;
    }

    /** Inner constructor */
    public XMLContextImpl(XMLContextImpl parent) {
        this.parent = parent;
    }

    @Override
    protected XMLContext inner() {
        return new XMLContextImpl(this);
    }

    @SuppressWarnings("unchecked")
    @Override
    protected <T> XMLFormat<T> searchFormat(Class<? extends T> type) {
        XMLFormat<T> format = (XMLFormat<T>) classToFormat.get(type);
        if (format != null) return format;
        if (parent != null) { // Searches parent.
            format = parent.searchFormat(type);
            classToFormat.put(type, format);
            return format;
        }
        // Root context (search inheritable annotations).
        DefaultXMLFormat annotation = type
                .getAnnotation(DefaultXMLFormat.class);
        if (annotation != null) { // Found it.
            try {
                format = (XMLFormat<T>) annotation.value().newInstance();
                classToFormat.put(type, format);
                return format;
            } catch (Throwable error) {
                LogContext.warning(error);
            }
        }
        if (Collection.class.isAssignableFrom(type)) {
            classToFormat.put(type, COLLECTION_XML);
            return (XMLFormat<T>) COLLECTION_XML;
        } else if (Map.class.isAssignableFrom(type)) {
            classToFormat.put(type, MAP_XML);
            return (XMLFormat<T>) MAP_XML;
        } else {
            classToFormat.put(type, OBJECT_XML);
            return (XMLFormat<T>) OBJECT_XML;
        }
    }

    @Override
    public <T> void setFormat(Class<? extends T> type, XMLFormat<T> format) {
        classToFormat.put(type, format);
    }

    /////////////////////////
    // PREDEFINED FORMATS  //
    /////////////////////////

    /**
     * THe default Object XML representation consists of the text representation
     * of the object as a "value" attribute.
     */
    private static final XMLFormat<Object> OBJECT_XML = new XMLFormat<Object>() {

        @Override
        public boolean isReferenceable() {
            return false; // Always by value.
        }

        @Override
        public Object newInstance(Class<?> cls, XMLFormat.InputElement xml)
                throws XMLStreamException {
            TextFormat<?> format = TextContext.getFormat(cls);
            CharArray value = xml.getAttribute("value");
            if (value == null) throw new XMLStreamException(
                    "Missing value attribute to parse " + cls + " instances.");
            return format.parse(value);
        }

        @Override
        public void read(XMLFormat.InputElement xml, Object obj)
                throws XMLStreamException {
            // Do nothing.
        }

        @Override
        public void write(Object obj, XMLFormat.OutputElement xml)
                throws XMLStreamException {
            TextBuilder tmp = new TextBuilder();
            TextFormat<Object> tf = TextContext.getFormat(obj.getClass());
            tf.format(obj, tmp);
            xml.setAttribute("value", tmp);
        }

    };

    /**
     * The default XML representation for {@link java.util.Collection}
     * consists of nested XML elements one for each element of the collection.
     * The elements' order is defined by the collection iterator order.
     * Collections are deserialized using their default constructor.
     */
    private static final XMLFormat<Collection> COLLECTION_XML = new XMLFormat<Collection>() {

        @SuppressWarnings("unchecked")
        @Override
        public void read(XMLFormat.InputElement xml, Collection collection)
                throws XMLStreamException {
            while (xml.hasNext()) {
                collection.add(xml.getNext());
            }
        }

        @Override
        public void write(Collection collection, XMLFormat.OutputElement xml)
                throws XMLStreamException {
            for (Iterator i = collection.iterator(); i.hasNext();) {
                xml.add(i.next());
            }
        }
    };

    /**
     * The default XML representation for {@link java.util.Map} consists of
     * key/value pair as nested XML elements. For example:[code]
     * <javolution.util.FastMap>
     *     <Key class="java.lang.String" value="ONE"/>
     *     <Value class="java.lang.Integer" value="1"/>
     *     <Key class="java.lang.String" value="TWO"/>
     *     <Value class="java.lang.Integer" value="2"/>
     *     <Key class="java.lang.String" value="THREE"/>
     *     <Value class="java.lang.Integer" value="3"/>
     * </javolution.util.FastMap>[/code]
     *
     * The elements' order is defined by the map's entries iterator order.
     * Maps are deserialized using their default constructor.
     */
    private static final XMLFormat<Map> MAP_XML = new XMLFormat<Map>() {

        @SuppressWarnings("unchecked")
        @Override
        public void read(XMLFormat.InputElement xml, Map map)
                throws XMLStreamException {
            while (xml.hasNext()) {
                Object key = xml.get("Key");
                Object value = xml.get("Value");
                map.put(key, value);
            }
        }

        @Override
        public void write(Map map, XMLFormat.OutputElement xml)
                throws XMLStreamException {
            for (Iterator it = map.entrySet().iterator(); it.hasNext();) {
                Map.Entry entry = (Map.Entry) it.next();
                xml.add(entry.getKey(), "Key");
                xml.add(entry.getValue(), "Value");
            }
        }
    };
}
TOP

Related Classes of javolution.xml.internal.XMLContextImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.