/** * This file Copyright (c) 2003-2012 Magnolia International * Ltd. (http://www.magnolia-cms.com). All rights reserved. * * * This file is dual-licensed under both the Magnolia * Network Agreement and the GNU General Public License. * You may elect to use one or the other of these licenses. * * This file is distributed in the hope that it will be * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT. * Redistribution, except as permitted by whichever of the GPL * or MNA you select, is prohibited. * * 1. For the GPL license (GPL), you can redistribute and/or * modify this file under the terms of the GNU General * Public License, Version 3, as published by the Free Software * Foundation. You should have received a copy of the GNU * General Public License, Version 3 along with this program; * if not, write to the Free Software Foundation, Inc., 51 * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * 2. For the Magnolia Network Agreement (MNA), this file * and the accompanying materials are made available under the * terms of the MNA which accompanies this distribution, and * is available at http://www.magnolia-cms.com/mna.html * * Any modifications to this file must keep this entire header * intact. * */ package info.magnolia.content2bean; import static org.junit.Assert.*; import info.magnolia.cms.core.Content; import info.magnolia.content2bean.impl.Content2BeanProcessorImpl; import info.magnolia.content2bean.impl.Content2BeanTransformerImpl; import info.magnolia.content2bean.impl.TypeMappingImpl; import info.magnolia.context.MgnlContext; import info.magnolia.repository.RepositoryConstants; import info.magnolia.test.ComponentsTestUtil; import info.magnolia.test.mock.MockComponentProvider; import info.magnolia.test.mock.MockUtil; import java.io.IOException; import java.util.AbstractMap; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Vector; import javax.jcr.RepositoryException; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; /** * @version $Id$ */ public class Content2BeanTest { @Before public void setUp() { ComponentsTestUtil.setImplementation(TypeMapping.class, TypeMappingImpl.class); ComponentsTestUtil.setImplementation(Content2BeanTransformer.class, Content2BeanTransformerImpl.class); ComponentsTestUtil.setImplementation(Content2BeanProcessor.class, Content2BeanProcessorImpl.class); } @After public void tearDown() { ComponentsTestUtil.clear(); MgnlContext.setInstance(null); } @Test public void testContentToBeanWithClassDefined() throws Content2BeanException { Content node = MockUtil.createNode("node", new Object[][] { { "class", "info.magnolia.content2bean.SimpleBean" }, { "prop1", "prop1Value" }, { "prop2", "prop2Value" } }); Object bean = Content2BeanUtil.toBean(node); assertTrue(bean instanceof SimpleBean); assertEquals("prop1Value", ((SimpleBean) bean).getProp1()); assertEquals("prop2Value", ((SimpleBean) bean).getProp2()); } @Test public void testContentToBeanWithDefaultClass() throws Content2BeanException { Content node = MockUtil.createNode("node", new Object[][] { { "prop1", "prop1Value" }, { "prop2", "prop2Value" } }); Object bean = Content2BeanUtil.toBean(node, SimpleBean.class); assertTrue(bean instanceof SimpleBean); assertEquals("prop1Value", ((SimpleBean) bean).getProp1()); assertEquals("prop2Value", ((SimpleBean) bean).getProp2()); } @Test public void testContentToBeanWithSubBean() throws Content2BeanException { Content node = MockUtil.createContent("parent", new String[][] { { "class", "info.magnolia.content2bean.BeanWithSubBean" }, { "prop1", "propParent1Value" }, { "prop2", "propParent2Value" } }, new Content[] { MockUtil.createNode("sub", new String[][] { { "class", "info.magnolia.content2bean.OtherSimpleBean" }, { "prop1", "propSub1Value" }, { "prop2", "propSub2Value" } }) }); BeanWithSubBean bean = (BeanWithSubBean) Content2BeanUtil.toBean(node, true); OtherSimpleBean sub = (OtherSimpleBean) bean.getSub(); assertNotNull(sub); assertEquals("propParent1Value", bean.getProp1()); assertEquals("propParent2Value", bean.getProp2()); assertEquals("propSub1Value", sub.getProp1()); assertEquals("propSub2Value", sub.getProp2()); } @Test public void testContentToBeanWithSubBeanAndAutoTypeResolving() throws Content2BeanException { Content node = MockUtil.createContent("parent", new String[][] { { "class", "info.magnolia.content2bean.BeanWithSubBean" }, { "prop1", "propParent1Value" }, { "prop2", "propParent2Value" } }, new Content[] { MockUtil.createNode("sub", new String[][] { { "prop1", "propSub1Value" }, { "prop2", "propSub2Value" } }) }); BeanWithSubBean bean = (BeanWithSubBean) Content2BeanUtil.toBean(node, true); SimpleBean sub = bean.getSub(); assertNotNull(sub); assertEquals("propParent1Value", bean.getProp1()); assertEquals("propParent2Value", bean.getProp2()); assertEquals("propSub1Value", sub.getProp1()); assertEquals("propSub2Value", sub.getProp2()); } @Test public void testContentToBeanWithSubMap() throws Content2BeanException { Content node = MockUtil.createContent("parent", new String[][] { { "class", "info.magnolia.content2bean.BeanWithMap" }, { "prop1", "propParent1Value" }, { "prop2", "propParent2Value" } }, new Content[] { MockUtil.createContent("beans", new String[][] {}, new Content[] { MockUtil.createNode("sub1", new String[][] { { "class", "info.magnolia.content2bean.SimpleBean" }, { "prop1", "prop1Sub1Value" }, { "prop2", "prop2Sub1Value" } }), MockUtil.createNode("sub2", new String[][] { { "class", "info.magnolia.content2bean.SimpleBean" }, { "prop1", "prop1Sub2Value" }, { "prop2", "prop2Sub2Value" } }), }) }); BeanWithMap bean = (BeanWithMap) Content2BeanUtil.toBean(node, true); Map beans = bean.getBeans(); assertNotNull(beans); assertNotNull(beans.get("sub1")); assertNotNull(beans.get("sub2")); assertEquals("prop1Sub1Value", ((SimpleBean) beans.get("sub1")).getProp1()); assertEquals("prop2Sub1Value", ((SimpleBean) beans.get("sub1")).getProp2()); assertEquals("prop1Sub2Value", ((SimpleBean) beans.get("sub2")).getProp1()); assertEquals("prop2Sub2Value", ((SimpleBean) beans.get("sub2")).getProp2()); } @Test public void testContentToBeanWithSubMapUsingMapping() throws Content2BeanException { Content node = MockUtil.createContent("parent", new String[][] { { "class", "info.magnolia.content2bean.BeanWithMap" }, { "prop1", "propParent1Value" }, { "prop2", "propParent2Value" } }, new Content[] { MockUtil.createContent("beans", new String[][] {}, new Content[] { MockUtil.createNode("sub1", new String[][] { { "prop1", "prop1Sub1Value" }, { "prop2", "prop2Sub1Value" } }), MockUtil.createNode("sub2", new String[][] { { "prop1", "prop1Sub2Value" }, { "prop2", "prop2Sub2Value" } }), }) }); Content2BeanUtil.addCollectionPropertyMapping(BeanWithMap.class, "beans", SimpleBean.class); BeanWithMap bean = (BeanWithMap) Content2BeanUtil.toBean(node, true); Map beans = bean.getBeans(); assertNotNull(beans); assertNotNull(beans.get("sub1")); assertNotNull(beans.get("sub2")); assertEquals("prop1Sub1Value", ((SimpleBean) beans.get("sub1")).getProp1()); assertEquals("prop2Sub1Value", ((SimpleBean) beans.get("sub1")).getProp2()); assertEquals("prop1Sub2Value", ((SimpleBean) beans.get("sub2")).getProp1()); assertEquals("prop2Sub2Value", ((SimpleBean) beans.get("sub2")).getProp2()); } @Test public void testContentToBeanWithSubMapUsingAdder() throws Content2BeanException { Content node = MockUtil.createContent("parent", new String[][] { { "class", "info.magnolia.content2bean.BeanWithMapAndAdder" }, { "prop1", "propParent1Value" }, { "prop2", "propParent2Value" } }, new Content[] { MockUtil.createContent("beans", new String[][] {}, new Content[] { MockUtil.createNode("sub1", new String[][] { { "prop1", "prop1Sub1Value" }, { "prop2", "prop2Sub1Value" } }), MockUtil.createNode("sub2", new String[][] { { "prop1", "prop1Sub2Value" }, { "prop2", "prop2Sub2Value" } }), }) }); BeanWithMapAndAdder bean = (BeanWithMapAndAdder) Content2BeanUtil.toBean(node, true); Map beans = bean.getBeans(); assertNotNull(beans); assertNotNull(beans.get("sub1")); assertNotNull(beans.get("sub2")); assertEquals("prop1Sub1Value", ((SimpleBean) beans.get("sub1")).getProp1()); assertEquals("prop2Sub1Value", ((SimpleBean) beans.get("sub1")).getProp2()); assertEquals("prop1Sub2Value", ((SimpleBean) beans.get("sub2")).getProp1()); assertEquals("prop2Sub2Value", ((SimpleBean) beans.get("sub2")).getProp2()); } @Test public void testContentToBeanWithArraysUsingAdder() throws Content2BeanException { Content node = MockUtil.createContent("parent", new String[][] { { "class", "info.magnolia.content2bean.BeanWithArrayAndAdder" }, { "prop1", "propParent1Value" }, { "prop2", "propParent2Value" } }, new Content[] { MockUtil.createContent("beans", new String[][] {}, new Content[] { MockUtil.createNode("sub1", new String[][] { { "prop1", "prop1Sub1Value" }, { "prop2", "prop2Sub1Value" } }), MockUtil.createNode("sub2", new String[][] { { "prop1", "prop1Sub2Value" }, { "prop2", "prop2Sub2Value" } }), }) }); BeanWithArrayAndAdder bean = (BeanWithArrayAndAdder) Content2BeanUtil.toBean(node, true); assertEquals(2, bean.getBeans().length); assertNotNull(bean.getBeans()[0]); assertNotNull(bean.getBeans()[1]); assertEquals("prop1Sub1Value", bean.getBeans()[0].getProp1()); assertEquals("prop2Sub1Value", bean.getBeans()[0].getProp2()); assertEquals("prop1Sub2Value", bean.getBeans()[1].getProp1()); assertEquals("prop2Sub2Value", bean.getBeans()[1].getProp2()); } @Test public void testClassPropertiesAreConvertedProperly() throws Content2BeanException { Content node = MockUtil.createContent("parent", new String[][] { { "class", "info.magnolia.content2bean.BeanWithClass" }, { "foo", "blah" }, { "clazz", "java.lang.String" } }, new Content[0]); BeanWithClass o = (BeanWithClass) Content2BeanUtil.toBean(node, true); assertEquals("blah", o.getFoo()); assertEquals(String.class, o.getClazz()); } @Test public void testJCRPropertiesTypes() throws Content2BeanException { Content node = MockUtil.createContent("parent", new Object[][] { { "class", "info.magnolia.content2bean.BeanWithPrimitiveProperties" }, { "integer", Integer.valueOf(5) }, { "bool", Boolean.TRUE } }, new Content[0]); BeanWithPrimitiveProperties bean = (BeanWithPrimitiveProperties) Content2BeanUtil.toBean(node, true); assertEquals(5, bean.getInteger()); assertEquals(true, bean.isBool()); } @Test public void testFromStringConversion() throws Content2BeanException { Content node = MockUtil.createContent("parent", new Object[][] { { "class", "info.magnolia.content2bean.BeanWithPrimitiveProperties" }, { "integer", "5" }, { "bool", "true" } }, new Content[0]); BeanWithPrimitiveProperties bean = (BeanWithPrimitiveProperties) Content2BeanUtil.toBean(node, true); assertEquals(5, bean.getInteger()); assertEquals(true, bean.isBool()); } @Test public void testFlatteningSubNodesToSimpleList() throws RepositoryException, Content2BeanException, IOException { String data = "/parent.class=" + BeanWithListOfString.class.getName() + "\n" + "/parent/values/sub1.value=one\n" + "/parent/values/sub2.value=two"; Content node = MockUtil.createHierarchyManager(RepositoryConstants.WEBSITE, data).getContent("/parent"); // System.out.println(Content2BeanUtil.toMap(node.getContent("values"), true)); BeanWithListOfString bean = (BeanWithListOfString) Content2BeanUtil.toBean(node, true); assertEquals("one", bean.getValues().get(0)); assertEquals("two", bean.getValues().get(1)); } @Test public void testCanConvertStringsToTheAppropriateEnumEquivalent() throws Exception { Content node = MockUtil.createContent("myNode", new String[][] { { "class", "info.magnolia.content2bean.BeanWithEnum" }, { "foobar", "Why, Hello !" }, { "sample", "two" } }, new Content[0]); BeanWithEnum result = (BeanWithEnum) Content2BeanUtil.toBean(node, true); assertEquals("Why, Hello !", result.getFoobar()); assertNotNull(result.getSample()); assertTrue(result.getSample().getClass().isEnum()); assertEquals(SampleEnum.two, result.getSample()); } @Test public void testCanSpecifySpecificMapImplementation() throws Exception { final Content node = MockUtil.createNode("/foo/bar", "/foo/bar.class=" + BeanWithMap.class.getName(), "/foo/bar/beans.class=" + MyMap.class.getName(), "/foo/bar/beans/a.class=" + SimpleBean.class.getName(), "/foo/bar/beans/a.prop1=hello", "/foo/bar/beans/b.class=" + SimpleBean.class.getName(), "/foo/bar/beans/b.prop1=world"); final BeanWithMap res = (BeanWithMap) Content2BeanUtil.toBean(node, true); // sanity checks: assertNotNull(res); final Map map = res.getBeans(); assertNotNull(map); assertEquals("hello", ((SimpleBean) map.get("a")).getProp1()); assertEquals("world", ((SimpleBean) map.get("b")).getProp1()); // actual test: assertTrue("we wanted a custom map impl!", map instanceof MyMap); } @Test @Ignore("TODO - MAGNOLIA-3160") public void testCanSpecifySpecificCollectionImplementation() throws Exception { final Content node = MockUtil.createNode("/foo/bar", "/foo/bar.class=" + BeanWithCollection.class.getName(), "/foo/bar/beans.class=" + Vector.class.getName(), "/foo/bar/beans/a.class=" + SimpleBean.class.getName(), "/foo/bar/beans/a.prop1=hello", "/foo/bar/beans/b.class=" + SimpleBean.class.getName(), "/foo/bar/beans/b.prop1=world"); final BeanWithCollection res = (BeanWithCollection) Content2BeanUtil.toBean(node, true); // sanity checks: assertNotNull(res); final Collection coll = res.getBeans(); assertNotNull(coll); assertEquals(2, coll.size()); final Iterator it = coll.iterator(); final SimpleBean a = (SimpleBean) it.next(); final SimpleBean b = (SimpleBean) it.next(); assertNotSame(a, b); assertFalse(a.getProp1().equals(b.getProp1())); assertTrue("hello".equals(a.getProp1()) || "hello".equals(b.getProp1())); assertTrue("world".equals(a.getProp1()) || "world".equals(b.getProp1())); // actual test: assertTrue("we wanted a custom collection impl!", coll instanceof Vector); } @Test public void testWillFailToUseACustomMapWhichIsNotConcrete() throws Exception { // DUH ! final Content node = MockUtil.createNode("/bar", "/bar.class=" + BeanWithMap.class.getName(), "/bar/beans.class=" + StupidMap.class.getName(), "/bar/beans/a.class=" + SimpleBean.class.getName(), "/bar/beans/a.prop1=hello", "/bar/beans/b.class=" + SimpleBean.class.getName(), "/bar/beans/b.prop1=world"); // TODO - forceCreation true by default - so we can't test via Content2BeanUtil.toBean() here final Content2BeanProcessorImpl proc = (Content2BeanProcessorImpl) Content2BeanUtil.getContent2BeanProcessor(); proc.setForceCreation(false); final Content2BeanTransformer trans = Content2BeanUtil.getContent2BeanTransformer(); try { proc.toBean(node, true, trans, new MockComponentProvider()); fail("should have failed"); } catch (Content2BeanException t) { assertEquals("Can't instantiate bean for /bar/beans", t.getMessage()); final String causeMsg = t.getCause().getMessage(); assertTrue(causeMsg.contains("StupidMap")); assertTrue(causeMsg.contains("No concrete implementation defined")); } } @Test public void testWillNotAddIncorrectTypesToMap() throws RepositoryException, IOException, Content2BeanException { // GIVEN final Content node = MockUtil.createNode("/foo", "/foo.class=" + BeanWithMapAndAdder.class.getName(), "/foo/beans.untitled=", "/foo/beans/a.prop1=test" ); // WHEN final BeanWithMapAndAdder bean = (BeanWithMapAndAdder) Content2BeanUtil.toBean(node, true); // THEN assertEquals(1, bean.getBeans().size()); assertTrue(bean.getBeans().get("a") instanceof SimpleBean); } @Test public void testWillNodAddIncorrectTypesToCollection() throws RepositoryException, IOException, Content2BeanException { // GIVEN final Content node = MockUtil.createNode("/foo", "/foo.class=" + BeanWithCollectionAndAdder.class.getName(), "/foo/beans.untitled=", "/foo/beans/a.prop1=test" ); // WHEN final BeanWithCollectionAndAdder bean = (BeanWithCollectionAndAdder) Content2BeanUtil.toBean(node, true); // THEN assertEquals(1, bean.getBeans().size()); assertTrue(bean.getBeans().iterator().next() instanceof SimpleBean); } public static class MyMap extends HashMap { } public abstract static class StupidMap extends AbstractMap { } }