Java tutorial
/* * Copyright 2010 JBoss Inc * * Licensed 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.container.spring.namespace; import static org.drools.container.spring.namespace.DefinitionParserHelper.emptyAttributeCheck; import java.util.ArrayList; import java.util.List; import org.drools.ClockType; import org.drools.SessionConfiguration; import org.drools.command.runtime.SetGlobalCommand; import org.drools.command.runtime.process.SignalEventCommand; import org.drools.command.runtime.process.StartProcessCommand; import org.drools.command.runtime.rule.FireAllRulesCommand; import org.drools.command.runtime.rule.FireUntilHaltCommand; import org.drools.command.runtime.rule.InsertObjectCommand; import org.drools.container.spring.beans.KnowledgeAgentBeanFactory; import org.drools.container.spring.beans.StatefulKnowledgeSessionBeanFactory; import org.drools.container.spring.beans.StatefulKnowledgeSessionBeanFactory.JpaConfiguration; import org.drools.container.spring.beans.StatelessKnowledgeSessionBeanFactory; import org.drools.event.DebugProcessEventListener; import org.drools.event.rule.DebugAgendaEventListener; import org.drools.event.rule.DebugWorkingMemoryEventListener; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.RuntimeBeanNameReference; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class KnowledgeSessionDefinitionParser extends AbstractBeanDefinitionParser { private static final String KBASE_ATTRIBUTE = "kbase"; private static final String EMF_ATTRIBUTE = "entity-manager-factory"; private static final String TX_MANAGER_ATTRIBUTE = "transaction-manager"; private static final String FORCLASS_ATTRIBUTE = "for-class"; private static final String IMPLEMENTATION_ATTRIBUTE = "implementation"; private static final String NAME_ATTRIBUTE = "name"; private static final String GRID_NODE_ATTRIBUTE = "node"; private static final String TYPE_ATTRIBUTE = "type"; private static final String LISTENERS_ATTRIBUTE = "listeners"; private static final String KEEP_REFERENCE = "keep-reference"; private static final String CLOCK_TYPE = "clock-type"; private static final String WORK_ITEMS = "work-item-handlers"; private static final String WORK_ITEM = "work-item-handler"; @SuppressWarnings("unchecked") protected AbstractBeanDefinition parseInternal(Element element, ParserContext parserContext) { String id = element.getAttribute("id"); emptyAttributeCheck(element.getLocalName(), "id", id); String kbase = element.getAttribute(KBASE_ATTRIBUTE); emptyAttributeCheck(element.getLocalName(), KBASE_ATTRIBUTE, kbase); String sessionType = element.getAttribute(TYPE_ATTRIBUTE); BeanDefinitionBuilder factory; if ("stateful".equals(sessionType)) { factory = BeanDefinitionBuilder.rootBeanDefinition(StatefulKnowledgeSessionBeanFactory.class); } else if ("stateless".equals(sessionType)) { factory = BeanDefinitionBuilder.rootBeanDefinition(StatelessKnowledgeSessionBeanFactory.class); } else { throw new IllegalArgumentException( "Invalid value for " + TYPE_ATTRIBUTE + " attribute: " + sessionType); } factory.addPropertyReference("kbase", kbase); String node = element.getAttribute(GRID_NODE_ATTRIBUTE); if (node != null && node.length() > 0) { factory.addPropertyReference("node", node); } String name = element.getAttribute(NAME_ATTRIBUTE); if (StringUtils.hasText(name)) { factory.addPropertyValue("name", name); } else { factory.addPropertyValue("name", id); } // Additions for JIRA JBRULES-3076 String listeners = element.getAttribute(LISTENERS_ATTRIBUTE); if (StringUtils.hasText(listeners)) { factory.addPropertyValue("eventListenersFromGroup", new RuntimeBeanReference(listeners)); } EventListenersUtil.parseEventListeners(parserContext, factory, element); // End of Additions for JIRA JBRULES-3076 Element ksessionConf = DomUtils.getChildElementByTagName(element, "configuration"); if (ksessionConf != null) { Element persistenceElm = DomUtils.getChildElementByTagName(ksessionConf, "jpa-persistence"); if (persistenceElm != null) { BeanDefinitionBuilder beanBuilder = BeanDefinitionBuilder .genericBeanDefinition(JpaConfiguration.class); String loadId = persistenceElm.getAttribute("load"); if (StringUtils.hasText(loadId)) { beanBuilder.addPropertyValue("id", Long.parseLong(loadId)); } Element tnxMng = DomUtils.getChildElementByTagName(persistenceElm, TX_MANAGER_ATTRIBUTE); String ref = tnxMng.getAttribute("ref"); beanBuilder.addPropertyReference("platformTransactionManager", ref); Element emf = DomUtils.getChildElementByTagName(persistenceElm, EMF_ATTRIBUTE); ref = emf.getAttribute("ref"); beanBuilder.addPropertyReference("entityManagerFactory", ref); Element variablePersisters = DomUtils.getChildElementByTagName(persistenceElm, "variable-persisters"); if (variablePersisters != null && variablePersisters.hasChildNodes()) { List<Element> childPersisterElems = DomUtils.getChildElementsByTagName(variablePersisters, "persister"); ManagedMap persistors = new ManagedMap(childPersisterElems.size()); for (Element persisterElem : childPersisterElems) { String forClass = persisterElem.getAttribute(FORCLASS_ATTRIBUTE); String implementation = persisterElem.getAttribute(IMPLEMENTATION_ATTRIBUTE); if (!StringUtils.hasText(forClass)) { throw new RuntimeException("persister element must have valid for-class attribute"); } if (!StringUtils.hasText(implementation)) { throw new RuntimeException( "persister element must have valid implementation attribute"); } persistors.put(forClass, implementation); } beanBuilder.addPropertyValue("variablePersisters", persistors); } factory.addPropertyValue("jpaConfiguration", beanBuilder.getBeanDefinition()); } BeanDefinitionBuilder rbaseConfBuilder = BeanDefinitionBuilder .rootBeanDefinition(SessionConfiguration.class); Element e = DomUtils.getChildElementByTagName(ksessionConf, KEEP_REFERENCE); if (e != null && StringUtils.hasText(e.getAttribute("enabled"))) { rbaseConfBuilder.addPropertyValue("keepReference", Boolean.parseBoolean(e.getAttribute("enabled"))); } e = DomUtils.getChildElementByTagName(ksessionConf, CLOCK_TYPE); if (e != null && StringUtils.hasText(e.getAttribute("type"))) { rbaseConfBuilder.addPropertyValue("clockType", ClockType.resolveClockType(e.getAttribute("type"))); } factory.addPropertyValue("conf", rbaseConfBuilder.getBeanDefinition()); e = DomUtils.getChildElementByTagName(ksessionConf, WORK_ITEMS); if (e != null) { List<Element> children = DomUtils.getChildElementsByTagName(e, WORK_ITEM); if (children != null && !children.isEmpty()) { ManagedMap workDefs = new ManagedMap(); for (Element child : children) { workDefs.put(child.getAttribute("name"), new RuntimeBeanReference(child.getAttribute("ref"))); } factory.addPropertyValue("workItems", workDefs); } } } Element batch = DomUtils.getChildElementByTagName(element, "batch"); if (batch == null) { // just temporary legacy suppport batch = DomUtils.getChildElementByTagName(element, "script"); } if (batch != null) { // we know there can only ever be one ManagedList children = new ManagedList(); for (int i = 0, length = batch.getChildNodes().getLength(); i < length; i++) { Node n = batch.getChildNodes().item(i); if (n instanceof Element) { Element e = (Element) n; BeanDefinitionBuilder beanBuilder = null; if ("insert-object".equals(e.getLocalName())) { String ref = e.getAttribute("ref"); Element nestedElm = getFirstElement(e.getChildNodes()); beanBuilder = BeanDefinitionBuilder.genericBeanDefinition(InsertObjectCommand.class); if (StringUtils.hasText(ref)) { beanBuilder.addConstructorArgReference(ref); } else if (nestedElm != null) { beanBuilder.addConstructorArgValue( parserContext.getDelegate().parsePropertySubElement(nestedElm, null, null)); } else { throw new IllegalArgumentException( "insert-object must either specify a 'ref' attribute or have a nested bean"); } } else if ("set-global".equals(e.getLocalName())) { String ref = e.getAttribute("ref"); Element nestedElm = getFirstElement(e.getChildNodes()); beanBuilder = BeanDefinitionBuilder.genericBeanDefinition(SetGlobalCommand.class); beanBuilder.addConstructorArgValue(e.getAttribute("identifier")); if (StringUtils.hasText(ref)) { beanBuilder.addConstructorArgReference(ref); } else if (nestedElm != null) { beanBuilder.addConstructorArgValue( parserContext.getDelegate().parsePropertySubElement(nestedElm, null, null)); } else { throw new IllegalArgumentException( "set-global must either specify a 'ref' attribute or have a nested bean"); } } else if ("fire-until-halt".equals(e.getLocalName())) { beanBuilder = BeanDefinitionBuilder.genericBeanDefinition(FireUntilHaltCommand.class); } else if ("fire-all-rules".equals(e.getLocalName())) { beanBuilder = BeanDefinitionBuilder.genericBeanDefinition(FireAllRulesCommand.class); String max = e.getAttribute("max"); if (StringUtils.hasText(max)) { beanBuilder.addPropertyValue("max", max); } } else if ("start-process".equals(e.getLocalName())) { beanBuilder = BeanDefinitionBuilder.genericBeanDefinition(StartProcessCommand.class); String processId = e.getAttribute("process-id"); if (!StringUtils.hasText(processId)) { throw new IllegalArgumentException("start-process must specify a process-id"); } beanBuilder.addConstructorArgValue(processId); List<Element> params = DomUtils.getChildElementsByTagName(e, "parameter"); if (!params.isEmpty()) { ManagedMap map = new ManagedMap(); for (Element param : params) { String identifier = param.getAttribute("identifier"); if (!StringUtils.hasText(identifier)) { throw new IllegalArgumentException( "start-process paramaters must specify an identifier"); } String ref = param.getAttribute("ref"); Element nestedElm = getFirstElement(param.getChildNodes()); if (StringUtils.hasText(ref)) { map.put(identifier, new RuntimeBeanReference(ref)); } else if (nestedElm != null) { map.put(identifier, parserContext.getDelegate() .parsePropertySubElement(nestedElm, null, null)); } else { throw new IllegalArgumentException( "start-process parameters must either specify a 'ref' attribute or have a nested bean"); } } beanBuilder.addPropertyValue("parameters", map); } } else if ("signal-event".equals(e.getLocalName())) { beanBuilder = BeanDefinitionBuilder.genericBeanDefinition(SignalEventCommand.class); String processInstanceId = e.getAttribute("process-instance-id"); if (StringUtils.hasText(processInstanceId)) { beanBuilder.addConstructorArgValue(processInstanceId); } beanBuilder.addConstructorArgValue(e.getAttribute("event-type")); String ref = e.getAttribute("ref"); Element nestedElm = getFirstElement(e.getChildNodes()); if (StringUtils.hasText(ref)) { beanBuilder.addConstructorArgReference(ref); } else if (nestedElm != null) { beanBuilder.addConstructorArgValue( parserContext.getDelegate().parsePropertySubElement(nestedElm, null, null)); } else { throw new IllegalArgumentException( "signal-event must either specify a 'ref' attribute or have a nested bean"); } } if (beanBuilder == null) { throw new IllegalStateException("Unknow element: " + e.getLocalName()); } children.add(beanBuilder.getBeanDefinition()); } } factory.addPropertyValue("batch", children); } // find any kagent's for the current kbase and assign (only if this // is a stateless session) if (sessionType.equals("stateless")) { for (String beanName : parserContext.getRegistry().getBeanDefinitionNames()) { BeanDefinition def = parserContext.getRegistry().getBeanDefinition(beanName); if (KnowledgeAgentBeanFactory.class.getName().equals(def.getBeanClassName())) { PropertyValue pvalue = def.getPropertyValues().getPropertyValue("kbase"); RuntimeBeanReference tbf = (RuntimeBeanReference) pvalue.getValue(); if (kbase.equals(tbf.getBeanName())) { factory.addPropertyValue("knowledgeAgent", new RuntimeBeanReference(beanName)); } } } } return factory.getBeanDefinition(); } private Element getFirstElement(NodeList list) { for (int j = 0, lengthj = list.getLength(); j < lengthj; j++) { if (list.item(j) instanceof Element) { return (Element) list.item(j); } } return null; } }