mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Persistence state classes doesn't have to implement "equals" anymore
If you don’t implement “equals” in your sub state class, XmlSerializer cannot check it for defaults. TextDiffSettingsHolder.State.SHARED_SETTINGS = new SharedSettings(); The problem — “new SharedSettings()” is not equals to “new SharedSettings()”. As result, user gets <option name="SHARED_SETTINGS"> <SharedSettings /> </option> even if SkipDefaultValuesSerializationFilters is used. While I dream about Kotlin, I can’t fight anymore against Java-developers. XmlSerializer can throw warning in this case, but to simplify developer life, it will compare objects by serializable fields, but not by reference (if equals is not implemented).
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -142,11 +142,11 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
Element state = new Element("state");
|
||||
XmlSerializer.serializeInto(myState, state, new SkipDefaultValuesSerializationFilters() {
|
||||
@Override
|
||||
protected boolean accepts(@NotNull Accessor accessor, @NotNull Object bean, @Nullable Object beanValue) {
|
||||
public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) {
|
||||
if (myState.compilerWasSpecified && "DEFAULT_COMPILER".equals(accessor.getName())) {
|
||||
return true;
|
||||
}
|
||||
return super.accepts(accessor, bean, beanValue);
|
||||
return super.accepts(accessor, bean);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -184,7 +184,7 @@ public class UISettings extends SimpleModificationTracker implements PersistentS
|
||||
|
||||
public static class FontFilter implements SerializationFilter {
|
||||
@Override
|
||||
public boolean accepts(@NotNull Accessor accessor, Object bean) {
|
||||
public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) {
|
||||
UISettings settings = (UISettings)bean;
|
||||
return !hasDefaultFontSetting(settings);
|
||||
}
|
||||
|
||||
+2
-2
@@ -49,9 +49,9 @@ class PersistableCodeStyleSchemes extends CodeStyleSchemesImpl implements Persis
|
||||
public Element getState() {
|
||||
return XmlSerializer.serialize(this, new SerializationFilter() {
|
||||
@Override
|
||||
public boolean accepts(@NotNull Accessor accessor, Object bean) {
|
||||
public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) {
|
||||
if ("CURRENT_SCHEME_NAME".equals(accessor.getName())) {
|
||||
return bean != null && !DEFAULT_SCHEME_NAME.equals(accessor.read(bean));
|
||||
return !DEFAULT_SCHEME_NAME.equals(accessor.read(bean));
|
||||
}
|
||||
else {
|
||||
return accessor.getValueClass().equals(String.class);
|
||||
|
||||
+3
-3
@@ -19,14 +19,14 @@ import com.intellij.openapi.components.StateStorage;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.util.JDOMExternalizable;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
|
||||
import com.intellij.util.xmlb.SkipDefaultsSerializationFilter;
|
||||
import com.intellij.util.xmlb.XmlSerializer;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
abstract class SaveSessionBase implements StateStorage.SaveSession, StateStorage.ExternalizationSession {
|
||||
private SkipDefaultValuesSerializationFilters serializationFilter;
|
||||
private SkipDefaultsSerializationFilter serializationFilter;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
@@ -42,7 +42,7 @@ abstract class SaveSessionBase implements StateStorage.SaveSession, StateStorage
|
||||
}
|
||||
else {
|
||||
if (serializationFilter == null) {
|
||||
serializationFilter = new SkipDefaultValuesSerializationFilters();
|
||||
serializationFilter = new SkipDefaultsSerializationFilter();
|
||||
}
|
||||
element = XmlSerializer.serializeIfNotDefault(state, serializationFilter);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,7 +39,7 @@ import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
class BeanBinding extends Binding {
|
||||
private static final Logger LOG = Logger.getInstance(BeanBinding.class);
|
||||
static final Logger LOG = Logger.getInstance(BeanBinding.class);
|
||||
|
||||
private static final Map<Class, List<Accessor>> ourAccessorCache = ContainerUtil.createConcurrentSoftValueMap();
|
||||
|
||||
@@ -47,7 +47,7 @@ class BeanBinding extends Binding {
|
||||
@SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized")
|
||||
private Binding[] myBindings;
|
||||
|
||||
private final Class<?> myBeanClass;
|
||||
final Class<?> myBeanClass;
|
||||
|
||||
public BeanBinding(@NotNull Class<?> beanClass, @Nullable Accessor accessor) {
|
||||
super(accessor);
|
||||
@@ -86,7 +86,13 @@ class BeanBinding extends Binding {
|
||||
public Element serializeInto(@NotNull Object o, @Nullable Element element, @NotNull SerializationFilter filter) {
|
||||
for (Binding binding : myBindings) {
|
||||
Accessor accessor = binding.getAccessor();
|
||||
if (!filter.accepts(accessor, o)) {
|
||||
|
||||
if (filter instanceof SkipDefaultsSerializationFilter) {
|
||||
if (((SkipDefaultsSerializationFilter)filter).equal(binding, o)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (!filter.accepts(accessor, o)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -121,6 +127,16 @@ class BeanBinding extends Binding {
|
||||
return instance;
|
||||
}
|
||||
|
||||
boolean equalByFields(@NotNull Object currentValue, @NotNull Object defaultValue, @NotNull SkipDefaultsSerializationFilter filter) {
|
||||
for (Binding binding : myBindings) {
|
||||
Accessor accessor = binding.getAccessor();
|
||||
if (!filter.equal(binding, accessor.read(currentValue), accessor.read(defaultValue))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TObjectFloatHashMap<String> computeBindingWeights(@NotNull LinkedHashSet<String> accessorNameTracker) {
|
||||
TObjectFloatHashMap<String> weights = new TObjectFloatHashMap<String>(accessorNameTracker.size());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.util.xmlb;
|
||||
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -39,7 +38,7 @@ class FieldAccessor implements Accessor {
|
||||
return myField.get(o);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new XmlSerializationException("Reading "+myField, e);
|
||||
throw new XmlSerializationException("Reading " + myField, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +51,7 @@ class FieldAccessor implements Accessor {
|
||||
myField.set(o, XmlSerializerImpl.convert(value, type));
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new XmlSerializationException("Writing "+myField,e);
|
||||
throw new XmlSerializationException("Writing " + myField, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,5 +18,5 @@ package com.intellij.util.xmlb;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface SerializationFilter {
|
||||
boolean accepts(@NotNull Accessor accessor, Object bean);
|
||||
boolean accepts(@NotNull Accessor accessor, @NotNull Object bean);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,10 +20,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class SerializationFilterBase implements SerializationFilter {
|
||||
@Override
|
||||
public final boolean accepts(@NotNull Accessor accessor, Object bean) {
|
||||
if (bean == null) {
|
||||
return true;
|
||||
}
|
||||
public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) {
|
||||
return accepts(accessor, bean, accessor.read(bean));
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,8 @@ public class SkipDefaultValuesSerializationFilters extends SerializationFilterBa
|
||||
}
|
||||
}
|
||||
|
||||
private Object getDefaultBean(@NotNull Object bean) {
|
||||
@NotNull
|
||||
Object getDefaultBean(@NotNull Object bean) {
|
||||
Class<?> c = bean.getClass();
|
||||
Object o = myDefaultBeans.get(c);
|
||||
if (o == null) {
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util.xmlb;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.util.ThreeState;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public final class SkipDefaultsSerializationFilter extends SkipDefaultValuesSerializationFilters {
|
||||
private Map<Class<?>, ThreeState> hasEqualMethod;
|
||||
|
||||
boolean equal(@NotNull Binding binding, @NotNull Object bean) {
|
||||
Accessor accessor = binding.getAccessor();
|
||||
return equal(binding, accessor.read(bean), accessor.read(getDefaultBean(bean)));
|
||||
}
|
||||
|
||||
boolean equal(@Nullable Binding binding, @Nullable Object currentValue, @Nullable Object defaultValue) {
|
||||
if (defaultValue instanceof Element && currentValue instanceof Element) {
|
||||
return JDOMUtil.areElementsEqual((Element)currentValue, (Element)defaultValue);
|
||||
}
|
||||
else {
|
||||
if (currentValue == defaultValue) {
|
||||
return true;
|
||||
}
|
||||
if (currentValue == null || defaultValue == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (binding instanceof BasePrimitiveBinding) {
|
||||
Binding referencedBinding = ((BasePrimitiveBinding)binding).myBinding;
|
||||
if (referencedBinding instanceof BeanBinding) {
|
||||
Class<?> referencedBeanClass = ((BeanBinding)referencedBinding).myBeanClass;
|
||||
ThreeState compareByFields;
|
||||
if (hasEqualMethod == null) {
|
||||
compareByFields = null;
|
||||
hasEqualMethod = new THashMap<Class<?>, ThreeState>();
|
||||
}
|
||||
else {
|
||||
compareByFields = hasEqualMethod.get(referencedBeanClass);
|
||||
}
|
||||
|
||||
if (compareByFields == null) {
|
||||
try {
|
||||
referencedBeanClass.getDeclaredMethod("equals", Object.class);
|
||||
compareByFields = ThreeState.NO;
|
||||
hasEqualMethod.put(referencedBeanClass, compareByFields);
|
||||
}
|
||||
catch (NoSuchMethodException ignored) {
|
||||
compareByFields = ThreeState.YES;
|
||||
hasEqualMethod.put(referencedBeanClass, compareByFields);
|
||||
}
|
||||
catch (Exception e) {
|
||||
BeanBinding.LOG.warn(e);
|
||||
}
|
||||
}
|
||||
|
||||
if (compareByFields == ThreeState.YES) {
|
||||
return ((BeanBinding)referencedBinding).equalByFields(currentValue, defaultValue, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Comparing.equal(currentValue, defaultValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,7 +19,6 @@ import com.intellij.util.ThreeState;
|
||||
import gnu.trove.TObjectFloatHashMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
|
||||
@@ -40,11 +39,11 @@ public final class SmartSerializer {
|
||||
} :
|
||||
new SkipDefaultValuesSerializationFilters() {
|
||||
@Override
|
||||
protected boolean accepts(@NotNull Accessor accessor, @NotNull Object bean, @Nullable Object beanValue) {
|
||||
public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) {
|
||||
if (mySerializedAccessorNameTracker != null && mySerializedAccessorNameTracker.contains(accessor.getName())) {
|
||||
return true;
|
||||
}
|
||||
return super.accepts(accessor, bean, beanValue);
|
||||
return super.accepts(accessor, bean);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,7 +31,7 @@ import java.util.Set;
|
||||
public class XmlSerializer {
|
||||
private static final SerializationFilter TRUE_FILTER = new SerializationFilter() {
|
||||
@Override
|
||||
public boolean accepts(@NotNull Accessor accessor, Object bean) {
|
||||
public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -158,6 +158,13 @@ public class XmlSerializerTest extends TestCase {
|
||||
bean);
|
||||
}
|
||||
|
||||
public void testSubBeanSerializationAndSkipDefaults() {
|
||||
BeanWithSubBean bean = new BeanWithSubBean();
|
||||
doSerializerTest(
|
||||
"<BeanWithSubBean />",
|
||||
bean, new SkipDefaultsSerializationFilter());
|
||||
}
|
||||
|
||||
public void testNullFieldValue() {
|
||||
BeanWithPublicFields bean1 = new BeanWithPublicFields();
|
||||
|
||||
@@ -538,7 +545,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
"</BeanWithPublicFields>",
|
||||
new SerializationFilter() {
|
||||
@Override
|
||||
public boolean accepts(@NotNull Accessor accessor, Object bean) {
|
||||
public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) {
|
||||
return accessor.getName().startsWith("I");
|
||||
}
|
||||
});
|
||||
@@ -851,7 +858,7 @@ public class XmlSerializerTest extends TestCase {
|
||||
}
|
||||
public static class PropertyFilterTest implements SerializationFilter {
|
||||
@Override
|
||||
public boolean accepts(@NotNull Accessor accessor, Object bean) {
|
||||
public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) {
|
||||
return !accessor.read(bean).equals("skip");
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -56,7 +56,7 @@ public class XDebuggerBreakpointsContextProvider extends WorkingContextProvider
|
||||
XBreakpointManagerImpl.BreakpointManagerState state = myBreakpointManager.getState();
|
||||
Element serialize = XmlSerializer.serialize(state, new SerializationFilter() {
|
||||
@Override
|
||||
public boolean accepts(@NotNull Accessor accessor, Object bean) {
|
||||
public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) {
|
||||
return accessor.read(bean) != null;
|
||||
}
|
||||
});
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -54,7 +54,7 @@ public class XDebuggerWatchesProvider extends WorkingContextProvider {
|
||||
XDebuggerWatchesManager.WatchesManagerState state = myWatchesManager.getState();
|
||||
Element serialize = XmlSerializer.serialize(state, new SerializationFilter() {
|
||||
@Override
|
||||
public boolean accepts(@NotNull Accessor accessor, Object bean) {
|
||||
public boolean accepts(@NotNull Accessor accessor, @NotNull Object bean) {
|
||||
return accessor.read(bean) != null;
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user