mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
ToolWindowManager — do not write defaults (workspace component, but anyway reduce workspace file size)
This commit is contained in:
@@ -33,7 +33,7 @@ class KotlinXmlSerializerTest {
|
||||
|
||||
val data = Foo()
|
||||
data.PLACES_MAP = "new"
|
||||
doSerializerTest("""
|
||||
testSerializer("""
|
||||
<bean>
|
||||
<option name="PLACES_MAP" value="new" />
|
||||
</bean>""", data)
|
||||
@@ -42,7 +42,7 @@ class KotlinXmlSerializerTest {
|
||||
@Test fun floatProperty() {
|
||||
val state = AState()
|
||||
state.floatProperty = 3.4f
|
||||
doSerializerTest("""
|
||||
testSerializer("""
|
||||
<AState>
|
||||
<option name="floatProperty" value="3.4" />
|
||||
</AState>
|
||||
@@ -58,7 +58,7 @@ class KotlinXmlSerializerTest {
|
||||
|
||||
val data = Foo()
|
||||
data.PLACES_MAP.put("", PlaceSettings())
|
||||
doSerializerTest("""
|
||||
testSerializer("""
|
||||
<bean>
|
||||
<option name="PLACES_MAP">
|
||||
<entry key="">
|
||||
|
||||
@@ -25,7 +25,7 @@ internal class XmlSerializerCollectionTest {
|
||||
bean.list.add("\u0001one")
|
||||
bean.list.add("two")
|
||||
bean.list.add("three")
|
||||
doSerializerTest("<b>\n" + " <list>\n" + " <item value=\"one\" />\n" + " <item value=\"two\" />\n" + " <item value=\"three\" />\n" + " </list>\n" + "</b>", bean, SkipDefaultsSerializationFilter())
|
||||
testSerializer("<b>\n" + " <list>\n" + " <item value=\"one\" />\n" + " <item value=\"two\" />\n" + " <item value=\"three\" />\n" + " </list>\n" + "</b>", bean, SkipDefaultsSerializationFilter())
|
||||
}
|
||||
|
||||
@Test fun CollectionBean() {
|
||||
@@ -33,7 +33,7 @@ internal class XmlSerializerCollectionTest {
|
||||
bean.list.add("one")
|
||||
bean.list.add("two")
|
||||
bean.list.add("three")
|
||||
doSerializerTest("<b>\n" + " <list>\n" + " <item value=\"one\" />\n" + " <item value=\"two\" />\n" + " <item value=\"three\" />\n" + " </list>\n" + "</b>", bean, SkipDefaultsSerializationFilter())
|
||||
testSerializer("<b>\n" + " <list>\n" + " <item value=\"one\" />\n" + " <item value=\"two\" />\n" + " <item value=\"three\" />\n" + " </list>\n" + "</b>", bean, SkipDefaultsSerializationFilter())
|
||||
}
|
||||
|
||||
@Test fun CollectionBeanReadJDOMExternalizableStringList() {
|
||||
@@ -58,11 +58,11 @@ internal class XmlSerializerCollectionTest {
|
||||
|
||||
val bean = BeanWithPolymorphicArray()
|
||||
|
||||
doSerializerTest("<bean>\n <option name=\"v\">\n <array />\n </option>\n</bean>", bean)
|
||||
testSerializer("<bean>\n <option name=\"v\">\n <array />\n </option>\n</bean>", bean)
|
||||
|
||||
bean.v = arrayOf(BeanWithPublicFields(), BeanWithPublicFieldsDescendant(), BeanWithPublicFields())
|
||||
|
||||
doSerializerTest("""<bean>
|
||||
testSerializer("""<bean>
|
||||
<option name="v">
|
||||
<array>
|
||||
<BeanWithPublicFields>
|
||||
@@ -85,7 +85,7 @@ internal class XmlSerializerCollectionTest {
|
||||
|
||||
@Test fun xCollection() {
|
||||
val bean = BeanWithArrayWithoutTagName()
|
||||
doSerializerTest(
|
||||
testSerializer(
|
||||
"""
|
||||
<BeanWithArrayWithoutTagName>
|
||||
<option name="foo">
|
||||
@@ -102,7 +102,7 @@ internal class XmlSerializerCollectionTest {
|
||||
|
||||
val bean = Bean()
|
||||
|
||||
doSerializerTest("""
|
||||
testSerializer("""
|
||||
<bean>
|
||||
<option name="v">
|
||||
<array>
|
||||
@@ -114,7 +114,7 @@ internal class XmlSerializerCollectionTest {
|
||||
|
||||
bean.v = arrayOf("1", "2", "3")
|
||||
|
||||
doSerializerTest(
|
||||
testSerializer(
|
||||
"<bean>\n" + " <option name=\"v\">\n" + " <array>\n" + " <vvalue v=\"1\" />\n" + " <vvalue v=\"2\" />\n" + " <vvalue v=\"3\" />\n" + " </array>\n" + " </option>\n" + "</bean>",
|
||||
bean)
|
||||
}
|
||||
@@ -129,7 +129,7 @@ internal class XmlSerializerCollectionTest {
|
||||
|
||||
val bean = Bean()
|
||||
|
||||
doSerializerTest("""
|
||||
testSerializer("""
|
||||
<bean>
|
||||
<option name="INT_V" value="1" />
|
||||
<option name="v">
|
||||
@@ -140,7 +140,7 @@ internal class XmlSerializerCollectionTest {
|
||||
|
||||
bean.v = arrayOf("1", "2", "3")
|
||||
|
||||
doSerializerTest("""
|
||||
testSerializer("""
|
||||
<bean>
|
||||
<option name="INT_V" value="1" />
|
||||
<option name="v">
|
||||
@@ -155,12 +155,12 @@ internal class XmlSerializerCollectionTest {
|
||||
|
||||
@Test fun array() {
|
||||
val bean = BeanWithArray()
|
||||
doSerializerTest(
|
||||
testSerializer(
|
||||
"<BeanWithArray>\n <option name=\"ARRAY_V\">\n <array>\n <option value=\"a\" />\n <option value=\"b\" />\n </array>\n </option>\n</BeanWithArray>",
|
||||
bean)
|
||||
|
||||
bean.ARRAY_V = arrayOf("1", "2", "3", "")
|
||||
doSerializerTest(
|
||||
testSerializer(
|
||||
"<BeanWithArray>\n <option name=\"ARRAY_V\">\n <array>\n <option value=\"1\" />\n <option value=\"2\" />\n <option value=\"3\" />\n <option value=\"\" />\n </array>\n </option>\n</BeanWithArray>",
|
||||
bean)
|
||||
}
|
||||
@@ -172,13 +172,13 @@ internal class XmlSerializerCollectionTest {
|
||||
@Test fun ListSerialization() {
|
||||
val bean = BeanWithList()
|
||||
|
||||
doSerializerTest(
|
||||
testSerializer(
|
||||
"<BeanWithList>\n <option name=\"VALUES\">\n <list>\n <option value=\"a\" />\n <option value=\"b\" />\n <option value=\"c\" />\n </list>\n </option>\n</BeanWithList>",
|
||||
bean)
|
||||
|
||||
bean.VALUES = ArrayList(Arrays.asList("1", "2", "3"))
|
||||
|
||||
doSerializerTest(
|
||||
testSerializer(
|
||||
"<BeanWithList>\n <option name=\"VALUES\">\n <list>\n <option value=\"1\" />\n <option value=\"2\" />\n <option value=\"3\" />\n </list>\n </option>\n</BeanWithList>",
|
||||
bean)
|
||||
}
|
||||
@@ -189,12 +189,12 @@ internal class XmlSerializerCollectionTest {
|
||||
|
||||
@Test fun SetSerialization() {
|
||||
val bean = BeanWithSet()
|
||||
doSerializerTest(
|
||||
testSerializer(
|
||||
"<BeanWithSet>\n <option name=\"VALUES\">\n <set>\n <option value=\"a\" />\n <option value=\"b\" />\n <option value=\"w\" />\n </set>\n </option>\n</BeanWithSet>",
|
||||
bean)
|
||||
bean.VALUES = LinkedHashSet(Arrays.asList("1", "2", "3"))
|
||||
|
||||
doSerializerTest(
|
||||
testSerializer(
|
||||
"<BeanWithSet>\n <option name=\"VALUES\">\n <set>\n <option value=\"1\" />\n <option value=\"2\" />\n <option value=\"3\" />\n </set>\n </option>\n</BeanWithSet>",
|
||||
bean)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.intellij.configurationStore.xml
|
||||
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.util.xmlb.Converter
|
||||
import com.intellij.util.xmlb.SkipDefaultsSerializationFilter
|
||||
import com.intellij.util.xmlb.annotations.Attribute
|
||||
import com.intellij.util.xmlb.annotations.OptionTag
|
||||
import com.intellij.util.xmlb.annotations.Tag
|
||||
import org.junit.Test
|
||||
|
||||
internal class XmlSerializerConversionTest {
|
||||
@Test
|
||||
fun converter() {
|
||||
val bean = BeanWithConverter()
|
||||
testSerializer("""
|
||||
<bean>
|
||||
<option name="bar" />
|
||||
</bean>""", bean)
|
||||
|
||||
bean.foo = Ref.create("testValue")
|
||||
testSerializer("""
|
||||
<bean foo="testValue">
|
||||
<option name="bar" />
|
||||
</bean>""", bean)
|
||||
|
||||
bean.foo = Ref.create<String>()
|
||||
bean.bar = Ref.create("testValue2")
|
||||
testSerializer("""
|
||||
<bean foo="">
|
||||
<option name="bar" value="testValue2" />
|
||||
</bean>""", bean)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun converterUsingSkipDefaultsFilter() {
|
||||
val bean = BeanWithConverter()
|
||||
testSerializer("<bean />", bean, SkipDefaultsSerializationFilter())
|
||||
|
||||
bean.foo = Ref.create("testValue")
|
||||
testSerializer("""<bean foo="testValue" />""", bean, SkipDefaultsSerializationFilter())
|
||||
|
||||
bean.foo = Ref.create<String>()
|
||||
bean.bar = Ref.create("testValue2")
|
||||
testSerializer("""
|
||||
<bean foo="">
|
||||
<option name="bar" value="testValue2" />
|
||||
</bean>""", bean)
|
||||
}
|
||||
|
||||
// @Test
|
||||
// fun `bean fromString`() {
|
||||
// val bean = BeanWithConverter2()
|
||||
// testSerializer("""
|
||||
// <bean>
|
||||
// <option name="bar" />
|
||||
// </bean>""", bean)
|
||||
//
|
||||
// bean.foo = StringRef("testValue")
|
||||
// testSerializer("""
|
||||
// <bean foo="testValue">
|
||||
// <option name="bar" />
|
||||
// </bean>""", bean)
|
||||
//
|
||||
// bean.foo = StringRef()
|
||||
// bean.bar = StringRef("testValue2")
|
||||
// testSerializer("""
|
||||
// <bean foo="">
|
||||
// <option name="bar" value="testValue2" />
|
||||
// </bean>""", bean)
|
||||
// }
|
||||
}
|
||||
|
||||
@Tag("bean")
|
||||
private class BeanWithConverter {
|
||||
private class MyConverter : Converter<Ref<String>>() {
|
||||
override fun fromString(value: String): Ref<String> = Ref.create(value)
|
||||
|
||||
override fun toString(o: Ref<String>) = StringUtil.notNullize(o.get())
|
||||
}
|
||||
|
||||
@Attribute(converter = MyConverter::class)
|
||||
var foo: Ref<String>? = null
|
||||
|
||||
@OptionTag(converter = MyConverter::class)
|
||||
var bar: Ref<String>? = null
|
||||
}
|
||||
|
||||
//private class StringRef(private var value: String? = null) : Converter<StringRef>() {
|
||||
// companion object {
|
||||
// @Suppress("unused")
|
||||
// @JvmStatic
|
||||
// fun fromText(value: String): StringRef = StringRef(value)
|
||||
// }
|
||||
//
|
||||
// override fun fromString(value: String) = StringRef(value)
|
||||
//
|
||||
// override fun toString(value: StringRef) = value.value
|
||||
//}
|
||||
//
|
||||
//@Tag("bean")
|
||||
//private class BeanWithConverter2 {
|
||||
// @Attribute
|
||||
// var foo: StringRef? = null
|
||||
//
|
||||
// @OptionTag
|
||||
// var bar: StringRef? = null
|
||||
//}
|
||||
@@ -32,7 +32,7 @@ internal class XmlSerializerMapTest {
|
||||
}
|
||||
|
||||
val bean = BeanWithMapWithBeanValue2()
|
||||
doSerializerTest("<bean />", bean, SkipDefaultsSerializationFilter())
|
||||
testSerializer("<bean />", bean, SkipDefaultsSerializationFilter())
|
||||
}
|
||||
|
||||
@Test fun mapAtTopLevel() {
|
||||
@@ -48,7 +48,7 @@ internal class XmlSerializerMapTest {
|
||||
val bean = BeanWithMapAtTopLevel()
|
||||
bean.map.put("a", "b")
|
||||
bean.option = "xxx"
|
||||
doSerializerTest("""
|
||||
testSerializer("""
|
||||
<bean>
|
||||
<option name="option" value="xxx" />
|
||||
<entry key="a" value="b" />
|
||||
@@ -69,7 +69,7 @@ internal class XmlSerializerMapTest {
|
||||
bean.MAP.put(BeanWithPublicFields(3, "c"), BeanWithTextAnnotation(4, "d"))
|
||||
bean.MAP.put(BeanWithPublicFields(5, "e"), BeanWithTextAnnotation(6, "f"))
|
||||
|
||||
doSerializerTest("""
|
||||
testSerializer("""
|
||||
<bean>
|
||||
<map>
|
||||
<pair>
|
||||
@@ -118,7 +118,7 @@ internal class XmlSerializerMapTest {
|
||||
bean.myValues.put("a", LinkedHashSet(Arrays.asList("first1", "second1")))
|
||||
bean.myValues.put("b", LinkedHashSet(Arrays.asList("first2", "second2")))
|
||||
|
||||
doSerializerTest("""
|
||||
testSerializer("""
|
||||
<bean>
|
||||
<option name="myValues">
|
||||
<entry-tag key-attr="a">
|
||||
@@ -153,13 +153,13 @@ internal class XmlSerializerMapTest {
|
||||
|
||||
@Test fun serialization() {
|
||||
val bean = BeanWithMap()
|
||||
doSerializerTest("<BeanWithMap>\n <option name=\"VALUES\">\n <map>\n <entry key=\"a\" value=\"1\" />\n <entry key=\"b\" value=\"2\" />\n <entry key=\"c\" value=\"3\" />\n </map>\n </option>\n</BeanWithMap>", bean)
|
||||
testSerializer("<BeanWithMap>\n <option name=\"VALUES\">\n <map>\n <entry key=\"a\" value=\"1\" />\n <entry key=\"b\" value=\"2\" />\n <entry key=\"c\" value=\"3\" />\n </map>\n </option>\n</BeanWithMap>", bean)
|
||||
bean.VALUES.clear()
|
||||
bean.VALUES.put("1", "a")
|
||||
bean.VALUES.put("2", "b")
|
||||
bean.VALUES.put("3", "c")
|
||||
|
||||
doSerializerTest("<BeanWithMap>\n <option name=\"VALUES\">\n <map>\n <entry key=\"1\" value=\"a\" />\n <entry key=\"2\" value=\"b\" />\n <entry key=\"3\" value=\"c\" />\n </map>\n </option>\n</BeanWithMap>", bean)
|
||||
testSerializer("<BeanWithMap>\n <option name=\"VALUES\">\n <map>\n <entry key=\"1\" value=\"a\" />\n <entry key=\"2\" value=\"b\" />\n <entry key=\"3\" value=\"c\" />\n </map>\n </option>\n</BeanWithMap>", bean)
|
||||
}
|
||||
|
||||
private class BeanWithMapWithAnnotations {
|
||||
@@ -176,13 +176,13 @@ internal class XmlSerializerMapTest {
|
||||
|
||||
@Test fun serializationWithAnnotations() {
|
||||
val bean = BeanWithMapWithAnnotations()
|
||||
doSerializerTest("<BeanWithMapWithAnnotations>\n <option name=\"a\" value=\"1\" />\n <option name=\"b\" value=\"2\" />\n <option name=\"c\" value=\"3\" />\n</BeanWithMapWithAnnotations>", bean)
|
||||
testSerializer("<BeanWithMapWithAnnotations>\n <option name=\"a\" value=\"1\" />\n <option name=\"b\" value=\"2\" />\n <option name=\"c\" value=\"3\" />\n</BeanWithMapWithAnnotations>", bean)
|
||||
bean.VALUES.clear()
|
||||
bean.VALUES.put("1", "a")
|
||||
bean.VALUES.put("2", "b")
|
||||
bean.VALUES.put("3", "c")
|
||||
|
||||
doSerializerTest("<BeanWithMapWithAnnotations>\n <option name=\"1\" value=\"a\" />\n <option name=\"2\" value=\"b\" />\n <option name=\"3\" value=\"c\" />\n</BeanWithMapWithAnnotations>", bean)
|
||||
testSerializer("<BeanWithMapWithAnnotations>\n <option name=\"1\" value=\"a\" />\n <option name=\"2\" value=\"b\" />\n <option name=\"3\" value=\"c\" />\n</BeanWithMapWithAnnotations>", bean)
|
||||
}
|
||||
|
||||
private class BeanWithMapWithBeanValue {
|
||||
@@ -196,7 +196,7 @@ internal class XmlSerializerMapTest {
|
||||
bean.VALUES.put("b", BeanWithProperty("Bond"))
|
||||
bean.VALUES.put("c", BeanWithProperty("Bill"))
|
||||
|
||||
doSerializerTest("<BeanWithMapWithBeanValue>\n <option name=\"VALUES\">\n <map>\n <entry key=\"a\">\n <value>\n <BeanWithProperty>\n <option name=\"name\" value=\"James\" />\n </BeanWithProperty>\n </value>\n </entry>\n <entry key=\"b\">\n <value>\n <BeanWithProperty>\n <option name=\"name\" value=\"Bond\" />\n </BeanWithProperty>\n </value>\n </entry>\n <entry key=\"c\">\n <value>\n <BeanWithProperty>\n <option name=\"name\" value=\"Bill\" />\n </BeanWithProperty>\n </value>\n </entry>\n </map>\n </option>\n</BeanWithMapWithBeanValue>", bean)
|
||||
testSerializer("<BeanWithMapWithBeanValue>\n <option name=\"VALUES\">\n <map>\n <entry key=\"a\">\n <value>\n <BeanWithProperty>\n <option name=\"name\" value=\"James\" />\n </BeanWithProperty>\n </value>\n </entry>\n <entry key=\"b\">\n <value>\n <BeanWithProperty>\n <option name=\"name\" value=\"Bond\" />\n </BeanWithProperty>\n </value>\n </entry>\n <entry key=\"c\">\n <value>\n <BeanWithProperty>\n <option name=\"name\" value=\"Bill\" />\n </BeanWithProperty>\n </value>\n </entry>\n </map>\n </option>\n</BeanWithMapWithBeanValue>", bean)
|
||||
}
|
||||
|
||||
@Test fun setKeysInMap() {
|
||||
@@ -209,7 +209,7 @@ internal class XmlSerializerMapTest {
|
||||
bean.myMap.put(LinkedHashSet(Arrays.asList("a", "b", "c")), "letters")
|
||||
bean.myMap.put(LinkedHashSet(Arrays.asList("1", "2", "3")), "numbers")
|
||||
|
||||
val bb = doSerializerTest("<bean>\n <option name=\"myMap\">\n <map>\n <entry value=\"letters\">\n <key>\n <set>\n <option value=\"a\" />\n <option value=\"b\" />\n <option value=\"c\" />\n </set>\n </key>\n </entry>\n <entry value=\"numbers\">\n <key>\n <set>\n <option value=\"1\" />\n <option value=\"2\" />\n <option value=\"3\" />\n </set>\n </key>\n </entry>\n </map>\n </option>\n</bean>", bean)
|
||||
val bb = testSerializer("<bean>\n <option name=\"myMap\">\n <map>\n <entry value=\"letters\">\n <key>\n <set>\n <option value=\"a\" />\n <option value=\"b\" />\n <option value=\"c\" />\n </set>\n </key>\n </entry>\n <entry value=\"numbers\">\n <key>\n <set>\n <option value=\"1\" />\n <option value=\"2\" />\n <option value=\"3\" />\n </set>\n </key>\n </entry>\n </map>\n </option>\n</bean>", bean)
|
||||
|
||||
for (collection in bb.myMap.keys) {
|
||||
Assertions.assertThat(collection).isInstanceOf(Set::class.java)
|
||||
|
||||
@@ -18,15 +18,13 @@ package com.intellij.configurationStore.xml
|
||||
import com.intellij.configurationStore.StoredPropertyStateTest
|
||||
import com.intellij.configurationStore.deserialize
|
||||
import com.intellij.configurationStore.serialize
|
||||
import com.intellij.openapi.util.JDOMUtil
|
||||
import com.intellij.openapi.util.Ref
|
||||
import com.intellij.openapi.util.text.StringUtil
|
||||
import com.intellij.testFramework.assertConcurrent
|
||||
import com.intellij.testFramework.assertions.Assertions.assertThat
|
||||
import com.intellij.util.loadElement
|
||||
import com.intellij.util.xmlb.*
|
||||
import com.intellij.util.xmlb.annotations.*
|
||||
import junit.framework.TestCase
|
||||
import org.assertj.core.api.Assertions.assertThat
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.jdom.Element
|
||||
import org.junit.Test
|
||||
@@ -40,7 +38,8 @@ import java.util.*
|
||||
XmlSerializerMapTest::class,
|
||||
XmlSerializerCollectionTest::class,
|
||||
StoredPropertyStateTest::class,
|
||||
KotlinXmlSerializerTest::class
|
||||
KotlinXmlSerializerTest::class,
|
||||
XmlSerializerConversionTest::class
|
||||
)
|
||||
class XmlSerializerTestSuite
|
||||
|
||||
@@ -53,7 +52,7 @@ internal class XmlSerializerTest {
|
||||
|
||||
val data = Bean()
|
||||
data.PLACES_MAP.put("foo", "bar")
|
||||
doSerializerTest("""
|
||||
testSerializer("""
|
||||
<Bean>
|
||||
<option name="PLACES_MAP">
|
||||
<entry key="foo" value="bar" />
|
||||
@@ -64,31 +63,31 @@ internal class XmlSerializerTest {
|
||||
@Test fun emptyBeanSerialization() {
|
||||
class EmptyBean
|
||||
|
||||
doSerializerTest("<EmptyBean />", EmptyBean())
|
||||
testSerializer("<EmptyBean />", EmptyBean())
|
||||
}
|
||||
|
||||
@Tag("Bean")
|
||||
private class EmptyBeanWithCustomName
|
||||
|
||||
@Test fun emptyBeanSerializationWithCustomName() {
|
||||
doSerializerTest("<Bean />", EmptyBeanWithCustomName())
|
||||
testSerializer("<Bean />", EmptyBeanWithCustomName())
|
||||
}
|
||||
|
||||
@Test fun publicFieldSerialization() {
|
||||
val bean = BeanWithPublicFields()
|
||||
|
||||
doSerializerTest("<BeanWithPublicFields>\n <option name=\"INT_V\" value=\"1\" />\n <option name=\"STRING_V\" value=\"hello\" />\n</BeanWithPublicFields>", bean)
|
||||
testSerializer("<BeanWithPublicFields>\n <option name=\"INT_V\" value=\"1\" />\n <option name=\"STRING_V\" value=\"hello\" />\n</BeanWithPublicFields>", bean)
|
||||
|
||||
bean.INT_V = 2
|
||||
bean.STRING_V = "bye"
|
||||
|
||||
doSerializerTest("<BeanWithPublicFields>\n <option name=\"INT_V\" value=\"2\" />\n <option name=\"STRING_V\" value=\"bye\" />\n</BeanWithPublicFields>", bean)
|
||||
testSerializer("<BeanWithPublicFields>\n <option name=\"INT_V\" value=\"2\" />\n <option name=\"STRING_V\" value=\"bye\" />\n</BeanWithPublicFields>", bean)
|
||||
}
|
||||
|
||||
@Test fun publicFieldSerializationWithInheritance() {
|
||||
val bean = BeanWithPublicFieldsDescendant()
|
||||
|
||||
doSerializerTest("""
|
||||
testSerializer("""
|
||||
<BeanWithPublicFieldsDescendant>
|
||||
<option name="NEW_S" value="foo" />
|
||||
<option name="INT_V" value="1" />
|
||||
@@ -99,7 +98,7 @@ internal class XmlSerializerTest {
|
||||
bean.STRING_V = "bye"
|
||||
bean.NEW_S = "bar"
|
||||
|
||||
doSerializerTest("""<BeanWithPublicFieldsDescendant>
|
||||
testSerializer("""<BeanWithPublicFieldsDescendant>
|
||||
<option name="NEW_S" value="bar" />
|
||||
<option name="INT_V" value="2" />
|
||||
<option name="STRING_V" value="bye" />
|
||||
@@ -113,16 +112,16 @@ internal class XmlSerializerTest {
|
||||
|
||||
@Test fun subBeanSerialization() {
|
||||
val bean = BeanWithSubBean()
|
||||
doSerializerTest("<BeanWithSubBean>\n" + " <option name=\"BEAN1\">\n" + " <Bean />\n" + " </option>\n" + " <option name=\"BEAN2\">\n" + " <BeanWithPublicFields>\n" + " <option name=\"INT_V\" value=\"1\" />\n" + " <option name=\"STRING_V\" value=\"hello\" />\n" + " </BeanWithPublicFields>\n" + " </option>\n" + "</BeanWithSubBean>", bean)
|
||||
testSerializer("<BeanWithSubBean>\n" + " <option name=\"BEAN1\">\n" + " <Bean />\n" + " </option>\n" + " <option name=\"BEAN2\">\n" + " <BeanWithPublicFields>\n" + " <option name=\"INT_V\" value=\"1\" />\n" + " <option name=\"STRING_V\" value=\"hello\" />\n" + " </BeanWithPublicFields>\n" + " </option>\n" + "</BeanWithSubBean>", bean)
|
||||
bean.BEAN2!!.INT_V = 2
|
||||
bean.BEAN2!!.STRING_V = "bye"
|
||||
|
||||
doSerializerTest("<BeanWithSubBean>\n" + " <option name=\"BEAN1\">\n" + " <Bean />\n" + " </option>\n" + " <option name=\"BEAN2\">\n" + " <BeanWithPublicFields>\n" + " <option name=\"INT_V\" value=\"2\" />\n" + " <option name=\"STRING_V\" value=\"bye\" />\n" + " </BeanWithPublicFields>\n" + " </option>\n" + "</BeanWithSubBean>", bean)
|
||||
testSerializer("<BeanWithSubBean>\n" + " <option name=\"BEAN1\">\n" + " <Bean />\n" + " </option>\n" + " <option name=\"BEAN2\">\n" + " <BeanWithPublicFields>\n" + " <option name=\"INT_V\" value=\"2\" />\n" + " <option name=\"STRING_V\" value=\"bye\" />\n" + " </BeanWithPublicFields>\n" + " </option>\n" + "</BeanWithSubBean>", bean)
|
||||
}
|
||||
|
||||
@Test fun SubBeanSerializationAndSkipDefaults() {
|
||||
val bean = BeanWithSubBean()
|
||||
doSerializerTest("<BeanWithSubBean />", bean, SkipDefaultsSerializationFilter())
|
||||
testSerializer("<BeanWithSubBean />", bean, SkipDefaultsSerializationFilter())
|
||||
}
|
||||
|
||||
@Suppress("EqualsOrHashCode")
|
||||
@@ -143,26 +142,26 @@ internal class XmlSerializerTest {
|
||||
@Test fun subBeanWithEqualsSerializationAndSkipDefaults() {
|
||||
val bean = BeanWithSubBeanWithEquals()
|
||||
val filter = SkipDefaultsSerializationFilter()
|
||||
doSerializerTest("<BeanWithSubBeanWithEquals />", bean, filter)
|
||||
testSerializer("<BeanWithSubBeanWithEquals />", bean, filter)
|
||||
|
||||
bean.BEAN2.STRING_V = "new"
|
||||
doSerializerTest("<BeanWithSubBeanWithEquals />", bean, filter)
|
||||
testSerializer("<BeanWithSubBeanWithEquals />", bean, filter)
|
||||
}
|
||||
|
||||
@Test fun nullFieldValue() {
|
||||
val bean1 = BeanWithPublicFields()
|
||||
|
||||
doSerializerTest("<BeanWithPublicFields>\n" + " <option name=\"INT_V\" value=\"1\" />\n" + " <option name=\"STRING_V\" value=\"hello\" />\n" + "</BeanWithPublicFields>", bean1)
|
||||
testSerializer("<BeanWithPublicFields>\n" + " <option name=\"INT_V\" value=\"1\" />\n" + " <option name=\"STRING_V\" value=\"hello\" />\n" + "</BeanWithPublicFields>", bean1)
|
||||
|
||||
bean1.STRING_V = null
|
||||
|
||||
doSerializerTest("<BeanWithPublicFields>\n" + " <option name=\"INT_V\" value=\"1\" />\n" + " <option name=\"STRING_V\" />\n" + "</BeanWithPublicFields>", bean1)
|
||||
testSerializer("<BeanWithPublicFields>\n" + " <option name=\"INT_V\" value=\"1\" />\n" + " <option name=\"STRING_V\" />\n" + "</BeanWithPublicFields>", bean1)
|
||||
|
||||
val bean2 = BeanWithSubBean()
|
||||
bean2.BEAN1 = null
|
||||
bean2.BEAN2 = null
|
||||
|
||||
doSerializerTest("<BeanWithSubBean>\n" + " <option name=\"BEAN1\" />\n" + " <option name=\"BEAN2\" />\n" + "</BeanWithSubBean>", bean2)
|
||||
testSerializer("<BeanWithSubBean>\n" + " <option name=\"BEAN1\" />\n" + " <option name=\"BEAN2\" />\n" + "</BeanWithSubBean>", bean2)
|
||||
}
|
||||
|
||||
private data class BeanWithOption(@OptionTag("path") var PATH: String? = null)
|
||||
@@ -170,7 +169,7 @@ internal class XmlSerializerTest {
|
||||
@Test fun optionTag() {
|
||||
val bean = BeanWithOption()
|
||||
bean.PATH = "123"
|
||||
doSerializerTest("<BeanWithOption>\n" + " <option name=\"path\" value=\"123\" />\n" + "</BeanWithOption>", bean)
|
||||
testSerializer("<BeanWithOption>\n" + " <option name=\"path\" value=\"123\" />\n" + "</BeanWithOption>", bean)
|
||||
}
|
||||
|
||||
private data class BeanWithCustomizedOption(@OptionTag(tag = "setting", nameAttribute = "key", valueAttribute = "saved") var PATH: String? = null)
|
||||
@@ -178,14 +177,14 @@ internal class XmlSerializerTest {
|
||||
@Test fun customizedOptionTag() {
|
||||
val bean = BeanWithCustomizedOption()
|
||||
bean.PATH = "123"
|
||||
doSerializerTest("<BeanWithCustomizedOption>\n" + " <setting key=\"PATH\" saved=\"123\" />\n" + "</BeanWithCustomizedOption>", bean)
|
||||
testSerializer("<BeanWithCustomizedOption>\n" + " <setting key=\"PATH\" saved=\"123\" />\n" + "</BeanWithCustomizedOption>", bean)
|
||||
}
|
||||
|
||||
@Test fun propertySerialization() {
|
||||
val bean = BeanWithProperty()
|
||||
doSerializerTest("<BeanWithProperty>\n" + " <option name=\"name\" value=\"James\" />\n" + "</BeanWithProperty>", bean)
|
||||
testSerializer("<BeanWithProperty>\n" + " <option name=\"name\" value=\"James\" />\n" + "</BeanWithProperty>", bean)
|
||||
bean.name = "Bond"
|
||||
doSerializerTest("<BeanWithProperty>\n" + " <option name=\"name\" value=\"Bond\" />\n" + "</BeanWithProperty>", bean)
|
||||
testSerializer("<BeanWithProperty>\n" + " <option name=\"name\" value=\"Bond\" />\n" + "</BeanWithProperty>", bean)
|
||||
}
|
||||
|
||||
private class BeanWithFieldWithTagAnnotation {
|
||||
@@ -210,7 +209,7 @@ internal class XmlSerializerTest {
|
||||
}
|
||||
|
||||
@Test fun `self class reference deserialization`() {
|
||||
doSerializerTest("""
|
||||
testSerializer("""
|
||||
<Complex>
|
||||
<option name="foo" />
|
||||
</Complex>""", Complex())
|
||||
@@ -218,22 +217,22 @@ internal class XmlSerializerTest {
|
||||
|
||||
@Test fun fieldWithTagAnnotation() {
|
||||
val bean = BeanWithFieldWithTagAnnotation()
|
||||
doSerializerTest("<BeanWithFieldWithTagAnnotation>\n" + " <name>hello</name>\n" + "</BeanWithFieldWithTagAnnotation>", bean)
|
||||
testSerializer("<BeanWithFieldWithTagAnnotation>\n" + " <name>hello</name>\n" + "</BeanWithFieldWithTagAnnotation>", bean)
|
||||
bean.STRING_V = "bye"
|
||||
doSerializerTest("<BeanWithFieldWithTagAnnotation>\n" + " <name>bye</name>\n" + "</BeanWithFieldWithTagAnnotation>", bean)
|
||||
testSerializer("<BeanWithFieldWithTagAnnotation>\n" + " <name>bye</name>\n" + "</BeanWithFieldWithTagAnnotation>", bean)
|
||||
}
|
||||
|
||||
@Test fun escapeCharsInTagText() {
|
||||
val bean = BeanWithFieldWithTagAnnotation()
|
||||
bean.STRING_V = "a\nb\"<"
|
||||
|
||||
doSerializerTest("<BeanWithFieldWithTagAnnotation>\n" + " <name>a\nb"<</name>\n" + "</BeanWithFieldWithTagAnnotation>", bean)
|
||||
testSerializer("<BeanWithFieldWithTagAnnotation>\n" + " <name>a\nb"<</name>\n" + "</BeanWithFieldWithTagAnnotation>", bean)
|
||||
}
|
||||
|
||||
@Test fun escapeCharsInAttributeValue() {
|
||||
val bean = BeanWithPropertiesBoundToAttribute()
|
||||
bean.name = "a\nb\"<"
|
||||
doSerializerTest("<BeanWithPropertiesBoundToAttribute count=\"3\" name=\"a b"<\" />", bean)
|
||||
testSerializer("<BeanWithPropertiesBoundToAttribute count=\"3\" name=\"a b"<\" />", bean)
|
||||
}
|
||||
|
||||
@Test fun shuffledDeserialize() {
|
||||
@@ -266,7 +265,7 @@ internal class XmlSerializerTest {
|
||||
@Transient fun getValue(): String = "foo"
|
||||
}
|
||||
|
||||
doSerializerTest("<Bean />", Bean())
|
||||
testSerializer("<Bean />", Bean())
|
||||
}
|
||||
|
||||
@Test fun PropertyWithoutTagWithPrimitiveType() {
|
||||
@@ -277,7 +276,7 @@ internal class XmlSerializerTest {
|
||||
|
||||
val bean = BeanWithPropertyWithoutTagOnPrimitiveValue()
|
||||
try {
|
||||
doSerializerTest("<BeanWithPropertyWithoutTagOnPrimitiveValue><name>hello</name></BeanWithPropertyWithoutTagOnPrimitiveValue>", bean)
|
||||
testSerializer("<BeanWithPropertyWithoutTagOnPrimitiveValue><name>hello</name></BeanWithPropertyWithoutTagOnPrimitiveValue>", bean)
|
||||
}
|
||||
catch (e: XmlSerializationException) {
|
||||
return
|
||||
@@ -296,7 +295,7 @@ internal class XmlSerializerTest {
|
||||
|
||||
val bean = BeanWithPropertyWithoutTag()
|
||||
|
||||
doSerializerTest("""<bean>
|
||||
testSerializer("""<bean>
|
||||
<option name="INT_V" value="1" />
|
||||
<BeanWithPublicFields>
|
||||
<option name="INT_V" value="1" />
|
||||
@@ -307,7 +306,7 @@ internal class XmlSerializerTest {
|
||||
bean.INT_V = 2
|
||||
bean.BEAN1.STRING_V = "junk"
|
||||
|
||||
doSerializerTest("""<bean>
|
||||
testSerializer("""<bean>
|
||||
<option name="INT_V" value="2" />
|
||||
<BeanWithPublicFields>
|
||||
<option name="INT_V" value="1" />
|
||||
@@ -328,7 +327,7 @@ internal class XmlSerializerTest {
|
||||
@Test fun arrayWithoutAllTags() {
|
||||
val bean = BeanWithArrayWithoutAllTag()
|
||||
|
||||
doSerializerTest("""<bean>
|
||||
testSerializer("""<bean>
|
||||
<option name="intV" value="1" />
|
||||
<vvalue v="a" />
|
||||
<vvalue v="b" />
|
||||
@@ -337,7 +336,7 @@ internal class XmlSerializerTest {
|
||||
bean.intV = 2
|
||||
bean.v = arrayOf("1", "2", "3")
|
||||
|
||||
doSerializerTest("""<bean>
|
||||
testSerializer("""<bean>
|
||||
<option name="intV" value="2" />
|
||||
<vvalue v="1" />
|
||||
<vvalue v="2" />
|
||||
@@ -356,7 +355,7 @@ internal class XmlSerializerTest {
|
||||
|
||||
val bean = BeanWithArrayWithoutAllTag2()
|
||||
|
||||
doSerializerTest("""<bean>
|
||||
testSerializer("""<bean>
|
||||
<option name="intV" value="1" />
|
||||
<vvalue>a</vvalue>
|
||||
<vvalue>b</vvalue>
|
||||
@@ -365,7 +364,7 @@ internal class XmlSerializerTest {
|
||||
bean.intV = 2
|
||||
bean.v = arrayOf("1", "2", "3")
|
||||
|
||||
doSerializerTest("""<bean>
|
||||
testSerializer("""<bean>
|
||||
<option name="intV" value="2" />
|
||||
<vvalue>1</vvalue>
|
||||
<vvalue>2</vvalue>
|
||||
@@ -391,12 +390,12 @@ internal class XmlSerializerTest {
|
||||
@Test fun BeanWithPrimitivePropertyBoundToAttribute() {
|
||||
val bean = BeanWithPropertiesBoundToAttribute()
|
||||
|
||||
doSerializerTest("<BeanWithPropertiesBoundToAttribute count=\"3\" name=\"James\" />", bean)
|
||||
testSerializer("<BeanWithPropertiesBoundToAttribute count=\"3\" name=\"James\" />", bean)
|
||||
|
||||
bean.COUNT = 10
|
||||
bean.name = "Bond"
|
||||
|
||||
doSerializerTest("<BeanWithPropertiesBoundToAttribute count=\"10\" name=\"Bond\" />", bean)
|
||||
testSerializer("<BeanWithPropertiesBoundToAttribute count=\"10\" name=\"Bond\" />", bean)
|
||||
}
|
||||
|
||||
|
||||
@@ -413,11 +412,11 @@ internal class XmlSerializerTest {
|
||||
@Test fun propertyFilter() {
|
||||
val bean = BeanWithPropertyFilter()
|
||||
|
||||
doSerializerTest("<BeanWithPropertyFilter>\n" + " <option name=\"STRING_V\" value=\"hello\" />\n" + "</BeanWithPropertyFilter>", bean)
|
||||
testSerializer("<BeanWithPropertyFilter>\n" + " <option name=\"STRING_V\" value=\"hello\" />\n" + "</BeanWithPropertyFilter>", bean)
|
||||
|
||||
bean.STRING_V = "bye"
|
||||
|
||||
doSerializerTest("<BeanWithPropertyFilter>\n" + " <option name=\"STRING_V\" value=\"bye\" />\n" + "</BeanWithPropertyFilter>", bean)
|
||||
testSerializer("<BeanWithPropertyFilter>\n" + " <option name=\"STRING_V\" value=\"bye\" />\n" + "</BeanWithPropertyFilter>", bean)
|
||||
|
||||
bean.STRING_V = "skip"
|
||||
|
||||
@@ -466,21 +465,21 @@ internal class XmlSerializerTest {
|
||||
|
||||
bean.actions = null
|
||||
val newText = "<BeanWithJDOMElementArray>\n" + " <option name=\"STRING_V\" value=\"bye\" />\n" + "</BeanWithJDOMElementArray>"
|
||||
doSerializerTest(newText, bean)
|
||||
testSerializer(newText, bean)
|
||||
|
||||
bean.actions = emptyArray()
|
||||
doSerializerTest(newText, bean)
|
||||
testSerializer(newText, bean)
|
||||
}
|
||||
|
||||
@Test fun textAnnotation() {
|
||||
val bean = BeanWithTextAnnotation()
|
||||
|
||||
doSerializerTest("<BeanWithTextAnnotation>\n" + " <option name=\"INT_V\" value=\"1\" />\n" + " hello\n" + "</BeanWithTextAnnotation>", bean)
|
||||
testSerializer("<BeanWithTextAnnotation>\n" + " <option name=\"INT_V\" value=\"1\" />\n" + " hello\n" + "</BeanWithTextAnnotation>", bean)
|
||||
|
||||
bean.INT_V = 2
|
||||
bean.STRING_V = "bye"
|
||||
|
||||
doSerializerTest("<BeanWithTextAnnotation>\n" + " <option name=\"INT_V\" value=\"2\" />\n" + " bye\n" + "</BeanWithTextAnnotation>", bean)
|
||||
testSerializer("<BeanWithTextAnnotation>\n" + " <option name=\"INT_V\" value=\"2\" />\n" + " bye\n" + "</BeanWithTextAnnotation>", bean)
|
||||
}
|
||||
|
||||
private class BeanWithEnum {
|
||||
@@ -496,11 +495,11 @@ internal class XmlSerializerTest {
|
||||
@Test fun enums() {
|
||||
val bean = BeanWithEnum()
|
||||
|
||||
doSerializerTest("<BeanWithEnum>\n" + " <option name=\"FLD\" value=\"VALUE_1\" />\n" + "</BeanWithEnum>", bean)
|
||||
testSerializer("<BeanWithEnum>\n" + " <option name=\"FLD\" value=\"VALUE_1\" />\n" + "</BeanWithEnum>", bean)
|
||||
|
||||
bean.FLD = BeanWithEnum.TestEnum.VALUE_3
|
||||
|
||||
doSerializerTest("<BeanWithEnum>\n" + " <option name=\"FLD\" value=\"VALUE_3\" />\n" + "</BeanWithEnum>", bean)
|
||||
testSerializer("<BeanWithEnum>\n" + " <option name=\"FLD\" value=\"VALUE_3\" />\n" + "</BeanWithEnum>", bean)
|
||||
}
|
||||
|
||||
@Tag("condition")
|
||||
@@ -520,11 +519,11 @@ internal class XmlSerializerTest {
|
||||
|
||||
var bean = Bean()
|
||||
bean.conditionBean.oldCondition = "2+2"
|
||||
doSerializerTest("<bean>\n <condition>2+2</condition>\n</bean>", bean)
|
||||
testSerializer("<bean>\n <condition>2+2</condition>\n</bean>", bean)
|
||||
|
||||
bean = Bean()
|
||||
bean.conditionBean.newCondition = "2+2"
|
||||
doSerializerTest("<bean>\n <condition expression=\"2+2\" />\n" + "</bean>", bean)
|
||||
testSerializer("<bean>\n <condition expression=\"2+2\" />\n" + "</bean>", bean)
|
||||
}
|
||||
|
||||
@Test fun `no_wrap`() {
|
||||
@@ -536,11 +535,11 @@ internal class XmlSerializerTest {
|
||||
|
||||
var bean = Bean()
|
||||
bean.conditionBean.oldCondition = "2+2"
|
||||
doSerializerTest("<bean>2+2</bean>", bean)
|
||||
testSerializer("<bean>2+2</bean>", bean)
|
||||
|
||||
bean = Bean()
|
||||
bean.conditionBean.newCondition = "2+2"
|
||||
doSerializerTest("<bean expression=\"2+2\" />", bean)
|
||||
testSerializer("<bean expression=\"2+2\" />", bean)
|
||||
}
|
||||
|
||||
@Test fun deserializeInto() {
|
||||
@@ -553,48 +552,6 @@ internal class XmlSerializerTest {
|
||||
assertThat(bean.STRING_V).isEqualTo("zzz")
|
||||
}
|
||||
|
||||
private class BeanWithConverter {
|
||||
private class MyConverter : Converter<Ref<String>>() {
|
||||
override fun fromString(value: String): Ref<String>? {
|
||||
return Ref.create(value)
|
||||
}
|
||||
|
||||
override fun toString(o: Ref<String>): String {
|
||||
return StringUtil.notNullize(o.get())
|
||||
}
|
||||
}
|
||||
|
||||
@Attribute(converter = MyConverter::class)
|
||||
var foo: Ref<String>? = null
|
||||
|
||||
@OptionTag(converter = MyConverter::class)
|
||||
var bar: Ref<String>? = null
|
||||
}
|
||||
|
||||
@Test fun converter() {
|
||||
val bean = BeanWithConverter()
|
||||
doSerializerTest("<BeanWithConverter>\n" + " <option name=\"bar\" />\n" + "</BeanWithConverter>", bean)
|
||||
|
||||
bean.foo = Ref.create("testValue")
|
||||
doSerializerTest("<BeanWithConverter foo=\"testValue\">\n" + " <option name=\"bar\" />\n" + "</BeanWithConverter>", bean)
|
||||
|
||||
bean.foo = Ref.create<String>()
|
||||
bean.bar = Ref.create("testValue2")
|
||||
doSerializerTest("<BeanWithConverter foo=\"\">\n" + " <option name=\"bar\" value=\"testValue2\" />\n" + "</BeanWithConverter>", bean)
|
||||
}
|
||||
|
||||
@Test fun converterUsingSkipDefaultsFilter() {
|
||||
val bean = BeanWithConverter()
|
||||
doSerializerTest("<BeanWithConverter />", bean, SkipDefaultsSerializationFilter())
|
||||
|
||||
bean.foo = Ref.create("testValue")
|
||||
doSerializerTest("<BeanWithConverter foo=\"testValue\" />", bean, SkipDefaultsSerializationFilter())
|
||||
|
||||
bean.foo = Ref.create<String>()
|
||||
bean.bar = Ref.create("testValue2")
|
||||
doSerializerTest("<BeanWithConverter foo=\"\">\n" + " <option name=\"bar\" value=\"testValue2\" />\n" + "</BeanWithConverter>", bean)
|
||||
}
|
||||
|
||||
@Test fun defaultAttributeName() {
|
||||
class BeanWithDefaultAttributeName {
|
||||
@Attribute fun getFoo() = "foo"
|
||||
@@ -603,7 +560,7 @@ internal class XmlSerializerTest {
|
||||
}
|
||||
}
|
||||
|
||||
doSerializerTest("<BeanWithDefaultAttributeName foo=\"foo\" />", BeanWithDefaultAttributeName())
|
||||
testSerializer("<BeanWithDefaultAttributeName foo=\"foo\" />", BeanWithDefaultAttributeName())
|
||||
}
|
||||
|
||||
private class Bean2 {
|
||||
@@ -621,13 +578,7 @@ internal class XmlSerializerTest {
|
||||
val bean = Bean2()
|
||||
bean.module = "module"
|
||||
bean.ab = "ab"
|
||||
doSerializerTest("<Bean2 ab=\"ab\" module=\"module\" />", bean, SkipDefaultsSerializationFilter())
|
||||
|
||||
checkSmartSerialization(Bean2(), "<Bean2 module=\"1\" ab=\"2\" ac=\"32\" />")
|
||||
checkSmartSerialization(Bean2(), "<Bean2 ab=\"2\" module=\"1\" ac=\"32\" />")
|
||||
checkSmartSerialization(Bean2(), "<Bean2 ac=\"2\" module=\"1\" ab=\"32\" />")
|
||||
checkSmartSerialization(Bean2(), "<Bean2 ac=\"2\" ab=\"32\" />")
|
||||
checkSmartSerialization(Bean2(), "<Bean2 ac=\"2\" ab=\"32\" module=\"\" />")
|
||||
testSerializer("<Bean2 ab=\"ab\" module=\"module\" />", bean, SkipDefaultsSerializationFilter())
|
||||
}
|
||||
|
||||
@Test fun cdataAfterNewLine() {
|
||||
@@ -646,30 +597,17 @@ internal class XmlSerializerTest {
|
||||
bean = loadElement("""<bean><description><![CDATA[<h4>Node.js integration</h4>]]></description></bean>""").deserialize<Bean>()
|
||||
assertThat(bean.description).isEqualTo("<h4>Node.js integration</h4>")
|
||||
}
|
||||
|
||||
private fun checkSmartSerialization(bean: Bean2, serialized: String) {
|
||||
val serializer = SmartSerializer()
|
||||
serializer.readExternal(bean, JDOMUtil.load(serialized))
|
||||
val serializedState = Element("Bean2")
|
||||
serializer.writeExternal(bean, serializedState)
|
||||
assertThat(JDOMUtil.writeElement(serializedState)).isEqualTo(serialized)
|
||||
}
|
||||
}
|
||||
|
||||
private val XML_PREFIX = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
|
||||
internal fun assertSerializer(bean: Any, expected: String, filter: SerializationFilter?, description: String = "Serialization failure"): Element {
|
||||
val element = bean.serialize(filter, createElementIfEmpty = true)!!
|
||||
var actual = JDOMUtil.writeElement(element).trim()
|
||||
if (!expected.startsWith(XML_PREFIX) && actual.startsWith(XML_PREFIX)) {
|
||||
actual = actual.substring(XML_PREFIX.length).trim()
|
||||
}
|
||||
|
||||
assertThat(actual).`as`(description).isEqualTo(expected)
|
||||
assertThat(element).`as`(description).isEqualTo(expected)
|
||||
return element
|
||||
}
|
||||
|
||||
internal fun <T: Any> doSerializerTest(@Language("XML") expectedText: String, bean: T, filter: SerializationFilter? = null): T {
|
||||
// no filter by default
|
||||
// ? = SerializationFilter { _, _ -> true }
|
||||
internal fun <T: Any> testSerializer(@Language("XML") expectedText: String, bean: T, filter: SerializationFilter? = SerializationFilter { _, _ -> true }): T {
|
||||
val expectedTrimmed = expectedText.trimIndent()
|
||||
val element = assertSerializer(bean, expectedTrimmed, filter)
|
||||
|
||||
|
||||
+3
-17
@@ -1,17 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.openapi.wm.impl;
|
||||
|
||||
@@ -26,8 +14,6 @@ import java.util.Arrays;
|
||||
/**
|
||||
* @author Vassiliy Kudryashov
|
||||
*/
|
||||
|
||||
|
||||
public class HiddenSidebarButtonTest extends ToolWindowManagerTestCase {
|
||||
private static final String LAYOUT = "<layout>" +
|
||||
"<window_info id=\"TODO\" active=\"false\" anchor=\"bottom\" auto_hide=\"false\" internal_type=\"DOCKED\" type=\"DOCKED\" visible=\"false\" show_stripe_button=\"false\" weight=\"0.42947903\" sideWeight=\"0.4874552\" order=\"6\" side_tool=\"false\" content_ui=\"tabs\" x=\"119\" y=\"106\" width=\"619\" height=\"748\"/>" +
|
||||
@@ -58,8 +44,8 @@ public class HiddenSidebarButtonTest extends ToolWindowManagerTestCase {
|
||||
for (int i = 0; i < IDS.length; i++) {
|
||||
assertTrue(layout.isToolWindowRegistered(IDS[i]));
|
||||
assertFalse(layout.isToolWindowUnregistered(IDS[i]));
|
||||
assertTrue(ESTIMATED_TO_SHOW[i] == layout.getInfo(IDS[i], true).isShowStripeButton());
|
||||
assertTrue(ESTIMATED_VISIBILITY[i] == myManager.getStripeButton(IDS[i]).isVisible());
|
||||
assertEquals(ESTIMATED_TO_SHOW[i], layout.getInfo(IDS[i], true).isShowStripeButton());
|
||||
assertEquals(ESTIMATED_VISIBILITY[i], myManager.getStripeButton(IDS[i]).isVisible());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,12 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.openapi.wm;
|
||||
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
@@ -34,7 +23,7 @@ public final class ToolWindowAnchor {
|
||||
myText = text;
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
public String toString() {
|
||||
return myText;
|
||||
}
|
||||
|
||||
@@ -64,7 +53,7 @@ public final class ToolWindowAnchor {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ToolWindowAnchor fromText(String anchor) {
|
||||
public static ToolWindowAnchor fromText(@Nullable String anchor) {
|
||||
for (ToolWindowAnchor a : new ToolWindowAnchor[]{TOP, LEFT, BOTTOM, RIGHT}) {
|
||||
if (a.myText.equals(anchor)) {
|
||||
return a;
|
||||
|
||||
@@ -1,24 +1,13 @@
|
||||
/*
|
||||
* Copyright 2000-2009 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.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.openapi.wm;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ToolWindowContentUiType {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.ToolWindowContentUiType");
|
||||
|
||||
public static final ToolWindowContentUiType TABBED = new ToolWindowContentUiType("tabs");
|
||||
@@ -34,7 +23,8 @@ public class ToolWindowContentUiType {
|
||||
return myName;
|
||||
}
|
||||
|
||||
public static ToolWindowContentUiType getInstance(String name) {
|
||||
@NotNull
|
||||
public static ToolWindowContentUiType getInstance(@Nullable String name) {
|
||||
if (TABBED.getName().equals(name)) {
|
||||
return TABBED;
|
||||
}
|
||||
|
||||
@@ -1,25 +1,17 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.openapi.wm.impl;
|
||||
|
||||
import com.intellij.configurationStore.XmlSerializer;
|
||||
import com.intellij.ide.ui.UISettings;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.JDOMUtil;
|
||||
import com.intellij.openapi.wm.ToolWindow;
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -27,10 +19,14 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.configurationStore.XmlSerializer.serialize;
|
||||
|
||||
/**
|
||||
* @author Vladimir Kondratyev
|
||||
*/
|
||||
public final class DesktopLayout {
|
||||
private static final Logger LOG = Logger.getInstance(DesktopLayout.class);
|
||||
|
||||
@NonNls static final String TAG = "layout";
|
||||
/**
|
||||
* Map between {@code id}s and registered {@code WindowInfo}s.
|
||||
@@ -39,7 +35,7 @@ public final class DesktopLayout {
|
||||
/**
|
||||
* Map between {@code id}s and unregistered {@code WindowInfo}s.
|
||||
*/
|
||||
private final Map<String, WindowInfoImpl> myUnregisteredId2Info = new HashMap<>();
|
||||
private final Map<String, WindowInfoImpl> myUnregisteredId2Info = new THashMap<>();
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@@ -62,8 +58,6 @@ public final class DesktopLayout {
|
||||
* if the cached data is invalid.
|
||||
*/
|
||||
private WindowInfoImpl[] myAllInfos;
|
||||
@NonNls private static final String ID_ATTR = "id";
|
||||
|
||||
|
||||
/**
|
||||
* Copies itself from the passed
|
||||
@@ -78,11 +72,11 @@ public final class DesktopLayout {
|
||||
continue;
|
||||
}
|
||||
info = myUnregisteredId2Info.get(info1.getId());
|
||||
if (info != null) {
|
||||
info.copyFrom(info1);
|
||||
if (info == null) {
|
||||
myUnregisteredId2Info.put(info1.getId(), info1.copy());
|
||||
}
|
||||
else {
|
||||
myUnregisteredId2Info.put(info1.getId(), info1.copy());
|
||||
info.copyFrom(info1);
|
||||
}
|
||||
}
|
||||
// invalidate caches
|
||||
@@ -105,20 +99,22 @@ public final class DesktopLayout {
|
||||
*/
|
||||
final WindowInfoImpl register(@NotNull String id, @NotNull ToolWindowAnchor anchor, final boolean splitMode) {
|
||||
WindowInfoImpl info = myUnregisteredId2Info.get(id);
|
||||
if (info != null) { // tool window has been already registered some time
|
||||
myUnregisteredId2Info.remove(id);
|
||||
}
|
||||
else { // tool window is being registered first time
|
||||
info = new WindowInfoImpl(id);
|
||||
if (info == null) {
|
||||
// tool window is being registered first time
|
||||
info = new WindowInfoImpl();
|
||||
info.setId(id);
|
||||
info.setAnchor(anchor);
|
||||
info.setSplit(splitMode);
|
||||
}
|
||||
else {
|
||||
// tool window has been already registered some time
|
||||
myUnregisteredId2Info.remove(id);
|
||||
}
|
||||
myRegisteredId2Info.put(id, info);
|
||||
// invalidate caches
|
||||
myRegisteredInfos = null;
|
||||
myUnregisteredInfos = null;
|
||||
myAllInfos = null;
|
||||
//
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -136,7 +132,7 @@ public final class DesktopLayout {
|
||||
* If {@code onlyRegistered} is {@code true} then returns not {@code null}
|
||||
* value if and only if window with {@code id} is registered one.
|
||||
*/
|
||||
final WindowInfoImpl getInfo(String id, final boolean onlyRegistered) {
|
||||
final WindowInfoImpl getInfo(@NotNull String id, final boolean onlyRegistered) {
|
||||
final WindowInfoImpl info = myRegisteredId2Info.get(id);
|
||||
if (onlyRegistered || info != null) {
|
||||
return info;
|
||||
@@ -216,11 +212,11 @@ public final class DesktopLayout {
|
||||
}
|
||||
}
|
||||
|
||||
final boolean isToolWindowRegistered(final String id) {
|
||||
final boolean isToolWindowRegistered(@NotNull String id) {
|
||||
return myRegisteredId2Info.containsKey(id);
|
||||
}
|
||||
|
||||
final boolean isToolWindowUnregistered(final String id) {
|
||||
final boolean isToolWindowUnregistered(@NotNull String id) {
|
||||
return myUnregisteredId2Info.containsKey(id);
|
||||
}
|
||||
|
||||
@@ -287,17 +283,18 @@ public final class DesktopLayout {
|
||||
|
||||
public final void readExternal(@NotNull Element layoutElement) {
|
||||
myUnregisteredInfos = null;
|
||||
for (Element e : layoutElement.getChildren()) {
|
||||
if (WindowInfoImpl.TAG.equals(e.getName())) {
|
||||
String id = e.getAttributeValue(ID_ATTR);
|
||||
assert id != null;
|
||||
final WindowInfoImpl info = new WindowInfoImpl(id);
|
||||
info.readExternal(e);
|
||||
if (info.getOrder() == -1) { // if order isn't defined then window's button will be the last one in the stripe
|
||||
info.setOrder(getMaxOrder(info.getAnchor()) + 1);
|
||||
}
|
||||
myUnregisteredId2Info.put(info.getId(), info);
|
||||
for (Element e : layoutElement.getChildren(WindowInfoImpl.TAG)) {
|
||||
WindowInfoImpl info = XmlSerializer.deserialize(e, WindowInfoImpl.class);
|
||||
if (info.getId() == null) {
|
||||
LOG.warn("Skip invalid window info (no id): " + JDOMUtil.writeElement(e));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info.getOrder() == -1) {
|
||||
// if order isn't defined then window's button will be the last one in the stripe
|
||||
info.setOrder(getMaxOrder(info.getAnchor()) + 1);
|
||||
}
|
||||
myUnregisteredId2Info.put(info.getId(), info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,9 +307,10 @@ public final class DesktopLayout {
|
||||
|
||||
Element state = new Element(tagName);
|
||||
for (WindowInfoImpl info : infos) {
|
||||
Element element = new Element(WindowInfoImpl.TAG);
|
||||
info.writeExternal(element);
|
||||
state.addContent(element);
|
||||
Element element = serialize(info);
|
||||
if (element != null) {
|
||||
state.addContent(element);
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.openapi.wm.impl;
|
||||
|
||||
@@ -1974,7 +1962,6 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This command creates and shows {@code FloatingDecorator}.
|
||||
*/
|
||||
@@ -1993,9 +1980,10 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
bounds.width > 0 &&
|
||||
bounds.height > 0 &&
|
||||
myWindowManager.isInsideScreenBounds(bounds.x, bounds.y, bounds.width)) {
|
||||
myFloatingDecorator.setBounds(bounds);
|
||||
myFloatingDecorator.setBounds(new Rectangle(bounds));
|
||||
}
|
||||
else { // place new frame at the center of main frame if there are no floating bounds
|
||||
else {
|
||||
// place new frame at the center of main frame if there are no floating bounds
|
||||
Dimension size = decorator.getSize();
|
||||
if (size.width == 0 || size.height == 0) {
|
||||
size = decorator.getPreferredSize();
|
||||
@@ -2065,7 +2053,7 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
|
||||
bounds.width > 0 &&
|
||||
bounds.height > 0 &&
|
||||
myWindowManager.isInsideScreenBounds(bounds.x, bounds.y, bounds.width)) {
|
||||
window.setBounds(bounds);
|
||||
window.setBounds(new Rectangle(bounds));
|
||||
}
|
||||
else { // place new frame at the center of main frame if there are no floating bounds
|
||||
Dimension size = decorator.getSize();
|
||||
|
||||
@@ -1,377 +1,29 @@
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.openapi.wm.impl
|
||||
|
||||
import com.intellij.openapi.util.Comparing
|
||||
import com.intellij.openapi.util.JDOMExternalizable
|
||||
import com.intellij.openapi.util.text.StringUtilRt
|
||||
import com.intellij.openapi.components.BaseState
|
||||
import com.intellij.openapi.diagnostic.logger
|
||||
import com.intellij.openapi.wm.*
|
||||
import com.intellij.util.xmlb.Converter
|
||||
import com.intellij.util.xmlb.annotations.Attribute
|
||||
import com.intellij.util.xmlb.annotations.Property
|
||||
import com.intellij.util.xmlb.annotations.Tag
|
||||
import org.jdom.Element
|
||||
import org.jetbrains.annotations.NonNls
|
||||
import java.awt.Rectangle
|
||||
|
||||
/**
|
||||
* @author Anton Katilin
|
||||
* @author Vladimir Kondratyev
|
||||
*/
|
||||
class WindowInfoImpl
|
||||
/**
|
||||
* Creates `WindowInfo` for tool window with specified `ID`.
|
||||
*/
|
||||
internal constructor(id: String) : Cloneable, JDOMExternalizable, WindowInfo {
|
||||
|
||||
private var myActive: Boolean = false
|
||||
private var myAnchor = ToolWindowAnchor.LEFT
|
||||
private var myAutoHide: Boolean = false
|
||||
/**
|
||||
* Bounds of window in "floating" mode. It equals to `null` if
|
||||
* floating bounds are undefined.
|
||||
*/
|
||||
private var myFloatingBounds: Rectangle? = null
|
||||
/**
|
||||
* @return `ID` of the tool window.
|
||||
*/
|
||||
internal var id: String? = null
|
||||
private set
|
||||
/**
|
||||
* @return type of the tool window in internal (docked or sliding) mode. Actually the tool
|
||||
* window can be in floating mode, but this method has sense if you want to know what type
|
||||
* tool window had when it was internal one. The method never returns `null`.
|
||||
*/
|
||||
internal var internalType: ToolWindowType? = null
|
||||
private set
|
||||
private var myType: ToolWindowType? = null
|
||||
internal var isVisible: Boolean = false
|
||||
private var myShowStripeButton = true
|
||||
private var myWeight = DEFAULT_WEIGHT
|
||||
private var mySideWeight = DEFAULT_SIDE_WEIGHT
|
||||
private var mySplitMode: Boolean = false
|
||||
|
||||
private var myContentUiType = ToolWindowContentUiType.TABBED
|
||||
/**
|
||||
* Defines order of tool window button inside the stripe.
|
||||
* The default value is `-1`.
|
||||
*/
|
||||
var order = -1
|
||||
|
||||
|
||||
private var myWasRead: Boolean = false
|
||||
|
||||
/**
|
||||
* @return internal weight of tool window. "weigth" means how much of internal desktop
|
||||
* area the tool window is occupied. The weight has sense if the tool window is docked or
|
||||
* sliding.
|
||||
*/
|
||||
/**
|
||||
* Sets window weight and adjust it to [0..1] range if necessary.
|
||||
*/
|
||||
internal var weight: Float
|
||||
get() = myWeight
|
||||
set(weight) {
|
||||
myWeight = Math.max(0f, Math.min(1f, weight))
|
||||
}
|
||||
|
||||
internal var sideWeight: Float
|
||||
get() = mySideWeight
|
||||
set(weight) {
|
||||
mySideWeight = Math.max(0f, Math.min(1f, weight))
|
||||
}
|
||||
|
||||
init {
|
||||
this.id = id
|
||||
setType(ToolWindowType.DOCKED)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates copy of `WindowInfo` object.
|
||||
*/
|
||||
fun copy(): WindowInfoImpl {
|
||||
try {
|
||||
val info = clone() as WindowInfoImpl
|
||||
if (myFloatingBounds != null) {
|
||||
info.myFloatingBounds = myFloatingBounds!!.clone() as Rectangle
|
||||
}
|
||||
return info
|
||||
}
|
||||
catch (e: CloneNotSupportedException) {
|
||||
throw RuntimeException(e)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all data from the passed `WindowInfo` into itself.
|
||||
*/
|
||||
internal fun copyFrom(info: WindowInfoImpl) {
|
||||
myActive = info.myActive
|
||||
myAnchor = info.myAnchor
|
||||
myAutoHide = info.myAutoHide
|
||||
myFloatingBounds = if (info.myFloatingBounds == null) null else info.myFloatingBounds!!.clone() as Rectangle
|
||||
id = info.id
|
||||
setTypeAndCheck(info.myType!!)
|
||||
internalType = info.internalType
|
||||
isVisible = info.isVisible
|
||||
myWeight = info.myWeight
|
||||
mySideWeight = info.mySideWeight
|
||||
order = info.order
|
||||
mySplitMode = info.mySplitMode
|
||||
myContentUiType = info.myContentUiType
|
||||
}
|
||||
|
||||
/**
|
||||
* @return tool window's anchor in internal mode.
|
||||
*/
|
||||
override fun getAnchor(): ToolWindowAnchor {
|
||||
return myAnchor
|
||||
}
|
||||
|
||||
override fun getContentUiType(): ToolWindowContentUiType {
|
||||
return myContentUiType
|
||||
}
|
||||
|
||||
internal fun setContentUiType(type: ToolWindowContentUiType) {
|
||||
myContentUiType = type
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bound of tool window in floating mode.
|
||||
*/
|
||||
override fun getFloatingBounds(): Rectangle? {
|
||||
return if (myFloatingBounds != null) Rectangle(myFloatingBounds!!) else null
|
||||
}
|
||||
|
||||
/**
|
||||
* @return current type of tool window.
|
||||
* @see ToolWindowType.DOCKED
|
||||
*
|
||||
* @see ToolWindowType.FLOATING
|
||||
*
|
||||
* @see ToolWindowType.SLIDING
|
||||
*/
|
||||
override fun getType(): ToolWindowType? {
|
||||
return myType
|
||||
}
|
||||
|
||||
override fun isActive(): Boolean {
|
||||
return myActive
|
||||
}
|
||||
|
||||
override fun isAutoHide(): Boolean {
|
||||
return myAutoHide
|
||||
}
|
||||
|
||||
override fun isDocked(): Boolean {
|
||||
return ToolWindowType.DOCKED == myType
|
||||
}
|
||||
|
||||
override fun isFloating(): Boolean {
|
||||
return ToolWindowType.FLOATING == myType
|
||||
}
|
||||
|
||||
override fun isWindowed(): Boolean {
|
||||
return ToolWindowType.WINDOWED == myType
|
||||
}
|
||||
|
||||
override fun isSliding(): Boolean {
|
||||
return ToolWindowType.SLIDING == myType
|
||||
}
|
||||
|
||||
override fun isShowStripeButton(): Boolean {
|
||||
return myShowStripeButton
|
||||
}
|
||||
|
||||
internal fun setShowStripeButton(showStripeButton: Boolean) {
|
||||
myShowStripeButton = showStripeButton
|
||||
}
|
||||
|
||||
override fun isSplit(): Boolean {
|
||||
return mySplitMode
|
||||
}
|
||||
|
||||
fun setSplit(sideTool: Boolean) {
|
||||
mySplitMode = sideTool
|
||||
}
|
||||
|
||||
override fun readExternal(element: Element) {
|
||||
id = element.getAttributeValue(ID_ATTR)
|
||||
myWasRead = true
|
||||
myActive = java.lang.Boolean.parseBoolean(element.getAttributeValue(ACTIVE_ATTR)) && canActivateOnStart(id)
|
||||
try {
|
||||
myAnchor = ToolWindowAnchor.fromText(element.getAttributeValue(ANCHOR_ATTR))
|
||||
}
|
||||
catch (ignored: IllegalArgumentException) {
|
||||
}
|
||||
|
||||
myAutoHide = java.lang.Boolean.parseBoolean(element.getAttributeValue(AUTOHIDE_ATTR))
|
||||
try {
|
||||
internalType = ToolWindowType.valueOf(element.getAttributeValue(INTERNAL_TYPE_ATTR))
|
||||
}
|
||||
catch (ignored: IllegalArgumentException) {
|
||||
}
|
||||
|
||||
try {
|
||||
setTypeAndCheck(ToolWindowType.valueOf(element.getAttributeValue(TYPE_ATTR)))
|
||||
}
|
||||
catch (ignored: IllegalArgumentException) {
|
||||
}
|
||||
|
||||
isVisible = java.lang.Boolean.parseBoolean(element.getAttributeValue(VISIBLE_ATTR)) && canActivateOnStart(id)
|
||||
myShowStripeButton = java.lang.Boolean.parseBoolean(element.getAttributeValue(SHOW_STRIPE_BUTTON, "true"))
|
||||
try {
|
||||
myWeight = java.lang.Float.parseFloat(element.getAttributeValue(WEIGHT_ATTR)!!)
|
||||
}
|
||||
catch (ignored: NumberFormatException) {
|
||||
}
|
||||
|
||||
try {
|
||||
val value = element.getAttributeValue(SIDE_WEIGHT_ATTR)
|
||||
if (value != null) {
|
||||
mySideWeight = java.lang.Float.parseFloat(value)
|
||||
}
|
||||
}
|
||||
catch (ignored: NumberFormatException) {
|
||||
mySideWeight = DEFAULT_SIDE_WEIGHT
|
||||
}
|
||||
|
||||
order = StringUtilRt.parseInt(element.getAttributeValue(ORDER_ATTR), order)
|
||||
myFloatingBounds = deserializeBounds(element)
|
||||
mySplitMode = java.lang.Boolean.parseBoolean(element.getAttributeValue(SIDE_TOOL_ATTR))
|
||||
|
||||
myContentUiType = ToolWindowContentUiType.getInstance(element.getAttributeValue(CONTENT_UI_ATTR))
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets new anchor.
|
||||
*/
|
||||
internal fun setAnchor(anchor: ToolWindowAnchor) {
|
||||
myAnchor = anchor
|
||||
}
|
||||
|
||||
internal fun setActive(active: Boolean) {
|
||||
myActive = active
|
||||
}
|
||||
|
||||
internal fun setAutoHide(autoHide: Boolean) {
|
||||
myAutoHide = autoHide
|
||||
}
|
||||
|
||||
internal fun setFloatingBounds(floatingBounds: Rectangle) {
|
||||
myFloatingBounds = floatingBounds
|
||||
}
|
||||
|
||||
internal fun setType(type: ToolWindowType) {
|
||||
if (ToolWindowType.DOCKED == type || ToolWindowType.SLIDING == type) {
|
||||
internalType = type
|
||||
}
|
||||
setTypeAndCheck(type)
|
||||
}
|
||||
|
||||
//Hardcoded to avoid single-usage-API
|
||||
private fun setTypeAndCheck(type: ToolWindowType) {
|
||||
myType = if (ToolWindowId.PREVIEW === id && type == ToolWindowType.DOCKED) ToolWindowType.SLIDING else type
|
||||
}
|
||||
|
||||
override fun writeExternal(element: Element) {
|
||||
element.setAttribute(ID_ATTR, id!!)
|
||||
|
||||
if (myActive) {
|
||||
element.setAttribute(ACTIVE_ATTR, java.lang.Boolean.toString(true))
|
||||
}
|
||||
|
||||
element.setAttribute(ANCHOR_ATTR, myAnchor.toString())
|
||||
if (myAutoHide) {
|
||||
element.setAttribute(AUTOHIDE_ATTR, java.lang.Boolean.toString(true))
|
||||
}
|
||||
element.setAttribute(INTERNAL_TYPE_ATTR, internalType!!.toString())
|
||||
element.setAttribute(TYPE_ATTR, myType!!.toString())
|
||||
element.setAttribute(VISIBLE_ATTR, java.lang.Boolean.toString(isVisible))
|
||||
if (!myShowStripeButton) {
|
||||
element.setAttribute(SHOW_STRIPE_BUTTON, java.lang.Boolean.toString(false))
|
||||
}
|
||||
element.setAttribute(WEIGHT_ATTR, java.lang.Float.toString(myWeight))
|
||||
|
||||
if (mySideWeight != DEFAULT_SIDE_WEIGHT) {
|
||||
element.setAttribute(SIDE_WEIGHT_ATTR, java.lang.Float.toString(mySideWeight))
|
||||
}
|
||||
element.setAttribute(ORDER_ATTR, Integer.toString(order))
|
||||
element.setAttribute(SIDE_TOOL_ATTR, java.lang.Boolean.toString(mySplitMode))
|
||||
element.setAttribute(CONTENT_UI_ATTR, myContentUiType.name)
|
||||
|
||||
if (myFloatingBounds != null) {
|
||||
serializeBounds(myFloatingBounds!!, element)
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(obj: Any?): Boolean {
|
||||
if (obj !is WindowInfoImpl) {
|
||||
return false
|
||||
}
|
||||
|
||||
val info = obj as WindowInfoImpl?
|
||||
return myActive == info!!.myActive &&
|
||||
myAnchor == info.myAnchor &&
|
||||
id == info.id &&
|
||||
myAutoHide == info.myAutoHide &&
|
||||
Comparing.equal(myFloatingBounds, info.myFloatingBounds) &&
|
||||
internalType == info.internalType &&
|
||||
myType == info.myType &&
|
||||
isVisible == info.isVisible &&
|
||||
myShowStripeButton == info.myShowStripeButton &&
|
||||
myWeight == info.myWeight &&
|
||||
mySideWeight == info.mySideWeight &&
|
||||
order == info.order &&
|
||||
mySplitMode == info.mySplitMode &&
|
||||
myContentUiType === info.myContentUiType
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return myAnchor.hashCode() + id!!.hashCode() + myType!!.hashCode() + order
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return (javaClass.name + "[myId=" + id
|
||||
+ "; myVisible=" + isVisible
|
||||
+ "; myShowStripeButton=" + myShowStripeButton
|
||||
+ "; myActive=" + myActive
|
||||
+ "; myAnchor=" + myAnchor
|
||||
+ "; myOrder=" + order
|
||||
+ "; myAutoHide=" + myAutoHide
|
||||
+ "; myWeight=" + myWeight
|
||||
+ "; mySideWeight=" + mySideWeight
|
||||
+ "; myType=" + myType
|
||||
+ "; myInternalType=" + internalType
|
||||
+ "; myFloatingBounds=" + myFloatingBounds
|
||||
+ "; mySplitMode=" + mySplitMode
|
||||
+ "; myContentUiType=" + myContentUiType.name +
|
||||
']')
|
||||
}
|
||||
|
||||
internal fun wasRead(): Boolean {
|
||||
return myWasRead
|
||||
}
|
||||
private val LOG = logger<WindowInfoImpl>()
|
||||
|
||||
@Suppress("EqualsOrHashCode")
|
||||
@Tag("window_info")
|
||||
@Property(style = Property.Style.ATTRIBUTE)
|
||||
class WindowInfoImpl : Cloneable, WindowInfo, BaseState() {
|
||||
companion object {
|
||||
/**
|
||||
* XML tag.
|
||||
*/
|
||||
@NonNls internal val TAG = "window_info"
|
||||
/**
|
||||
* Default window weight.
|
||||
*/
|
||||
internal val DEFAULT_WEIGHT = 0.33f
|
||||
private val DEFAULT_SIDE_WEIGHT = 0.5f
|
||||
@NonNls private val ID_ATTR = "id"
|
||||
@NonNls private val ACTIVE_ATTR = "active"
|
||||
@NonNls private val ANCHOR_ATTR = "anchor"
|
||||
@NonNls private val AUTOHIDE_ATTR = "auto_hide"
|
||||
@NonNls private val INTERNAL_TYPE_ATTR = "internal_type"
|
||||
@NonNls private val TYPE_ATTR = "type"
|
||||
@NonNls private val VISIBLE_ATTR = "visible"
|
||||
@NonNls private val WEIGHT_ATTR = "weight"
|
||||
@NonNls private val SIDE_WEIGHT_ATTR = "sideWeight"
|
||||
@NonNls private val ORDER_ATTR = "order"
|
||||
@NonNls private val SIDE_TOOL_ATTR = "side_tool"
|
||||
@NonNls private val CONTENT_UI_ATTR = "content_ui"
|
||||
@NonNls private val SHOW_STRIPE_BUTTON = "show_stripe_button"
|
||||
@JvmField
|
||||
internal val TAG = "window_info"
|
||||
@JvmField
|
||||
val DEFAULT_WEIGHT = 0.33f
|
||||
|
||||
private fun canActivateOnStart(id: String?): Boolean {
|
||||
for (ep in ToolWindowEP.EP_NAME.extensions) {
|
||||
@@ -383,4 +35,136 @@ internal constructor(id: String) : Cloneable, JDOMExternalizable, WindowInfo {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
override var isActive by property(false)
|
||||
|
||||
@get:Attribute(converter = ToolWindowAnchorConverter::class)
|
||||
override var anchor: ToolWindowAnchor by property(ToolWindowAnchor.LEFT) { it == ToolWindowAnchor.LEFT }
|
||||
|
||||
@get:Attribute("auto_hide")
|
||||
override var isAutoHide by property(false)
|
||||
|
||||
/**
|
||||
* Bounds of window in "floating" mode. It equals to `null` if
|
||||
* floating bounds are undefined.
|
||||
*/
|
||||
@get:Property(flat = true, style = Property.Style.ATTRIBUTE)
|
||||
override var floatingBounds by property<Rectangle?>()
|
||||
|
||||
/**
|
||||
* @return `ID` of the tool window
|
||||
*/
|
||||
var id by string()
|
||||
|
||||
/**
|
||||
* @return type of the tool window in internal (docked or sliding) mode. Actually the tool
|
||||
* window can be in floating mode, but this method has sense if you want to know what type
|
||||
* tool window had when it was internal one.
|
||||
*/
|
||||
@get:Attribute("internal_type")
|
||||
var internalType by property<ToolWindowType?>()
|
||||
|
||||
override var type: ToolWindowType by property(ToolWindowType.DOCKED) { it == ToolWindowType.DOCKED }
|
||||
|
||||
@get:Attribute("visible")
|
||||
var isVisible by property(false)
|
||||
|
||||
@get:Attribute("show_stripe_button")
|
||||
override var isShowStripeButton by property(true)
|
||||
|
||||
/**
|
||||
* Internal weight of tool window. "weight" means how much of internal desktop
|
||||
* area the tool window is occupied. The weight has sense if the tool window is docked or
|
||||
* sliding.
|
||||
*/
|
||||
var weight by property(DEFAULT_WEIGHT) { Math.max(0f, Math.min(1f, it)) }
|
||||
|
||||
var sideWeight by property(0.5f) { Math.max(0f, Math.min(1f, it)) }
|
||||
|
||||
@get:Attribute("side_tool")
|
||||
override var isSplit by property(false)
|
||||
|
||||
@get:Attribute("content_ui", converter = ContentUiTypeConverter::class)
|
||||
override var contentUiType: ToolWindowContentUiType by property(ToolWindowContentUiType.TABBED, { it == ToolWindowContentUiType.TABBED })
|
||||
|
||||
/**
|
||||
* Defines order of tool window button inside the stripe.
|
||||
*/
|
||||
var order by property(-1)
|
||||
|
||||
private var wasRead: Boolean = false
|
||||
|
||||
init {
|
||||
this.id = id
|
||||
}
|
||||
|
||||
fun copy(): WindowInfoImpl {
|
||||
val info = WindowInfoImpl()
|
||||
info.copyFrom(this)
|
||||
return info
|
||||
}
|
||||
|
||||
override val isDocked: Boolean
|
||||
get() = type == ToolWindowType.DOCKED
|
||||
|
||||
override val isFloating: Boolean
|
||||
get() = type == ToolWindowType.FLOATING
|
||||
|
||||
override val isWindowed: Boolean
|
||||
get() = type == ToolWindowType.WINDOWED
|
||||
|
||||
override val isSliding: Boolean
|
||||
get() = type == ToolWindowType.SLIDING
|
||||
|
||||
fun readExternal(element: Element) {
|
||||
wasRead = true
|
||||
|
||||
try {
|
||||
setTypeAndCheck(ToolWindowType.valueOf(element.getAttributeValue("type")))
|
||||
}
|
||||
catch (ignored: IllegalArgumentException) {
|
||||
}
|
||||
|
||||
if (isVisible && !canActivateOnStart(id)) {
|
||||
isVisible = false
|
||||
}
|
||||
}
|
||||
|
||||
internal fun setType(type: ToolWindowType) {
|
||||
if (ToolWindowType.DOCKED == type || ToolWindowType.SLIDING == type) {
|
||||
internalType = type
|
||||
}
|
||||
setTypeAndCheck(type)
|
||||
}
|
||||
|
||||
//Hardcoded to avoid single-usage-API
|
||||
private fun setTypeAndCheck(value: ToolWindowType) {
|
||||
type = if (ToolWindowId.PREVIEW === id && value == ToolWindowType.DOCKED) ToolWindowType.SLIDING else value
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return anchor.hashCode() + id!!.hashCode() + type.hashCode() + order
|
||||
}
|
||||
|
||||
fun wasRead() = wasRead
|
||||
}
|
||||
|
||||
private class ContentUiTypeConverter : Converter<ToolWindowContentUiType>() {
|
||||
override fun fromString(value: String): ToolWindowContentUiType = ToolWindowContentUiType.getInstance(value)
|
||||
|
||||
override fun toString(value: ToolWindowContentUiType): String = value.name
|
||||
}
|
||||
|
||||
private class ToolWindowAnchorConverter : Converter<ToolWindowAnchor>() {
|
||||
override fun fromString(value: String): ToolWindowAnchor {
|
||||
try {
|
||||
return ToolWindowAnchor.fromText(value)
|
||||
}
|
||||
catch (e: IllegalArgumentException) {
|
||||
LOG.warn(e)
|
||||
return ToolWindowAnchor.LEFT
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(value: ToolWindowAnchor): String = value.toString()
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.wm
|
||||
|
||||
import com.intellij.configurationStore.deserialize
|
||||
import com.intellij.configurationStore.serialize
|
||||
import com.intellij.openapi.components.BaseState
|
||||
import com.intellij.openapi.util.JDOMUtil
|
||||
import com.intellij.openapi.wm.ToolWindowAnchor
|
||||
import com.intellij.openapi.wm.impl.WindowInfoImpl
|
||||
import com.intellij.testFramework.ProjectRule
|
||||
import com.intellij.testFramework.assertions.Assertions.assertThat
|
||||
import org.intellij.lang.annotations.Language
|
||||
import org.jdom.Element
|
||||
import org.junit.ClassRule
|
||||
import org.junit.Test
|
||||
import java.awt.Rectangle
|
||||
|
||||
internal class WindowInfoTest {
|
||||
companion object {
|
||||
@JvmField
|
||||
@ClassRule
|
||||
val projectRule = ProjectRule()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test() {
|
||||
val a = WindowInfoImpl()
|
||||
a.id = "a"
|
||||
doSerializerTest("""<window_info id="a" />""", a)
|
||||
|
||||
a.isActive = true
|
||||
doSerializerTest("""<window_info active="true" id="a" />""", a)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `anchor, isAutoHide`() {
|
||||
val a = WindowInfoImpl()
|
||||
a.id = "a"
|
||||
a.anchor = ToolWindowAnchor.BOTTOM
|
||||
a.isAutoHide = false
|
||||
doSerializerTest("""<window_info anchor="bottom" id="a" />""", a)
|
||||
|
||||
a.isAutoHide = true
|
||||
doSerializerTest("""<window_info anchor="bottom" auto_hide="true" id="a" />""", a)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `floatingBounds`() {
|
||||
val a = WindowInfoImpl()
|
||||
a.id = "a"
|
||||
a.floatingBounds = Rectangle(1, 42, 23, 4)
|
||||
doSerializerTest("""<window_info x="1" y="42" width="23" height="4" id="a" />""", a)
|
||||
}
|
||||
}
|
||||
|
||||
private fun <T : BaseState> doSerializerTest(@Language("XML") expectedText: String, bean: T): T {
|
||||
// test deserializer
|
||||
val expectedTrimmed = expectedText.trimIndent()
|
||||
val element = assertSerializer(bean, expectedTrimmed)
|
||||
|
||||
// test deserializer
|
||||
val o = (element ?: Element("state")).deserialize(bean.javaClass)
|
||||
assertSerializer(o, expectedTrimmed, "Deserialization failure")
|
||||
return o
|
||||
}
|
||||
|
||||
private fun assertSerializer(bean: Any, expected: String, description: String = "Serialization failure"): Element? {
|
||||
val element = bean.serialize()
|
||||
assertThat(element?.let { JDOMUtil.writeElement(element).trim() }).`as`(description).isEqualTo(expected)
|
||||
return element
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
@file:JvmName("XmlSerializer")
|
||||
package com.intellij.configurationStore
|
||||
|
||||
@@ -31,16 +33,21 @@ private fun getDefaultSerializationFilter(): SkipDefaultsSerializationFilter {
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun <T : Any> T.serialize(filter: SerializationFilter? = getDefaultSerializationFilter(), createElementIfEmpty: Boolean = false): Element? {
|
||||
fun <T : Any> T.serialize(filter: SerializationFilter? = null, createElementIfEmpty: Boolean = false): Element? {
|
||||
try {
|
||||
val clazz = javaClass
|
||||
val binding = serializer.getClassBinding(clazz)
|
||||
return if (binding is BeanBinding) {
|
||||
// top level expects not null (null indicates error, empty element will be omitted)
|
||||
binding.serialize(this, createElementIfEmpty, filter)
|
||||
val effectiveFilter = when {
|
||||
filter != null -> filter
|
||||
this !is BaseState -> getDefaultSerializationFilter()
|
||||
else -> null /* BaseState implements SerializationFilter filter */
|
||||
}
|
||||
binding.serialize(this, createElementIfEmpty, effectiveFilter)
|
||||
}
|
||||
else {
|
||||
binding.serialize(this, null, filter) as Element
|
||||
binding.serialize(this, null, filter ?: getDefaultSerializationFilter()) as Element
|
||||
}
|
||||
}
|
||||
catch (e: XmlSerializationException) {
|
||||
|
||||
@@ -125,8 +125,8 @@ abstract class BaseState : SerializationFilter, ModificationTracker {
|
||||
return result
|
||||
}
|
||||
|
||||
fun property(defaultValue: Float = 0f): StoredPropertyBase<Float> {
|
||||
val result = FloatStoredProperty(defaultValue)
|
||||
fun property(defaultValue: Float = 0f, valueNormalizer: ((value: Float) -> Float)? = null): StoredPropertyBase<Float> {
|
||||
val result = FloatStoredProperty(defaultValue, valueNormalizer)
|
||||
properties.add(result)
|
||||
return result
|
||||
}
|
||||
|
||||
+5
-4
@@ -63,15 +63,16 @@ internal class LongStoredProperty(override val defaultValue: Long) : PrimitiveSt
|
||||
}
|
||||
}
|
||||
|
||||
internal class FloatStoredProperty(override val defaultValue: Float) : PrimitiveStoredPropertyBase<Float>() {
|
||||
internal class FloatStoredProperty(override val defaultValue: Float, private val valueNormalizer: ((value: Float) -> Float)?) : PrimitiveStoredPropertyBase<Float>() {
|
||||
override var value = defaultValue
|
||||
|
||||
override operator fun getValue(thisRef: BaseState, property: KProperty<*>) = value
|
||||
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, value: Float) {
|
||||
if (this.value != value) {
|
||||
override fun setValue(thisRef: BaseState, property: KProperty<*>, @Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") rawNewValue: Float) {
|
||||
val newValue = valueNormalizer?.invoke(value) ?: rawNewValue
|
||||
if (value != newValue) {
|
||||
thisRef.ownModificationCount++
|
||||
this.value = value
|
||||
value = newValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,22 +3,30 @@
|
||||
*/
|
||||
package com.intellij.util.xmlb;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtilRt;
|
||||
import com.intellij.util.xmlb.annotations.Property;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
class AccessorBindingWrapper extends Binding implements MultiNodeBinding {
|
||||
protected final Binding myBinding;
|
||||
|
||||
private final boolean myFlat;
|
||||
private final Property.Style beanStyle;
|
||||
|
||||
public AccessorBindingWrapper(@NotNull MutableAccessor accessor, @NotNull Binding binding, boolean flat) {
|
||||
public AccessorBindingWrapper(@NotNull MutableAccessor accessor,
|
||||
@NotNull Binding binding,
|
||||
boolean flat,
|
||||
Property.Style beanStyle) {
|
||||
super(accessor);
|
||||
|
||||
myBinding = binding;
|
||||
myFlat = flat;
|
||||
this.beanStyle = beanStyle;
|
||||
}
|
||||
|
||||
public boolean isFlat() {
|
||||
@@ -33,7 +41,18 @@ class AccessorBindingWrapper extends Binding implements MultiNodeBinding {
|
||||
throw new XmlSerializationException("Property " + myAccessor + " of object " + o + " (" + o.getClass() + ") must not be null");
|
||||
}
|
||||
if (myFlat) {
|
||||
((BeanBinding)myBinding).serializeInto(value, (Element)context, filter);
|
||||
Element element = (Element)context;
|
||||
if (beanStyle == Property.Style.ATTRIBUTE && value instanceof Rectangle) {
|
||||
Rectangle bounds = (Rectangle)value;
|
||||
LOG.assertTrue(element != null);
|
||||
element.setAttribute("x", Integer.toString(bounds.x));
|
||||
element.setAttribute("y", Integer.toString(bounds.y));
|
||||
element.setAttribute("width", Integer.toString(bounds.width));
|
||||
element.setAttribute("height", Integer.toString(bounds.height));
|
||||
}
|
||||
else {
|
||||
((BeanBinding)myBinding).serializeInto(value, element, filter);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
@@ -53,7 +72,18 @@ class AccessorBindingWrapper extends Binding implements MultiNodeBinding {
|
||||
((BeanBinding)myBinding).deserializeInto(currentValue, element);
|
||||
}
|
||||
else {
|
||||
Object deserializedValue = myBinding.deserializeUnsafe(currentValue, element);
|
||||
Object deserializedValue;
|
||||
if (beanStyle == Property.Style.ATTRIBUTE && myBinding instanceof BeanBinding && ((BeanBinding)myBinding).myBeanClass == Rectangle.class) {
|
||||
int x = StringUtilRt.parseInt(element.getAttributeValue("x"), 0);
|
||||
int y = StringUtilRt.parseInt(element.getAttributeValue("y"), 0);
|
||||
int w = StringUtilRt.parseInt(element.getAttributeValue("width"), 0);
|
||||
int h = StringUtilRt.parseInt(element.getAttributeValue("height"), 0);
|
||||
deserializedValue = new Rectangle(x, y, w, h);
|
||||
}
|
||||
else {
|
||||
deserializedValue = myBinding.deserializeUnsafe(currentValue, element);
|
||||
}
|
||||
|
||||
if (currentValue != deserializedValue) {
|
||||
myAccessor.set(context, deserializedValue);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.util.xmlb;
|
||||
|
||||
@@ -22,8 +10,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
class AttributeBinding extends BasePrimitiveBinding {
|
||||
private final Class<?> valueClass;
|
||||
|
||||
public AttributeBinding(@NotNull MutableAccessor accessor, @NotNull Attribute attribute) {
|
||||
super(accessor, attribute.value(), attribute.converter());
|
||||
public AttributeBinding(@NotNull MutableAccessor accessor, @Nullable Attribute attribute) {
|
||||
super(accessor, attribute == null ? null : attribute.value(), attribute == null ? null : attribute.converter());
|
||||
|
||||
valueClass = XmlSerializerImpl.typeToClass(accessor.getGenericType());
|
||||
}
|
||||
@@ -36,12 +24,16 @@ class AttributeBinding extends BasePrimitiveBinding {
|
||||
return null;
|
||||
}
|
||||
|
||||
Converter<Object> converter = getConverter();
|
||||
String stringValue;
|
||||
if (myConverter == null) {
|
||||
if (converter == null) {
|
||||
stringValue = XmlSerializerImpl.convertToString(value);
|
||||
}
|
||||
else {
|
||||
stringValue = myConverter.toString(value);
|
||||
stringValue = converter.toString(value);
|
||||
if (stringValue == null) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return new org.jdom.Attribute(myName, stringValue);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.util.xmlb;
|
||||
|
||||
@@ -65,4 +53,19 @@ abstract class BasePrimitiveBinding extends Binding {
|
||||
public final Object deserializeUnsafe(Object context, @NotNull Element element) {
|
||||
return deserialize(context, element);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected final Converter<Object> getConverter() {
|
||||
//Converter<Object> converter = myConverter;
|
||||
//if (converter == null && o instanceof Converter) {
|
||||
// try {
|
||||
// //noinspection unchecked
|
||||
// converter = (Converter<Object>)o;
|
||||
// }
|
||||
// catch (Exception e) {
|
||||
// LOG.warn(e);
|
||||
// }
|
||||
//}
|
||||
return myConverter;
|
||||
}
|
||||
}
|
||||
@@ -50,10 +50,12 @@ public class BeanBinding extends NotNullDeserializeBinding {
|
||||
public synchronized void init(@NotNull Type originalType, @NotNull Serializer serializer) {
|
||||
assert myBindings == null;
|
||||
|
||||
Property classAnnotation = myBeanClass.getAnnotation(Property.class);
|
||||
|
||||
List<MutableAccessor> accessors = getAccessors(myBeanClass);
|
||||
myBindings = new Binding[accessors.size()];
|
||||
for (int i = 0, size = accessors.size(); i < size; i++) {
|
||||
Binding binding = createBinding(accessors.get(i), serializer);
|
||||
Binding binding = createBinding(accessors.get(i), serializer, classAnnotation == null ? Property.Style.OLD : classAnnotation.style());
|
||||
binding.init(originalType, serializer);
|
||||
myBindings[i] = binding;
|
||||
}
|
||||
@@ -251,6 +253,7 @@ public class BeanBinding extends NotNullDeserializeBinding {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
String name = aClass.getSimpleName();
|
||||
if (name.isEmpty()) {
|
||||
name = aClass.getSuperclass().getSimpleName();
|
||||
@@ -263,7 +266,8 @@ public class BeanBinding extends NotNullDeserializeBinding {
|
||||
return name;
|
||||
}
|
||||
|
||||
private static String getTagNameFromAnnotation(Class<?> aClass) {
|
||||
@Nullable
|
||||
private static String getTagNameFromAnnotation(@NotNull Class<?> aClass) {
|
||||
Tag tag = aClass.getAnnotation(Tag.class);
|
||||
return tag != null && !tag.value().isEmpty() ? tag.value() : null;
|
||||
}
|
||||
@@ -278,11 +282,12 @@ public class BeanBinding extends NotNullDeserializeBinding {
|
||||
accessors = new ArrayList<MutableAccessor>();
|
||||
|
||||
Map<String, Couple<Method>> nameToAccessors;
|
||||
if (aClass != Rectangle.class) { // special case for Rectangle.class to avoid infinite recursion during serialization due to bounds() method
|
||||
nameToAccessors = collectPropertyAccessors(aClass, accessors);
|
||||
// special case for Rectangle.class to avoid infinite recursion during serialization due to bounds() method
|
||||
if (aClass == Rectangle.class) {
|
||||
nameToAccessors = Collections.emptyMap();
|
||||
}
|
||||
else {
|
||||
nameToAccessors = Collections.emptyMap();
|
||||
nameToAccessors = collectPropertyAccessors(aClass, accessors);
|
||||
}
|
||||
|
||||
int propertyAccessorCount = accessors.size();
|
||||
@@ -351,6 +356,7 @@ public class BeanBinding extends NotNullDeserializeBinding {
|
||||
}
|
||||
|
||||
private static boolean hasStoreAnnotations(@NotNull AccessibleObject object) {
|
||||
//noinspection deprecation
|
||||
return object.getAnnotation(OptionTag.class) != null ||
|
||||
object.getAnnotation(Tag.class) != null ||
|
||||
object.getAnnotation(Attribute.class) != null ||
|
||||
@@ -414,7 +420,7 @@ public class BeanBinding extends NotNullDeserializeBinding {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Binding createBinding(@NotNull MutableAccessor accessor, @NotNull Serializer serializer) {
|
||||
private static Binding createBinding(@NotNull MutableAccessor accessor, @NotNull Serializer serializer, @NotNull Property.Style propertyStyle) {
|
||||
Binding binding = serializer.getBinding(accessor);
|
||||
if (binding instanceof JDOMElementBinding) {
|
||||
return binding;
|
||||
@@ -436,7 +442,7 @@ public class BeanBinding extends NotNullDeserializeBinding {
|
||||
}
|
||||
|
||||
if (binding instanceof CompactCollectionBinding) {
|
||||
return new AccessorBindingWrapper(accessor, binding, false);
|
||||
return new AccessorBindingWrapper(accessor, binding, false, Property.Style.OLD);
|
||||
}
|
||||
|
||||
boolean surroundWithTag = true;
|
||||
@@ -454,7 +460,7 @@ public class BeanBinding extends NotNullDeserializeBinding {
|
||||
if (binding == null || binding instanceof TextBinding) {
|
||||
throw new XmlSerializationException("Text-serializable properties can't be serialized without surrounding tags: " + accessor);
|
||||
}
|
||||
return new AccessorBindingWrapper(accessor, binding, inline);
|
||||
return new AccessorBindingWrapper(accessor, binding, inline, property.style());
|
||||
}
|
||||
|
||||
XCollection xCollection = accessor.getAnnotation(XCollection.class);
|
||||
@@ -462,6 +468,9 @@ public class BeanBinding extends NotNullDeserializeBinding {
|
||||
return new TagBinding(accessor, xCollection.propertyElementName());
|
||||
}
|
||||
|
||||
if (propertyStyle == Property.Style.ATTRIBUTE) {
|
||||
return new AttributeBinding(accessor, null);
|
||||
}
|
||||
return new OptionTagBinding(accessor, accessor.getAnnotation(OptionTag.class));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,6 @@ public abstract class Converter<T> {
|
||||
@Nullable
|
||||
public abstract T fromString(@NotNull String value);
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
public abstract String toString(@NotNull T value);
|
||||
}
|
||||
@@ -1,16 +1,6 @@
|
||||
// Copyright 2000-2017 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.
|
||||
/*
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.util.xmlb;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -62,7 +52,8 @@ class OptionTagBinding extends BasePrimitiveBinding {
|
||||
return targetElement;
|
||||
}
|
||||
|
||||
if (myConverter == null) {
|
||||
Converter<Object> converter = getConverter();
|
||||
if (converter == null) {
|
||||
if (myBinding == null) {
|
||||
targetElement.setAttribute(myValueAttribute, XmlSerializerImpl.removeControlChars(XmlSerializerImpl.convertToString(value)));
|
||||
}
|
||||
@@ -77,7 +68,10 @@ class OptionTagBinding extends BasePrimitiveBinding {
|
||||
}
|
||||
}
|
||||
else {
|
||||
targetElement.setAttribute(myValueAttribute, XmlSerializerImpl.removeControlChars(myConverter.toString(value)));
|
||||
String text = converter.toString(value);
|
||||
if (text != null) {
|
||||
targetElement.setAttribute(myValueAttribute, XmlSerializerImpl.removeControlChars(text));
|
||||
}
|
||||
}
|
||||
return targetElement;
|
||||
}
|
||||
@@ -102,16 +96,20 @@ class OptionTagBinding extends BasePrimitiveBinding {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (myConverter == null) {
|
||||
try {
|
||||
XmlSerializerImpl.doSet(context, valueAttribute.getValue(), myAccessor, XmlSerializerImpl.typeToClass(myAccessor.getGenericType()));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Cannot set value for field " + myName, e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
myAccessor.set(context, myConverter.fromString(valueAttribute.getValue()));
|
||||
String value = valueAttribute.getValue();
|
||||
if (myConverter == null) {
|
||||
try {
|
||||
XmlSerializerImpl
|
||||
.doSet(context, value, myAccessor, XmlSerializerImpl.typeToClass(myAccessor.getGenericType()));
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException("Cannot set value for field " + myName, e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
myAccessor.set(context, myConverter.fromString(value));
|
||||
}
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -16,10 +16,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.lang.reflect.WildcardType;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -293,10 +290,43 @@ public final class XmlSerializerImpl {
|
||||
else if (valueClass == Float.class) {
|
||||
deserializedValue = Float.parseFloat(value);
|
||||
}
|
||||
else if (callFromStringIfDefined(host, value, accessor, valueClass)) {
|
||||
return;
|
||||
}
|
||||
|
||||
accessor.set(host, deserializedValue);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean callFromStringIfDefined(@NotNull Object host,
|
||||
@NotNull String value,
|
||||
@NotNull MutableAccessor accessor,
|
||||
@NotNull Class<?> valueClass) {
|
||||
Method fromText;
|
||||
try {
|
||||
fromText = valueClass.getMethod("fromText", String.class);
|
||||
}
|
||||
catch (NoSuchMethodException ignored) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
fromText.setAccessible(true);
|
||||
}
|
||||
catch (SecurityException ignored) {
|
||||
}
|
||||
|
||||
try {
|
||||
accessor.set(host, fromText.invoke(null, value));
|
||||
return true;
|
||||
}
|
||||
catch (IllegalAccessException ignored) {
|
||||
}
|
||||
catch (InvocationTargetException ignored) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static String convertToString(@NotNull Object value) {
|
||||
if (value instanceof Date) {
|
||||
|
||||
@@ -1,17 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
*/
|
||||
package com.intellij.util.xmlb.annotations;
|
||||
|
||||
@@ -36,6 +24,12 @@ public @interface Property {
|
||||
boolean flat() default false;
|
||||
|
||||
Class<? extends SerializationFilter> filter() default SerializationFilter.class;
|
||||
|
||||
|
||||
boolean alwaysWrite() default false;
|
||||
|
||||
enum Style {
|
||||
OLD, ATTRIBUTE
|
||||
}
|
||||
|
||||
Style style() default Style.OLD;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user