All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.drools.impact.analysis.parser.internal.ImpactModelBuilderImpl Maven / Gradle / Ivy

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.drools.impact.analysis.parser.internal;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.drools.compiler.builder.impl.KnowledgeBuilderConfigurationImpl;
import org.drools.compiler.builder.impl.KnowledgeBuilderImpl;
import org.drools.compiler.builder.impl.TypeDeclarationFactory;
import org.drools.compiler.builder.impl.processors.AnnotationNormalizer;
import org.drools.compiler.builder.impl.processors.OtherDeclarationCompilationPhase;
import org.drools.compiler.compiler.PackageRegistry;
import org.drools.compiler.lang.descr.CompositePackageDescr;
import org.drools.base.definitions.InternalKnowledgePackage;
import org.drools.base.rule.TypeDeclaration;
import org.drools.drl.ast.descr.AbstractClassTypeDeclarationDescr;
import org.drools.drl.ast.descr.EnumDeclarationDescr;
import org.drools.drl.ast.descr.GlobalDescr;
import org.drools.drl.ast.descr.ImportDescr;
import org.drools.drl.ast.descr.PackageDescr;
import org.drools.drl.ast.descr.TypeDeclarationDescr;
import org.drools.impact.analysis.model.AnalysisModel;
import org.drools.impact.analysis.parser.impl.PackageParser;
import org.drools.model.codegen.execmodel.PackageModel;
import org.drools.model.codegen.execmodel.generator.DRLIdGenerator;
import org.drools.util.StringUtils;
import org.kie.api.builder.ReleaseId;
import org.kie.api.io.Resource;
import org.kie.internal.builder.conf.LanguageLevelOption;

import static java.util.Collections.emptyList;
import static org.drools.compiler.builder.impl.ClassDefinitionFactory.createClassDefinition;
import static org.drools.base.util.Drools.hasMvel;

public class ImpactModelBuilderImpl extends KnowledgeBuilderImpl {

    private final ReleaseId releaseId;

    private final DRLIdGenerator exprIdGenerator = new DRLIdGenerator();

    private final Map packageModels = new HashMap<>();

    private Collection compositePackages;
    private Map compositePackagesMap;

    private final AnalysisModel analysisModel = new AnalysisModel();

    public ImpactModelBuilderImpl( KnowledgeBuilderConfigurationImpl configuration, ReleaseId releaseId) {
        super(configuration);
        this.releaseId = releaseId;
    }

    @Override
    protected void doFirstBuildStep( Collection packages ) {
        this.compositePackages = packages;
    }

    @Override
    protected void addPackageWithResource(final PackageDescr packageDescr, final Resource resource) {
        if (compositePackagesMap == null) {
            compositePackagesMap = new HashMap<>();
            if(compositePackages != null) {
                for (CompositePackageDescr pkg : compositePackages) {
                    compositePackagesMap.put(pkg.getNamespace(), pkg);
                }
            } else {
                compositePackagesMap.put(packageDescr.getNamespace(), new CompositePackageDescr(packageDescr.getResource(), packageDescr));
            }
            compositePackages = null;
        }

        CompositePackageDescr pkgDescr = compositePackagesMap.get(packageDescr.getNamespace());
        if (pkgDescr == null) {
            compositePackagesMap.put(packageDescr.getNamespace(), new CompositePackageDescr( packageDescr.getResource(), packageDescr) );
        } else {
            pkgDescr.addPackageDescr( packageDescr.getResource(), packageDescr );
        }

        PackageRegistry pkgRegistry = getOrCreatePackageRegistry(packageDescr);
        InternalKnowledgePackage pkg = pkgRegistry.getPackage();
        for (final ImportDescr importDescr : packageDescr.getImports()) {
            pkgRegistry.addImport(importDescr);
        }
        for (GlobalDescr globalDescr : packageDescr.getGlobals()) {
            try {
                Class globalType = pkg.getTypeResolver().resolveType( globalDescr.getType() );
                addGlobal( globalDescr.getIdentifier(), globalType );
                pkg.addGlobal( globalDescr.getIdentifier(), globalType );
            } catch (ClassNotFoundException e) {
                throw new RuntimeException( e );
            }
        }
    }

    @Override
    protected void doSecondBuildStep(Collection compositePackages) {
        Collection packages = findPackages(compositePackages);
        initPackageRegistries(packages);
        registerTypeDeclarations( packages );
        buildOtherDeclarations(packages);
        buildRules(packages);
    }

    protected void buildOtherDeclarations(Collection packages) {
        for (CompositePackageDescr packageDescr : packages) {
            PackageRegistry pkgRegistry = getPackageRegistry(packageDescr.getNamespace());
            setAssetFilter(packageDescr.getFilter());
            OtherDeclarationCompilationPhase otherDeclarationProcessor = new OtherDeclarationCompilationPhase(
                    pkgRegistry,
                    packageDescr,
                    getGlobalVariableContext(),
                    this,
                    getKnowledgeBase(),
                    getBuilderConfiguration(),
                    this.getAssetFilter());
            otherDeclarationProcessor.process();
            this.getBuildResultCollector().addAll(otherDeclarationProcessor.getResults());
            setAssetFilter(null);
        }
    }

    private Collection findPackages(Collection compositePackages) {
        Collection packages;
        if (compositePackages != null && !compositePackages.isEmpty()) {
            packages = compositePackages;
        } else if (compositePackagesMap != null) {
            packages = compositePackagesMap.values();
        } else {
            packages = emptyList();
        }
        return packages;
    }

    protected void initPackageRegistries(Collection packages) {
        for ( CompositePackageDescr packageDescr : packages ) {
            if ( StringUtils.isEmpty(packageDescr.getName()) ) {
                packageDescr.setName( getBuilderConfiguration().getDefaultPackageName() );
            }

            PackageRegistry pkgRegistry = getPackageRegistry( packageDescr.getNamespace() );
            if (pkgRegistry == null) {
                getOrCreatePackageRegistry( packageDescr );
            } else {
                for (ImportDescr importDescr : packageDescr.getImports()) {
                    pkgRegistry.registerImport(importDescr.getTarget());
                }
            }
        }
    }

    private void registerTypeDeclarations( Collection packages ) {
        for (CompositePackageDescr packageDescr : packages) {
            InternalKnowledgePackage pkg = getOrCreatePackageRegistry(packageDescr).getPackage();
            for (TypeDeclarationDescr typeDescr : packageDescr.getTypeDeclarations()) {
                processTypeDeclarationDescr(pkg, typeDescr);
            }
            for (EnumDeclarationDescr enumDeclarationDescr : packageDescr.getEnumDeclarations()) {
                processTypeDeclarationDescr(pkg, enumDeclarationDescr);
            }
        }
    }

    private void processTypeDeclarationDescr(InternalKnowledgePackage pkg, AbstractClassTypeDeclarationDescr typeDescr) {
        AnnotationNormalizer annotationNormalizer =
                AnnotationNormalizer.of(
                        pkg.getTypeResolver(),
                        getBuilderConfiguration().getOption(LanguageLevelOption.KEY).useJavaAnnotations());

        annotationNormalizer.normalize(typeDescr);
        this.getBuildResultCollector().addAll(annotationNormalizer.getResults());

        try {
            Class typeClass = pkg.getTypeResolver().resolveType( typeDescr.getTypeName() );
            String typePkg = typeClass.getPackage().getName();
            String typeName = typeClass.getName().substring( typePkg.length() + 1 );
            TypeDeclaration type = new TypeDeclaration(typeName );
            type.setTypeClass( typeClass );
            type.setResource( typeDescr.getResource() );
            if (hasMvel()) {
                type.setTypeClassDef( createClassDefinition( typeClass, typeDescr.getResource() ) );
            }
            TypeDeclarationFactory.processAnnotations(typeDescr, type);
            getOrCreatePackageRegistry(new PackageDescr(typePkg)).getPackage().addTypeDeclaration(type );
        } catch (ClassNotFoundException e) {
            TypeDeclaration type = new TypeDeclaration( typeDescr.getTypeName() );
            type.setResource( typeDescr.getResource() );
            TypeDeclarationFactory.processAnnotations(typeDescr, type);
            pkg.addTypeDeclaration( type );
        }
    }

    protected void buildRules(Collection packages) {
        if (hasErrors()) { // if Error while generating pojo do not try compile rule as they very likely depends hence fail too.
            return;
        }

        for (CompositePackageDescr packageDescr : packages) {
            setAssetFilter(packageDescr.getFilter());
            PackageRegistry pkgRegistry = getPackageRegistry(packageDescr.getNamespace());

            PackageModel packageModel = getPackageModel(packageDescr, pkgRegistry, packageDescr.getName());
            PackageModel.initPackageModel( this, pkgRegistry.getPackage(), pkgRegistry.getTypeResolver(), packageDescr, packageModel );
            analysisModel.addPackage( new PackageParser(this, packageModel, packageDescr, pkgRegistry).parse() );
        }
    }

    private PackageModel getPackageModel(PackageDescr packageDescr, PackageRegistry pkgRegistry, String pkgName) {
        return packageModels.computeIfAbsent(pkgName, s -> PackageModel.createPackageModel(getBuilderConfiguration(), packageDescr, pkgRegistry, pkgName, releaseId, exprIdGenerator));
    }

    public AnalysisModel getAnalysisModel() {
        return analysisModel;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy