we cache binding/accessors in soft reference cache map, so, SmartSerializer must not hold references to Binding

This commit is contained in:
Vladimir Krivosheev
2014-11-08 10:06:58 +01:00
parent 63f4ceb77e
commit 59877c647c
3 changed files with 28 additions and 21 deletions
@@ -26,7 +26,7 @@ import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.xmlb.annotations.*;
import gnu.trove.TObjectDoubleHashMap;
import gnu.trove.TObjectFloatHashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -85,12 +85,7 @@ class BeanBinding extends Binding {
@Nullable
public Element serializeInto(@NotNull Object o, @Nullable Element element, @NotNull SerializationFilter filter) {
return serializeInto(o, element, filter, myBindings);
}
@Nullable
public Element serializeInto(@NotNull Object o, @Nullable Element element, @NotNull SerializationFilter filter, @Nullable Binding[] bindings) {
for (Binding binding : bindings == null ? myBindings : bindings) {
for (Binding binding : myBindings) {
Accessor accessor = binding.getAccessor();
if (!filter.accepts(accessor, o)) {
continue;
@@ -128,10 +123,10 @@ class BeanBinding extends Binding {
}
@NotNull
public Binding[] computeOrderedBindings(@NotNull LinkedHashSet<String> accessorNameTracker) {
final TObjectDoubleHashMap<String> weights = new TObjectDoubleHashMap<String>(accessorNameTracker.size());
double weight = 0;
double step = (double)myBindings.length / (double)accessorNameTracker.size();
public TObjectFloatHashMap<String> computeBindingWeights(@NotNull LinkedHashSet<String> accessorNameTracker) {
TObjectFloatHashMap<String> weights = new TObjectFloatHashMap<String>(accessorNameTracker.size());
float weight = 0;
float step = (float)myBindings.length / (float)accessorNameTracker.size();
for (String name : accessorNameTracker) {
weights.put(name, weight);
weight += step;
@@ -146,19 +141,20 @@ class BeanBinding extends Binding {
weight++;
}
return weights;
}
Binding[] result = Arrays.copyOf(myBindings, myBindings.length);
Arrays.sort(result, new Comparator<Binding>() {
public void sortBindings(@NotNull final TObjectFloatHashMap<String> weights) {
Arrays.sort(myBindings, new Comparator<Binding>() {
@Override
public int compare(@NotNull Binding o1, @NotNull Binding o2) {
String n1 = o1.getAccessor().getName();
String n2 = o2.getAccessor().getName();
double w1 = weights.get(n1);
double w2 = weights.get(n2);
float w1 = weights.get(n1);
float w2 = weights.get(n2);
return (int)(w1 - w2);
}
});
return result;
}
public void deserializeInto(@NotNull Object result, @NotNull Element element, @Nullable Set<String> accessorNameTracker) {
@@ -16,6 +16,7 @@
package com.intellij.util.xmlb;
import com.intellij.util.ThreeState;
import gnu.trove.TObjectFloatHashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -24,7 +25,7 @@ import java.util.LinkedHashSet;
public final class SmartSerializer {
private final LinkedHashSet<String> mySerializedAccessorNameTracker;
private Binding[] myOrderedBindings;
private TObjectFloatHashMap<String> myOrderedBindings;
private final SerializationFilter mySerializationFilter;
public SmartSerializer(boolean trackSerializedNames, boolean useSkipEmptySerializationFilter) {
@@ -58,15 +59,24 @@ public final class SmartSerializer {
myOrderedBindings = null;
}
BeanBinding beanBinding = (BeanBinding)XmlSerializerImpl.getBinding(bean.getClass());
BeanBinding beanBinding = getBinding(bean);
beanBinding.deserializeInto(bean, element, mySerializedAccessorNameTracker);
if (mySerializedAccessorNameTracker != null) {
myOrderedBindings = beanBinding.computeOrderedBindings(mySerializedAccessorNameTracker);
myOrderedBindings = beanBinding.computeBindingWeights(mySerializedAccessorNameTracker);
}
}
public void writeExternal(@NotNull Object bean, @NotNull Element element) {
((BeanBinding)XmlSerializerImpl.getBinding(bean.getClass())).serializeInto(bean, element, mySerializationFilter, myOrderedBindings);
BeanBinding binding = getBinding(bean);
if (myOrderedBindings != null) {
binding.sortBindings(myOrderedBindings);
}
binding.serializeInto(bean, element, mySerializationFilter);
}
@NotNull
private static BeanBinding getBinding(@NotNull Object bean) {
return (BeanBinding)XmlSerializerImpl.getBinding(bean.getClass());
}
}
@@ -1236,12 +1236,13 @@ public class XmlSerializerTest extends TestCase {
Bean2 bean = new Bean2();
bean.module = "module";
bean.ab = "ab";
doSerializerTest("<Bean2 ab=\"ab\" module=\"module\" />", bean);
doSerializerTest("<Bean2 ab=\"ab\" module=\"module\" />", bean, new SkipDefaultValuesSerializationFilters());
checkSmartSerialization(new Bean2(), "<Bean2 module=\"1\" ab=\"2\" ac=\"32\" />");
checkSmartSerialization(new Bean2(), "<Bean2 ab=\"2\" module=\"1\" ac=\"32\" />");
checkSmartSerialization(new Bean2(), "<Bean2 ac=\"2\" module=\"1\" ab=\"32\" />");
checkSmartSerialization(new Bean2(), "<Bean2 ac=\"2\" ab=\"32\" />");
checkSmartSerialization(new Bean2(), "<Bean2 ac=\"2\" ab=\"32\" module=\"\" />");
}
private static void checkSmartSerialization(@NotNull Bean2 bean, @NotNull String serialized) throws IOException, JDOMException {