public function generate(ReflectionClass $originalClass, ClassGenerator $classGenerator)
    {
        CanProxyAssertion::assertClassCanBeProxied($originalClass, false);

        $annotation = null;
        $forceLazyInitProperty = new ForceLazyInitProperty();
        $sessionBeansProperty = new SessionBeansProperty();
        $postProcessorsProperty = new BeanPostProcessorsProperty();
        $parameterValuesProperty = new ParameterValuesProperty();
        $beanFactoryConfigurationProperty = new BeanFactoryConfigurationProperty();
        $aliasesProperty = new AliasesProperty();
        $getParameterMethod = new GetParameter($parameterValuesProperty);
        $wrapBeanAsLazyMethod = new WrapBeanAsLazy($beanFactoryConfigurationProperty);

        try {
            $reader = new AnnotationReader();
            $annotation = $reader->getClassAnnotation($originalClass, Configuration::class);
        } catch (Exception $e) {
            throw new InvalidProxiedClassException($e->getMessage(), $e->getCode(), $e);
        }

        if (null === $annotation) {
            throw new InvalidProxiedClassException(
                sprintf(
                    '"%s" seems not to be a valid configuration class. @Configuration annotation missing!',
                    $originalClass->name
                )
            );
        }

        $classGenerator->setExtendedClass($originalClass->getName());
        $classGenerator->setImplementedInterfaces([AliasContainerInterface::class]);
        $classGenerator->addPropertyFromGenerator($forceLazyInitProperty);
        $classGenerator->addPropertyFromGenerator($sessionBeansProperty);
        $classGenerator->addPropertyFromGenerator($postProcessorsProperty);
        $classGenerator->addPropertyFromGenerator($parameterValuesProperty);
        $classGenerator->addPropertyFromGenerator($beanFactoryConfigurationProperty);
        $classGenerator->addPropertyFromGenerator($aliasesProperty);

        $postProcessorMethods = [];
        $parentAliases = [];
        $localAliases = [];
        $methods = $originalClass->getMethods(ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED);
        foreach ($methods as $method) {
            $methodReflection = new MethodReflection(
                $method->class,
                $method->name
            );

            /** @var \bitExpert\Disco\Annotations\Bean|null $beanAnnotation */
            $beanAnnotation = $reader->getMethodAnnotation($method, Bean::class);
            if (null === $beanAnnotation) {
                /** @var \bitExpert\Disco\Annotations\BeanPostProcessor $beanAnnotation */
                $beanAnnotation = $reader->getMethodAnnotation($method, BeanPostProcessor::class);
                if ($beanAnnotation instanceof BeanPostProcessor) {
                    $postProcessorMethods[] = $method->name;

                    $proxyMethod = BeanPostProcessorMethod::generateMethod(
                        $methodReflection,
                        $beanAnnotation,
                        $getParameterMethod
                    );
                    $classGenerator->addMethodFromGenerator($proxyMethod);
                    continue;
                }

                if ($method->isProtected()) {
                    continue;
                }

                // every method needs either @Bean or @PostPostprocessor annotation
                throw new InvalidProxiedClassException(
                    sprintf(
                        'Method "%s" on "%s" is missing the @Bean annotation!',
                        $method->name,
                        $originalClass->name
                    )
                );
            }

            foreach ($beanAnnotation->getAliases() as $beanAlias) {
                $alias = $beanAlias->isTypeAlias() ? (string) $method->getReturnType() : $beanAlias->getName();
                if (empty($alias)) {
                    continue;
                }

                $hasAlias = '';
                if ($method->getDeclaringClass()->name === $originalClass->name) {
                    $hasAlias = $localAliases[$alias] ?? '';
                } else {
                    $hasAlias= $parentAliases[$alias] ?? '';
                }

                if ($hasAlias !== '') {
                    throw new InvalidProxiedClassException(
                        sprintf(
                            'Alias "%s" of method "%s" on "%s" is already used by method "%s" of another Bean!'
                            . ' Did you use a type alias twice?',
                            $alias,
                            $method->name,
                            $originalClass->name,
                            $hasAlias
                        )
                    );
                }

                if ($method->getDeclaringClass()->name === $originalClass->name) {
                    $localAliases[$alias] = $method->name;
                } else {
                    $parentAliases[$alias] = $method->name;
                }
            }

            $proxyMethod = BeanMethod::generateMethod(
                $methodReflection,
                $beanAnnotation,
                $method->getReturnType(),
                $forceLazyInitProperty,
                $sessionBeansProperty,
                $postProcessorsProperty,
                $beanFactoryConfigurationProperty,
                $getParameterMethod,
                $wrapBeanAsLazyMethod
            );

            $classGenerator->addMethodFromGenerator($proxyMethod);
        }

        $aliasesProperty->setDefaultValue($parentAliases + $localAliases);

        $classGenerator->addMethodFromGenerator(
            new Constructor(
                $parameterValuesProperty,
                $sessionBeansProperty,
                $beanFactoryConfigurationProperty,
                $postProcessorsProperty,
                $postProcessorMethods
            )
        );
        $classGenerator->addMethodFromGenerator($wrapBeanAsLazyMethod);
        $classGenerator->addMethodFromGenerator($getParameterMethod);
        $classGenerator->addMethodFromGenerator(
            new MagicSleep(
                $originalClass,
                $sessionBeansProperty
            )
        );
        $classGenerator->addMethodFromGenerator(
            new GetAlias($aliasesProperty)
        );
        $classGenerator->addMethodFromGenerator(
            new HasAlias($aliasesProperty)
        );
    }
public function generate(ReflectionClass $originalClass, ClassGenerator $classGenerator)
    {
        CanProxyAssertion::assertClassCanBeProxied($originalClass, false);

        $annotation = null;
        $forceLazyInitProperty = new ForceLazyInitProperty();
        $sessionBeansProperty = new SessionBeansProperty();
        $postProcessorsProperty = new BeanPostProcessorsProperty();
        $parameterValuesProperty = new ParameterValuesProperty();
        $beanFactoryConfigurationProperty = new BeanFactoryConfigurationProperty();
        $aliasesProperty = new AliasesProperty();
        $getParameterMethod = new GetParameter($parameterValuesProperty);
        $wrapBeanAsLazyMethod = new WrapBeanAsLazy($beanFactoryConfigurationProperty);

        try {
            $reader = new AnnotationReader();
            $annotation = $reader->getClassAnnotation($originalClass, Configuration::class);
        } catch (Exception $e) {
            throw new InvalidProxiedClassException($e->getMessage(), $e->getCode(), $e);
        }

        if (null === $annotation) {
            throw new InvalidProxiedClassException(
                sprintf(
                    '"%s" seems not to be a valid configuration class. @Configuration annotation missing!',
                    $originalClass->name
                )
            );
        }

        $classGenerator->setExtendedClass($originalClass->getName());
        $classGenerator->setImplementedInterfaces([AliasContainerInterface::class]);
        $classGenerator->addPropertyFromGenerator($forceLazyInitProperty);
        $classGenerator->addPropertyFromGenerator($sessionBeansProperty);
        $classGenerator->addPropertyFromGenerator($postProcessorsProperty);
        $classGenerator->addPropertyFromGenerator($parameterValuesProperty);
        $classGenerator->addPropertyFromGenerator($beanFactoryConfigurationProperty);
        $classGenerator->addPropertyFromGenerator($aliasesProperty);

        $postProcessorMethods = [];
        $parentAliases = [];
        $localAliases = [];
        $methods = $originalClass->getMethods(ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED);
        foreach ($methods as $method) {
            $methodReflection = new MethodReflection(
                $method->class,
                $method->name
            );

            
            $beanAnnotation = $reader->getMethodAnnotation($method, Bean::class);
            if (null === $beanAnnotation) {
                
                $beanAnnotation = $reader->getMethodAnnotation($method, BeanPostProcessor::class);
                if ($beanAnnotation instanceof BeanPostProcessor) {
                    $postProcessorMethods[] = $method->name;

                    $proxyMethod = BeanPostProcessorMethod::generateMethod(
                        $methodReflection,
                        $beanAnnotation,
                        $getParameterMethod
                    );
                    $classGenerator->addMethodFromGenerator($proxyMethod);
                    continue;
                }

                if ($method->isProtected()) {
                    continue;
                }

                
                throw new InvalidProxiedClassException(
                    sprintf(
                        'Method "%s" on "%s" is missing the @Bean annotation!',
                        $method->name,
                        $originalClass->name
                    )
                );
            }

            foreach ($beanAnnotation->getAliases() as $beanAlias) {
                $alias = $beanAlias->isTypeAlias() ? (string) $method->getReturnType() : $beanAlias->getName();
                if (empty($alias)) {
                    continue;
                }

                $hasAlias = '';
                if ($method->getDeclaringClass()->name === $originalClass->name) {
                    $hasAlias = $localAliases[$alias] ?? '';
                } else {
                    $hasAlias= $parentAliases[$alias] ?? '';
                }

                if ($hasAlias !== '') {
                    throw new InvalidProxiedClassException(
                        sprintf(
                            'Alias "%s" of method "%s" on "%s" is already used by method "%s" of another Bean!'
                            . ' Did you use a type alias twice?',
                            $alias,
                            $method->name,
                            $originalClass->name,
                            $hasAlias
                        )
                    );
                }

                if ($method->getDeclaringClass()->name === $originalClass->name) {
                    $localAliases[$alias] = $method->name;
                } else {
                    $parentAliases[$alias] = $method->name;
                }
            }

            $proxyMethod = BeanMethod::generateMethod(
                $methodReflection,
                $beanAnnotation,
                $method->getReturnType(),
                $forceLazyInitProperty,
                $sessionBeansProperty,
                $postProcessorsProperty,
                $beanFactoryConfigurationProperty,
                $getParameterMethod,
                $wrapBeanAsLazyMethod
            );

            $classGenerator->addMethodFromGenerator($proxyMethod);
        }

        $aliasesProperty->setDefaultValue($parentAliases + $localAliases);

        $classGenerator->addMethodFromGenerator(
            new Constructor(
                $parameterValuesProperty,
                $sessionBeansProperty,
                $beanFactoryConfigurationProperty,
                $postProcessorsProperty,
                $postProcessorMethods
            )
        );
        $classGenerator->addMethodFromGenerator($wrapBeanAsLazyMethod);
        $classGenerator->addMethodFromGenerator($getParameterMethod);
        $classGenerator->addMethodFromGenerator(
            new MagicSleep(
                $originalClass,
                $sessionBeansProperty
            )
        );
        $classGenerator->addMethodFromGenerator(
            new GetAlias($aliasesProperty)
        );
        $classGenerator->addMethodFromGenerator(
            new HasAlias($aliasesProperty)
        );
    }
public function generate ( ReflectionClass $ originalClass , ClassGenerator $ classGenerator ) { CanProxyAssertion :: assertClassCanBeProxied ( $ originalClass , false ) ; $ annotation = null ; $ forceLazyInitProperty = new ForceLazyInitProperty ( ) ; $ sessionBeansProperty = new SessionBeansProperty ( ) ; $ postProcessorsProperty = new BeanPostProcessorsProperty ( ) ; $ parameterValuesProperty = new ParameterValuesProperty ( ) ; $ beanFactoryConfigurationProperty = new BeanFactoryConfigurationProperty ( ) ; $ aliasesProperty = new AliasesProperty ( ) ; $ getParameterMethod = new GetParameter ( $ parameterValuesProperty ) ; $ wrapBeanAsLazyMethod = new WrapBeanAsLazy ( $ beanFactoryConfigurationProperty ) ; try { $ reader = new AnnotationReader ( ) ; $ annotation = $ reader -> getClassAnnotation ( $ originalClass , Configuration :: class ) ; } catch ( Exception $ e ) { throw new InvalidProxiedClassException ( $ e -> getMessage ( ) , $ e -> getCode ( ) , $ e ) ; } if ( null === $ annotation ) { throw new InvalidProxiedClassException ( sprintf ( '"%s" seems not to be a valid configuration class. @Configuration annotation missing!' , $ originalClass -> name ) ) ; } $ classGenerator -> setExtendedClass ( $ originalClass -> getName ( ) ) ; $ classGenerator -> setImplementedInterfaces ( [ AliasContainerInterface :: class ] ) ; $ classGenerator -> addPropertyFromGenerator ( $ forceLazyInitProperty ) ; $ classGenerator -> addPropertyFromGenerator ( $ sessionBeansProperty ) ; $ classGenerator -> addPropertyFromGenerator ( $ postProcessorsProperty ) ; $ classGenerator -> addPropertyFromGenerator ( $ parameterValuesProperty ) ; $ classGenerator -> addPropertyFromGenerator ( $ beanFactoryConfigurationProperty ) ; $ classGenerator -> addPropertyFromGenerator ( $ aliasesProperty ) ; $ postProcessorMethods = [ ] ; $ parentAliases = [ ] ; $ localAliases = [ ] ; $ methods = $ originalClass -> getMethods ( ReflectionMethod :: IS_PUBLIC | ReflectionMethod :: IS_PROTECTED ) ; foreach ( $ methods as $ method ) { $ methodReflection = new MethodReflection ( $ method -> class , $ method -> name ) ; /** @var \bitExpert\Disco\Annotations\Bean|null $beanAnnotation */ $ beanAnnotation = $ reader -> getMethodAnnotation ( $ method , Bean :: class ) ; if ( null === $ beanAnnotation ) { /** @var \bitExpert\Disco\Annotations\BeanPostProcessor $beanAnnotation */ $ beanAnnotation = $ reader -> getMethodAnnotation ( $ method , BeanPostProcessor :: class ) ; if ( $ beanAnnotation instanceof BeanPostProcessor ) { $ postProcessorMethods [ ] = $ method -> name ; $ proxyMethod = BeanPostProcessorMethod :: generateMethod ( $ methodReflection , $ beanAnnotation , $ getParameterMethod ) ; $ classGenerator -> addMethodFromGenerator ( $ proxyMethod ) ; continue ; } if ( $ method -> isProtected ( ) ) { continue ; } // every method needs either @Bean or @PostPostprocessor annotation throw new InvalidProxiedClassException ( sprintf ( 'Method "%s" on "%s" is missing the @Bean annotation!' , $ method -> name , $ originalClass -> name ) ) ; } foreach ( $ beanAnnotation -> getAliases ( ) as $ beanAlias ) { $ alias = $ beanAlias -> isTypeAlias ( ) ? ( string ) $ method -> getReturnType ( ) : $ beanAlias -> getName ( ) ; if ( empty ( $ alias ) ) { continue ; } $ hasAlias = '' ; if ( $ method -> getDeclaringClass ( ) -> name === $ originalClass -> name ) { $ hasAlias = $ localAliases [ $ alias ] ?? '' ; } else { $ hasAlias = $ parentAliases [ $ alias ] ?? '' ; } if ( $ hasAlias !== '' ) { throw new InvalidProxiedClassException ( sprintf ( 'Alias "%s" of method "%s" on "%s" is already used by method "%s" of another Bean!' . ' Did you use a type alias twice?' , $ alias , $ method -> name , $ originalClass -> name , $ hasAlias ) ) ; } if ( $ method -> getDeclaringClass ( ) -> name === $ originalClass -> name ) { $ localAliases [ $ alias ] = $ method -> name ; } else { $ parentAliases [ $ alias ] = $ method -> name ; } } $ proxyMethod = BeanMethod :: generateMethod ( $ methodReflection , $ beanAnnotation , $ method -> getReturnType ( ) , $ forceLazyInitProperty , $ sessionBeansProperty , $ postProcessorsProperty , $ beanFactoryConfigurationProperty , $ getParameterMethod , $ wrapBeanAsLazyMethod ) ; $ classGenerator -> addMethodFromGenerator ( $ proxyMethod ) ; } $ aliasesProperty -> setDefaultValue ( $ parentAliases + $ localAliases ) ; $ classGenerator -> addMethodFromGenerator ( new Constructor ( $ parameterValuesProperty , $ sessionBeansProperty , $ beanFactoryConfigurationProperty , $ postProcessorsProperty , $ postProcessorMethods ) ) ; $ classGenerator -> addMethodFromGenerator ( $ wrapBeanAsLazyMethod ) ; $ classGenerator -> addMethodFromGenerator ( $ getParameterMethod ) ; $ classGenerator -> addMethodFromGenerator ( new MagicSleep ( $ originalClass , $ sessionBeansProperty ) ) ; $ classGenerator -> addMethodFromGenerator ( new GetAlias ( $ aliasesProperty ) ) ; $ classGenerator -> addMethodFromGenerator ( new HasAlias ( $ aliasesProperty ) ) ; }
{@inheritDoc}
@throws InvalidProxiedClassException
@throws InvalidArgumentException
@throws \ReflectionException
{