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

org.drools.compiler.builder.impl.KnowledgeBuilderImpl Maven / Gradle / Ivy

The newest version!
/**
 * 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.compiler.builder.impl;

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Type;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ForkJoinPool;
import java.util.function.Supplier;

import org.drools.base.RuleBase;
import org.drools.base.base.ObjectType;
import org.drools.base.definitions.InternalKnowledgePackage;
import org.drools.base.definitions.rule.impl.RuleImpl;
import org.drools.base.rule.Function;
import org.drools.base.rule.ImportDeclaration;
import org.drools.base.rule.TypeDeclaration;
import org.drools.compiler.builder.InternalKnowledgeBuilder;
import org.drools.compiler.builder.PackageRegistryManager;
import org.drools.compiler.builder.impl.processors.CompilationPhase;
import org.drools.compiler.builder.impl.processors.CompositePackageCompilationPhase;
import org.drools.compiler.builder.impl.processors.ConsequenceCompilationPhase;
import org.drools.compiler.builder.impl.processors.FunctionCompiler;
import org.drools.compiler.builder.impl.processors.PackageCompilationPhase;
import org.drools.compiler.builder.impl.processors.ReteCompiler;
import org.drools.compiler.builder.impl.processors.RuleCompilationPhase;
import org.drools.compiler.builder.impl.processors.RuleValidator;
import org.drools.compiler.builder.impl.resources.ResourceHandler;
import org.drools.compiler.compiler.DroolsWarning;
import org.drools.compiler.compiler.DuplicateFunction;
import org.drools.compiler.compiler.PackageBuilderErrors;
import org.drools.compiler.compiler.PackageRegistry;
import org.drools.compiler.compiler.ProcessBuilder;
import org.drools.compiler.compiler.ProcessBuilderFactory;
import org.drools.compiler.compiler.ResourceTypeDeclarationWarning;
import org.drools.compiler.kie.builder.impl.BuildContext;
import org.drools.compiler.lang.descr.CompositePackageDescr;
import org.drools.core.impl.RuleBaseFactory;
import org.drools.drl.ast.descr.AttributeDescr;
import org.drools.drl.ast.descr.ImportDescr;
import org.drools.drl.ast.descr.PackageDescr;
import org.drools.drl.parser.DrlParser;
import org.drools.drl.parser.DroolsParserException;
import org.drools.drl.parser.ParserError;
import org.drools.drl.parser.lang.dsl.DSLMappingFile;
import org.drools.drl.parser.lang.dsl.DSLTokenizedMappingFile;
import org.drools.drl.parser.lang.dsl.DefaultExpander;
import org.drools.io.BaseResource;
import org.drools.io.InternalResource;
import org.drools.io.ReaderResource;
import org.drools.kiesession.rulebase.InternalKnowledgeBase;
import org.drools.kiesession.rulebase.KnowledgeBaseFactory;
import org.drools.wiring.api.ComponentsFactory;
import org.kie.api.KieBase;
import org.kie.api.KieBaseConfiguration;
import org.kie.api.KieServices;
import org.kie.api.builder.ReleaseId;
import org.kie.api.definition.KiePackage;
import org.kie.api.definition.process.Process;
import org.kie.api.internal.assembler.KieAssemblers;
import org.kie.api.internal.io.ResourceTypePackage;
import org.kie.api.internal.utils.KieService;
import org.kie.api.io.Resource;
import org.kie.api.io.ResourceConfiguration;
import org.kie.api.io.ResourceType;
import org.kie.api.io.ResourceWithConfiguration;
import org.kie.internal.builder.CompositeKnowledgeBuilder;
import org.kie.internal.builder.KnowledgeBuilderConfiguration;
import org.kie.internal.builder.KnowledgeBuilderError;
import org.kie.internal.builder.KnowledgeBuilderErrors;
import org.kie.internal.builder.KnowledgeBuilderFactory;
import org.kie.internal.builder.KnowledgeBuilderResult;
import org.kie.internal.builder.KnowledgeBuilderResults;
import org.kie.internal.builder.ResourceChange;
import org.kie.internal.builder.ResultSeverity;
import org.kie.internal.builder.conf.DefaultDialectOption;
import org.kie.internal.builder.conf.LanguageLevelOption;
import org.kie.internal.builder.conf.ParallelRulesBuildThresholdOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static java.util.Arrays.asList;

public class KnowledgeBuilderImpl implements InternalKnowledgeBuilder, TypeDeclarationContext, BuildResultCollector, GlobalVariableContext {
    protected static final transient Logger logger = LoggerFactory.getLogger(KnowledgeBuilderImpl.class);

    private static final KieAssemblers ASSEMBLERS = KieService.load(KieAssemblers.class);

    private final PackageRegistryManagerImpl pkgRegistryManager;

    private final BuildResultCollectorImpl results;

    private final KnowledgeBuilderConfiguration configuration;

    /**
     * Optional RuleBase for incremental live building
     */
    private InternalKnowledgeBase kBase;

    /**
     * default dialect
     */
    private final String defaultDialect;

    private final ClassLoader rootClassLoader;

    private int parallelRulesBuildThreshold;

    private final GlobalVariableContext globals = new GlobalVariableContextImpl();

    private List dslFiles;

    private final org.drools.compiler.compiler.ProcessBuilder processBuilder;

    private final Deque> buildResources = new ArrayDeque<>();

    private AssetFilter assetFilter = null;

    private TypeDeclarationManagerImpl typeDeclarationManager;

    private Map builderCache;

    private ReleaseId releaseId;

    private BuildContext buildContext;

    /**
     * Use this when package is starting from scratch.
     */
    public KnowledgeBuilderImpl() {
        this((InternalKnowledgeBase) null,
             null);
    }

    /**
     * This will allow you to merge rules into this pre existing package.
     */

    public KnowledgeBuilderImpl(final InternalKnowledgePackage pkg) {
        this(pkg,
             null);
    }

    public KnowledgeBuilderImpl(final InternalKnowledgeBase kBase) {
        this(kBase,
             null);
    }

    public KnowledgeBuilderImpl(InternalKnowledgeBase kBase,
                                KnowledgeBuilderConfiguration configuration) {
        if (configuration == null) {
            this.configuration = KnowledgeBuilderFactory.newKnowledgeBuilderConfiguration();
        } else {
            this.configuration = configuration;
        }

        if (kBase != null) {
            this.rootClassLoader = kBase.getRootClassLoader();
        } else {
            this.rootClassLoader = this.configuration.getClassLoader();
        }

        this.defaultDialect = this.configuration.getOption(DefaultDialectOption.KEY).dialectName();

        this.parallelRulesBuildThreshold = this.configuration.getOption(ParallelRulesBuildThresholdOption.KEY).getParallelRulesBuildThreshold();

        this.results = new BuildResultCollectorImpl();

        this.kBase = kBase;

        this.pkgRegistryManager =
                new PackageRegistryManagerImpl(
                        this.configuration, this, this);

        processBuilder = ProcessBuilderFactory.newProcessBuilder(this);

        this.typeDeclarationManager = new TypeDeclarationManagerImpl(createTypeDeclarationBuilder(), this.kBase);
    }

    /**
     * Pass a specific configuration for the PackageBuilder
     * 

* PackageBuilderConfiguration is not thread safe and it also contains * state. Once it is created and used in one or more PackageBuilders it * should be considered immutable. Do not modify its properties while it is * being used by a PackageBuilder. */ public KnowledgeBuilderImpl(final KnowledgeBuilderConfiguration configuration) { this((InternalKnowledgeBase) null, configuration); } public KnowledgeBuilderImpl(InternalKnowledgePackage pkg, KnowledgeBuilderConfiguration configuration) { if (configuration == null) { this.configuration = new KnowledgeBuilderFactoryServiceImpl().newKnowledgeBuilderConfiguration(); } else { this.configuration = configuration; } this.rootClassLoader = this.configuration.getClassLoader(); this.defaultDialect = this.configuration.getOption(DefaultDialectOption.KEY).dialectName(); this.parallelRulesBuildThreshold = this.configuration.getOption(ParallelRulesBuildThresholdOption.KEY).getParallelRulesBuildThreshold(); this.results = new BuildResultCollectorImpl(); this.pkgRegistryManager = new PackageRegistryManagerImpl( this.configuration, this, this); PackageRegistry pkgRegistry = new PackageRegistry(rootClassLoader, this.configuration, pkg); pkgRegistry.setDialect(this.defaultDialect); this.pkgRegistryManager.getPackageRegistry().put(pkg.getName(), pkgRegistry); // add imports to pkg registry for (final ImportDeclaration implDecl : pkg.getImports().values()) { pkgRegistry.addImport(new ImportDescr(implDecl.getTarget())); } processBuilder = ProcessBuilderFactory.newProcessBuilder(this); this.typeDeclarationManager = new TypeDeclarationManagerImpl(createTypeDeclarationBuilder(), this.kBase); } private TypeDeclarationBuilder createTypeDeclarationBuilder() { TypeDeclarationBuilderFactory typeDeclarationBuilderFactory = Optional.ofNullable(KieService.load(TypeDeclarationBuilderFactory.class)) .orElse(new DefaultTypeDeclarationBuilderFactory()); return typeDeclarationBuilderFactory.createTypeDeclarationBuilder(this); } public ReleaseId getReleaseId() { return releaseId; } public void setReleaseId(ReleaseId releaseId ) { this.releaseId = releaseId; } public BuildContext getBuildContext() { if (buildContext == null) { buildContext = createBuildContext(); } return buildContext; } protected BuildContext createBuildContext() { return new BuildContext(); } public void setBuildContext(BuildContext buildContext) { this.buildContext = buildContext; } public InternalKnowledgeBase getKnowledgeBase() { return kBase; } public TypeDeclarationBuilder getTypeBuilder() { return typeDeclarationManager.getTypeDeclarationBuilder(); } /** * Load a rule package from DRL source. * * @throws DroolsParserException * @throws java.io.IOException */ public void addPackageFromDrl(final Reader reader) throws DroolsParserException, IOException { addPackageFromDrl(reader, new ReaderResource(reader, ResourceType.DRL)); } /** * Load a rule package from DRL source and associate all loaded artifacts * with the given resource. * * @param reader * @param sourceResource the source resource for the read artifacts * @throws DroolsParserException */ public void addPackageFromDrl(final Reader reader, final Resource sourceResource) throws DroolsParserException, IOException { final DrlParser parser = new DrlParser(configuration.getOption(LanguageLevelOption.KEY)); final PackageDescr pkg = parser.parse(sourceResource, reader); this.results.addAll(parser.getErrors()); if (pkg == null) { addBuilderResult(new ParserError(sourceResource, "Parser returned a null Package", 0, 0)); } if (!parser.hasErrors()) { addPackageWithResource(pkg, sourceResource); } } public static File createDumpDrlFile(File dumpDir, String fileName, String extension) { return new File(dumpDir, fileName.replaceAll("[^a-zA-Z0-9\\.\\-_]+", "_") + extension); } public void addDsl(Resource resource) throws IOException { DSLTokenizedMappingFile file = new DSLTokenizedMappingFile(); try (Reader reader = resource.getReader()) { if (!file.parseAndLoad(reader)) { this.results.addAll(file.getErrors()); } if (this.dslFiles == null) { this.dslFiles = new ArrayList<>(); } this.dslFiles.add(file); } } /** * Add a ruleflow (.rfm) asset to this package. */ public void addRuleFlow(Reader processSource) { addKnowledgeResource( new ReaderResource(processSource, ResourceType.DRF), ResourceType.DRF, null); } @Deprecated public void addProcessFromXml(Resource resource) { addKnowledgeResource( resource, resource.getResourceType(), resource.getConfiguration()); } public ProcessBuilder getProcessBuilder() { return processBuilder; } @Deprecated public void addProcessFromXml( Reader processSource) { addProcessFromXml(new ReaderResource(processSource, ResourceType.DRF)); } public void addKnowledgeResource(Resource resource, ResourceType type, ResourceConfiguration configuration) { try { ((InternalResource) resource).setResourceType(type); ResourceHandlerManager handlerManager = new ResourceHandlerManager(this.getBuilderConfiguration(), this.releaseId, this::getDslExpander); if (handlerManager.handles(type)){ ResourceHandler handler = handlerManager.handlerForType(type); PackageDescr descr = handler.process(resource,ResourceType.DTABLE.equals(type) ? configuration : null); this.results.addAll(handler.getResults()); addPackageWithResource(descr, resource); } else if (ResourceType.DSL.equals(type)) { addDsl(resource); } else if (ResourceType.XSD.equals(type)) { addPackageFromXSD(resource, configuration); } else { addPackageForExternalType(resource, type, configuration); } } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } } @Deprecated void addPackageForExternalType(Resource resource, ResourceType type, ResourceConfiguration configuration) throws Exception { ASSEMBLERS.addResourceAfterRules(this, resource, type, configuration); } @Deprecated void addPackageForExternalType(ResourceType type, List resources) throws Exception { ASSEMBLERS.addResourcesAfterRules(this, resources, type); } void addPackageFromXSD(Resource resource, ResourceConfiguration configuration) throws IOException { if (configuration != null) { ComponentsFactory.addPackageFromXSD( this, resource, configuration ); } } /** * Adds a package from a Descr/AST also triggering its compilation * and the generation of the corresponding rete/phreak network */ @Override public final void addPackage(final PackageDescr packageDescr) { addPackageWithResource(packageDescr, null); } // this is only overridden by org.drools.verifier.builder.VerifierPackageBuilder.InnerBuilder protected void addPackageWithResource(PackageDescr packageDescr, Resource resource) { PackageRegistry pkgRegistry = getOrCreatePackageRegistry(packageDescr); if (pkgRegistry == null) { return; } // merge into existing package PackageCompilationPhase packageProcessor = new PackageCompilationPhase(this, kBase, configuration, typeDeclarationManager.getTypeDeclarationBuilder(), assetFilter, pkgRegistry, packageDescr, resource); packageProcessor.process(); this.results.addAll(packageProcessor.getResults()); compileKnowledgePackages(packageDescr, pkgRegistry, resource); wireAllRules(); compileRete(pkgRegistry, packageDescr); } private void compileKnowledgePackages(PackageDescr packageDescr, PackageRegistry pkgRegistry, Resource resource) { pkgRegistry.setDialect(getPackageDialect(packageDescr)); PackageRegistry packageRegistry = this.pkgRegistryManager.getPackageRegistry(packageDescr.getNamespace()); Map packageAttributes = this.pkgRegistryManager.getPackageAttributes().get(packageDescr.getNamespace()); List phases = asList( new RuleValidator(packageRegistry, packageDescr, configuration), // validateUniqueRuleNames FunctionCompiler.of(pkgRegistry, packageDescr, assetFilter, rootClassLoader), RuleCompilationPhase.of(pkgRegistry, packageDescr, kBase, parallelRulesBuildThreshold, assetFilter, packageAttributes, resource, this)); phases.forEach(CompilationPhase::process); phases.forEach(p -> this.results.addAll(p.getResults())); } protected void wireAllRules() { ConsequenceCompilationPhase compilationPhase = new ConsequenceCompilationPhase(pkgRegistryManager); compilationPhase.process(); results.addAll(compilationPhase.getResults()); } protected void processKieBaseTypes() { if (!hasErrors() && this.kBase != null) { List pkgs = new ArrayList<>(); for (PackageRegistry pkgReg : pkgRegistryManager.getPackageRegistry().values()) { pkgs.add(pkgReg.getPackage()); } this.kBase.processAllTypesDeclaration(pkgs); } } private void compileRete(PackageRegistry pkgRegistry, PackageDescr packageDescr) { if (!hasErrors() && this.kBase != null) { ReteCompiler reteCompiler = new ReteCompiler(pkgRegistry, packageDescr, kBase, assetFilter); reteCompiler.process(); } } public void addBuilderResult(KnowledgeBuilderResult result) { this.results.addBuilderResult(result); } protected BuildResultCollector getBuildResultCollector() { return this.results; } @Override public > T computeIfAbsent( ResourceType resourceType, String namespace, java.util.function.Function mappingFunction) { PackageRegistry pkgReg = getOrCreatePackageRegistry(new PackageDescr(namespace)); InternalKnowledgePackage kpkgs = pkgReg.getPackage(); return kpkgs.getResourceTypePackages() .computeIfAbsent( resourceType, mappingFunction); } public PackageRegistry getOrCreatePackageRegistry(PackageDescr packageDescr) { return this.pkgRegistryManager.getOrCreatePackageRegistry(packageDescr); } public void registerPackage(PackageDescr packageDescr) { this.pkgRegistryManager.registerPackage(packageDescr); } protected PackageRegistryManager getPackageRegistryManager() { return pkgRegistryManager; } public static class ForkJoinPoolHolder { public static final ForkJoinPool COMPILER_POOL = new ForkJoinPool(); // avoid common pool } public boolean filterAccepts(ResourceChange.Type type, String namespace, String name) { return assetFilter == null || !AssetFilter.Action.DO_NOTHING.equals(assetFilter.accept(type, namespace, name)); } private String getPackageDialect(PackageDescr packageDescr) { String dialectName = this.defaultDialect; // see if this packageDescr overrides the current default dialect for (AttributeDescr value : packageDescr.getAttributes()) { if ("dialect".equals(value.getName())) { dialectName = value.getValue(); break; } } return dialectName; } // test public void updateResults() { // some of the rules and functions may have been redefined updateResults(new ArrayList<>(this.results.getAllResults())); } public void updateResults(List results) { this.results.addAll(getResults(results)); } public void compileAll() { this.pkgRegistryManager.compileAll(); } public void reloadAll() { this.pkgRegistryManager.reloadAll(); } private List getResults(List results) { results.addAll(this.pkgRegistryManager.getResults()); return results; } public synchronized void addPackage(InternalKnowledgePackage newPkg) { PackageRegistry pkgRegistry = this.pkgRegistryManager.getPackageRegistry(newPkg.getName()); InternalKnowledgePackage pkg = null; if (pkgRegistry != null) { pkg = pkgRegistry.getPackage(); } if (pkg == null) { PackageDescr packageDescr = new PackageDescr(newPkg.getName()); pkgRegistry = getOrCreatePackageRegistry(packageDescr); PackageCompilationPhase packageProcessor = new PackageCompilationPhase(this, kBase, configuration, typeDeclarationManager.getTypeDeclarationBuilder(), assetFilter, this.pkgRegistryManager.getPackageRegistry(packageDescr.getNamespace()), packageDescr, null); packageProcessor.process(); this.results.addAll(packageProcessor.getResults()); pkg = pkgRegistry.getPackage(); } // first merge anything related to classloader re-wiring pkg.getDialectRuntimeRegistry().merge(newPkg.getDialectRuntimeRegistry(), this.rootClassLoader); if (newPkg.getFunctions() != null) { for (Map.Entry entry : newPkg.getFunctions().entrySet()) { if (pkg.getFunctions().containsKey(entry.getKey())) { addBuilderResult(new DuplicateFunction(entry.getValue(), this.configuration)); } pkg.addFunction(entry.getValue()); } } pkg.mergeStore(newPkg); pkg.getDialectRuntimeRegistry().onBeforeExecute(); // we have to do this before the merging, as it does some classloader resolving TypeDeclaration lastType = null; try { // Resolve the class for the type declaation if (newPkg.getTypeDeclarations() != null) { // add type declarations for (TypeDeclaration type : newPkg.getTypeDeclarations().values()) { lastType = type; type.setTypeClass(this.rootClassLoader.loadClass(type.getTypeClassName())); } } } catch (ClassNotFoundException e) { throw new RuntimeException("unable to resolve Type Declaration class '" + lastType.getTypeName() + "'"); } // now merge the new package into the existing one mergePackage(pkg, newPkg); } /** * Merge a new package with an existing package. Most of the work is done by * the concrete implementations, but this class does some work (including * combining imports, compilation data, globals, and the actual Rule objects * into the package). */ private void mergePackage(InternalKnowledgePackage pkg, InternalKnowledgePackage newPkg) { // Merge imports final Map imports = pkg.getImports(); imports.putAll(newPkg.getImports()); // merge globals if (newPkg.getGlobals() != null && !newPkg.getGlobals().isEmpty()) { Map pkgGlobals = pkg.getGlobals(); // Add globals for (final Map.Entry entry : newPkg.getGlobals().entrySet()) { final String identifier = entry.getKey(); final Type type = entry.getValue(); if (pkgGlobals.containsKey(identifier) && !pkgGlobals.get(identifier).equals(type)) { throw new RuntimeException(pkg.getName() + " cannot be integrated"); } else { pkg.addGlobal(identifier, type); // this isn't a package merge, it's adding to the rulebase, but I've put it here for convenience this.globals.addGlobal(identifier, type ); } } } // merge the type declarations if (newPkg.getTypeDeclarations() != null) { // add type declarations for (TypeDeclaration type : newPkg.getTypeDeclarations().values()) { // @TODO should we allow overrides? only if the class is not in use. if (!pkg.getTypeDeclarations().containsKey(type.getTypeName())) { // add to package list of type declarations pkg.addTypeDeclaration(type); } } } for (final org.kie.api.definition.rule.Rule newRule : newPkg.getRules()) { pkg.addRule(((RuleImpl) newRule)); } //Merge The Rule Flows if (newPkg.getRuleFlows() != null) { final Map flows = newPkg.getRuleFlows(); for (Object o : flows.values()) { final Process flow = (Process) o; pkg.addProcess(flow); } } } public TypeDeclaration getAndRegisterTypeDeclaration(Class cls, String packageName) { return typeDeclarationManager.getAndRegisterTypeDeclaration(cls, packageName); } public InternalKnowledgePackage[] getPackages() { InternalKnowledgePackage[] pkgs = new InternalKnowledgePackage[this.pkgRegistryManager.getPackageRegistry().size()]; String errors = null; if (!getErrors().isEmpty()) { errors = getErrors().toString(); } int i = 0; for (PackageRegistry pkgRegistry : this.pkgRegistryManager.getPackageRegistry().values()) { InternalKnowledgePackage pkg = pkgRegistry.getPackage(); pkg.getDialectRuntimeRegistry().onBeforeExecute(); if (errors != null) { pkg.setError(errors); } pkgs[i++] = pkg; } return pkgs; } /** * Return the PackageBuilderConfiguration for this PackageBuilder session * * @return The PackageBuilderConfiguration */ public KnowledgeBuilderConfigurationImpl getBuilderConfiguration() { return configuration.as(KnowledgeBuilderConfigurationImpl.KEY); } public PackageRegistry getPackageRegistry(String name) { return this.pkgRegistryManager.getPackageRegistry(name); } @Override public InternalKnowledgePackage getPackage(String name) { PackageRegistry registry = this.getPackageRegistry(name); return registry == null ? null : registry.getPackage(); } public Map getPackageRegistry() { return this.pkgRegistryManager.getPackageRegistry(); } public Collection getPackageNames() { return this.pkgRegistryManager.getPackageNames(); } public List getPackageDescrs(String packageName) { return pkgRegistryManager.getPackageDescrs(packageName); } /** * Returns an expander for DSLs (only if there is a DSL configured for this * package). */ public DefaultExpander getDslExpander() { DefaultExpander expander = new DefaultExpander(); if (this.dslFiles == null || this.dslFiles.isEmpty()) { return null; } for (DSLMappingFile file : this.dslFiles) { expander.addDSLMapping(file.getMapping()); } return expander; } @Override public Map getGlobals() { return this.globals.getGlobals(); } @Override public void addGlobal(String name, Type type) { this.globals.addGlobal(name, type); } protected GlobalVariableContext getGlobalVariableContext() { return globals; } /** * This will return true if there were errors in the package building and * compiling phase */ public boolean hasErrors() { return results.hasErrors(); } public KnowledgeBuilderResults getResults(ResultSeverity... problemTypes) { return results.getResults(problemTypes); } public boolean hasResults(ResultSeverity... problemTypes) { return results.hasResults(problemTypes); } public boolean hasWarnings() { return results.hasWarnings(); } public boolean hasInfo() { return results.hasInfo(); } public List getWarnings() { return results.getWarnings(); } @Override public void reportError(KnowledgeBuilderError error) { results.reportError(error); } /** * @return A list of Error objects that resulted from building and compiling * the package. */ public PackageBuilderErrors getErrors() { return results.getErrors(); } /** * Reset the error list. This is useful when incrementally building * packages. Care should be used when building this, if you clear this when * there were errors on items that a rule depends on (eg functions), then * you will get spurious errors which will not be that helpful. */ public void resetErrors() { results.resetErrors(); } public void resetWarnings() { results.resetWarnings(); } public void resetProblems() { this.results.resetProblems(); if (this.processBuilder != null) { this.processBuilder.getErrors().clear(); } } public ClassLoader getRootClassLoader() { return this.rootClassLoader; } public void registerBuildResource(final Resource resource, ResourceType type) { InternalResource ires = (InternalResource) resource; if (ires.getResourceType() == null) { ires.setResourceType(type); } else if (ires.getResourceType() != type) { addBuilderResult(new ResourceTypeDeclarationWarning(resource, ires.getResourceType(), type)); } buildResources.push(Collections.singletonList(resource)); } public void registerBuildResources(List resources) { buildResources.push(resources); } public void undo() { if (buildResources.isEmpty()) { return; } for (Resource resource : buildResources.pop()) { removeObjectsGeneratedFromResource(resource); } } public ResourceRemovalResult removeObjectsGeneratedFromResource(Resource resource) { boolean modified = false; for (PackageRegistry packageRegistry : this.pkgRegistryManager.getPackageRegistry().values()) { modified = packageRegistry.removeObjectsGeneratedFromResource(resource) || modified; } if (results != null) { results.getAllResults().removeIf(knowledgeBuilderResult -> resource.equals(knowledgeBuilderResult.getResource())); } if (processBuilder != null && processBuilder.getErrors() != null) { processBuilder.getErrors().removeIf(knowledgeBuilderResult -> resource.equals(knowledgeBuilderResult.getResource())); } if (results != null && results.getAllResults().size() == 0) { // TODO Error attribution might be bugged for (PackageRegistry packageRegistry : this.pkgRegistryManager.getPackageRegistry().values()) { packageRegistry.getPackage().resetErrors(); } } Collection removedTypes = typeDeclarationManager.getTypeDeclarationBuilder().removeTypesGeneratedFromResource(resource); for (List pkgDescrs : pkgRegistryManager.getPackageDescrs()) { for (PackageDescr pkgDescr : pkgDescrs) { pkgDescr.removeObjectsGeneratedFromResource(resource); } } if (kBase != null) { modified = kBase.removeObjectsGeneratedFromResource(resource, kBase.getWorkingMemories()) || modified; } return new ResourceRemovalResult(modified, removedTypes); } @Override public void rewireAllClassObjectTypes() { if (kBase != null) { for (InternalKnowledgePackage pkg : kBase.getPackagesMap().values()) { pkg.getDialectRuntimeRegistry().getDialectData("java").setDirty(true); pkg.wireStore(); } } } public void setAssetFilter(AssetFilter assetFilter) { this.assetFilter = assetFilter; } protected AssetFilter getAssetFilter() { return this.assetFilter; } public void add(Resource resource, ResourceType type) { ResourceConfiguration resourceConfiguration = resource instanceof BaseResource ? resource.getConfiguration() : null; add(resource, type, resourceConfiguration); } public CompositeKnowledgeBuilder batch() { return new CompositeKnowledgeBuilderImpl(this); } public void add(Resource resource, ResourceType type, ResourceConfiguration configuration) { registerBuildResource(resource, type); addKnowledgeResource(resource, type, configuration); } @Override public Collection getKnowledgePackages() { if (hasErrors()) { return new ArrayList<>(0); } InternalKnowledgePackage[] pkgs = getPackages(); List list = new ArrayList<>(pkgs.length); Collections.addAll(list, pkgs); return list; } public KieBase newKieBase() { return newKnowledgeBase(KieServices.get().newKieBaseConfiguration()); } public KieBase newKnowledgeBase(KieBaseConfiguration conf) { KnowledgeBuilderErrors errors = getErrors(); if (!errors.isEmpty()) { for (KnowledgeBuilderError error : errors) { logger.error(error.toString()); } throw new IllegalArgumentException("Could not parse knowledge. See the logs for details."); } RuleBase kbase = RuleBaseFactory.newRuleBase(conf); kbase.addPackages(asList(getPackages())); return KnowledgeBaseFactory.newKnowledgeBase(kbase); } public TypeDeclaration getTypeDeclaration(Class cls) { return typeDeclarationManager.getTypeDeclaration(cls); } public TypeDeclaration getTypeDeclaration(ObjectType objectType) { return typeDeclarationManager.getTypeDeclaration(objectType); } private Map getBuilderCache() { if (builderCache == null) { builderCache = new HashMap<>(); } return builderCache; } public T getCachedOrCreate(String key, Supplier creator) { final Map builderCache = getBuilderCache(); final T cachedValue = (T) builderCache.get(key); if (cachedValue == null) { final T newValue = creator.get(); builderCache.put(key, newValue); return newValue; } else { return cachedValue; } } public final void buildPackages( Collection packages ) { // this 2 build steps are called in sequence here, but are interleaved by processes and assemblers compilation // during the build lifecycle of the CompositeKnowledgeBuilderImpl doFirstBuildStep(packages); doSecondBuildStep(packages); } // composite build lifecycle /** * Performs the actual building of rules, but may be empty in subclasses */ protected void doFirstBuildStep( Collection packages ) { buildPackagesWithoutRules(packages); buildRules(packages); } /** * Used by subclasses that need to perform the build after the assemblers */ protected void doSecondBuildStep( Collection packages ) { } public void buildPackagesWithoutRules(Collection packages ) { CompositePackageCompilationPhase compositePackageCompilationPhase = new CompositePackageCompilationPhase( packages, pkgRegistryManager, typeDeclarationManager.getTypeDeclarationBuilder(), globals, this, // as DroolsAssemblerContext results, kBase, configuration.as(KnowledgeBuilderConfigurationImpl.KEY)); compositePackageCompilationPhase.process(); } private void buildRules(Collection packages) { for (CompositePackageDescr packageDescr : packages) { setAssetFilter(packageDescr.getFilter()); PackageRegistry pkgRegistry = getPackageRegistry(packageDescr.getNamespace()); compileKnowledgePackages(packageDescr, pkgRegistry, null); setAssetFilter(null); } wireAllRules(); processKieBaseTypes(); for (CompositePackageDescr packageDescr : packages) { setAssetFilter(packageDescr.getFilter()); PackageRegistry pkgRegistry = getPackageRegistry(packageDescr.getNamespace()); compileRete(pkgRegistry, packageDescr); setAssetFilter(null); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy