/* * Copyright 2016 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.jbpm.test.container.tools; import java.util.Collection; import java.util.List; import java.util.UUID; import org.assertj.core.api.Assertions; import org.kie.api.KieServices; import org.kie.api.builder.KieBuilder; import org.kie.api.builder.KieFileSystem; import org.kie.api.builder.Message; import org.kie.api.builder.Message.Level; import org.kie.api.builder.ReleaseId; import org.kie.api.builder.model.KieBaseModel; import org.kie.api.builder.model.KieModuleModel; import org.kie.api.builder.model.KieSessionModel.KieSessionType; import org.kie.api.conf.EqualityBehaviorOption; import org.kie.api.conf.EventProcessingOption; import org.kie.api.io.Resource; import org.kie.api.io.ResourceType; import org.kie.api.runtime.conf.ClockTypeOption; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Set of convenience methods to help with Kie API */ public class KieUtils { private static final Logger LOGGER = LoggerFactory.getLogger(KieUtils.class); /** * Creates a new KieBuilder with KieFileSystem containing specified * resources. Then the module is built and it is asserted that there are no * build errors. * * @param resources * resources to be built * @return KieBuilder used to build the resources */ public static final KieBuilder newKieBuilder(Collection<Resource> resources) { return buildResources(resources.toArray(new Resource[resources.size()])); } /** * Creates a new KieBuilder with KieFileSystem containing specified * resources. Then the module is built and it is asserted that there are no * build errors. * * @param resources * resources to be built * @return KieBuilder used to build the resources */ public static final KieBuilder newKieBuilder(Resource... resources) { return buildResources(resources); } /** * Creates a new KieBuilder with KieFileSystem containing specified * resources. Then the module is built and if indicated, it is asserted that * there are no build errors. * * @param assertNoErrors * whether to assert there are no errors * @param resources * resources to be built * @return KieBuilder used to build the resources */ public static final KieBuilder newKieBuilder(boolean assertNoErrors, Resource... resources) { return buildResources(assertNoErrors, resources); } /** * Creates a new KieBuilder with KieFileSystem containing specified * resources and defining a KieBase in STREAM mode. Then the module is built * and it is asserted that there are no build errors. * * @param resources * resources to be built * @return KieBuilder used to build the resources */ public static final KieBuilder newCEPKieBuilder(Resource... resources) { return buildCEPResources(resources); } /** * Creates a new KieBuilder with KieFileSystem containing specified * resources and defining a KieBase in STREAM mode. Then the module is built * and if indicated, it is asserted that there are no build errors. * * @param assertNoErrors * whether to assert there are no errors * @param resources * resources to be built * @return KieBuilder used to build the resources */ public static final KieBuilder newCEPKieBuilder(boolean assertNoErrors, Resource... resources) { return buildCEPResources(assertNoErrors, resources); } public static ReleaseId buildKieModule(Collection<Resource> resources) { return buildKieModule(resources.toArray(new Resource[resources.size()])); } /** * Creates the kmodule.xml file and the KieModule from given resources. Kie * module contains cross product of these KieBase and KieSession settings: * KieBases: * <ul> * <li>default settings - stream mode, identity based equality</li> * <li>cloud mode, identity based equality</li> * <li>stream mode, equality based equality</li> * </ul> * KieSessions: * <ul> * <li>default stateless</li> * <li>default stateful - realtime clock</li> * <li>stateful with pseudo clock</li> * </ul> * * @param resources * resources to be added to the KieBase * @return id to reference the KieModule */ public static ReleaseId buildKieModule(Resource... resources) { ReleaseId id = generateReleaseId(); buildKieModule(id, resources); return id; } /** * Returns ReleaseId with randomly generated UUID as artifactId. */ public static ReleaseId generateReleaseId() { final KieServices ks = KieServices.Factory.get(); final String moduleName = UUID.randomUUID().toString(); return ks.newReleaseId("org.jboss.qa.brms", moduleName, "1.0.0"); } /** * Creates the kmodule.xml file and the KieModule from given resources with * given ReleaseId. Kie module contains cross product of these KieBase and * KieSession settings: KieBases: * <ul> * <li>default settings - stream mode, identity based equality</li> * <li>cloud mode, identity based equality</li> * <li>stream mode, equality based equality</li> * </ul> * KieSessions: * <ul> * <li>default stateless</li> * <li>default stateful - realtime clock</li> * <li>stateful with pseudo clock</li> * </ul> * * @param id * id to reference the KieModule * @param resources * resources to be added to the KieBase */ public static void buildKieModule(ReleaseId id, Resource... resources) { KieServices ks = KieServices.Factory.get(); KieModuleModel module = ks.newKieModuleModel(); { // kie base and sessions with default options (STREAM mode!) final String name = KBASE_DEFAULT; KieBaseModel base = module.newKieBaseModel(name); base.setDefault(true); base.addPackage("*"); base.setEventProcessingMode(EventProcessingOption.STREAM); base.newKieSessionModel(getSessionName(name, KSESSION_STATELESS)).setDefault(true) .setType(KieSessionType.STATELESS); base.newKieSessionModel(getSessionName(name, KSESSION_DEFAULT)).setDefault(true) .setType(KieSessionType.STATEFUL); base.newKieSessionModel(getSessionName(name, KSESSION_PSEUDO)).setType(KieSessionType.STATEFUL) .setClockType(ClockTypeOption.get("pseudo")); } { // kie base and sessions working in CLOUD mode final String name = KBASE_CLOUD; KieBaseModel base = module.newKieBaseModel(name); base.addInclude(KBASE_DEFAULT); // include resources from default // KieBase base.setEventProcessingMode(EventProcessingOption.CLOUD); base.newKieSessionModel(getSessionName(name, KSESSION_STATELESS)).setType(KieSessionType.STATELESS); base.newKieSessionModel(getSessionName(name, KSESSION_DEFAULT)).setType(KieSessionType.STATEFUL); base.newKieSessionModel(getSessionName(name, KSESSION_PSEUDO)).setType(KieSessionType.STATEFUL) .setClockType(ClockTypeOption.get("pseudo")); } { // kie base and sessions with equality behavior and STREAM mode final String name = KBASE_EQUALITY; KieBaseModel base = module.newKieBaseModel(name); base.addInclude(KBASE_DEFAULT); // include resources from default // KieBase base.setEventProcessingMode(EventProcessingOption.STREAM); base.setEqualsBehavior(EqualityBehaviorOption.EQUALITY); base.newKieSessionModel(getSessionName(name, KSESSION_STATELESS)).setType(KieSessionType.STATELESS); base.newKieSessionModel(getSessionName(name, KSESSION_DEFAULT)).setType(KieSessionType.STATEFUL); base.newKieSessionModel(getSessionName(name, KSESSION_PSEUDO)).setType(KieSessionType.STATEFUL) .setClockType(ClockTypeOption.get("pseudo")); } KieFileSystem kfs = ks.newKieFileSystem(); LOGGER.debug("kmodule.xml: {}", module.toXML()); kfs.writeKModuleXML(module.toXML()); kfs.generateAndWritePomXML(id); KieBuilder kbuilder = buildResources(kfs, resources); ks.getRepository().addKieModule(kbuilder.getKieModule()); } /** * Combines session name and base name to create unique identifier of a * session. See the constants * * @param baseName * name of the kie base * @param sessionName * name of the kie session * @return session unique identifier */ public static String getSessionName(String baseName, String sessionName) { return String.format("%s-%s", baseName, sessionName); } /** * Gets the KieBase name from the session name. It is expected, that session * name was created with method <code>getSessionName</code>. * * @param sessionName * @return */ public static String getBaseName(String sessionName) { String result = null; if (sessionName != null && sessionName.contains("-")) { result = sessionName.split("-")[0]; } return result; } /** * Creates kmodule.xml defining single default KieBase in STREAM mode and * containing given resources. * * @return KieBuilder for this KieBase */ private static KieBuilder buildCEPResources(Resource... resources) { return buildResources(createDefaultKieFileSystemForCEP(), resources); } /** * Creates kmodule.xml defining single default KieBase in STREAM mode and * containing given resources. * * @return KieBuilder for this KieBase */ private static KieBuilder buildCEPResources(boolean assertNoErrors, Resource... resources) { return buildResources(createDefaultKieFileSystemForCEP(), assertNoErrors, resources); } private static KieFileSystem createDefaultKieFileSystemForCEP() { KieServices ks = KieServices.Factory.get(); KieModuleModel module = ks.newKieModuleModel(); KieBaseModel base = module.newKieBaseModel(KBASE_DEFAULT); base.setDefault(true); base.addPackage("*"); base.setEventProcessingMode(EventProcessingOption.STREAM); KieFileSystem kfs = ks.newKieFileSystem(); kfs.writeKModuleXML(module.toXML()); return kfs; } private static KieBuilder buildResources(Resource... resources) { return buildResources(KieServices.Factory.get().newKieFileSystem(), true, resources); } private static KieBuilder buildResources(boolean assertNoErrors, Resource... resources) { return buildResources(KieServices.Factory.get().newKieFileSystem(), assertNoErrors, resources); } private static KieBuilder buildResources(KieFileSystem kfs, Resource... resources) { return buildResources(kfs, true, resources); } private static KieBuilder buildResources(KieFileSystem kfs, boolean assertNoErrors, Resource... resources) { int counter = 1; for (Resource res : resources) { if (res.getSourcePath() == null && res.getTargetPath() == null) { res.setTargetPath(String.format("/org/jboss/qa/brms/asset%s.%s", counter++, getAssetExtension(res))); } kfs.write(res); } KieBuilder kbuilder = KieServices.Factory.get().newKieBuilder(kfs); kbuilder.buildAll(); List<Message> msgs; // Messages from KieBuilder with increasing severity msgs = kbuilder.getResults().getMessages(Level.INFO); if (msgs.size() > 0) { LOGGER.info("KieBuilder information: {}", msgs.toString()); } msgs = kbuilder.getResults().getMessages(Level.WARNING); if (msgs.size() > 0) { LOGGER.warn("KieBuilder warnings: {}", msgs.toString()); } msgs = kbuilder.getResults().getMessages(Level.ERROR); if (msgs.size() > 0) { LOGGER.error("KieBuilder errors: {}", msgs.toString()); } if (assertNoErrors) { Assertions.assertThat(msgs.size()).as(msgs.toString()).isEqualTo(0); } return kbuilder; } private static String getAssetExtension(Resource res) { ResourceType type = res.getResourceType(); if (type == null) { LOGGER.debug("Resource without ResourceType encountered: {}", res); return "drl"; } else { return type.getDefaultExtension(); } } public static final String KBASE_DEFAULT = "default"; public static final String KBASE_CLOUD = "cloud"; public static final String KBASE_EQUALITY = "equality"; public static final String KSESSION_STATELESS = "stateless"; public static final String KSESSION_DEFAULT = "stateful"; public static final String KSESSION_PSEUDO = "stateful-pseudo"; }