| /* |
| * Copyright 2000-2013 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.util.xml; |
| |
| import com.intellij.openapi.application.Result; |
| import com.intellij.openapi.command.WriteCommandAction; |
| import com.intellij.psi.*; |
| import com.intellij.psi.search.GlobalSearchScope; |
| import com.intellij.psi.xml.XmlTag; |
| import com.intellij.util.IncorrectOperationException; |
| import com.intellij.util.xml.events.DomEvent; |
| import com.intellij.util.xml.impl.DomTestCase; |
| import com.intellij.util.xml.ui.DomUIFactory; |
| import org.jetbrains.annotations.NonNls; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.List; |
| |
| /** |
| * @author peter |
| */ |
| public class DomSimpleValuesTest extends DomTestCase { |
| |
| private MyElement createElement(final String xml) throws IncorrectOperationException { |
| return createElement(xml, MyElement.class); |
| } |
| |
| public void testGetValue() throws Throwable { |
| final String text = "<a>foo</a>"; |
| assertEquals("foo", createElement(text).getTagValue()); |
| assertEquals("foo", createElement(text).getValue()); |
| } |
| |
| public void testSetValue() throws Throwable { |
| final MyElement element = createElement("<a/>"); |
| assertEquals("", element.getValue()); |
| element.setValue(239); |
| assertEquals("239", element.getValue()); |
| assertEquals("239", element.getXmlTag().getValue().getText()); |
| myCallRegistry.putExpected(new DomEvent(element, false)); |
| |
| myCallRegistry.assertResultsAndClear(); |
| } |
| |
| public void testDefineAndSet() throws Throwable { |
| final MyElement element = getDomManager().getFileElement(createXmlFile(""), MyElement.class, "root").getRootElement(); |
| myCallRegistry.clear(); |
| assertNull(element.getXmlTag()); |
| element.setValue(42); |
| assertNotNull(element.getXmlTag()); |
| assertEquals("42", element.getXmlTag().getValue().getText()); |
| final DomElement element1 = element; |
| myCallRegistry.putExpected(new DomEvent(element1, true)); |
| myCallRegistry.putExpected(new DomEvent(element, false)); |
| |
| element.setValue((Integer)null); |
| assertNull(element.getXmlTag()); |
| assertEquals(null, element.getValue()); |
| |
| myCallRegistry.putExpected(new DomEvent(element, false)); |
| myCallRegistry.assertResultsAndClear(); |
| } |
| |
| |
| public void testSimpleConverters() throws Throwable { |
| assertEquals(239, createElement("<a>239</a>").getInt()); |
| assertEquals(true, createElement("<a>true</a>").getBoolean()); |
| assertEquals("true", createElement("<a>true</a>").getBuffer().toString()); |
| |
| try { |
| createElement("<a>true</a>").getInt(); |
| fail(); |
| } |
| catch (NullPointerException e) { |
| } |
| try { |
| createElement("<a>42</a>").getBoolean(); |
| fail(); |
| } |
| catch (NullPointerException e) { |
| } |
| } |
| |
| public void testComment() throws Throwable { |
| assertEquals(239, createElement("<a>" + |
| " <!-- some comment-->" + |
| " 239" + |
| " <!-- some another comment-->" + |
| "</a>").getInt()); |
| } |
| |
| public void testPsiClassConverter() throws Throwable { |
| final String className = Object.class.getName(); |
| final PsiClass objectClass = getJavaFacade().findClass(className, GlobalSearchScope.allScope(getProject())); |
| assertEquals(objectClass, createElement("<a>" + className + "</a>").getPsiClass()); |
| |
| assertNull(createElement("<a>abcdef</a>").getPsiClass()); |
| } |
| |
| public void testEnums() throws Throwable { |
| final MyElement element = createElement("<a/>", MyElement.class); |
| assertNull(element.getEnum()); |
| |
| element.setEnum(DomTestCase.MyEnum.BAR); |
| assertEquals(DomTestCase.MyEnum.BAR, element.getEnum()); |
| assertEquals(DomTestCase.MyEnum.BAR.getValue(), element.getXmlTag().getValue().getText()); |
| |
| element.setEnum(null); |
| assertNull(element.getEnum()); |
| assertNull(element.getXmlTag()); |
| |
| element.setValue(239); |
| assertNull(element.getEnum()); |
| } |
| |
| public void testAttributeValues() throws Throwable { |
| final MyElement element = createElement("<a attra=\"foo\"/>"); |
| final GenericAttributeValue<String> attributeValue = element.getAttributeValue(); |
| assertEquals("attra", attributeValue.getXmlElementName()); |
| assertEquals("foo", attributeValue.getValue()); |
| |
| final GenericAttributeValue<Integer> attr = element.getAttr(); |
| attr.setValue(239); |
| assertEquals(239, (int)attr.getValue()); |
| assertEquals("239", element.getXmlTag().getAttributeValue("attr")); |
| final DomElement element1 = attr; |
| myCallRegistry.putExpected(new DomEvent(element1, true)); |
| myCallRegistry.assertResultsAndClear(); |
| |
| attr.setValue(42); |
| myCallRegistry.putExpected(new DomEvent(attr, false)); |
| myCallRegistry.assertResultsAndClear(); |
| |
| attr.setValue(null); |
| assertNull(attr.getValue()); |
| assertNull(element.getXmlTag().getAttributeValue("attr")); |
| assertNull(element.getXmlTag().getAttribute("attr", "")); |
| myCallRegistry.putExpected(new DomEvent(attr, false)); |
| myCallRegistry.assertResultsAndClear(); |
| |
| assertEquals("some-attribute", element.getSomeAttribute().getXmlElementName()); |
| |
| assertNull(createElement("<a attra\"attr\"/>").getAttributeValue().getStringValue()); |
| assertNull(createElement("<a attra\"\"/>").getAttributeValue().getStringValue()); |
| assertNull(createElement("<a attra\"/>").getAttributeValue().getStringValue()); |
| } |
| |
| public void testGenericValue() throws Throwable { |
| final MyElement element = createElement("<a><generic-child>239</generic-child></a>"); |
| final GenericDomValue<Integer> integerChild = element.getGenericChild(); |
| assertEquals(239, (int)integerChild.getValue()); |
| assertEquals("239", integerChild.getStringValue()); |
| integerChild.setValue(42); |
| assertEquals(42, (int)integerChild.getValue()); |
| assertEquals("42", integerChild.getStringValue()); |
| } |
| |
| public void testAnnotatedGenericValue() throws Throwable { |
| final MyElement element = createElement("<a><buffer>239</buffer></a>"); |
| element.getGenericChild().getValue(); |
| final GenericDomValue<StringBuffer> genericChild2 = element.getGenericChild2(); |
| assertEquals("239", genericChild2.getValue().toString()); |
| } |
| |
| public void testSpecialCharacters() throws Throwable { |
| final MyElement element = createElement(""); |
| element.setValue("<"); |
| assertEquals("<", element.getValue()); |
| assertEquals("<![CDATA[<]]>", element.getXmlTag().getValue().getText()); |
| |
| element.getAttributeValue().setValue("<"); |
| assertEquals("<", element.getAttributeValue().getValue()); |
| assertEquals("\"<\"", element.getXmlTag().getAttribute("attra", null).getValueElement().getText()); |
| } |
| |
| public void testIndicators() throws Throwable { |
| final MyElement element = createElement("<a><indicator/></a>"); |
| final GenericDomValue<Boolean> indicator = element.getIndicator(); |
| assertTrue(indicator.getValue()); |
| |
| indicator.setValue(false); |
| assertFalse(indicator.getValue()); |
| assertNull(indicator.getStringValue()); |
| assertNull(indicator.getXmlTag()); |
| assertEquals(0, element.getXmlTag().getSubTags().length); |
| putExpected(new DomEvent(indicator, false)); |
| assertResultsAndClear(); |
| |
| indicator.setValue(true); |
| assertTrue(indicator.getValue()); |
| assertEquals("", indicator.getStringValue()); |
| assertSame(indicator.getXmlTag(), element.getXmlTag().getSubTags()[0]); |
| final DomElement element1 = indicator; |
| putExpected(new DomEvent(element1, true)); |
| assertResultsAndClear(); |
| |
| final XmlTag tag = element.getXmlTag(); |
| new WriteCommandAction(getProject()) { |
| @Override |
| protected void run(Result result) throws Throwable { |
| tag.add(createTag("<indicator/>")); |
| tag.add(createTag("<indicator/>")); |
| } |
| }.execute(); |
| |
| assertTrue(element.isValid()); |
| assertTrue(element.getIndicator().getValue()); |
| element.getIndicator().setValue(false); |
| assertFalse(element.getIndicator().getValue()); |
| assertEquals(0, element.getXmlTag().findSubTags("indicator").length); |
| } |
| |
| public void testConcreteGenericValue() throws Throwable { |
| final ConcreteGeneric generic = createElement("", ConcreteGeneric.class); |
| generic.setValue("abc"); |
| assertEquals("abc", generic.getValue()); |
| |
| DomUIFactory.SET_VALUE_METHOD.invoke(generic, "def"); |
| assertEquals("def", DomUIFactory.GET_VALUE_METHOD.invoke(generic)); |
| } |
| |
| public void testConcreteGenericValueWithMethods() throws Throwable { |
| final ConcreteGenericWithMethods generic = createElement("", ConcreteGenericWithMethods.class); |
| generic.setValue("abc"); |
| assertEquals("abc", generic.getValue()); |
| |
| DomUIFactory.SET_VALUE_METHOD.invoke(generic, "def"); |
| assertEquals("def", DomUIFactory.GET_VALUE_METHOD.invoke(generic)); |
| } |
| |
| public void testNameValueInPresentation() throws Throwable { |
| final MyElement element = createElement(""); |
| element.getAttr().setValue(23942); |
| assertEquals("23942", element.getPresentation().getElementName()); |
| } |
| |
| public void testResolveToDomElement() throws Throwable { |
| final RootInterface element = createElement("", RootInterface.class); |
| final MyElement child1 = element.addChild(); |
| child1.getAttr().setValue(555); |
| final MyElement child2 = element.addChild(); |
| child2.getAttr().setValue(777); |
| |
| final GenericDomValue<MyElement> resolve = child2.getResolve(); |
| resolve.setStringValue("777"); |
| assertEquals(child2, resolve.getValue()); |
| |
| resolve.setValue(child1); |
| assertEquals("555", resolve.getStringValue()); |
| assertEquals(child1, resolve.getValue()); |
| |
| resolve.setStringValue("239"); |
| assertNull(resolve.getValue()); |
| |
| final GenericDomValue<MyElement> resolve2 = child2.getResolve2(); |
| resolve2.setStringValue("777"); |
| assertEquals(child2, resolve2.getValue()); |
| } |
| |
| public void testPlainPsiTypeConverter() throws Throwable { |
| assertNull(createElement("").getPsiType()); |
| assertSame(PsiType.INT, createElement("<a>int</a>").getPsiType()); |
| final PsiType psiType = createElement("<a>java.lang.String</a>").getPsiType(); |
| assertEquals(CommonClassNames.JAVA_LANG_STRING, assertInstanceOf(psiType, PsiClassType.class).getCanonicalText()); |
| |
| final PsiType arrayType = createElement("<a>int[]</a>").getPsiType(); |
| assertTrue(arrayType instanceof PsiArrayType); |
| assertSame(PsiType.INT, ((PsiArrayType) arrayType).getComponentType()); |
| } |
| |
| public void testJvmPsiTypeConverter() throws Throwable { |
| assertNull(createElement("").getJvmPsiType()); |
| assertNotNull(createElement("<a>int</a>").getJvmPsiType()); |
| final PsiClassType string = PsiType.getJavaLangString(getPsiManager(), GlobalSearchScope.allScope(getProject())); |
| final PsiType psiType = createElement("<a>java.lang.String</a>").getJvmPsiType(); |
| assertEquals(CommonClassNames.JAVA_LANG_STRING, assertInstanceOf(psiType, PsiClassType.class).getCanonicalText()); |
| |
| final PsiArrayType intArray = assertInstanceOf(createElement("<a>[I</a>").getJvmPsiType(), PsiArrayType.class); |
| final PsiArrayType stringArray = assertInstanceOf(createElement("<a>[Ljava.lang.String;</a>").getJvmPsiType(), PsiArrayType.class); |
| assertSame(PsiType.INT, intArray.getComponentType()); |
| assertEquals(CommonClassNames.JAVA_LANG_STRING, assertInstanceOf(stringArray.getComponentType(), PsiClassType.class).getCanonicalText()); |
| |
| assertJvmPsiTypeToString(intArray, "[I"); |
| assertJvmPsiTypeToString(stringArray, "[Ljava.lang.String;"); |
| assertJvmPsiTypeToString(string, "java.lang.String"); |
| } |
| |
| public void testValueCaching() throws Throwable { |
| final GenericDomValue<String> element = createElement("<a><cached-value/></a>", MyElement.class).getCachedValue(); |
| assertEquals(0, ((MyConverter) element.getConverter()).fromStringCalls); |
| assertEquals("", element.getValue()); |
| assertEquals(1, ((MyConverter) element.getConverter()).fromStringCalls); |
| assertEquals("", element.getValue()); |
| assertEquals(1, ((MyConverter) element.getConverter()).fromStringCalls); |
| element.setValue("1"); |
| assertEquals(1, ((MyConverter) element.getConverter()).fromStringCalls); |
| assertEquals("1", element.getValue()); |
| assertEquals(2, ((MyConverter) element.getConverter()).fromStringCalls); |
| } |
| |
| |
| private void assertJvmPsiTypeToString(final PsiType type, final String expected) throws IncorrectOperationException { |
| final MyElement element = createElement(""); |
| element.setJvmPsiType(type); |
| assertEquals(expected, element.getValue()); |
| } |
| |
| public void testJavaStyledElement() throws IncorrectOperationException { |
| JavaStyledElement element = createElement("<tag javaStyledAttribute=\"666\"></tag>", JavaStyledElement.class); |
| assertEquals(element.getJavaStyledAttribute().getXmlElementName(), "javaStyledAttribute"); |
| } |
| |
| public void testGenericValueListConverter() throws Throwable { |
| final MyElement element = createElement("<a><string-buffer>abc</string-buffer></a>"); |
| assertEquals("abc", element.getStringBuffers().get(0).getValue().toString()); |
| } |
| |
| public void testConvertAnnotationOnType() throws Throwable { |
| final MyElement element = |
| createElement("<a>" + "<my-generic-value>abc</my-generic-value>" + "<my-foo-generic-value>abc</my-foo-generic-value>" + ""); |
| assertEquals("bar", element.getMyGenericValue().getValue()); |
| assertEquals("foo", element.getMyFooGenericValue().getValue()); |
| } |
| |
| public void testEntities() throws Throwable { |
| final MyElement element = createElement("<!DOCTYPE a SYSTEM \"aaa\"\n" + |
| "[<!ENTITY idgenerator \"identity\">]>\n" + |
| "<a attra=\"a<b\" some-attribute=\"&idgenerator;\">&xxx;+&idgenerator;+&</a>"); |
| assertEquals("a<b", element.getAttributeValue().getValue()); |
| assertEquals("identity", element.getSomeAttribute().getValue()); |
| // assertEquals("&xxx;+identity+&", element.getValue()); |
| } |
| |
| public interface RootInterface extends DomElement { |
| List<MyElement> getChildren(); |
| MyElement addChild(); |
| } |
| |
| |
| public interface MyElement extends DomElement { |
| @Attribute("attra") |
| GenericAttributeValue<String> getAttributeValue(); |
| |
| @NameValue |
| GenericAttributeValue<Integer> getAttr(); |
| |
| GenericAttributeValue<String> getSomeAttribute(); |
| |
| String getValue(); |
| |
| void setValue(Integer value); |
| |
| @TagValue() |
| int getInt(); |
| |
| void setValue(String value); |
| |
| @TagValue() |
| boolean getBoolean(); |
| |
| @TagValue() |
| PsiType getPsiType(); |
| |
| @Convert(JvmPsiTypeConverter.class) |
| @TagValue() |
| PsiType getJvmPsiType(); |
| |
| @TagValue() |
| @Convert(JvmPsiTypeConverter.class) |
| void setJvmPsiType(PsiType psiType); |
| |
| @TagValue() |
| DomTestCase.MyEnum getEnum(); |
| |
| @TagValue |
| void setEnum(DomTestCase.MyEnum value); |
| |
| @TagValue() |
| @Convert(StringBufferConverter.class) |
| StringBuffer getBuffer(); |
| |
| @TagValue() |
| PsiClass getPsiClass(); |
| |
| @TagValue() |
| String getTagValue(); |
| |
| GenericDomValue<Integer> getGenericChild(); |
| |
| @SubTag("buffer") |
| @Convert(StringBufferConverter.class) |
| GenericDomValue<StringBuffer> getGenericChild2(); |
| |
| @SubTag(indicator = true) |
| GenericDomValue<Boolean> getIndicator(); |
| |
| @Resolve(MyElement.class) |
| GenericDomValue<MyElement> getResolve(); |
| |
| GenericDomValue<MyElement> getResolve2(); |
| |
| @Convert(StringBufferConverter.class) |
| List<GenericDomValue<StringBuffer>> getStringBuffers(); |
| |
| @Convert(MyConverter.class) GenericDomValue<String> getCachedValue(); |
| |
| MyGenericValue getMyGenericValue(); |
| |
| @Convert(FooConverter.class) |
| MyGenericValue getMyFooGenericValue(); |
| |
| } |
| |
| @Convert(BarConverter.class) |
| public interface MyGenericValue extends GenericDomValue<String> { |
| } |
| |
| @NameStrategyForAttributes(JavaNameStrategy.class) |
| public interface JavaStyledElement extends DomElement { |
| GenericAttributeValue<String> getJavaStyledAttribute(); |
| } |
| |
| public interface ConcreteGeneric extends GenericDomValue<String> { |
| } |
| |
| public interface ConcreteGenericWithMethods extends GenericDomValue<String> { |
| @Override |
| String getValue(); |
| |
| @Override |
| void setValue(String s); |
| } |
| |
| public void testFuhrer() throws Throwable { |
| final FieldGroup group = createElement("<field-group>\n" + |
| "<group-name>myGroup</load-group-name>\n" + |
| "<field-name>myField1</field-name>\n" + |
| "<field-name>myField2</field-name>\n" + |
| "</field-group>", |
| FieldGroup.class); |
| assertEquals(2, group.getFieldNames().size()); |
| assertEquals("myField1", group.getFieldNames().get(0).getValue().getName().getValue()); |
| assertEquals(null, group.getFieldNames().get(1).getValue()); |
| } |
| |
| public interface JavaeeModelElement { |
| } |
| |
| public interface JavaeeDomModelElement extends JavaeeModelElement, DomElement { |
| } |
| |
| public interface FieldGroup extends JavaeeDomModelElement { |
| |
| GenericDomValue<String> getGroupName(); |
| |
| List<GroupField> getFieldNames(); |
| |
| GroupField addFieldName(); |
| } |
| |
| public interface GroupField extends JavaeeDomModelElement { |
| |
| @Convert(value = CmpFieldConverter.class) |
| CmpField getValue(); |
| |
| @Convert(value = CmpFieldConverter.class) |
| void setValue(CmpField value); |
| } |
| |
| public static class CmpFieldConverter extends ResolvingConverter<CmpField> { |
| |
| @Override |
| public CmpField fromString(String s, ConvertContext context) { |
| return ElementPresentationManager.findByName(getVariants(context), s); |
| } |
| |
| @Override |
| public String toString(CmpField t, ConvertContext context) { |
| return t == null ? null : t.getName().getValue(); |
| } |
| |
| @Override |
| @NotNull |
| public Collection<CmpField> getVariants(ConvertContext context) { |
| final DomElement element = context.getInvocationElement(); |
| return Arrays.asList(createCmpField(null, element), createCmpField("myField1", element), createCmpField("def", element)); |
| } |
| |
| private CmpField createCmpField(String name, DomElement element) { |
| final CmpField mockElement = element.getManager().createMockElement(CmpField.class, element.getModule(), false); |
| mockElement.getName().setValue(name); |
| return mockElement; |
| } |
| } |
| |
| public interface CmpField extends JavaeeDomModelElement { |
| @NameValue |
| public GenericDomValue<String> getName(); |
| } |
| |
| public static class MyConverter extends Converter<String> { |
| public int fromStringCalls = 0; |
| |
| @Override |
| public String fromString(@Nullable @NonNls String s, final ConvertContext context) { |
| fromStringCalls++; |
| return s; |
| } |
| |
| @Override |
| public String toString(@Nullable String s, final ConvertContext context) { |
| return s; |
| } |
| } |
| |
| public static class FooConverter extends Converter<String> { |
| @Override |
| public String fromString(@Nullable @NonNls final String s, final ConvertContext context) { |
| return s == null ? null : "foo"; |
| } |
| |
| @Override |
| public String toString(@Nullable final String s, final ConvertContext context) { |
| return s; |
| } |
| } |
| public static class BarConverter extends Converter<String> { |
| @Override |
| public String fromString(@Nullable @NonNls final String s, final ConvertContext context) { |
| return s == null ? null : "bar"; |
| } |
| |
| @Override |
| public String toString(@Nullable final String s, final ConvertContext context) { |
| return s; |
| } |
| } |
| |
| } |