Title: [2134] trunk: Optimized XML structure for java.awt.Font.

Diff

Modified: trunk/xstream/src/java/com/thoughtworks/xstream/XStream.java (2133 => 2134)


--- trunk/xstream/src/java/com/thoughtworks/xstream/XStream.java	2013-09-26 18:07:27 UTC (rev 2133)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/XStream.java	2013-09-26 19:13:29 UTC (rev 2134)
@@ -794,7 +794,7 @@
         registerConverter(new JavaMethodConverter(classLoaderReference), PRIORITY_NORMAL);
         registerConverter(new JavaFieldConverter(classLoaderReference), PRIORITY_NORMAL);
         if (JVM.isAWTAvailable()) {
-            registerConverter(new FontConverter(), PRIORITY_NORMAL);
+            registerConverter(new FontConverter(mapper), PRIORITY_NORMAL);
             registerConverter(new ColorConverter(), PRIORITY_NORMAL);
             registerConverter(new TextAttributeConverter(), PRIORITY_NORMAL);
         }

Modified: trunk/xstream/src/java/com/thoughtworks/xstream/converters/extended/FontConverter.java (2133 => 2134)


--- trunk/xstream/src/java/com/thoughtworks/xstream/converters/extended/FontConverter.java	2013-09-26 18:07:27 UTC (rev 2133)
+++ trunk/xstream/src/java/com/thoughtworks/xstream/converters/extended/FontConverter.java	2013-09-26 19:13:29 UTC (rev 2134)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2004, 2005 Joe Walnes.
- * Copyright (C) 2006, 2007 XStream Committers.
+ * Copyright (C) 2006, 2007, 2013 XStream Committers.
  * All rights reserved.
  *
  * The software in this package is published under the terms of the BSD
@@ -13,35 +13,105 @@
 
 import com.thoughtworks.xstream.converters.Converter;
 import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.SingleValueConverter;
 import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.io.ExtendedHierarchicalStreamWriterHelper;
 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+import com.thoughtworks.xstream.mapper.Mapper;
 
 import javax.swing.plaf.FontUIResource;
 
 import java.awt.Font;
+import java.awt.font.TextAttribute;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
 
 public class FontConverter implements Converter {
 
+    private final SingleValueConverter textAttributeConverter;
+    private final Mapper mapper;
+
+    /**
+     * Constructs a FontConverter.
+     * @deprecated As of upcoming
+     */
+    public FontConverter() {
+        this(null);
+    }
+
+    /**
+     * Constructs a FontConverter.
+     * @param mapper
+     * @since upcoming
+     */
+    public FontConverter(Mapper mapper) {
+        this.mapper = mapper;
+        if (mapper == null) {
+            textAttributeConverter = null;
+        } else {
+            textAttributeConverter = new TextAttributeConverter();
+        }
+    }
+    
     public boolean canConvert(Class type) {
         // String comparison is used here because Font.class loads the class which in turns instantiates AWT,
         // which is nasty if you don't want it.
         return type.getName().equals("java.awt.Font") || type.getName().equals("javax.swing.plaf.FontUIResource");
     }
 
-    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
-        Font font = (Font) source;
+    public void marshal(Object source, HierarchicalStreamWriter writer,
+        MarshallingContext context) {
+        Font font = (Font)source;
         Map attributes = font.getAttributes();
-        writer.startNode("attributes"); // <attributes>
-        context.convertAnother(attributes);
-        writer.endNode(); // </attributes>
+        if (mapper != null) {
+            String classAlias = mapper.aliasForSystemAttribute("class");
+            for (Iterator iter = attributes.entrySet().iterator(); iter.hasNext();) {
+                Map.Entry entry = (Map.Entry)iter.next();
+                String name = textAttributeConverter.toString(entry.getKey());
+                Object value = entry.getValue();
+                Class type = value != null ? value.getClass() : Mapper.Null.class;
+                ExtendedHierarchicalStreamWriterHelper.startNode(writer, name, type);
+                writer.addAttribute(classAlias, mapper.serializedClass(type));
+                if (value != null) {
+                    context.convertAnother(value);
+                }
+                writer.endNode();
+            }
+        } else {
+            writer.startNode("attributes"); // <attributes>
+            context.convertAnother(attributes);
+            writer.endNode(); // </attributes>
+        }
     }
 
     public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
-        reader.moveDown(); // into <attributes>
-        Map attributes = (Map) context.convertAnother(null, Map.class);
-        reader.moveUp(); // out of </attributes>
+        final Map attributes;
+        if (reader.hasMoreChildren()) {
+            reader.moveDown();
+            if (!reader.getNodeName().equals("attributes")) {
+                String classAlias = mapper.aliasForSystemAttribute("class");
+                attributes = new HashMap();
+                do {
+                    if (!attributes.isEmpty()) {
+                        reader.moveDown();
+                    }
+                    Class type = mapper.realClass(reader.getAttribute(classAlias));
+                    TextAttribute attribute = (TextAttribute)textAttributeConverter.fromString(reader.getNodeName());
+                    Object value = type == Mapper.Null.class ? null : context.convertAnother(null, type);
+                    attributes.put(attribute, value);
+                    reader.moveUp();
+                } while(reader.hasMoreChildren());
+            } else {
+                // in <attributes>
+                attributes = (Map)context.convertAnother(null, Map.class);
+                reader.moveUp(); // out of </attributes>
+            }
+        } else {
+            attributes = Collections.EMPTY_MAP;
+        }
         Font font = Font.getFont(attributes);
         if (context.getRequiredType() == FontUIResource.class) {
             return new FontUIResource(font);

Modified: trunk/xstream/src/test/com/thoughtworks/xstream/converters/extended/FontConverterTest.java (2133 => 2134)


--- trunk/xstream/src/test/com/thoughtworks/xstream/converters/extended/FontConverterTest.java	2013-09-26 18:07:27 UTC (rev 2133)
+++ trunk/xstream/src/test/com/thoughtworks/xstream/converters/extended/FontConverterTest.java	2013-09-26 19:13:29 UTC (rev 2134)
@@ -69,6 +69,70 @@
 
         assertEquals(inAttributes, outAttributes);
     }
+    
+    public void testUnmarshalsCurrentFormat() {
+        // XML representation since 1.4.5
+        String xml= (""
+                + "<awt-font>\n"
+                + "  <posture class='null'/>\n"
+                + "  <weight class='float'>2.0</weight>\n"
+                + "  <superscript class='null'/>\n"
+                + "  <transform class='null'/>\n"
+                + "  <size class='float'>20.0</size>\n"
+                + "  <width class='null'/>\n"
+                + "  <family class='string'>Arial</family>\n"
+                + "  <tracking class='null'/>\n"
+                + "</awt-font>").replace('\'', '"');
+        Font out = (Font) xstream.fromXML(xml);
+        
+        // assert
+        assertEquals(in, out);
+    }
+    
+    public void testUnmarshalsOldFormat() {
+        // XML representation pre 1.4.5
+        String xml = ""
+            + "<awt-font>\n"
+            + "  <attributes>\n"
+            + "    <entry>\n"
+            + "      <awt-text-attribute>posture</awt-text-attribute>\n"
+            + "      <null/>\n"
+            + "    </entry>\n"
+            + "    <entry>\n"
+            + "      <awt-text-attribute>weight</awt-text-attribute>\n"
+            + "      <float>2.0</float>\n"
+            + "    </entry>\n"
+            + "    <entry>\n"
+            + "      <awt-text-attribute>superscript</awt-text-attribute>\n"
+            + "      <null/>\n"
+            + "    </entry>\n"
+            + "    <entry>\n"
+            + "      <awt-text-attribute>transform</awt-text-attribute>\n"
+            + "      <null/>\n"
+            + "    </entry>\n"
+            + "    <entry>\n"
+            + "      <awt-text-attribute>size</awt-text-attribute>\n"
+            + "      <float>20.0</float>\n"
+            + "    </entry>\n"
+            + "    <entry>\n"
+            + "      <awt-text-attribute>width</awt-text-attribute>\n"
+            + "      <null/>\n"
+            + "    </entry>\n"
+            + "    <entry>\n"
+            + "      <awt-text-attribute>family</awt-text-attribute>\n"
+            + "      <string>Arial</string>\n"
+            + "    </entry>\n"
+            + "    <entry>\n"
+            + "      <awt-text-attribute>tracking</awt-text-attribute>\n"
+            + "      <null/>\n"
+            + "    </entry>\n"
+            + "  </attributes>\n"
+            + "</awt-font>";
+        Font out = (Font) xstream.fromXML(xml);
+        
+        // assert
+        assertEquals(in, out);
+    }
 
     public void testCorrectlyInitializesFontToPreventJvmCrash() {
         // If a font has not been constructed in the correct way, the JVM crashes horribly through some internal
@@ -79,6 +143,5 @@
 
         Toolkit.getDefaultToolkit().getFontMetrics(out);
         // if the JVM hasn't crashed yet, we're good.
-
     }
 }

Modified: trunk/xstream-distribution/src/content/changes.html (2133 => 2134)


--- trunk/xstream-distribution/src/content/changes.html	2013-09-26 18:07:27 UTC (rev 2133)
+++ trunk/xstream-distribution/src/content/changes.html	2013-09-26 19:13:29 UTC (rev 2134)
@@ -58,7 +58,8 @@
     	inner elements.</li>
     	<li>JIRA:XSTR-726: New annotation XStreamAliasType to support declarative definition of XStream.aliasType().</li>
     	<li>JIRA:XSTR-735: Support for JDOM2 with JDom2Driver, JDom2Reader and JDom2Writer.</li>
-    	<li>Fix: ToAttributedValueConverter silently appends fields without attribute support to the value.</li>
+    	<li>Optimized XML structure for java.awt.Font.</li>
+    	<li>Fix: ToAttributedValueConverter silently appends fields without attribute support to the value producing mixed-mode XML.</li>
     	<li>JIRA:XSTR-566 and JIRA:XSTR-249: Better compatibility with Google AppEngine and J2ME, setup no longer fails for unavailable converters.</li>
     </ul>
 
@@ -96,26 +97,26 @@
     <h2>API changes</h2>
 
     <ul>
-    	<li>Added c.t.x.converter.extended.NamedCollectionConverter for free element names in collections.</li>
-    	<li>Added c.t.x.converter.extended.NamedMapConverter for free element names in maps.</li>
+    	<li>Added c.t.x.convertesr.extended.NamedCollectionConverter for free element names in collections.</li>
+    	<li>Added c.t.x.converters.extended.NamedMapConverter for free element names in maps.</li>
     	<li>Added c.t.x.io.xml.StandardStaxDriver to use the StAX implementation delivered with the Java 6 runtime.</li>
     	<li>Deprecated c.t.x.io.xml.SjsxpStaxDriver to select the internal StAX implementation of Oracle.</li>
     	<li>Added static methods getStaxInputFactory and getStaxOutputFactory to 	c.t.x.core.JVM as returning the
     	implementations of javax.xml.stream.XMLInputFactory (resp. javax.xml.stream.XMLOutputFactory) delivered with
     	the Java Runtime since Java 6.</li>
     	<li>Added c.t.x.core.ClassLoaderReference.</li>
-    	<li>Added constructors taking an additional type argument for c.t.x.converter.collections.CollectionConverter
-    	and c.t.x.converter.collections.MapConverter.</li>
+    	<li>Added constructors taking an additional Class argument for c.t.x.converters.collections.CollectionConverter
+    	and c.t.x.converters.collections.MapConverter.</li>
     	<li>Added constructors taking a ClassLoaderReference instead of a ClassLoader and deprecated the ones taking the ClassLoader:
     		<ul>
     		<li>c.t.x.XStream</li>
-    		<li>c.t.x.converter.extended.DynamicProxyConverter</li>
-    		<li>c.t.x.converter.extended.JavaClassConverter</li>
-    		<li>c.t.x.converter.extended.JavaFieldConverter</li>
-    		<li>c.t.x.converter.extended.JavaMethodConverter</li>
-    		<li>c.t.x.converter.reflection.CGLIBEnhancedConverter</li>
-    		<li>c.t.x.converter.reflection.ExternalizableConverter</li>
-    		<li>c.t.x.converter.reflection.SerializableConverter</li>
+    		<li>c.t.x.converters.extended.DynamicProxyConverter</li>
+    		<li>c.t.x.converters.extended.JavaClassConverter</li>
+    		<li>c.t.x.converters.extended.JavaFieldConverter</li>
+    		<li>c.t.x.converters.extended.JavaMethodConverter</li>
+    		<li>c.t.x.converters.reflection.CGLIBEnhancedConverter</li>
+    		<li>c.t.x.converters.reflection.ExternalizableConverter</li>
+    		<li>c.t.x.converters.reflection.SerializableConverter</li>
     		<li>c.t.x.mapper.AnnotationMapper</li>
     		<li>c.t.x.mapper.DefaultMapper</li>
     		</ul>
@@ -132,6 +133,8 @@
     	String).</li>
     	<li>Deprecated constructor c.t.x.converters.extended.RegexPatternConverter(Converter)
     	in favor of c.t.x.converters.extended.RegexPatternConverter().</li>
+    	<li>Deprecated default constructor of c.t.x.converters.extended.FontConverter in favor of
+    	c.t.x.converters.extended.FontConverter(Mapper).</li>
     	<li>Deprecated constructor c.t.x.converters.extended.ThrowableConverter(Converter)
     	in favor of c.t.x.converters.extended.ThrowableConverter(ConverterLookup).</li>
     	<li>Deprecated class c.t.x.converters.reflection.SelfStreamingInstanceChecker and moved

Modified: trunk/xstream-distribution/src/content/converters.html (2133 => 2134)


--- trunk/xstream-distribution/src/content/converters.html	2013-09-26 18:07:27 UTC (rev 2133)
+++ trunk/xstream-distribution/src/content/converters.html	2013-09-26 19:13:29 UTC (rev 2134)
@@ -692,7 +692,16 @@
                 <td><a href=""
                 <td>java.awt.Font<br/>
                 javax.swing.plaf.FontUIResource</td>
-                <td class="example">&lt;font&gt;Arial&lt;/font&gt;</td>
+                <td class="example">
+                    &lt;awt-font&gt;<br/>
+                    &nbsp;&nbsp;&lt;family class=&quot;string&quot;&gt;Arial&lt;/family&gt;<br/>
+                    &nbsp;&nbsp;&lt;size class=&quot;float&quot;&gt;20.0&lt;/size&gt;<br/>
+                    &nbsp;&nbsp;&lt;width class=&quot;null&quot;/&gt;<br/>
+                    &nbsp;&nbsp;&lt;posture class=&quot;null&quot;/&gt;<br/>
+                    &nbsp;&nbsp;&lt;weight class=&quot;float&quot;&gt;2.0&lt;/weight&gt;<br/>
+                    &nbsp;&nbsp;&lt;superscript class=&quot;null&quot;/&gt;<br/>
+                    &lt;/awt-font&gt;
+                </td>
                 <td>Only automatically registered if runtime has AWT support.<br/>
                 <b>Warning:</b> The AWT toolkit is definitely initialized when a Font is deserialized.</td>
                 <td>normal</td>

To unsubscribe from this list please visit:

http://xircles.codehaus.org/manage_email

Reply via email to