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

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

There is a newer version: 10.0.0
Show newest version
/*
 * 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 java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.drools.compiler.compiler.BPMN2ProcessFactory;
import org.drools.compiler.compiler.CMMNCaseFactory;
import org.drools.compiler.lang.descr.CompositePackageDescr;
import org.drools.compiler.lang.descr.PackageDescr;
import org.drools.core.builder.conf.impl.JaxbConfigurationImpl;
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.ChangeType;
import org.kie.internal.builder.CompositeKnowledgeBuilder;
import org.kie.internal.builder.ResourceChange;
import org.kie.internal.builder.ResourceChangeSet;
import org.kie.internal.io.ResourceWithConfigurationImpl;

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();
        buildProcesses();
        buildOthers();
        resourcesByType.clear();
        if (buildException != null) {
            throw buildException;
        }
    }

    private void buildPackages() {
        kBuilder.buildPackages( buildPackageDescr() );
    }

    private void buildProcesses() {
    	buildResourceType(ResourceBuilder.BPMN2_RESOURCE_BUILDER, ResourceType.BPMN2);
    	buildResourceType(ResourceBuilder.CMMN_RESOURCE_BUILDER, ResourceType.CMMN);
    }

    private void buildResources() {
        buildResourceType(ResourceBuilder.DSL_RESOURCE_BUILDER, ResourceType.DSL);
        buildResourceType(ResourceBuilder.DRF_RESOURCE_BUILDER, ResourceType.DRF);
        buildResourceType(ResourceBuilder.PKG_RESOURCE_BUILDER, ResourceType.PKG);
        buildResourceType(ResourceBuilder.CHANGE_SET_RESOURCE_BUILDER, ResourceType.CHANGE_SET);
        buildResourceType(ResourceBuilder.XSD_RESOURCE_BUILDER, ResourceType.XSD);
        buildResourceType(ResourceBuilder.SCD_RESOURCE_BUILDER, ResourceType.SCARD);
        buildResourceType(ResourceBuilder.GSCD_RESOURCE_BUILDER, ResourceType.SCGD);
    }

    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 void buildOthers() {
        try {
            for (Map.Entry> entry : resourcesByType.entrySet()) {
                List rds = entry.getValue().stream().map(CompositeKnowledgeBuilderImpl::descrToResourceWithConfiguration).collect(Collectors.toList());
                kBuilder.addPackageForExternalType(entry.getKey(), rds);
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException( e );
        }
    }

    private static ResourceWithConfiguration descrToResourceWithConfiguration(ResourceDescr rd) {
        return new ResourceWithConfigurationImpl(rd.resource,
                                                 rd.configuration,
                                                 kb -> ((KnowledgeBuilderImpl) kb).setAssetFilter(rd.getFilter()),
                                                 kb -> ((KnowledgeBuilderImpl) kb).setAssetFilter(null));
    }

    private Collection buildPackageDescr() {
        Map packages = new HashMap<>();
        buildResource(packages, ResourceType.DRL, ResourceToPkgDescrMapper.DRL_TO_PKG_DESCR);
        buildResource(packages, ResourceType.GDRL,ResourceToPkgDescrMapper. DRL_TO_PKG_DESCR);
        buildResource(packages, ResourceType.RDRL, ResourceToPkgDescrMapper.DRL_TO_PKG_DESCR);
        buildResource(packages, ResourceType.DESCR, ResourceToPkgDescrMapper.DRL_TO_PKG_DESCR);
        buildResource(packages, ResourceType.DSLR, ResourceToPkgDescrMapper.DSLR_TO_PKG_DESCR);
        buildResource(packages, ResourceType.RDSLR, ResourceToPkgDescrMapper.DSLR_TO_PKG_DESCR);
        buildResource(packages, ResourceType.XDRL, ResourceToPkgDescrMapper.XML_TO_PKG_DESCR);
        buildResource(packages, ResourceType.DTABLE, ResourceToPkgDescrMapper.DTABLE_TO_PKG_DESCR);
        buildResource(packages, ResourceType.TDRL, ResourceToPkgDescrMapper.DRL_TO_PKG_DESCR);
        buildResource(packages, ResourceType.TEMPLATE, ResourceToPkgDescrMapper.TEMPLATE_TO_PKG_DESCR);
        buildResource(packages, ResourceType.GDST, ResourceToPkgDescrMapper.GUIDED_DTABLE_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;
        }
    }

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

        ResourceBuilder DSL_RESOURCE_BUILDER = ( kBuilder, resourceDescr ) -> kBuilder.addDsl( resourceDescr.resource );


        ResourceBuilder XSD_RESOURCE_BUILDER = ( kBuilder, resourceDescr ) -> {
            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 );
            }
        };

        ResourceBuilder SCD_RESOURCE_BUILDER = ( kBuilder, resourceDescr ) -> kBuilder.addPackageFromScoreCard(resourceDescr.resource, resourceDescr.configuration);

        ResourceBuilder GSCD_RESOURCE_BUILDER = ( kBuilder, resourceDescr ) -> kBuilder.addPackageFromGuidedScoreCard(resourceDescr.resource);

        ResourceBuilder CHANGE_SET_RESOURCE_BUILDER = ( kBuilder, resourceDescr ) -> kBuilder.addPackageFromChangeSet( resourceDescr.resource);

        ResourceBuilder PKG_RESOURCE_BUILDER = ( kBuilder, resourceDescr ) -> kBuilder.addPackageFromInputStream(resourceDescr.resource );

        ResourceBuilder BPMN2_RESOURCE_BUILDER = ( kBuilder, resourceDescr ) -> {
            BPMN2ProcessFactory.configurePackageBuilder( kBuilder );
            kBuilder.addProcessFromXml( resourceDescr.resource );
        };
        
        ResourceBuilder CMMN_RESOURCE_BUILDER = ( kBuilder, resourceDescr ) -> {
            CMMNCaseFactory.configurePackageBuilder( kBuilder );
            kBuilder.addProcessFromXml( resourceDescr.resource );
        };

        ResourceBuilder DRF_RESOURCE_BUILDER = ( kBuilder, resourceDescr ) -> kBuilder.addProcessFromXml(resourceDescr.resource);
    }

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

        ResourceToPkgDescrMapper DRL_TO_PKG_DESCR = ( kBuilder, resourceDescr ) -> kBuilder.drlToPackageDescr(resourceDescr.resource);
        ResourceToPkgDescrMapper TEMPLATE_TO_PKG_DESCR = ( kBuilder, resourceDescr ) -> kBuilder.templateToPackageDescr( resourceDescr.resource);
        ResourceToPkgDescrMapper DSLR_TO_PKG_DESCR = ( kBuilder, resourceDescr ) -> kBuilder.dslrToPackageDescr(resourceDescr.resource);
        ResourceToPkgDescrMapper XML_TO_PKG_DESCR = ( kBuilder, resourceDescr ) -> kBuilder.xmlToPackageDescr(resourceDescr.resource);
        ResourceToPkgDescrMapper DTABLE_TO_PKG_DESCR = ( kBuilder, resourceDescr ) -> kBuilder.decisionTableToPackageDescr(resourceDescr.resource, resourceDescr.configuration);
        ResourceToPkgDescrMapper GUIDED_DTABLE_TO_PKG_DESCR = ( kBuilder, resourceDescr ) -> kBuilder.guidedDecisionTableToPackageDescr(resourceDescr.resource);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy