com.github.yihtserns.jaxbean.unmarshaller.api.SpringBeanHandlerTest.java Source code

Java tutorial

Introduction

Here is the source code for com.github.yihtserns.jaxbean.unmarshaller.api.SpringBeanHandlerTest.java

Source

/*
 * Copyright 2016 yihtserns.
 *
 * 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.github.yihtserns.jaxbean.unmarshaller.api;

import com.github.yihtserns.jaxbean.unmarshaller.AbstractSpecTest;
import com.github.yihtserns.jaxbean.unmarshaller.JaxbeanUnmarshaller;
import java.io.StringReader;
import org.junit.Test;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.NamespaceHandler;
import org.springframework.beans.factory.xml.NamespaceHandlerResolver;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.context.support.GenericApplicationContext;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

/**
 * @author yihtserns
 */
public class SpringBeanHandlerTest extends AbstractSpecTest {

    @Override
    protected <T> T unmarshal(String xml, Class<T> rootType, Class<?>... allTypes) throws Exception {
        JaxbeanUnmarshaller unmarshaller = JaxbeanUnmarshaller.newInstance(merge(rootType, allTypes));
        final UnmarshallerNamespaceHandler unmarshallerNamespaceHandler = new UnmarshallerNamespaceHandler(
                unmarshaller);

        GenericApplicationContext appContext = new GenericApplicationContext();
        XmlBeanDefinitionReader xmlReader = new XmlBeanDefinitionReader(appContext) {

            @Override
            protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
                final NamespaceHandlerResolver defaultResolver = super.createDefaultNamespaceHandlerResolver();
                return new NamespaceHandlerResolver() {

                    public NamespaceHandler resolve(String namespaceUri) {
                        if (namespaceUri.equals("http://example.com/jaxb")) {
                            return unmarshallerNamespaceHandler;
                        }
                        return defaultResolver.resolve(namespaceUri);
                    }
                };
            }
        };
        xmlReader.setValidating(false);
        xmlReader.loadBeanDefinitions(new InputSource(new StringReader(xml)));
        appContext.refresh();

        return appContext.getBean(rootType);
    }

    @Test
    public void canResolvePropertyPlaceholders() throws Exception {
        String xml = "<beans xmlns=\"http://www.springframework.org/schema/beans\""
                + "     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
                + "     xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd\""
                + "  >\n"
                + "  <bean class=\"org.springframework.beans.factory.config.PropertyPlaceholderConfigurer\">\n"
                + "    <property name=\"properties\">\n" + "      <value>\n" + "        obj.count=3\n"
                + "        obj.displayName=JAXB\n" + "        obj.duration=#{10*10}\n" + "        obj.valid=true\n"
                + "        obj.description=${obj.displayName} Object\n" + "        obj.skip=true\n"
                + "        obj.executable=false\n" + "        obj.child.name=A Child\n"
                + "        obj.child.counter=100\n" + "        obj.child.duration=200\n"
                + "        obj.child.valid=true\n" + "        obj.child.description=${obj.child.name} Element\n"
                + "        obj.child.skip=false\n" + "        obj.child.executable=true\n"
                + "        obj.secondObj.valid=true\n" + "        obj.child.named.valid=true\n"
                + "        obj.parent.child.valid=true\n" + "        obj.parent.child.named.valid=true\n"
                + "        obj.setter.child.valid=true\n" + "        obj.getter.child.valid=true\n"
                + "        obj.setter.child.named.valid=true\n" + "        obj.children[1].valid=true\n"
                + "        obj.children[2].valid=false\n" + "        obj.children[3].valid=true\n"
                + "        obj.children.1.valid=true\n" + "        obj.children.2.valid=false\n"
                + "        obj.children.3.valid=true\n" + "        obj.child.note=A child\n"
                + "        obj.alias[1]=This\n" + "        obj.alias[2]=That\n" + "        obj.alias[3]=It\n"
                + "        obj.options1.options1.1=skip-invalid\n"
                + "        obj.options1.options1.2=purge-skipped\n"
                + "        obj.options2.option2.1=skip-invalid\n" + "        obj.options2.option2.2=purge-skipped\n"
                + "        obj.wrappedOptions3.options3.1=skip-invalid\n"
                + "        obj.wrappedOptions3.options3.2=purge-skipped\n"
                + "        obj.wrappedOptions4.option4.1=skip-invalid\n"
                + "        obj.wrappedOptions4.option4.2=purge-skipped\n"
                + "        obj.wrappedOptions5.option5.1.valid=true\n"
                + "        obj.wrappedOptions5.option5.2.valid=false\n" + "        obj.child.typed.name=A Child\n"
                + "        obj.child1.valid=true\n" + "        obj.childList1.1.valid=true\n"
                + "        obj.childList2.1.valid=false\n" + "        obj.childList2.2.valid=true\n"
                + "        obj.childList1.2.valid=false\n" + "        obj.options6.child1.valid=true\n"
                + "        obj.options6.child2.valid=false\n" + "        obj2.annotation=WIP\n"
                + "        obj2.metadata.entry1.key=author\n" + "        obj2.metadata.entry1.value=Me\n"
                + "        obj2.metadata.entry2.key=obsolete\n" + "        obj2.metadata.entry2.value=Yes\n"
                + "        obj.message1=1st rev: An object\n" + "        obj.annotation=Dangerous one\n"
                + "        obj.message2=2nd rev: Reduce power\n" + "        obj2.obj.displayName=First ref\n"
                + "        obj2.annotationAttr=WIP\n" + "      </value>\n" + "    </property>\n" + "  </bean>\n"
                + "\n" + "  <root xmlns=\"http://example.com/jaxb\">\n" + "    <jaxbObject"
                + "      count=\"${obj.count}\"" + "      displayName=\"${obj.displayName}\""
                + "      duration=\"${obj.duration}\"" + "      valid=\"${obj.valid}\""
                + "      description=\"${obj.description}\"" + "      skip=\"${obj.skip}\""
                + "      executable=\"${obj.executable}\"" + "    >\n" + "      <child"
                + "        name=\"${obj.child.name}\"" + "        counter=\"${obj.child.counter}\""
                + "        duration=\"${obj.child.duration}\"" + "        valid=\"${obj.child.valid}\""
                + "        description=\"${obj.child.description}\"" + "        skip=\"${obj.child.skip}\""
                + "        executable=\"${obj.child.executable}\"" + "      >\n"
                + "        <note>${obj.child.note}</note>\n" + "      </child>\n"
                + "      <secondJaxbObject valid=\"${obj.secondObj.valid}\"/>\n"
                + "      <childWithName valid=\"${obj.child.named.valid}\"/>\n"
                + "      <parentChild valid=\"${obj.parent.child.valid}\"/>\n"
                + "      <parentChildWithName valid=\"${obj.parent.child.named.valid}\"/>\n"
                + "      <setterChild valid=\"${obj.setter.child.valid}\"/>\n"
                + "      <getterChild valid=\"${obj.getter.child.valid}\"/>\n"
                + "      <setterChildWithName valid=\"${obj.setter.child.named.valid}\"/>\n"
                + "      <childrenArray valid=\"${obj.children[1].valid}\"/>\n"
                + "      <childrenArray valid=\"${obj.children[2].valid}\"/>\n"
                + "      <childrenArray valid=\"${obj.children[3].valid}\"/>\n"
                + "      <children valid=\"${obj.children.1.valid}\"/>\n"
                + "      <children valid=\"${obj.children.2.valid}\"/>\n"
                + "      <children valid=\"${obj.children.3.valid}\"/>\n" + "      <alias>${obj.alias[1]}</alias>\n"
                + "      <alias>${obj.alias[2]}</alias>\n" + "      <alias>${obj.alias[3]}</alias>\n"
                + "      <options1>\n" + "        <options1>${obj.options1.options1.1}</options1>\n"
                + "        <options1>${obj.options1.options1.2}</options1>\n" + "      </options1>\n"
                + "      <options2>\n" + "        <option2>${obj.options2.option2.1}</option2>\n"
                + "        <option2>${obj.options2.option2.2}</option2>\n" + "      </options2>\n"
                + "      <wrappedOptions3>\n" + "        <options3>${obj.wrappedOptions3.options3.1}</options3>\n"
                + "        <options3>${obj.wrappedOptions3.options3.2}</options3>\n" + "      </wrappedOptions3>\n"
                + "      <wrappedOptions4>\n" + "        <option4>${obj.wrappedOptions4.option4.1}</option4>\n"
                + "        <option4>${obj.wrappedOptions4.option4.2}</option4>\n" + "      </wrappedOptions4>\n"
                + "      <wrappedOptions5>\n"
                + "        <option5 valid=\"${obj.wrappedOptions5.option5.1.valid}\"/>\n"
                + "        <option5 valid=\"${obj.wrappedOptions5.option5.2.valid}\"/>\n"
                + "      </wrappedOptions5>\n" + "      <typedChild name=\"${obj.child.typed.name}\"/>\n"
                + "      <child1 valid=\"${obj.child1.valid}\"/>\n"
                + "      <childList1 valid=\"${obj.childList1.1.valid}\"/>\n"
                + "      <childList2 valid=\"${obj.childList2.1.valid}\"/>\n"
                + "      <childList2 valid=\"${obj.childList2.2.valid}\"/>\n"
                + "      <childList1 valid=\"${obj.childList1.2.valid}\"/>\n" + "      <options6>\n"
                + "        <child1 valid=\"${obj.options6.child1.valid}\"/>\n"
                + "        <child2 valid=\"${obj.options6.child2.valid}\"/>\n" + "      </options6>\n"
                + "      <message>${obj.message1}</message>\n"
                + "      <annotation>${obj.annotation}</annotation>\n"
                + "      <message>${obj.message2}</message>\n" + "    </jaxbObject>\n"
                + "    <secondJaxbObject annotationAttr=\"${obj2.annotationAttr}\">\n"
                + "      <jaxbObject displayName=\"${obj2.obj.displayName}\"/>\n"
                + "      <annotation>${obj2.annotation}</annotation>\n" + "      <metadata>\n"
                + "        <entry key=\"${obj2.metadata.entry1.key}\" value=\"${obj2.metadata.entry1.value}\"/>\n"
                + "        <entry key=\"${obj2.metadata.entry2.key}\" value=\"${obj2.metadata.entry2.value}\"/>\n"
                + "      </metadata>\n" + "    </secondJaxbObject>\n" + "  </root>\n" + "</beans>";

        Root root = unmarshal(xml, Root.class, AbstractSpecTest.JaxbObject.class,
                AbstractSpecTest.JaxbObject2.class, AbstractSpecTest.Message.class,
                AbstractSpecTest.Annotation.class);
        {
            AbstractSpecTest.JaxbObject result = root.getJaxbObject();
            assertThat(result.getCount(), is(3));
            assertThat(result.getId(), is("JAXB"));
            assertThat(result.getLength(), is(100L));
            assertThat(result.isValid(), is(true));
            assertThat(result.getDescription(), is("JAXB Object"));
            assertThat(result.isIgnore(), is(true));
            assertThat(result.isRunnable(), is(false));
            assertThat(result.getChild().getName(), is("A Child"));
            assertThat(result.getChild().getCount(), is(100L));
            assertThat(result.getChild().getLength(), is(200L));
            assertThat(result.getChild().isValid(), is(true));
            assertThat(result.getChild().getDescription(), is("A Child Element"));
            assertThat(result.getChild().isIgnore(), is(false));
            assertThat(result.getChild().isRunnable(), is(true));
            assertThat(result.getGlobalChild().isValid(), is(true));
            assertThat(result.getNamedChild().isValid(), is(true));
            assertThat(result.getParentChild().isValid(), is(true));
            assertThat(result.getNamedParentChild().isValid(), is(true));
            assertThat(result.getSetterChild().isValid(), is(true));
            assertThat(result.getGetterChild().isValid(), is(true));
            assertThat(result.getNamedSetterChild().isValid(), is(true));
            assertThat(result.getChildrenArray()[0].isValid(), is(true));
            assertThat(result.getChildrenArray()[1].isValid(), is(false));
            assertThat(result.getChildrenArray()[2].isValid(), is(true));
            assertThat(result.getChildren().get(0).isValid(), is(true));
            assertThat(result.getChildren().get(1).isValid(), is(false));
            assertThat(result.getChildren().get(2).isValid(), is(true));
            assertThat(result.getAliases(), contains("This", "That", "It"));
            assertThat(result.getOptions1(), contains("skip-invalid", "purge-skipped"));
            assertThat(result.getOptions2(), contains("skip-invalid", "purge-skipped"));
            assertThat(result.getOptions3(), contains("skip-invalid", "purge-skipped"));
            assertThat(result.getOptions4(), contains("skip-invalid", "purge-skipped"));
            assertThat(result.getOptions5().get(0).isValid(), is(true));
            assertThat(result.getOptions5().get(1).isValid(), is(false));
            assertThat(((AbstractSpecTest.JaxbChild) result.getTypedChild()).getName(), is("A Child"));
            assertThat(result.getTwoTypes().isValid(), is(true));
            assertThat(result.getTwoTypeList().get(0).isValid(), is(true));
            assertThat(result.getTwoTypeList().get(1).isValid(), is(false));
            assertThat(result.getTwoTypeList().get(2).isValid(), is(true));
            assertThat(result.getTwoTypeList().get(3).isValid(), is(false));
            assertThat(result.getOptions6().get(0).isValid(), is(true));
            assertThat(result.getOptions6().get(1).isValid(), is(false));
            assertThat(result.getChild().getNote().getText(), is("A child"));
            assertThat(result.getNotes().get(0).getText(), is("1st rev: An object"));
            assertThat(result.getNotes().get(1).getText(), is("Dangerous one"));
            assertThat(result.getNotes().get(2).getText(), is("2nd rev: Reduce power"));
        }
        {
            AbstractSpecTest.JaxbObject2 result = root.getSecondJaxbObject();
            assertThat(((AbstractSpecTest.JaxbObject) result.getMultiGlobalChild()).getId(), is("First ref"));
            assertThat(result.getAnnotation().getText(), is("WIP"));
            assertThat(result.getMetadata(), hasEntry("author", "Me"));
            assertThat(result.getMetadata(), hasEntry("obsolete", "Yes"));
            assertThat(result.getAnnotationAttr().getText(), is("WIP"));
        }
    }

    private static final class UnmarshallerNamespaceHandler extends AbstractBeanDefinitionParser
            implements NamespaceHandler {

        private JaxbeanUnmarshaller unmarshaller;

        public UnmarshallerNamespaceHandler(JaxbeanUnmarshaller unmarshaller) {
            this.unmarshaller = unmarshaller;
        }

        @Override
        protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) {
            try {
                return (AbstractBeanDefinition) unmarshaller.unmarshal(element, SpringBeanHandler.INSTANCE);
            } catch (Exception ex) {
                String localName = parserContext.getDelegate().getLocalName(element);

                parserContext.getReaderContext().fatal("Unable to unmarshal element '" + localName + "'", element,
                        ex);
                return null;
            }
        }

        @Override
        protected boolean shouldGenerateIdAsFallback() {
            return true;
        }

        public void init() {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }

        public BeanDefinitionHolder decorate(Node source, BeanDefinitionHolder definition,
                ParserContext parserContext) {
            throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
        }
    }
}