private ContributionDef createContributionToMasterObjectProvider()

in tapestry-spring/src/main/java/org/apache/tapestry5/internal/spring/SpringModuleDef.java [264:361]


    private ContributionDef createContributionToMasterObjectProvider()
    {

        ContributionDef def = new AbstractContributionDef()
        {
            @Override
            public String getServiceId()
            {
                return "MasterObjectProvider";
            }

            @Override
            public void contribute(ModuleBuilderSource moduleSource, ServiceResources resources,
                                   OrderedConfiguration configuration)
            {
                final OperationTracker tracker = resources.getTracker();

                final ApplicationContext context = resources.getService(SERVICE_ID,
                        ApplicationContext.class);

                final ObjectProvider springBeanProvider = new ObjectProvider()
                {
                    @Override
                    public <T> T provide(Class<T> objectType,
                                         AnnotationProvider annotationProvider, ObjectLocator locator)
                    {

                        Map beanMap = context.getBeansOfType(objectType);

                        switch (beanMap.size())
                        {
                            case 0:
                                return null;

                            case 1:

                                Object bean = beanMap.values().iterator().next();

                                return objectType.cast(bean);

                            default:

                                String message = String
                                        .format(
                                                "Spring context contains %d beans assignable to type %s: %s.",
                                                beanMap.size(), PlasticUtils.toTypeName(objectType), InternalUtils
                                                .joinSorted(beanMap.keySet()));

                                throw new IllegalArgumentException(message);
                        }
                    }
                };

                final ObjectProvider springBeanProviderInvoker = new ObjectProvider()
                {
                    @Override
                    public <T> T provide(final Class<T> objectType,
                                         final AnnotationProvider annotationProvider, final ObjectLocator locator)
                    {
                        return tracker.invoke(
                                "Resolving dependency by searching Spring ApplicationContext",
                                new Invokable<T>()
                                {
                                    @Override
                                    public T invoke()
                                    {
                                        return springBeanProvider.provide(objectType,
                                                annotationProvider, locator);
                                    }
                                });
                    }
                };

                ObjectProvider outerCheck = new ObjectProvider()
                {
                    @Override
                    public <T> T provide(Class<T> objectType,
                                         AnnotationProvider annotationProvider, ObjectLocator locator)
                    {
                        // I think the following line is the only reason we put the
                        // SpringBeanProvider here,
                        // rather than in SpringModule.

                        if (!applicationContextCreated.get())
                            return null;

                        return springBeanProviderInvoker.provide(objectType, annotationProvider,
                                locator);
                    }
                };


                configuration.add("SpringBean", outerCheck, "after:AnnotationBasedContributions", "after:ServiceOverride");
            }
        };

        return def;
    }