mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
AppletConfiguration — don't save defaults — get rid of "module"
This commit is contained in:
@@ -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<JavaRunConfigu
|
||||
public AppletConfiguration(@NotNull Project project, ConfigurationFactory factory) {
|
||||
super(new JavaRunConfigurationModule(project, false), factory);
|
||||
|
||||
mySerializer = new SmartSerializer(project.isDefault(), true);
|
||||
mySerializer = new SmartSerializer(!project.isDefault(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -193,12 +193,18 @@ public class AppletConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
|
||||
@Override
|
||||
public void readExternal(final Element parentNode) throws InvalidDataException {
|
||||
mySerializer.readExternal(this, parentNode);
|
||||
readModule(parentNode);
|
||||
final ArrayList<AppletParameter> parameters = new ArrayList<AppletParameter>();
|
||||
for (final Element element : parentNode.getChildren(PARAMETER_ELEMENT_NAME)) {
|
||||
parameters.add(new AppletParameter(element.getAttributeValue(NAME_ATTR), element.getAttributeValue(VALUE_ATTR)));
|
||||
|
||||
List<Element> paramList = parentNode.getChildren(PARAMETER_ELEMENT_NAME);
|
||||
if (paramList.isEmpty()) {
|
||||
myAppletParameters = null;
|
||||
}
|
||||
else {
|
||||
List<AppletParameter> parameters = new SmartList<AppletParameter>();
|
||||
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<JavaRunConfigu
|
||||
|
||||
@Override
|
||||
public void writeExternal(final Element parentNode) throws WriteExternalException {
|
||||
writeModule(parentNode);
|
||||
mySerializer.writeExternal(this, parentNode);
|
||||
if (myAppletParameters != null) {
|
||||
for (AppletParameter myAppletParameter : myAppletParameters) {
|
||||
@@ -227,6 +232,7 @@ public class AppletConfiguration extends ModuleBasedConfiguration<JavaRunConfigu
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transient
|
||||
public PsiClass getMainClass() {
|
||||
return getConfigurationModule().findClass(MAIN_CLASS_NAME);
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@ import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
|
||||
/**
|
||||
* Created by Max Medvedev on 28/03/14
|
||||
*/
|
||||
@Transient
|
||||
public class SimpleModificationTracker implements ModificationTracker {
|
||||
static {
|
||||
// field made public to workaround bug in JDK7 when AtomicIntegerFieldUpdater can't be created for private field, even from within its own class
|
||||
// fixed in JDK8
|
||||
assert Patches.JDK_BUG_ID_7103570;
|
||||
}
|
||||
|
||||
@Transient
|
||||
|
||||
public volatile int myCounter;
|
||||
|
||||
@Override
|
||||
|
||||
+4
@@ -24,6 +24,7 @@ import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.util.xmlb.annotations.Property;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -39,7 +40,10 @@ import java.util.Set;
|
||||
*/
|
||||
public abstract class ModuleBasedConfiguration<ConfigurationModule extends RunConfigurationModule> 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";
|
||||
|
||||
|
||||
+8
@@ -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);
|
||||
|
||||
@@ -39,4 +39,6 @@ public interface Accessor {
|
||||
Class<?> getValueClass();
|
||||
|
||||
Type getGenericType();
|
||||
|
||||
boolean isFinal();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<Binding> 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<Binding> computeOrderedBindings(@NotNull LinkedHashSet<String> accessorNameTracker) {
|
||||
final TObjectDoubleHashMap<String> weights = new TObjectDoubleHashMap<String>(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<Binding>() {
|
||||
@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<String> accessorNameTracker) {
|
||||
Set<Binding> bindings = myPropertyBindings.keySet();
|
||||
MultiMap<Binding, Object> data = MultiMap.createSmartList();
|
||||
MultiMap<Binding, Object> 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<Accessor> 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<Accessor> 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
|
||||
|
||||
@@ -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() + "]";
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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() +"]";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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<String> mySerializedAccessorNameTracker;
|
||||
private final LinkedHashSet<String> mySerializedAccessorNameTracker;
|
||||
private List<Binding> myOrderedBindings;
|
||||
private final SerializationFilter mySerializationFilter;
|
||||
|
||||
public SmartSerializer(boolean trackSerializedNames, boolean useSkipEmptySerializationFilter) {
|
||||
mySerializedAccessorNameTracker = trackSerializedNames ? new THashSet<String>() : null;
|
||||
mySerializedAccessorNameTracker = trackSerializedNames ? new LinkedHashSet<String>() : 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);
|
||||
}
|
||||
}
|
||||
@@ -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<? extends Content> 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<Content> childrenList = new SmartList<Content>();
|
||||
children = new SmartList<Content>();
|
||||
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.<Content>singletonList(new Text(myTextIfEmpty));
|
||||
}
|
||||
|
||||
Object v = myBinding.deserialize(myAccessor.read(o), ArrayUtil.toObjectArray(children));
|
||||
myAccessor.write(o, XmlSerializerImpl.convert(v, myAccessor.getValueClass()));
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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("<BeanWithDefaultAttributeName foo=\"foo\" />", 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("<Bean2 ab=\"ab\" module=\"module\" />", bean);
|
||||
|
||||
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\" />");
|
||||
}
|
||||
|
||||
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<T> aClass = (Class<T>)bean.getClass();
|
||||
T o = XmlSerializer.deserialize(element, aClass);
|
||||
assertSerializer(o, expectedText, "Deserialization failure", filter);
|
||||
|
||||
Reference in New Issue
Block a user