001    /*****************************************************************************
002     * Copyright (c) PicoContainer Organization. All rights reserved.            *
003     * ------------------------------------------------------------------------- *
004     * The software in this package is published under the terms of the BSD      *
005     * style license a copy of which has been included with this distribution in *
006     * the LICENSE.txt file.                                                     *
007     *                                                                           *
008     *****************************************************************************/
009    
010    package org.picocontainer.behaviors;
011    
012    
013    import static org.junit.Assert.assertEquals;
014    import static org.junit.Assert.assertNotNull;
015    
016    import org.junit.Test;
017    import org.picocontainer.Characteristics;
018    import org.picocontainer.ComponentAdapter;
019    import org.picocontainer.ComponentFactory;
020    import org.picocontainer.DefaultPicoContainer;
021    import org.picocontainer.adapters.InstanceAdapter;
022    import org.picocontainer.injectors.AdaptingInjection;
023    import org.picocontainer.injectors.ConstructorInjection;
024    import org.picocontainer.injectors.ConstructorInjector;
025    import org.picocontainer.lifecycle.NullLifecycleStrategy;
026    import org.picocontainer.monitors.NullComponentMonitor;
027    import org.picocontainer.tck.AbstractComponentFactoryTest;
028    
029    
030    public class ImplementationHidingTestCase extends AbstractComponentFactoryTest{
031    
032        @Test public void testAddComponentUsesImplementationHidingBehavior() {
033            DefaultPicoContainer pico =
034                new DefaultPicoContainer(new ImplementationHiding().wrap(new ConstructorInjection()));
035            pico.addComponent("foo", String.class);
036            ComponentAdapter<?> foo = pico.getComponentAdapter("foo");
037            assertEquals(HiddenImplementation.class, foo.getClass());
038            assertEquals(ConstructorInjector.class, ((AbstractBehavior) foo).getDelegate().getClass());
039        }
040    
041        @Test public void testAddComponentUsesImplementationHidingBehaviorWithRedundantHideImplProperty() {
042            DefaultPicoContainer pico =
043                new DefaultPicoContainer(new ImplementationHiding().wrap(new ConstructorInjection()));
044            pico.change(Characteristics.HIDE_IMPL).addComponent("foo", String.class);
045            ComponentAdapter<?> foo = pico.getComponentAdapter("foo");
046            assertEquals(HiddenImplementation.class, foo.getClass());
047            assertEquals(ConstructorInjector.class, ((AbstractBehavior) foo).getDelegate().getClass());
048        }
049    
050        @Test public void testAddComponentNoesNotUseImplementationHidingBehaviorWhenNoCachePropertyIsSpecified() {
051            DefaultPicoContainer pico =
052                new DefaultPicoContainer(new ImplementationHiding().wrap(new ConstructorInjection()));
053            pico.change(Characteristics.NO_HIDE_IMPL).addComponent("foo", String.class);
054            ComponentAdapter<?> foo = pico.getComponentAdapter("foo");
055            assertEquals(ConstructorInjector.class, foo.getClass());
056        }
057    
058        @Test public void testAddAdapterUsesImplementationHidingBehavior() {
059            DefaultPicoContainer pico =
060                new DefaultPicoContainer(new ImplementationHiding().wrap(new ConstructorInjection()));
061            pico.addAdapter(new InstanceAdapter("foo", "bar", new NullLifecycleStrategy(), new NullComponentMonitor()));
062            ComponentAdapter<?> foo = pico.getComponentAdapter("foo");
063            assertEquals(HiddenImplementation.class, foo.getClass());
064            assertEquals(InstanceAdapter.class, ((AbstractBehavior) foo).getDelegate().getClass());
065        }
066    
067        @Test public void testAddAdapterUsesImplementationHidingBehaviorWithRedundantHideImplProperty() {
068            DefaultPicoContainer pico =
069                new DefaultPicoContainer(new ImplementationHiding().wrap(new ConstructorInjection()));
070            pico.change(Characteristics.HIDE_IMPL).addAdapter(new InstanceAdapter("foo", "bar", new NullLifecycleStrategy(), new NullComponentMonitor()));
071            ComponentAdapter<?> foo = pico.getComponentAdapter("foo");
072            assertEquals(HiddenImplementation.class, foo.getClass());
073            assertEquals(InstanceAdapter.class, ((AbstractBehavior) foo).getDelegate().getClass());
074        }
075    
076        @Test public void testAddAdapterNoesNotUseImplementationHidingBehaviorWhenNoCachePropertyIsSpecified() {
077            DefaultPicoContainer pico =
078                new DefaultPicoContainer(new ImplementationHiding().wrap(new ConstructorInjection()));
079            pico.change(Characteristics.NO_HIDE_IMPL).addAdapter(new InstanceAdapter("foo", "bar", new NullLifecycleStrategy(), new NullComponentMonitor()));
080            ComponentAdapter<?> foo = pico.getComponentAdapter("foo");
081            assertEquals(InstanceAdapter.class, foo.getClass());
082        }
083    
084    
085        private final ComponentFactory implementationHidingComponentFactory =
086            new ImplementationHiding().wrap(new AdaptingInjection());
087    
088        protected ComponentFactory createComponentFactory() {
089            return implementationHidingComponentFactory;
090        }
091    
092    
093        public static interface NeedsStringBuilder {
094            void foo();
095        }
096        public static class NeedsStringBuilderImpl implements NeedsStringBuilder {
097            StringBuilder sb;
098    
099            public NeedsStringBuilderImpl(StringBuilder sb) {
100                this.sb = sb;
101                sb.append("<init>");
102            }
103            public void foo() {
104                sb.append("foo()");
105            }
106        }
107        public static class NeedsNeedsStringBuilder {
108    
109            NeedsStringBuilder nsb;
110    
111            public NeedsNeedsStringBuilder(NeedsStringBuilder nsb) {
112                this.nsb = nsb;
113            }
114            public void foo() {
115                nsb.foo();
116            }
117        }
118    
119        @Test public void testLazyInstantiationSideEffectWhenForceOfDelayedInstantiationOfDependantClass() {
120            DefaultPicoContainer pico =
121                new DefaultPicoContainer(new ImplementationHiding().wrap(new Caching().wrap(new ConstructorInjection())));
122            pico.addComponent(StringBuilder.class);
123            pico.addComponent(NeedsStringBuilder.class, NeedsStringBuilderImpl.class);
124            pico.addComponent(NeedsNeedsStringBuilder.class);
125            NeedsNeedsStringBuilder nnsb = pico.getComponent(NeedsNeedsStringBuilder.class);
126            assertNotNull(nnsb);
127            StringBuilder sb = pico.getComponent(StringBuilder.class);
128            assertEquals("", sb.toString()); // not instantiated yet
129            nnsb.foo();
130            assertEquals("<init>foo()", sb.toString()); // instantiated
131        }
132    
133        @Test public void shouldNotInstantiateForEveryMethodCall() {
134            DefaultPicoContainer parent = new DefaultPicoContainer(new Caching());
135            parent.addComponent(StringBuilder.class);
136            DefaultPicoContainer pico =
137                new DefaultPicoContainer(new ImplementationHiding(), parent);
138            pico.addComponent(NeedsStringBuilder.class, NeedsStringBuilderImpl.class);
139            NeedsStringBuilder nsb = pico.getComponent(NeedsStringBuilder.class);
140            assertNotNull(nsb);
141            nsb.foo();
142            nsb.foo();
143            StringBuilder sb = pico.getComponent(StringBuilder.class);
144            assertEquals("<init>foo()foo()", sb.toString());
145        }
146    
147    
148    
149    }