All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feilong.lib.xstream.converters.extended.NamedMapConverter Maven / Gradle / Ivy

Go to download

feilong is a suite of core and expanded libraries that include utility classes, http, excel,cvs, io classes, and much much more.

There is a newer version: 4.0.8
Show newest version
/*
 * Copyright (C) 2013, 2016, 2018 XStream Committers.
 * All rights reserved.
 *
 * The software in this package is published under the terms of the BSD
 * style license a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 *
 * Created on 20. September 2013 by Joerg Schaible
 */
package com.feilong.lib.xstream.converters.extended;

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

import com.feilong.lib.xstream.converters.ConversionException;
import com.feilong.lib.xstream.converters.Converter;
import com.feilong.lib.xstream.converters.ConverterLookup;
import com.feilong.lib.xstream.converters.MarshallingContext;
import com.feilong.lib.xstream.converters.SingleValueConverter;
import com.feilong.lib.xstream.converters.UnmarshallingContext;
import com.feilong.lib.xstream.converters.collections.MapConverter;
import com.feilong.lib.xstream.core.JVM;
import com.feilong.lib.xstream.core.util.HierarchicalStreams;
import com.feilong.lib.xstream.io.ExtendedHierarchicalStreamWriterHelper;
import com.feilong.lib.xstream.io.HierarchicalStreamReader;
import com.feilong.lib.xstream.io.HierarchicalStreamWriter;
import com.feilong.lib.xstream.mapper.Mapper;

/**
 * A map converter that uses predefined names for its elements.
 * 

* To be used as local converter. Note, suppress the usage of the implicit type argument, if * registered with annotation. Depending on the constructor arguments it is possible to support * various formats: *

*
    *
  • new NamedMapConverter(xstream.getMapper(), "entry", "key", String.class, "value", * Integer.class); * *
     * <map>
     *   <entry>
     *     <key>keyValue</key>
     *     <value>0</value>
     *   </entry>
     * </map>
     * 
    * *
  • *
  • new NamedMapConverter(xstream.getMapper(), null, "key", String.class, "value", * Integer.class); * *
     * <map>
     *   <key>keyValue</key>
     *   <value>0</value>
     * </map>
     * 
    * *
  • *
  • new NamedMapConverter(xstream.getMapper(), "entry", "key", String.class, "value", * Integer.class, true, true, xstream.getConverterLookup()); * *
     * <map>
     *   <entry> key="keyValue" value="0"/>
     * </map>
     * 
    * *
  • *
  • new NamedMapConverter(xstream.getMapper(), "entry", "key", String.class, "value", * Integer.class, true, false, xstream.getConverterLookup()); * *
     * <map>
     *   <entry key="keyValue">
     *     <value>0</value>
     *   </entry>
     * </map>
     * 
    * *
  • *
  • new NamedMapConverter(xstream.getMapper(), "entry", "key", String.class, "value", * Integer.class, false, true, xstream.getConverterLookup()); * *
     * <map>
     *   <entry value="0">
     *     <key>keyValue</key>
     *   </entry>
     * </map>
     * 
    * *
  • *
  • new NamedMapConverter(xstream.getMapper(), "entry", "key", String.class, null, * Integer.class, true, false, xstream.getConverterLookup()); * *
     * <map>
     *   <entry key="keyValue">0</entry>
     * </map>
     * 
    * *
  • *
* * @author Jörg Schaible * @since 1.4.5 */ public class NamedMapConverter extends MapConverter{ private final String entryName; private final String keyName; private final Class keyType; private final String valueName; private final Class valueType; private final boolean keyAsAttribute; private final boolean valueAsAttribute; private final ConverterLookup lookup; private final Mapper enumMapper; /** * Constructs a NamedMapConverter. * * @param mapper * the mapper * @param entryName * the name of the entry elements * @param keyName * the name of the key elements * @param keyType * the base type of key elements * @param valueName * the name of the value elements * @param valueType * the base type of value elements * @since 1.4.5 */ public NamedMapConverter(Mapper mapper, String entryName, String keyName, Class keyType, String valueName, Class valueType){ this(mapper, entryName, keyName, keyType, valueName, valueType, false, false, null); } /** * Constructs a NamedMapConverter handling an explicit Map type. * * @param type * the Map type this instance will handle * @param mapper * the mapper * @param entryName * the name of the entry elements * @param keyName * the name of the key elements * @param keyType * the base type of key elements * @param valueName * the name of the value elements * @param valueType * the base type of value elements * @since 1.4.5 */ public NamedMapConverter(Class type, Mapper mapper, String entryName, String keyName, Class keyType, String valueName, Class valueType){ this(type, mapper, entryName, keyName, keyType, valueName, valueType, false, false, null); } /** * Constructs a NamedMapConverter with attribute support. * * @param mapper * the mapper * @param entryName * the name of the entry elements * @param keyName * the name of the key elements * @param keyType * the base type of key elements * @param valueName * the name of the value elements * @param valueType * the base type of value elements * @param keyAsAttribute * flag to write key as attribute of entry element * @param valueAsAttribute * flag to write value as attribute of entry element * @param lookup * used to lookup SingleValueConverter for attributes * @since 1.4.5 */ public NamedMapConverter(Mapper mapper, String entryName, String keyName, Class keyType, String valueName, Class valueType, boolean keyAsAttribute, boolean valueAsAttribute, ConverterLookup lookup){ this(null, mapper, entryName, keyName, keyType, valueName, valueType, keyAsAttribute, valueAsAttribute, lookup); } /** * Constructs a NamedMapConverter with attribute support handling an explicit Map type. * * @param type * the Map type this instance will handle * @param mapper * the mapper * @param entryName * the name of the entry elements * @param keyName * the name of the key elements * @param keyType * the base type of key elements * @param valueName * the name of the value elements * @param valueType * the base type of value elements * @param keyAsAttribute * flag to write key as attribute of entry element * @param valueAsAttribute * flag to write value as attribute of entry element * @param lookup * used to lookup SingleValueConverter for attributes * @since 1.4.5 */ public NamedMapConverter(Class type, Mapper mapper, String entryName, String keyName, Class keyType, String valueName, Class valueType, boolean keyAsAttribute, boolean valueAsAttribute, ConverterLookup lookup){ super(mapper, type); this.entryName = entryName != null && entryName.length() == 0 ? null : entryName; this.keyName = keyName != null && keyName.length() == 0 ? null : keyName; this.keyType = keyType; this.valueName = valueName != null && valueName.length() == 0 ? null : valueName; this.valueType = valueType; this.keyAsAttribute = keyAsAttribute; this.valueAsAttribute = valueAsAttribute; this.lookup = lookup; enumMapper = JVM.isVersion(5) ? UseAttributeForEnumMapper.createEnumMapper(mapper) : null; if (keyType == null || valueType == null){ throw new IllegalArgumentException("Class types of key and value are mandatory"); } if (entryName == null){ if (keyAsAttribute || valueAsAttribute){ throw new IllegalArgumentException("Cannot write attributes to map entry, if map entry must be omitted"); } if (valueName == null){ throw new IllegalArgumentException("Cannot write value as text of entry, if entry must be omitted"); } } if (keyName == null){ throw new IllegalArgumentException("Cannot write key without name"); } if (valueName == null){ if (valueAsAttribute){ throw new IllegalArgumentException("Cannot write value as attribute without name"); }else if (!keyAsAttribute){ throw new IllegalArgumentException("Cannot write value as text of entry, if key is also child element"); } } if (keyAsAttribute && valueAsAttribute && keyName.equals(valueName)){ throw new IllegalArgumentException("Cannot write key and value with same attribute name"); } } @Override public void marshal(Object source,HierarchicalStreamWriter writer,MarshallingContext context){ Map map = (Map) source; SingleValueConverter keyConverter = null; SingleValueConverter valueConverter = null; if (keyAsAttribute){ keyConverter = getSingleValueConverter(keyType, "key"); } if (valueAsAttribute || valueName == null){ valueConverter = getSingleValueConverter(valueType, "value"); } for (Iterator iterator = map.entrySet().iterator(); iterator.hasNext();){ Map.Entry entry = (Map.Entry) iterator.next(); Object key = entry.getKey(); Object value = entry.getValue(); if (entryName != null){ ExtendedHierarchicalStreamWriterHelper.startNode(writer, entryName, entry.getClass()); if (keyConverter != null && key != null){ writer.addAttribute(keyName, keyConverter.toString(key)); } if (valueName != null && valueConverter != null && value != null){ writer.addAttribute(valueName, valueConverter.toString(value)); } } if (keyConverter == null){ writeItem(keyName, keyType, key, context, writer); } if (valueConverter == null){ writeItem(valueName, valueType, value, context, writer); }else if (valueName == null){ writer.setValue(valueConverter.toString(value)); } if (entryName != null){ writer.endNode(); } } } @Override protected void populateMap(HierarchicalStreamReader reader,UnmarshallingContext context,Map map,Map target){ SingleValueConverter keyConverter = null; SingleValueConverter valueConverter = null; if (keyAsAttribute){ keyConverter = getSingleValueConverter(keyType, "key"); } if (valueAsAttribute || valueName == null){ valueConverter = getSingleValueConverter(valueType, "value"); } while (reader.hasMoreChildren()){ Object key = null; Object value = null; if (entryName != null){ reader.moveDown(); if (keyConverter != null){ String attribute = reader.getAttribute(keyName); if (attribute != null){ key = keyConverter.fromString(attribute); } } if (valueAsAttribute && valueConverter != null){ String attribute = reader.getAttribute(valueName); if (attribute != null){ value = valueConverter.fromString(attribute); } } } if (keyConverter == null){ reader.moveDown(); if (valueConverter == null && !keyName.equals(valueName) && reader.getNodeName().equals(valueName)){ value = readItem(valueType, reader, context, map); }else{ key = readItem(keyType, reader, context, map); } reader.moveUp(); } if (valueConverter == null){ reader.moveDown(); if (keyConverter == null && key == null && value != null){ key = readItem(keyType, reader, context, map); }else{ value = readItem(valueType, reader, context, map); } reader.moveUp(); }else if (!valueAsAttribute){ value = valueConverter.fromString(reader.getValue()); } target.put(key, value); if (entryName != null){ reader.moveUp(); } } } private SingleValueConverter getSingleValueConverter(Class type,String part){ SingleValueConverter conv = UseAttributeForEnumMapper.isEnum(type) ? enumMapper.getConverterFromItemType(null, type, null) : mapper().getConverterFromItemType(null, type, null); if (conv == null){ Converter converter = lookup.lookupConverterForType(type); if (converter instanceof SingleValueConverter){ conv = (SingleValueConverter) converter; }else{ throw new ConversionException("No SingleValueConverter for " + part + " available"); } } return conv; } protected void writeItem(String name,Class type,Object item,MarshallingContext context,HierarchicalStreamWriter writer){ Class itemType = item == null ? Mapper.Null.class : item.getClass(); ExtendedHierarchicalStreamWriterHelper.startNode(writer, name, itemType); if (!itemType.equals(type)){ String attributeName = mapper().aliasForSystemAttribute("class"); if (attributeName != null){ writer.addAttribute(attributeName, mapper().serializedClass(itemType)); } } if (item != null){ context.convertAnother(item); } writer.endNode(); } protected Object readItem(Class type,HierarchicalStreamReader reader,UnmarshallingContext context,Object current){ String className = HierarchicalStreams.readClassAttribute(reader, mapper()); Class itemType = className == null ? type : mapper().realClass(className); if (Mapper.Null.class.equals(itemType)){ return null; }else{ return context.convertAnother(current, itemType); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy