From 0443b40293719e104f716b523810e8fd030edb3f Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Thu, 6 Nov 2014 17:10:06 +0100 Subject: [PATCH] =?UTF-8?q?AppletConfiguration=20=E2=80=94=20don't=20save?= =?UTF-8?q?=20defaults=20=E2=80=94=20get=20rid=20of=20"module"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../execution/applet/AppletConfiguration.java | 22 +++-- .../util/SimpleModificationTracker.java | 4 +- .../ModuleBasedConfiguration.java | 4 + .../RunConfigurationModule.java | 8 ++ .../src/com/intellij/util/xmlb/Accessor.java | 2 + .../util/xmlb/AccessorBindingWrapper.java | 12 ++- .../com/intellij/util/xmlb/BeanBinding.java | 89 ++++++++++++++----- .../com/intellij/util/xmlb/FieldAccessor.java | 6 ++ .../util/xmlb/PrimitiveValueBinding.java | 6 +- .../intellij/util/xmlb/PropertyAccessor.java | 5 ++ .../xmlb/SkipEmptySerializationFilter.java | 4 +- .../intellij/util/xmlb/SmartSerializer.java | 19 ++-- .../com/intellij/util/xmlb/TagBinding.java | 37 +++++--- .../intellij/util/xmlb/XmlSerializerImpl.java | 14 ++- .../intellij/util/xmlb/XmlSerializerTest.java | 34 +++++++ 15 files changed, 207 insertions(+), 59 deletions(-) diff --git a/java/execution/impl/src/com/intellij/execution/applet/AppletConfiguration.java b/java/execution/impl/src/com/intellij/execution/applet/AppletConfiguration.java index 9d00cad60172..f69ad997c8dc 100644 --- a/java/execution/impl/src/com/intellij/execution/applet/AppletConfiguration.java +++ b/java/execution/impl/src/com/intellij/execution/applet/AppletConfiguration.java @@ -35,6 +35,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; import com.intellij.refactoring.listeners.RefactoringElementListener; +import com.intellij.util.SmartList; import com.intellij.util.xmlb.SmartSerializer; import com.intellij.util.xmlb.annotations.Transient; import org.jdom.Element; @@ -46,7 +47,6 @@ import java.io.FileWriter; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; -import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -74,7 +74,7 @@ public class AppletConfiguration extends ModuleBasedConfiguration parameters = new ArrayList(); - for (final Element element : parentNode.getChildren(PARAMETER_ELEMENT_NAME)) { - parameters.add(new AppletParameter(element.getAttributeValue(NAME_ATTR), element.getAttributeValue(VALUE_ATTR))); + + List paramList = parentNode.getChildren(PARAMETER_ELEMENT_NAME); + if (paramList.isEmpty()) { + myAppletParameters = null; + } + else { + List parameters = new SmartList(); + for (Element element : paramList) { + parameters.add(new AppletParameter(element.getAttributeValue(NAME_ATTR), element.getAttributeValue(VALUE_ATTR))); + } + myAppletParameters = parameters.toArray(new AppletParameter[parameters.size()]); } - myAppletParameters = parameters.toArray(new AppletParameter[parameters.size()]); } @Override @@ -208,7 +214,6 @@ public class AppletConfiguration extends ModuleBasedConfiguration extends LocatableConfigurationBase implements Cloneable, ModuleRunConfiguration { private static final Logger LOG = Logger.getInstance("#com.intellij.execution.configurations.ModuleBasedConfiguration"); + + @Property(surroundWithTag = false) private final ConfigurationModule myModule; + @NonNls protected static final String TO_CLONE_ELEMENT_NAME = "toClone"; diff --git a/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationModule.java b/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationModule.java index 189696892b66..21292428f11d 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationModule.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationModule.java @@ -26,6 +26,9 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.JDOMExternalizable; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.xmlb.annotations.Attribute; +import com.intellij.util.xmlb.annotations.Tag; +import com.intellij.util.xmlb.annotations.Transient; import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -33,6 +36,7 @@ import org.jetbrains.annotations.Nullable; import java.util.List; +@Tag("module") public class RunConfigurationModule implements JDOMExternalizable { private static final Logger LOG = Logger.getInstance(RunConfigurationModule.class); @@ -40,7 +44,10 @@ public class RunConfigurationModule implements JDOMExternalizable { @NonNls private static final String ATTRIBUTE = "name"; private Module myModule = null; + + @Attribute("name") private String myModuleName; + private final Project myProject; public RunConfigurationModule(@NotNull Project project) { @@ -81,6 +88,7 @@ public class RunConfigurationModule implements JDOMExternalizable { } @Nullable + @Transient public Module getModule() { if (myModuleName != null) { //caching myModule = findModule(myModuleName); diff --git a/platform/util/src/com/intellij/util/xmlb/Accessor.java b/platform/util/src/com/intellij/util/xmlb/Accessor.java index 02c007ffb85a..7e364b9b6105 100644 --- a/platform/util/src/com/intellij/util/xmlb/Accessor.java +++ b/platform/util/src/com/intellij/util/xmlb/Accessor.java @@ -39,4 +39,6 @@ public interface Accessor { Class getValueClass(); Type getGenericType(); + + boolean isFinal(); } diff --git a/platform/util/src/com/intellij/util/xmlb/AccessorBindingWrapper.java b/platform/util/src/com/intellij/util/xmlb/AccessorBindingWrapper.java index e071b6b915ec..c5be1e8f7e31 100644 --- a/platform/util/src/com/intellij/util/xmlb/AccessorBindingWrapper.java +++ b/platform/util/src/com/intellij/util/xmlb/AccessorBindingWrapper.java @@ -15,6 +15,7 @@ */ package com.intellij.util.xmlb; +import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,9 +42,14 @@ class AccessorBindingWrapper implements Binding { @Nullable public Object deserialize(Object context, @NotNull Object... nodes) { Object currentValue = myAccessor.read(context); - Object deserializedValue = myBinding.deserialize(currentValue, nodes); - if (currentValue != deserializedValue) { - myAccessor.write(context, deserializedValue); + if (myBinding instanceof BeanBinding && myAccessor.isFinal()) { + ((BeanBinding)myBinding).deserializeInto(currentValue, (Element)nodes[0], null); + } + else { + Object deserializedValue = myBinding.deserialize(currentValue, nodes); + if (currentValue != deserializedValue) { + myAccessor.write(context, deserializedValue); + } } return context; } diff --git a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java index c9078e63b009..7f7022e48c0e 100644 --- a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java @@ -28,6 +28,7 @@ import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.hash.LinkedHashMap; import com.intellij.util.xmlb.annotations.*; +import gnu.trove.TObjectDoubleHashMap; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,9 +38,8 @@ import java.beans.Introspector; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.*; import java.util.List; -import java.util.Map; -import java.util.Set; class BeanBinding implements Binding { private static final Logger LOG = Logger.getInstance(BeanBinding.class); @@ -81,23 +81,26 @@ class BeanBinding implements Binding { @Nullable public Element serializeInto(@NotNull Object o, @Nullable Element element, @NotNull SerializationFilter filter) { - for (Binding binding : myPropertyBindings.keySet()) { + return serializeInto(o, element, filter, myPropertyBindings.keySet()); + } + + @Nullable + Element serializeInto(@NotNull Object o, @Nullable Element element, @NotNull SerializationFilter filter, @Nullable Collection bindings) { + for (Binding binding : (bindings == null ? myPropertyBindings.keySet() : bindings)) { Accessor accessor = myPropertyBindings.get(binding); + if (accessor == null) { + LOG.warn("Illegal state: accessor null, " + binding.toString()); + continue; + } if (!filter.accepts(accessor, o)) { continue; } //todo: optimize. Cache it. Property property = accessor.getAnnotation(Property.class); - if (property != null && property.filter() != SerializationFilter.class) { - try { - if (!ReflectionUtil.newInstance(property.filter()).accepts(accessor, o)) { - continue; - } - } - catch (RuntimeException e) { - throw new XmlSerializationException(e); - } + if (property != null && property.filter() != SerializationFilter.class && + !ReflectionUtil.newInstance(property.filter()).accepts(accessor, o)) { + continue; } if (element == null) { @@ -130,14 +133,48 @@ class BeanBinding implements Binding { if (element == null) { return o; } - Object instance = XmlSerializerImpl.newInstance(myBeanClass); + Object instance = ReflectionUtil.newInstance(myBeanClass); deserializeInto(instance, element, null); return instance; } + @NotNull + List computeOrderedBindings(@NotNull LinkedHashSet accessorNameTracker) { + final TObjectDoubleHashMap weights = new TObjectDoubleHashMap(accessorNameTracker.size()); + double weight = 0; + double step = (double)myPropertyBindings.size() / (double)accessorNameTracker.size(); + for (String name : accessorNameTracker) { + weights.put(name, weight); + weight += step; + } + + weight = 0; + for (Accessor accessor : myPropertyBindings.values()) { + String name = accessor.getName(); + if (!weights.containsKey(name)) { + weights.put(name, weight); + } + + weight++; + } + + Binding[] result = myPropertyBindings.keySet().toArray(new Binding[myPropertyBindings.size()]); + Arrays.sort(result, new Comparator() { + @Override + public int compare(@NotNull Binding o1, @NotNull Binding o2) { + String n1 = myPropertyBindings.get(o1).getName(); + String n2 = myPropertyBindings.get(o2).getName(); + double w1 = weights.get(n1); + double w2 = weights.get(n2); + return (int)(w1 - w2); + } + }); + return Arrays.asList(result); + } + public void deserializeInto(@NotNull Object result, @NotNull Element element, @Nullable Set accessorNameTracker) { Set bindings = myPropertyBindings.keySet(); - MultiMap data = MultiMap.createSmartList(); + MultiMap data = MultiMap.createLinked(); nextNode: for (Object child : ContainerUtil.concat(element.getContent(), element.getAttributes())) { if (XmlSerializerImpl.isIgnoredNode(child)) { @@ -244,15 +281,25 @@ class BeanBinding implements Binding { } } - private static void collectFieldAccessors(Class aClass, List accessors) { - for (Field field : aClass.getFields()) { - final int modifiers = field.getModifiers(); - if (Modifier.isPublic(modifiers) && !Modifier.isStatic(modifiers) && - !Modifier.isFinal(modifiers) && !Modifier.isTransient(modifiers) && - field.getAnnotation(Transient.class) == null) { - accessors.add(new FieldAccessor(field)); + private static void collectFieldAccessors(@NotNull Class aClass, @NotNull List accessors) { + Class currentClass = aClass; + do { + for (Field field : currentClass.getDeclaredFields()) { + int modifiers = field.getModifiers(); + if (!Modifier.isStatic(modifiers) && + (field.getAnnotation(OptionTag.class) != null || + field.getAnnotation(Tag.class) != null || + field.getAnnotation(Attribute.class) != null || + field.getAnnotation(Property.class) != null || + (Modifier.isPublic(modifiers) && + !Modifier.isFinal(modifiers) && + !Modifier.isTransient(modifiers) && + field.getAnnotation(Transient.class) == null))) { + accessors.add(new FieldAccessor(field)); + } } } + while ((currentClass = currentClass.getSuperclass()) != null && currentClass.getAnnotation(Transient.class) == null); } @Nullable diff --git a/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java b/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java index 172b5e364825..c7fd18abad65 100644 --- a/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java +++ b/platform/util/src/com/intellij/util/xmlb/FieldAccessor.java @@ -21,6 +21,7 @@ import org.jetbrains.annotations.NotNull; import java.lang.annotation.Annotation; import java.lang.reflect.Field; +import java.lang.reflect.Modifier; import java.lang.reflect.Type; class FieldAccessor implements Accessor { @@ -81,6 +82,11 @@ class FieldAccessor implements Accessor { return myField.getGenericType(); } + @Override + public boolean isFinal() { + return Modifier.isFinal(myField.getModifiers()); + } + @NonNls public String toString() { return "FieldAccessor[" + myField.getDeclaringClass() + "." + myField.getName() + "]"; diff --git a/platform/util/src/com/intellij/util/xmlb/PrimitiveValueBinding.java b/platform/util/src/com/intellij/util/xmlb/PrimitiveValueBinding.java index 3c303b07b410..84e94ef4c216 100644 --- a/platform/util/src/com/intellij/util/xmlb/PrimitiveValueBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/PrimitiveValueBinding.java @@ -16,6 +16,8 @@ package com.intellij.util.xmlb; import com.intellij.openapi.util.JDOMUtil; +import org.jdom.Attribute; +import org.jdom.Content; import org.jdom.Text; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -44,8 +46,8 @@ class PrimitiveValueBinding implements Binding { value = JDOMUtil.concatTextNodesValues(nodes); } else { - assert nodes[0] != null; - value = JDOMUtil.getValue(nodes[0]); + Object node = nodes[0]; + value = node instanceof Attribute ? ((Attribute)node).getValue() : ((Content)node).getValue(); } return convertString(value); } diff --git a/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java b/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java index 9bef1ab7bf8a..9780e683154d 100644 --- a/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java +++ b/platform/util/src/com/intellij/util/xmlb/PropertyAccessor.java @@ -110,6 +110,11 @@ class PropertyAccessor implements Accessor { return myGenericType; } + @Override + public boolean isFinal() { + return false; + } + @NonNls public String toString() { return "PropertyAccessor[" + myReadMethod.getDeclaringClass().getName() + "." + getName() +"]"; diff --git a/platform/util/src/com/intellij/util/xmlb/SkipEmptySerializationFilter.java b/platform/util/src/com/intellij/util/xmlb/SkipEmptySerializationFilter.java index 4a98cf7a5cb8..aec1ab68e74a 100644 --- a/platform/util/src/com/intellij/util/xmlb/SkipEmptySerializationFilter.java +++ b/platform/util/src/com/intellij/util/xmlb/SkipEmptySerializationFilter.java @@ -36,8 +36,8 @@ public class SkipEmptySerializationFilter extends SerializationFilterBase { if (Boolean.FALSE.equals(beanValue) || (beanValue instanceof String && ((String)beanValue).isEmpty()) || - (beanValue instanceof Map && ((Map)beanValue).isEmpty()) || - (beanValue instanceof Collection && ((Collection)beanValue).isEmpty())) { + beanValue instanceof Collection && ((Collection)beanValue).isEmpty() || + (beanValue instanceof Map && ((Map)beanValue).isEmpty())) { return false; } diff --git a/platform/util/src/com/intellij/util/xmlb/SmartSerializer.java b/platform/util/src/com/intellij/util/xmlb/SmartSerializer.java index dd6a7cb916d3..805934e3c76e 100644 --- a/platform/util/src/com/intellij/util/xmlb/SmartSerializer.java +++ b/platform/util/src/com/intellij/util/xmlb/SmartSerializer.java @@ -16,19 +16,20 @@ package com.intellij.util.xmlb; import com.intellij.util.ThreeState; -import gnu.trove.THashSet; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Set; +import java.util.LinkedHashSet; +import java.util.List; public final class SmartSerializer { - private final Set mySerializedAccessorNameTracker; + private final LinkedHashSet mySerializedAccessorNameTracker; + private List myOrderedBindings; private final SerializationFilter mySerializationFilter; public SmartSerializer(boolean trackSerializedNames, boolean useSkipEmptySerializationFilter) { - mySerializedAccessorNameTracker = trackSerializedNames ? new THashSet() : null; + mySerializedAccessorNameTracker = trackSerializedNames ? new LinkedHashSet() : null; mySerializationFilter = useSkipEmptySerializationFilter ? new SkipEmptySerializationFilter() { @@ -56,10 +57,16 @@ public final class SmartSerializer { if (mySerializedAccessorNameTracker != null) { mySerializedAccessorNameTracker.clear(); } - XmlSerializer.deserializeInto(bean, element, mySerializedAccessorNameTracker); + + BeanBinding beanBinding = (BeanBinding)XmlSerializerImpl.getBinding(bean.getClass()); + beanBinding.deserializeInto(bean, element, mySerializedAccessorNameTracker); + + if (mySerializedAccessorNameTracker != null) { + myOrderedBindings = beanBinding.computeOrderedBindings(mySerializedAccessorNameTracker); + } } public void writeExternal(@NotNull Object bean, @NotNull Element element) { - XmlSerializer.serializeInto(bean, element, mySerializationFilter); + ((BeanBinding)XmlSerializerImpl.getBinding(bean.getClass())).serializeInto(bean, element, mySerializationFilter, myOrderedBindings); } } \ No newline at end of file diff --git a/platform/util/src/com/intellij/util/xmlb/TagBinding.java b/platform/util/src/com/intellij/util/xmlb/TagBinding.java index 78336be646fe..37b013b5333d 100644 --- a/platform/util/src/com/intellij/util/xmlb/TagBinding.java +++ b/platform/util/src/com/intellij/util/xmlb/TagBinding.java @@ -16,6 +16,7 @@ package com.intellij.util.xmlb; import com.intellij.openapi.util.JDOMUtil; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.SmartList; import com.intellij.util.xmlb.annotations.Tag; @@ -25,6 +26,7 @@ import org.jdom.Text; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; import java.util.List; class TagBinding extends BasePrimitiveBinding { @@ -33,7 +35,7 @@ class TagBinding extends BasePrimitiveBinding { public TagBinding(@NotNull Accessor accessor, @NotNull Tag tagAnnotation) { super(accessor, tagAnnotation.value(), null); - myTextIfEmpty = tagAnnotation.textIfEmpty(); + myTextIfEmpty = StringUtil.nullize(tagAnnotation.textIfEmpty()); } @Nullable @@ -57,28 +59,35 @@ class TagBinding extends BasePrimitiveBinding { @Nullable public Object deserialize(Object o, @NotNull Object... nodes) { assert nodes.length > 0; - Object[] children; + List children; + boolean isBeanBinding = myBinding instanceof BeanBinding; if (nodes.length == 1) { - children = JDOMUtil.getContent((Element)nodes[0]); + Element node = (Element)nodes[0]; + children = isBeanBinding ? node.getChildren() : node.getContent(); } else { String name = ((Element)nodes[0]).getName(); - List childrenList = new SmartList(); + children = new SmartList(); for (Object node : nodes) { - assert ((Element)node).getName().equals(name); - childrenList.addAll(((Element)node).getContent()); + Element element = (Element)node; + assert element.getName().equals(name); + //noinspection unchecked + children.addAll(((List)(isBeanBinding ? element.getChildren() : element.getContent()))); } - children = ArrayUtil.toObjectArray(childrenList); - } - - if (children.length == 0) { - children = new Object[] {new Text(myTextIfEmpty)}; } assert myBinding != null; - Object v = myBinding.deserialize(myAccessor.read(o), children); - Object value = XmlSerializerImpl.convert(v, myAccessor.getValueClass()); - myAccessor.write(o, value); + if (isBeanBinding && myAccessor.isFinal()) { + ((BeanBinding)myBinding).deserializeInto(o, (Element)children.get(0), null); + } + else { + if (children.isEmpty() && myTextIfEmpty != null) { + children = Collections.singletonList(new Text(myTextIfEmpty)); + } + + Object v = myBinding.deserialize(myAccessor.read(o), ArrayUtil.toObjectArray(children)); + myAccessor.write(o, XmlSerializerImpl.convert(v, myAccessor.getValueClass())); + } return o; } diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java index ee16d1270500..fafaaaa93442 100644 --- a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java +++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java @@ -26,6 +26,7 @@ import java.lang.annotation.Annotation; import java.lang.ref.SoftReference; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; import java.util.*; import java.util.concurrent.ConcurrentHashMap; @@ -72,7 +73,18 @@ class XmlSerializerImpl { } static Binding getTypeBinding(@NotNull Type type, @Nullable Accessor accessor) { - return _getClassBinding(type instanceof Class ? (Class)type : (Class)((ParameterizedType)type).getRawType(), type, accessor); + Class aClass; + if (type instanceof Class) { + aClass = (Class)type; + } + else if (type instanceof TypeVariable) { + Type bound = ((TypeVariable)type).getBounds()[0]; + aClass = bound instanceof Class ? (Class)bound : (Class)((ParameterizedType)bound).getRawType(); + } + else { + aClass = (Class)((ParameterizedType)type).getRawType(); + } + return _getClassBinding(aClass, type, accessor); } private static synchronized Binding _getClassBinding(@NotNull Class aClass, @NotNull Type originalType, @Nullable Accessor accessor) { diff --git a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java index 0f7217c5241e..a5b8edc491aa 100644 --- a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java +++ b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java @@ -24,9 +24,11 @@ import junit.framework.AssertionFailedError; import junit.framework.TestCase; import org.intellij.lang.annotations.Language; import org.jdom.Element; +import org.jdom.JDOMException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.IOException; import java.util.*; import java.util.concurrent.atomic.AtomicReference; @@ -1219,6 +1221,37 @@ public class XmlSerializerTest extends TestCase { doSerializerTest("", bean); } + static class Bean2 { + @Attribute + public String ab; + + @Attribute + public String module; + + @Attribute + public String ac; + } + + public void testOrdered() throws IOException, JDOMException { + Bean2 bean = new Bean2(); + bean.module = "module"; + bean.ab = "ab"; + doSerializerTest("", bean); + + checkSmartSerialization(new Bean2(), ""); + checkSmartSerialization(new Bean2(), ""); + checkSmartSerialization(new Bean2(), ""); + checkSmartSerialization(new Bean2(), ""); + } + + private static void checkSmartSerialization(@NotNull Bean2 bean, @NotNull String serialized) throws IOException, JDOMException { + SmartSerializer serializer = new SmartSerializer(); + serializer.readExternal(bean, JDOMUtil.loadDocument(serialized).getRootElement()); + Element serializedState = new Element("Bean2"); + serializer.writeExternal(bean, serializedState); + assertEquals(serialized, JDOMUtil.writeElement(serializedState)); + } + //--------------------------------------------------------------------------------------------------- private static Element assertSerializer(Object bean, String expected, SerializationFilter filter) { return assertSerializer(bean, expected, "Serialization failure", filter); @@ -1232,6 +1265,7 @@ public class XmlSerializerTest extends TestCase { Element element = assertSerializer(bean, expectedText, filter); //test deserializer + @SuppressWarnings("unchecked") Class aClass = (Class)bean.getClass(); T o = XmlSerializer.deserialize(element, aClass); assertSerializer(o, expectedText, "Deserialization failure", filter);