Package org.drools.compiler.cdi

Source Code of org.drools.compiler.cdi.KieCDIExtension

package org.drools.compiler.cdi;

import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.event.Observes;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Default;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.ProcessInjectionTarget;
import javax.enterprise.util.AnnotationLiteral;
import javax.inject.Named;

import org.drools.core.util.StringUtils;
import org.drools.compiler.kproject.models.KieSessionModelImpl;
import org.kie.api.KieBase;
import org.kie.api.KieServices;
import org.kie.api.builder.model.KieBaseModel;
import org.kie.api.builder.model.KieSessionModel;
import org.kie.api.builder.model.KieSessionModel.KieSessionType;
import org.kie.api.builder.ReleaseId;
import org.drools.compiler.kie.builder.impl.InternalKieModule;
import org.drools.compiler.kie.builder.impl.KieContainerImpl;
import org.drools.compiler.kie.builder.impl.KieProject;
import org.kie.api.cdi.KBase;
import org.kie.api.cdi.KReleaseId;
import org.kie.api.cdi.KSession;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.internal.runtime.StatefulKnowledgeSession;
import org.kie.api.runtime.StatelessKieSession;
import org.kie.internal.runtime.StatelessKnowledgeSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class KieCDIExtension
    implements
    Extension {

    private static final Logger                     log           = LoggerFactory.getLogger( KieCDIExtension.class );

    private Map<KieCDIEntry, KieCDIEntry>           kContainerNames;
    private Map<KieCDIEntry, KieCDIEntry>           kBaseNames;
    private Map<KieCDIEntry, KieCDIEntry>           kSessionNames;

    private Map<ReleaseId, KieContainer>            gavs;

    private Map<String, KieCDIEntry>                named;

    private KieContainerImpl                        classpathKContainer;

    private final static AnnotationLiteral<Default> defaultAnnLit = new AnnotationLiteral<Default>() {
                                                                  };
    private final static AnnotationLiteral<Any>     anyAnnLit     = new AnnotationLiteral<Any>() {
                                                                  };
    public KieCDIExtension() { }

    public void init() {
        final KieServices ks = KieServices.Factory.get();
        gavs = new HashMap<ReleaseId, KieContainer>();
        classpathKContainer = (KieContainerImpl) ks.newKieClasspathContainer(); //new KieContainerImpl( kProject, null );
        named = new HashMap<String, KieCDIExtension.KieCDIEntry>();
    }

    public <Object> void processInjectionTarget(@Observes ProcessInjectionTarget<Object> pit,
                                                BeanManager beanManager) {
        if ( classpathKContainer == null ) {
            init();
        }

        KieServices ks = KieServices.Factory.get();

        // Find all uses of KieBaseModel and KieSessionModel and add to Set index
        if ( !pit.getInjectionTarget().getInjectionPoints().isEmpty() ) {
            for ( InjectionPoint ip : pit.getInjectionTarget().getInjectionPoints() ) {               
                boolean kBaseExists = false;
                boolean kSessionExists = false;
                boolean kContainerExists = false;
                Class clazz = getClassType(ip);

                if (clazz != null) {
                    KBase kBase = null;
                    KSession kSession = null;
                    if ( ( KieSession.class.isAssignableFromclazz ) || StatelessKieSession.class.isAssignableFrom( clazz ) )  ) {
                        kSession = ip.getAnnotated().getAnnotation( KSession.class );
                        kSessionExists = true;
                    } else if KieBase.class.isAssignableFrom( clazz ) ) {
                        kBaseExists = true;
                        kBase = ip.getAnnotated().getAnnotation( KBase.class );
                    } else if KieContainer.class.isAssignableFrom( clazz ) ) {
                        kContainerExists = true;
                    }

                    if ( !kSessionExists && !kBaseExists && !kContainerExists) {
                        continue;
                    }



                    KReleaseId kReleaseId = ip.getAnnotated().getAnnotation( KReleaseId.class );
                    ReleaseId releaseId = null;
                    if ( kReleaseId != null ) {
                        releaseId = ks.newReleaseId(kReleaseId.groupId(),
                                                    kReleaseId.artifactId(),
                                                    kReleaseId.version());
                        gavs.put(releaseId,
                                  null );
                    }

                    Class< ? extends Annotation> scope = ApplicationScoped.class;

                    if ( kBaseExists ) {
                        addKBaseInjectionPoint(ip, kBase,scope, releaseId, kReleaseId);
                    } else if ( kSessionExists ) {
                        addKSessionInjectionPoint(ip, kSession, scope, releaseId, kReleaseId);
                    } else if ( kContainerExists ) {
                        addKContainerInjectionPoint(ip, null, scope, releaseId, kReleaseId);
                    }
                }
            }
        }
    }
   
    public void addKBaseInjectionPoint(InjectionPoint ip, KBase kBase, Class< ? extends Annotation> scope, ReleaseId releaseId, KReleaseId kReleaseId) {
        if ( kBaseNames == null ) {
            kBaseNames = new HashMap<KieCDIEntry, KieCDIEntry>();
        }
       
        String namedStr = ( kBase == null ) ? null : kBase.name();

        KieCDIEntry newEntry = new KieCDIEntry( (kBase == null) ? null : kBase.value(),
                                                KieBase.class,
                                                scope,
                                                releaseId,
                                                kReleaseId,
                                                namedStr );

        KieCDIEntry existingEntry = kBaseNames.remove( newEntry );
        if ( existingEntry != null ) {
            // it already exists, so just update its Set of InjectionPoints
            // Note any duplicate "named" would be handled via this.
            existingEntry.addInjectionPoint( ip );
            kBaseNames.put( existingEntry, existingEntry );
        }
       
        if ( !StringUtils.isEmpty( namedStr ) ) {
            existingEntry = named.get( namedStr );  
            if ( existingEntry == null ) {
                // it is named, but nothing existing for it to clash ambigously with
                named.put( namedStr, newEntry );
                kBaseNames.put(newEntry,newEntry);                           
            } else {
                // this name exists, but we know it's a different KieCDIEntry due to the previous existing check
                log.error( "name={} declaration used ambiguiously existing: {} new: {}",
                           new String[] { namedStr,
                                          existingEntry.toString(),
                                          newEntry.toString() });
            }

        } else {
            // is not named and no existing entry
            kBaseNames.put(newEntry,newEntry);
        }       
    }

    public void addKSessionInjectionPoint(InjectionPoint ip, KSession kSession, Class< ? extends Annotation> scope, ReleaseId releaseId, KReleaseId kReleaseId) {
        if ( kSessionNames == null ) {
            kSessionNames = new HashMap<KieCDIEntry, KieCDIEntry>();
        }
       
        String namedStr = ( kSession == null ) ? null : kSession.name();
       
        KieCDIEntry newEntry = new KieCDIEntry( (kSession == null) ? null : kSession.value(),
                                                getClassType(ip),
                                                scope,
                                                releaseId,
                                                kReleaseId,
                                                namedStr );

        KieCDIEntry existingEntry = kSessionNames.remove( newEntry );
        if ( existingEntry != null ) {
            // it already exists, so just update its Set of InjectionPoints
            // Note any duplicate "named" would be handled via this.
            existingEntry.addInjectionPoint( ip );
            kSessionNames.put( existingEntry, existingEntry );
        }
       
        if ( !StringUtils.isEmpty( namedStr ) ) {
            existingEntry = named.get( namedStr );  
            if ( existingEntry == null ) {
                // it is named, but nothing existing for it to clash ambiguously with
                named.put( namedStr, newEntry );
                kSessionNames.put(newEntry,newEntry);                           
            } else {
                // this name exists, but we know it's a different KieCDIEntry due to the previous existing check
                log.error( "name={} declaration used ambiguiously existing: {} new: {}",
                           new String[] { namedStr,
                                          existingEntry.toString(),
                                          newEntry.toString() });
            }

        } else {
            // is not named and no existing entry
            kSessionNames.put(newEntry,newEntry);
        }       
    }
   
    public void addKContainerInjectionPoint(InjectionPoint ip, String namedStr, Class< ? extends Annotation> scope, ReleaseId releaseId, KReleaseId kReleaseId) {
        if ( kContainerNames == null ) {
            kContainerNames = new HashMap<KieCDIEntry, KieCDIEntry>();
        }
       
        KieCDIEntry newEntry = new KieCDIEntry( null,
                                                KieContainer.class,
                                                scope,
                                                releaseId,
                                                kReleaseId,
                                                namedStr );

        KieCDIEntry existingEntry = kContainerNames.remove( newEntry );
        if ( existingEntry != null ) {
            // it already exists, so just update its Set of InjectionPoints
            // Note any duplicate "named" would be handled via this.
            existingEntry.addInjectionPoint( ip );
            kContainerNames.put( existingEntry, existingEntry );
        }
       
        if ( !StringUtils.isEmpty( namedStr ) ) {
            existingEntry = named.get( namedStr );  
            if ( existingEntry == null ) {
                // it is named, but nothing existing for it to clash ambigously with
                named.put( namedStr, newEntry );
                kContainerNames.put(newEntry,newEntry);                           
            } else {
                // this name exists, but we know it's a different KieCDIEntry due to the previous existing check
                log.error( "name={} declaration used ambiguiously existing: {} new: {}",
                           new String[] { namedStr,
                                          existingEntry.toString(),
                                          newEntry.toString() });
            }

        } else {
            // is not named and no existing entry
            kContainerNames.put(newEntry,newEntry);
        }       
    }   
       
   
    public void afterBeanDiscovery(@Observes AfterBeanDiscovery abd,
                                   BeanManager bm) {
        if ( classpathKContainer != null ) {
            // if classpathKContainer null, processInjectionTarget was not called, so beans to create
            KieServices ks = KieServices.Factory.get();

            // to array, so we don't mutate that which we are iterating over
            if ( !gavs.isEmpty() ) {
                for ( ReleaseId releaseId : gavs.keySet().toArray( new ReleaseId[gavs.size()] ) ) {
                    KieContainer kContainer = ks.newKieContainer(releaseId);
                    if ( kContainer == null ) {
                        log.error( "Unable to retrieve KieContainer for @ReleaseId({})",
                                   releaseId.toString() );
                    } else {
                        log.debug( "KieContainer retrieved for @ReleaseId({})",
                                   releaseId.toString() );
                    }
                    gavs.put(releaseId,
                             kContainer );
                }
            }
           
            if ( kContainerNames != null ) {
                for ( KieCDIEntry entry : kContainerNames.keySet() ) {
                    addKContainerBean( abd,
                                       entry );
                }
            }
           
            if ( kBaseNames != null ) {
                for ( KieCDIEntry entry : kBaseNames.keySet() ) {
                    addKBaseBean( abd,
                                  entry );
                }
            }
            kBaseNames = null;

            if ( kSessionNames != null ) {
                for ( KieCDIEntry entry : kSessionNames.keySet() ) {
                    addKSessionBean( abd,
                                     entry );
                }
            }
            kSessionNames = null;
        }
    }

    public void addKContainerBean(AfterBeanDiscovery abd,
                                  KieCDIEntry entry) {       
        ReleaseId releaseId = entry.getReleaseId();
        KieContainerImpl kieContainer = classpathKContainer; // default to classpath, but allow it to be overriden
        if ( releaseId != null ) { //&& !StringUtils.isEmpty( releaseId.getGroupId() ) && !StringUtils.isEmpty( releaseId.getArtifactId() ) && !StringUtils.isEmpty( releaseId.getArtifactId())) {
            kieContainer = (KieContainerImpl) gavs.get(releaseId);
            if ( kieContainer == null ) {
                log.error( "Could not retrieve KieContainer for ReleaseId {}",
                           entry.getValue(),
                           releaseId.toString() );
                return;
            }
        }

        KContainerBean bean = new KContainerBean(kieContainer,
                                                 entry.getKReleaseId(),
                                                 entry.getName(),
                                                 entry.getInjectionPoints() );
       
        if ( log.isDebugEnabled() ) {
            log.debug( "Added Bean for @KContainer({})",
                       releaseId );
        }
        abd.addBean( bean );
    }   
   
   
    public void addKBaseBean(AfterBeanDiscovery abd,
                             KieCDIEntry entry) {
        ReleaseId releaseId = entry.getReleaseId();
        KieContainerImpl kieContainer = classpathKContainer; // default to classpath, but allow it to be overriden
        if ( releaseId != null ) {
            kieContainer = (KieContainerImpl) gavs.get(releaseId);
            if ( kieContainer == null ) {
                log.error( "Unable to create @KBase({}), could not retrieve KieContainer for ReleaseId {}",
                           entry.getValue(),
                           releaseId.toString() );
                return;
            }
        }
        KieProject kProject = kieContainer.getKieProject();

        KieBaseModel kBaseModel = null;
        String kBaseQName = entry.getValue();
        if ( StringUtils.isEmpty( kBaseQName  )) {
            kBaseModel = kProject.getDefaultKieBaseModel();
        } else {
            kBaseModel = kProject.getKieBaseModel( kBaseQName );  
        }       
        if ( kBaseModel == null ) {
            log.error( "Annotation @KBase({}) found, but no KieBaseModel exist.\nEither the required kproject.xml does not exist, was corrupted, or mising the KieBase entry",
                       kBaseQName );
            return;
        }
        if ( !kBaseModel.getScope().trim().equals( entry.getScope().getClass().getName() ) ) {
            try {
                if ( kBaseModel.getScope().indexOf( '.' ) >= 0 ) {
                    entry.setScope( (Class< ? extends Annotation>) Class.forName( kBaseModel.getScope() ) );
                } else {
                    entry.setScope( (Class< ? extends Annotation>) Class.forName( "javax.enterprise.context." + kBaseModel.getScope() ) );
                }
            } catch ( ClassNotFoundException e ) {
                log.error( "KieBaseModule {} overrides default annotation, but it was not able to find it {}\n{}",
                           new String[]{kBaseQName, kBaseModel.getScope(), e.getMessage()} );
            }
        }
        KBaseBean bean = new KBaseBean( kBaseModel,
                                        kieContainer,
                                        entry.getKReleaseId(),
                                        entry.getScope(),
                                        entry.getName(),
                                        entry.getInjectionPoints() );
        if ( log.isDebugEnabled() ) {
            InternalKieModule kModule = kProject.getKieModuleForKBase( kBaseQName );
            log.debug( "Added Bean for @KBase({})",
                       kBaseQName,
                       kModule );
        }
        abd.addBean( bean );
    }

    public void addKSessionBean(AfterBeanDiscovery abd,
                                KieCDIEntry entry) {
        ReleaseId releaseId = entry.getReleaseId();
        KieContainerImpl kieContainer = classpathKContainer; // default to classpath, but allow it to be overriden
        if ( releaseId != null ) {
            kieContainer = (KieContainerImpl) gavs.get(releaseId);
            if ( kieContainer == null ) {
                log.error( "Unable to create KSession({}), could not retrieve KieContainer for ReleaseId {}",
                           entry.getValue(),
                           releaseId.toString() );
                return;
            }
        }
        KieProject kProject = kieContainer.getKieProject();

        String kSessionName = entry.getValue();
        KieSessionModel kSessionModel = null;
        if ( StringUtils.isEmpty( kSessionName  )) {
            kSessionModel = ( entry.getType() == KieSession.class ) ? kProject.getDefaultKieSession() : kProject.getDefaultStatelessKieSession();
        } else {
            kSessionModel =  kProject.getKieSessionModel(kSessionName);
        }        
        if ( kSessionModel == null ) {
            log.error( "Annotation @KSession({}) found, but no KieSessioneModel exist.\nEither the required kproject.xml does not exist, was corrupted, or mising the KieBase entry",
                       kSessionName );
            return;
        }

        if ( !kSessionModel.getScope().trim().equals( entry.getScope().getClass().getName() ) ) {
            try {
                if ( kSessionModel.getScope().indexOf( '.' ) >= 0 ) {
                    entry.setScope( (Class< ? extends Annotation>) Class.forName( kSessionModel.getScope() ) );
                } else {
                    entry.setScope( (Class< ? extends Annotation>) Class.forName( "javax.enterprise.context." + kSessionModel.getScope() ) );
                }
            } catch ( ClassNotFoundException e ) {
                log.error( "KieBaseModule {} overrides default annotation, but it was not able to find it {}\n{}",
                           new String[]{kSessionName, kSessionModel.getScope(), e.getMessage()} );
            }
        }

        if ( KieSessionType.STATELESS.equals( kSessionModel.getType() ) ) {
            if ( log.isDebugEnabled() ) {
                InternalKieModule kModule = kProject.getKieModuleForKBase( ((KieSessionModelImpl) kSessionModel).getKieBaseModel().getName() );
                log.debug( "Added Bean for Stateless @KSession({}) from: {}",
                           kSessionName,
                           kModule );
            }
            abd.addBean( new StatelessKSessionBean( kSessionModel,
                                                    kieContainer,
                                                    entry.getKReleaseId(),
                                                    entry.getScope(),
                                                    entry.getName(),
                                                    entry.getInjectionPoints() ) );
        } else {
            InternalKieModule kModule = kProject.getKieModuleForKBase( ((KieSessionModelImpl) kSessionModel).getKieBaseModel().getName() );
            log.debug( "Added Bean for Stateful @KSession({})  from: {}",
                       kSessionName,
                       kModule );
            abd.addBean( new StatefulKSessionBean( kSessionModel,
                                                   kieContainer,
                                                   entry.getKReleaseId(),
                                                   entry.getScope(),
                                                   entry.getName(),
                                                   entry.getInjectionPoints()  ) );
        }
    }
   
    public static class KContainerBean
        implements
        Bean<KieContainer> {
        static final Set<Type>                     types = Collections.unmodifiableSet( new HashSet<Type>( Arrays.asList( KieContainer.class,
                                                                                                                          Object.class ) ) );

        private final Set<Annotation>              qualifiers;

        private KieContainer                       kContainer;

        private final String                       named;

        private final Set<InjectionPoint>          injectionPoints;

        public KContainerBean(KieContainer kContainer,
                              KReleaseId kReleaseId,
                              final String named,
                              Set<InjectionPoint> injectionPoints) {
            this.kContainer = kContainer;
            this.named = named;
            this.injectionPoints = injectionPoints;

            Set<Annotation> set = new HashSet<Annotation>();
            if ( kReleaseId == null ) {
                set.add( defaultAnnLit );
            }
            set.add( anyAnnLit );

            if ( named != null ) {
                set.add( new Named() {
                    public Class< ? extends Annotation> annotationType() {
                        return Named.class;
                    }

                    public String value() {
                        return named;
                    }

                    public String toString() {
                        return "Named[" + named + "]";
                    }
                } );
            }
           
            if ( kReleaseId != null ) {
                set.add( kReleaseId );
            }

            this.qualifiers = Collections.unmodifiableSet( set );
        }
       
        public KieContainer create(CreationalContext ctx) {
            return kContainer;
        }

        public void destroy(KieContainer kContainer,
                            CreationalContext ctx) {
            this.kContainer = null;
            ctx.release();
        }

        public Class getBeanClass() {
            return KieContainer.class;
        }

        public Set<InjectionPoint> getInjectionPoints() {
            return injectionPoints;
        }

        public String getName() {
            return named;
        }

        public Set<Annotation> getQualifiers() {
            return qualifiers;
        }

        public Class< ? extends Annotation> getScope() {
            return Dependent.class;
        }

        public Set<Class< ? extends Annotation>> getStereotypes() {
            return Collections.emptySet();
        }

        public Set<Type> getTypes() {
            return types;
        }

        public boolean isAlternative() {
            return false;
        }

        public boolean isNullable() {
            return false;
        }

        @Override
        public String toString() {
            return "KieContainer [qualifiers=" + qualifiers + "]";
        }
       
    }

    public static class KBaseBean
        implements
        Bean<KieBase> {
        static final Set<Type>               types = Collections.unmodifiableSet( new HashSet<Type>( Arrays.asList( KieBase.class,
                                                                                                                    Object.class ) ) );

        private final Set<Annotation>              qualifiers;

        private KieContainer                       kContainer;

        private final KieBaseModel                 kBaseModel;

        private final Class< ? extends Annotation> scope;

        private final String                       named;
       
        private final Set<InjectionPoint>          injectionPoints;

        public KBaseBean(final KieBaseModel kBaseModel,
                         KieContainer kContainer,
                         KReleaseId kReleaseId,
                         Class< ? extends Annotation> scope,
                         final String named,
                         Set<InjectionPoint> injectionPoints) {
            this.kBaseModel = kBaseModel;
            this.kContainer = kContainer;
            this.scope = scope;
            this.named = StringUtils.isEmpty( named ) ? null : named;
            this.injectionPoints = injectionPoints;

            Set<Annotation> set = new HashSet<Annotation>();
            if ( kBaseModel.isDefault() && kReleaseId == null ) {
                set.add( defaultAnnLit );
            }
            set.add( anyAnnLit );
            set.add( new KBase() {
                public Class< ? extends Annotation> annotationType() {
                    return KBase.class;
                }

                public String value() {
                    return kBaseModel.getName();
                }
               
                public String name() {
                    return named;
                }
            } );

            if ( kReleaseId != null ) {
                set.add( kReleaseId );
            }

            this.qualifiers = Collections.unmodifiableSet( set );
        }

        public KieBase create(CreationalContext ctx) {
            return kContainer.getKieBase( kBaseModel.getName() );
        }

        public void destroy(KieBase kBase,
                            CreationalContext ctx) {
            this.kContainer = null;
            ctx.release();
        }

        public Class getBeanClass() {
            return KieBase.class;
        }

        public Set<InjectionPoint> getInjectionPoints() {
            return injectionPoints;
        }

        public String getName() {
            return named;
        }

        public Set<Annotation> getQualifiers() {
            return qualifiers;
        }

        public Class< ? extends Annotation> getScope() {
            return this.scope;
        }

        public Set<Class< ? extends Annotation>> getStereotypes() {
            return Collections.emptySet();
        }

        public Set<Type> getTypes() {
            return types;
        }

        public boolean isAlternative() {
            return false;
        }

        public boolean isNullable() {
            return false;
        }

        @Override
        public String toString() {
            return "KBaseBean [kBase=" + kBaseModel.getName() + ", qualifiers=" + qualifiers + "]";
        }

    }

    public static class StatelessKSessionBean
        implements
        Bean<StatelessKieSession> {
        static final Set<Type>               types = Collections.unmodifiableSet( new HashSet<Type>( Arrays.asList( StatelessKieSession.class,
                                                                                                                    Object.class ) ) );

        private final Set<Annotation>              qualifiers;

        private final KieSessionModel              kSessionModel;

        private final KieContainer                 kContainer;

        private final Class< ? extends Annotation> scope;

        private final String                       named;
       
        private final Set<InjectionPoint>          injectionPoints;

        public StatelessKSessionBean(final KieSessionModel kieSessionModelModel,
                                     KieContainer kContainer,
                                     KReleaseId kReleaseId,
                                     Class< ? extends Annotation> scope,
                                     final String named,
                                     Set<InjectionPoint> injectionPoints) {
            this.kSessionModel = kieSessionModelModel;
            this.kContainer = kContainer;
            this.scope = scope;
            this.named = StringUtils.isEmpty( named ) ? null : named;
            this.injectionPoints = injectionPoints;

            Set<Annotation> set = new HashSet<Annotation>();
            if ( kieSessionModelModel.isDefault() && kReleaseId == null ) {
                set.add( defaultAnnLit );
            }
            set.add( anyAnnLit );
            set.add( new KSession() {
                public Class< ? extends Annotation> annotationType() {
                    return KSession.class;
                }

                public String value() {
                    return kSessionModel.getName();
                }
               
                public String name() {
                    return named;
                }               
            } );
            if ( kReleaseId != null ) {
                set.add( kReleaseId );
            }
            this.qualifiers = Collections.unmodifiableSet( set );
        }

        public StatelessKieSession create(CreationalContext ctx) {
            return kContainer.newStatelessKieSession(kSessionModel.getName());
        }

        public void destroy(StatelessKieSession kSession,
                            CreationalContext ctx) {
            ctx.release();
        }

        public Class getBeanClass() {
            return StatelessKnowledgeSession.class;
        }

        public Set<InjectionPoint> getInjectionPoints() {
            return injectionPoints;
        }

        public String getName() {
            return named;
        }

        public Set<Annotation> getQualifiers() {
            return qualifiers;
        }

        public Class< ? extends Annotation> getScope() {
            return scope;
        }

        public Set<Class< ? extends Annotation>> getStereotypes() {
            return Collections.emptySet();
        }

        public Set<Type> getTypes() {
            return types;
        }

        public boolean isAlternative() {
            return false;
        }

        public boolean isNullable() {
            return false;
        }
    }

    public static class StatefulKSessionBean
        implements
        Bean<KieSession> {
        static final Set<Type>               types = Collections.unmodifiableSet( new HashSet<Type>( Arrays.asList( KieSession.class,
                                                                                                                    Object.class ) ) );

        private final Set<Annotation>              qualifiers;

        private final KieSessionModel              kSessionModel;

        private final KieContainer                 kContainer;

        private final Class< ? extends Annotation> scope;

        private final String                       named;
       
        private final Set<InjectionPoint>          injectionPoints;

        public StatefulKSessionBean(final KieSessionModel kieSessionModelModel,
                                    KieContainer kContainer,
                                    KReleaseId kReleaseId,
                                    Class< ? extends Annotation> scope,
                                    final String named,
                                    Set<InjectionPoint> injectionPoints) {
            this.kSessionModel = kieSessionModelModel;
            this.kContainer = kContainer;
            this.scope = scope;
            this.named = StringUtils.isEmpty( named ) ? null : named;
            this.injectionPoints = injectionPoints;

            Set<Annotation> set = new HashSet<Annotation>();
            if ( kieSessionModelModel.isDefault() && kReleaseId == null ) {
                set.add( defaultAnnLit );
            }
            set.add( anyAnnLit );
            set.add( new KSession() {
                public Class< ? extends Annotation> annotationType() {
                    return KSession.class;
                }

                public String value() {
                    return kSessionModel.getName();
                }
               
                public String name() {
                    return named;
                }               
            } );

            if ( kReleaseId != null ) {
                set.add( kReleaseId );
            }

            this.qualifiers = Collections.unmodifiableSet( set );
        }

        public KieSession create(CreationalContext ctx) {
            return kContainer.newKieSession(kSessionModel.getName());
        }

        public void destroy(KieSession kBase,
                            CreationalContext ctx) {
            ctx.release();
        }

        public Class getBeanClass() {
            return StatefulKnowledgeSession.class;
        }

        public Set<InjectionPoint> getInjectionPoints() {
            return injectionPoints;
        }

        public String getName() {
            return named;
        }

        public Set<Annotation> getQualifiers() {
            return qualifiers;
        }

        public Class< ? extends Annotation> getScope() {
            return this.scope;
        }

        public Set<Class< ? extends Annotation>> getStereotypes() {
            return Collections.emptySet();
        }

        public Set<Type> getTypes() {
            return types;
        }

        public boolean isAlternative() {
            return false;
        }

        public boolean isNullable() {
            return false;
        }
    }

    public static class KieCDIEntry {
        private String                       value;
        private Class                        type;
        private Class< ? extends Annotation> scope;
        private ReleaseId                    releaseId;
        private KReleaseId                   kReleaseId;
        private String                       name;       
        private Set<InjectionPoint>          injectionPoints;

        public KieCDIEntry(String value,
                           Class type,
                           Class< ? extends Annotation> scope,
                           ReleaseId releaseId,
                           KReleaseId kReleaseId,
                           String named) {
            super();
            this.value = value;
            this.type = type;
            this.scope = scope;
            this.releaseId = releaseId;
            this.kReleaseId = kReleaseId;
            this.name = named;
            this.injectionPoints = new HashSet<InjectionPoint>();
        }

        public KieCDIEntry(String value) {
            super();
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }              

        public Class getType() {
            return type;
        }

        public void setType(Class type) {
            this.type = type;
        }

        public String getName() {
            return name;
        }

        public void setName(String named) {
            this.name = named;
        }

        public void setScope(Class< ? extends Annotation> scope) {
            this.scope = scope;
        }

        public Class< ? extends Annotation> getScope() {
            return scope;
        }

        public ReleaseId getReleaseId() {
            return releaseId;
        }

        public void setReleaseId(ReleaseId releaseId) {
            this.releaseId = releaseId;
        }

        public KReleaseId getKReleaseId() {
            return kReleaseId;
        }

        public void setKReleaseId(KReleaseId kReleaseId) {
            this.kReleaseId = kReleaseId;
        }

        /**
         * InjectionPoints is not to be included in the equals/hashcode test
         * @return
         */       
        public void addInjectionPoint(InjectionPoint ip) {
            this.injectionPoints.add( ip );
        }

        /**
         * InjectionPoints is not to be included in the equals/hashcode test
         * @return
         */
        public Set<InjectionPoint> getInjectionPoints() {
            return injectionPoints;
        }

        /**
         * InjectionPoints is not to be included in the equals/hashcode test
         * @return
         */       
        public void setInjectionPoints(Set<InjectionPoint> injectionPoints) {
            this.injectionPoints = injectionPoints;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((releaseId == null) ? 0 : releaseId.hashCode());
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            result = prime * result + ((scope == null) ? 0 : scope.hashCode());
            result = prime * result + ((type == null) ? 0 : type.hashCode());
            result = prime * result + ((value == null) ? 0 : value.hashCode());
            return result;
        }

        @Override
        public boolean equals(java.lang.Object obj) {
            if ( this == obj ) return true;
            if ( obj == null ) return false;
            if ( getClass() != obj.getClass() ) return false;
            KieCDIEntry other = (KieCDIEntry) obj;
            if ( releaseId == null ) {
                if ( other.releaseId != null ) return false;
            } else if ( !releaseId.equals( other.releaseId ) ) return false;
            if ( name == null ) {
                if ( other.name != null ) return false;
            } else if ( !name.equals( other.name ) ) return false;
            if ( scope == null ) {
                if ( other.scope != null ) return false;
            } else if ( !scope.equals( other.scope ) ) return false;
            if ( type == null ) {
                if ( other.type != null ) return false;
            } else if ( !type.equals( other.type ) ) return false;
            if ( value == null ) {
                if ( other.value != null ) return false;
            } else if ( !value.equals( other.value ) ) return false;
            return true;
        }


    }

    private Class getClassType(InjectionPoint ip) {
        if (ip.getType() instanceof Class) {

            return (Class )ip.getType();
        } else if (ip.getType() instanceof ParameterizedType) {
            Type rawType = ((ParameterizedType) ip.getType()).getRawType();
            Type[] types = ((ParameterizedType) ip.getType()).getActualTypeArguments();
            if (rawType instanceof Class) {
                if (rawType instanceof Class && ((Class) rawType).isAssignableFrom(Instance.class) && types.length == 1) {

                    if (types[0] instanceof Class) {
                        return  (Class )types[0];
                    }
                }
            }
        }

        return null;
    }
}
TOP

Related Classes of org.drools.compiler.cdi.KieCDIExtension

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.