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

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

/*
 * Copyright 2015 Red Hat, Inc. and/or its affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * 
 *      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 org.drools.compiler.compiler.BPMN2ProcessFactory;
import org.drools.compiler.compiler.PackageRegistry;
import org.drools.compiler.lang.descr.AbstractClassTypeDeclarationDescr;
import org.drools.compiler.lang.descr.CompositePackageDescr;
import org.drools.compiler.lang.descr.EnumDeclarationDescr;
import org.drools.compiler.lang.descr.ImportDescr;
import org.drools.compiler.lang.descr.PackageDescr;
import org.drools.compiler.lang.descr.TypeDeclarationDescr;
import org.drools.core.builder.conf.impl.JaxbConfigurationImpl;
import org.drools.core.util.StringUtils;
import org.kie.api.io.Resource;
import org.kie.api.io.ResourceConfiguration;
import org.kie.api.io.ResourceType;
import org.kie.internal.builder.ChangeType;
import org.kie.internal.builder.CompositeKnowledgeBuilder;
import org.kie.internal.builder.ResourceChange;
import org.kie.internal.builder.ResourceChangeSet;

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

public class CompositeKnowledgeBuilderImpl implements CompositeKnowledgeBuilder {

    private final KnowledgeBuilderImpl kBuilder;

    private final Map> resourcesByType = new HashMap>();

    private RuntimeException buildException = null;

    public ResourceType currentType = null;

    public CompositeKnowledgeBuilderImpl(KnowledgeBuilderImpl kBuilder) {
        this.kBuilder = kBuilder;
    }

    public CompositeKnowledgeBuilder type(ResourceType type) {
        currentType = type;
        return this;
    }

    public CompositeKnowledgeBuilder add(Resource resource) {
        if (currentType == null) {
            throw new RuntimeException("You must declare the type of the resource");
        }
        return add(resource, currentType);
    }

    public CompositeKnowledgeBuilder add(Resource resource, ResourceType type) {
        return add(resource, type, resource.getConfiguration());
    }

    public CompositeKnowledgeBuilder add(Resource resource, ResourceType type, ResourceChangeSet changes) {
        return add(resource, type, resource.getConfiguration(), changes);
    }

    public CompositeKnowledgeBuilder add(Resource resource, ResourceType type, ResourceConfiguration configuration) {
        return add(resource, type, configuration, null);
    }

    public CompositeKnowledgeBuilder add(Resource resource, ResourceType type, ResourceConfiguration configuration, ResourceChangeSet changes) {
        ResourceDescr resourceDescr = new ResourceDescr(configuration, resource, changes);
        List resourceDescrs = this.resourcesByType.get(type);
        if (resourceDescrs == null) {
            resourceDescrs = new ArrayList();
            resourcesByType.put(type, resourceDescrs);
        }
        resourceDescrs.add(resourceDescr);
        return this;
    }

    private List getResources() {
        List resources = new ArrayList();
        for (List resourceDescrs : resourcesByType.values()) {
            for (ResourceDescr resourceDescr : resourceDescrs) {
                resources.add(resourceDescr.resource);
            }
        }
        return resources;
    }

    public void build() {
        buildException = null;
        kBuilder.registerBuildResources(getResources());
        buildResources();
        buildPackages();
        buildOthers();
        resourcesByType.clear();
        if (buildException != null) {
            throw buildException;
        }
    }

    private void buildPackages() {
        Collection packages = buildPackageDescr();
        initPackageRegistries(packages);
        normalizeTypeAnnotations( packages );
        buildTypeDeclarations(packages);
        buildEntryPoints( packages );
        buildOtherDeclarations(packages);
        normalizeRuleAnnotations( packages );
        buildRules(packages);
    }

    private void normalizeTypeAnnotations( Collection packages ) {
        for (CompositePackageDescr packageDescr : packages) {
            kBuilder.normalizeTypeDeclarationAnnotations( packageDescr );
        }
    }
      
    private void normalizeRuleAnnotations( Collection packages ) {
        for (CompositePackageDescr packageDescr : packages) {
            kBuilder.normalizeRuleAnnotations( packageDescr );
        }
    }

    private void buildEntryPoints( Collection packages ) {
        for (CompositePackageDescr packageDescr : packages) {
            kBuilder.processEntryPointDeclarations(kBuilder.getPackageRegistry( packageDescr.getNamespace() ), packageDescr);
        }
    }

    private void buildResources() {
        buildResourceType(DSL_RESOURCE_BUILDER, ResourceType.DSL);
        buildResourceType(DRF_RESOURCE_BUILDER, ResourceType.DRF);
        buildResourceType(BPMN2_RESOURCE_BUILDER, ResourceType.BPMN2);
        buildResourceType(PKG_RESOURCE_BUILDER, ResourceType.PKG);
        buildResourceType(CHANGE_SET_RESOURCE_BUILDER, ResourceType.CHANGE_SET);
        buildResourceType(XSD_RESOURCE_BUILDER, ResourceType.XSD);
        buildResourceType(PMML_RESOURCE_BUILDER, ResourceType.PMML);
    }

    private void buildResourceType(ResourceBuilder resourceBuilder, ResourceType resourceType) {
        List resourcesByType = this.resourcesByType.remove(resourceType);
        if (resourcesByType != null) {
            for (ResourceDescr resourceDescr : resourcesByType) {
                try {
                    kBuilder.setAssetFilter(resourceDescr.getFilter());
                    resourceBuilder.build( kBuilder, resourceDescr );
                } catch (RuntimeException e) {
                    if (buildException == null) {
                        buildException = e;
                    }
                } catch (Exception e) {
                    if (buildException == null) {
                        buildException = new RuntimeException( e );
                    }
                } finally{
                    kBuilder.setAssetFilter(null);
                }
            }
        }
    }

    private interface ResourceBuilder {
        void build(KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr) throws Exception;
    }

    private static final ResourceBuilder DSL_RESOURCE_BUILDER = new ResourceBuilder() {
        @Override
        public void build( KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr ) throws Exception {
            kBuilder.addDsl( resourceDescr.resource );
        }
    };

    private static final ResourceBuilder PMML_RESOURCE_BUILDER = new ResourceBuilder() {
        @Override
        public void build( KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr ) throws Exception {
            kBuilder.addPackageFromPMML(resourceDescr.resource, ResourceType.PMML, resourceDescr.configuration);
        }
    };

    private static final ResourceBuilder XSD_RESOURCE_BUILDER = new ResourceBuilder() {
        @Override
        public void build( KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr ) throws Exception {
            if (resourceDescr.configuration instanceof JaxbConfigurationImpl) {
                // if the xsd file doesn't have a jaxb configuration it doesn't belong to the kprojact and then can be skipped
                kBuilder.addPackageFromXSD( resourceDescr.resource, (JaxbConfigurationImpl) resourceDescr.configuration );
            }
        }
    };

    private static final ResourceBuilder CHANGE_SET_RESOURCE_BUILDER = new ResourceBuilder() {
        @Override
        public void build( KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr ) throws Exception {
            kBuilder.addPackageFromChangeSet( resourceDescr.resource);
        }
    };

    private static final ResourceBuilder PKG_RESOURCE_BUILDER = new ResourceBuilder() {
        @Override
        public void build( KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr ) throws Exception {
            kBuilder.addPackageFromInputStream(resourceDescr.resource );
        }
    };

    private static final ResourceBuilder BPMN2_RESOURCE_BUILDER = new ResourceBuilder() {
        @Override
        public void build( KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr ) throws Exception {
            BPMN2ProcessFactory.configurePackageBuilder( kBuilder );
            kBuilder.addProcessFromXml( resourceDescr.resource );
        }
    };

    private static final ResourceBuilder DRF_RESOURCE_BUILDER = new ResourceBuilder() {
        @Override
        public void build( KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr ) throws Exception {
            kBuilder.addProcessFromXml(resourceDescr.resource);
        }
    };

    private void buildOthers() {
        try {
            for (Map.Entry> entry : resourcesByType.entrySet()) {
                for (ResourceDescr resourceDescr : entry.getValue()) {
                    kBuilder.setAssetFilter(resourceDescr.getFilter());
                    kBuilder.addPackageForExternalType(resourceDescr.resource, entry.getKey(), resourceDescr.configuration);
                    kBuilder.setAssetFilter(null);
                }
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException( e );
        }
    }

    private void buildOtherDeclarations(Collection packages) {
        for (CompositePackageDescr packageDescr : packages) {
            kBuilder.setAssetFilter(packageDescr.getFilter());
            PackageRegistry pkgRegistry = kBuilder.getPackageRegistry(packageDescr.getNamespace());
            kBuilder.processOtherDeclarations( pkgRegistry, packageDescr );
            kBuilder.setAssetFilter(null);
        }
    }

    private void buildRules(Collection packages) {
        for (CompositePackageDescr packageDescr : packages) {
            kBuilder.setAssetFilter(packageDescr.getFilter());
            PackageRegistry pkgRegistry = kBuilder.getPackageRegistry(packageDescr.getNamespace());
            kBuilder.compileAllRules(packageDescr, pkgRegistry);
            kBuilder.setAssetFilter(null);
        }
    }

    private void buildTypeDeclarations( Collection packages ) {
        Map unprocesseableDescrs = new HashMap();
        List unresolvedTypes = new ArrayList();
        List unsortedDescrs = new ArrayList();
        for (CompositePackageDescr packageDescr : packages) {
            for (TypeDeclarationDescr typeDeclarationDescr : packageDescr.getTypeDeclarations()) {
                unsortedDescrs.add( typeDeclarationDescr );
            }
            for (EnumDeclarationDescr enumDeclarationDescr : packageDescr.getEnumDeclarations()) {
                unsortedDescrs.add( enumDeclarationDescr );
            }
        }

        kBuilder.getTypeBuilder().processTypeDeclarations( packages, unsortedDescrs, unresolvedTypes, unprocesseableDescrs );

        for ( CompositePackageDescr packageDescr : packages ) {
            for ( ImportDescr importDescr : packageDescr.getImports() ) {
                kBuilder.getPackageRegistry( packageDescr.getNamespace() ).addImport( importDescr );
            }
        }
    }

    private void initPackageRegistries(Collection packages) {
        for ( CompositePackageDescr packageDescr : packages ) {
            if ( kBuilder.getPackageRegistry( packageDescr.getName() ) == null ) {
                if ( StringUtils.isEmpty(packageDescr.getName()) ) {
                    packageDescr.setName( kBuilder.getBuilderConfiguration().getDefaultPackageName() );
                }
                kBuilder.createPackageRegistry( packageDescr );
            }
        }
    }

    private Collection buildPackageDescr() {
        Map packages = new HashMap();
        buildResource(packages, ResourceType.DRL, DRL_TO_PKG_DESCR);
        buildResource(packages, ResourceType.GDRL, DRL_TO_PKG_DESCR);
        buildResource(packages, ResourceType.RDRL, DRL_TO_PKG_DESCR);
        buildResource(packages, ResourceType.DESCR, DRL_TO_PKG_DESCR);
        buildResource(packages, ResourceType.DSLR, DSLR_TO_PKG_DESCR);
        buildResource(packages, ResourceType.RDSLR, DSLR_TO_PKG_DESCR);
        buildResource(packages, ResourceType.XDRL, XML_TO_PKG_DESCR);
        buildResource(packages, ResourceType.DTABLE, DTABLE_TO_PKG_DESCR);
        buildResource(packages, ResourceType.SCARD, SCARD_TO_PKG_DESCR);
        buildResource(packages, ResourceType.TDRL, DRL_TO_PKG_DESCR);
        buildResource(packages, ResourceType.TEMPLATE, TEMPLATE_TO_PKG_DESCR);
        buildResource(packages, ResourceType.GDST, GUIDED_DTABLE_TO_PKG_DESCR);
        buildResource(packages, ResourceType.SCGD, GUIDED_SCARD_TO_PKG_DESCR);
        this.resourcesByType.remove(ResourceType.DRT); // drt is a template for dtables but doesn't have to be built on its own
        return packages.values();
    }

    private void buildResource(Map packages, ResourceType resourceType, ResourceToPkgDescrMapper mapper) {
        List resourcesByType = this.resourcesByType.remove(resourceType);
        if (resourcesByType != null) {
            for (ResourceDescr resourceDescr : resourcesByType) {
                try {
                    registerPackageDescr(resourceDescr, packages, resourceDescr.resource, mapper.map(kBuilder, resourceDescr));
                } catch (RuntimeException e) {
                    if (buildException == null) {
                        buildException = e;
                    }
                } catch (Exception e) {
                    if (buildException == null) {
                        buildException = new RuntimeException( e );
                    }
                }
            }
        }
    }

    private void registerPackageDescr(ResourceDescr resourceDescr, Map packages, Resource resource, PackageDescr packageDescr) {
        if (packageDescr != null) {
            CompositePackageDescr compositePackageDescr = packages.get(packageDescr.getNamespace());
            if (compositePackageDescr == null) {
                compositePackageDescr = packageDescr instanceof CompositePackageDescr ?
                                        ( (CompositePackageDescr) packageDescr ) :
                                        new CompositePackageDescr(resource, packageDescr);
                packages.put(packageDescr.getNamespace(), compositePackageDescr);
            } else {
                compositePackageDescr.addPackageDescr(resource, packageDescr);
            }
            compositePackageDescr.addFilter( resourceDescr.getFilter() );
        }
    }

    private static class ResourceDescr {
        final Resource resource;
        final ResourceConfiguration configuration;
        final ResourceChangeSet changes;
        final Map changeMap;
        final ChangeType globalChangeType;

        private ResourceDescr(ResourceConfiguration configuration, Resource resource, ResourceChangeSet changes) {
            this.configuration = configuration;
            this.resource = resource;
            this.changes = changes;
            if ( changes != null ) {
                changeMap = new HashMap();
                if (!changes.getChanges().isEmpty()) {
                    for ( ResourceChange c : changes.getChanges() ) {
                        changeMap.put( assetId( c.getType(), c.getName() ), c );
                    }
                    globalChangeType = null;
                } else {
                    globalChangeType = changes.getChangeType();
                }
            } else {
                changeMap = null;
                globalChangeType = null;
            }
        }
        
        public KnowledgeBuilderImpl.AssetFilter getFilter() {
            return changeMap == null ? null : this.new ChangeSetAssetFilter();
        }
        
        private class ChangeSetAssetFilter implements KnowledgeBuilderImpl.AssetFilter {
            @Override
            public Action accept(ResourceChange.Type type, String pkgName, String assetName) {
                if (globalChangeType != null) {
                    return toFilterAction( globalChangeType );
                }
                ResourceChange change = changeMap.get( assetId(type, assetName) );
                return change != null ? toFilterAction( change.getChangeType() ) : Action.DO_NOTHING;
            }

            private Action toFilterAction( ChangeType changeType ) {
                switch (changeType) {
                    case ADDED: return Action.ADD;
                    case REMOVED: return Action.REMOVE;
                    case UPDATED: return Action.UPDATE;
                }
                return Action.DO_NOTHING;
            }
        }

        private String assetId(ResourceChange.Type type, String assetName) {
            return type + "_" + assetName;
        }
    }

    private interface ResourceToPkgDescrMapper {
        PackageDescr map(KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr) throws Exception;
    }

    private static final ResourceToPkgDescrMapper DRL_TO_PKG_DESCR = new ResourceToPkgDescrMapper() {
        public PackageDescr map(KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr) throws Exception {
            return kBuilder.drlToPackageDescr(resourceDescr.resource);
        }
    };

    private static final ResourceToPkgDescrMapper TEMPLATE_TO_PKG_DESCR = new ResourceToPkgDescrMapper() {
        public PackageDescr map(KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr) throws Exception {
            return kBuilder.templateToPackageDescr( resourceDescr.resource);
        }
    };

    private static final ResourceToPkgDescrMapper DSLR_TO_PKG_DESCR = new ResourceToPkgDescrMapper() {
        public PackageDescr map(KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr) throws Exception {
            return kBuilder.dslrToPackageDescr(resourceDescr.resource);
        }
    };

    private static final ResourceToPkgDescrMapper XML_TO_PKG_DESCR = new ResourceToPkgDescrMapper() {
        public PackageDescr map(KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr) throws Exception {
            return kBuilder.xmlToPackageDescr(resourceDescr.resource);
        }
    };

    private static final ResourceToPkgDescrMapper DTABLE_TO_PKG_DESCR = new ResourceToPkgDescrMapper() {
        public PackageDescr map(KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr) throws Exception {
            return kBuilder.decisionTableToPackageDescr(resourceDescr.resource, resourceDescr.configuration);
        }
    };

    private static final ResourceToPkgDescrMapper SCARD_TO_PKG_DESCR = new ResourceToPkgDescrMapper() {
        public PackageDescr map(KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr) throws Exception {
            return kBuilder.scoreCardToPackageDescr(resourceDescr.resource, resourceDescr.configuration);
        }
    };

    private static final ResourceToPkgDescrMapper GUIDED_DTABLE_TO_PKG_DESCR = new ResourceToPkgDescrMapper() {
        public PackageDescr map(KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr) throws Exception {
            return kBuilder.guidedDecisionTableToPackageDescr(resourceDescr.resource);
        }
    };

    private static final ResourceToPkgDescrMapper GUIDED_SCARD_TO_PKG_DESCR = new ResourceToPkgDescrMapper() {
        public PackageDescr map(KnowledgeBuilderImpl kBuilder, ResourceDescr resourceDescr) throws Exception {
            return kBuilder.guidedScoreCardToPackageDescr(resourceDescr.resource);
        }
    };
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy