Java tutorial
/** * Copyright (c) 1997-2013, www.tinygroup.org (luo_guo@icloud.com). * * Licensed under the GPL, Version 3.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.gnu.org/licenses/gpl.html * * 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.tinygroup.flow.impl; import org.apache.commons.beanutils.PropertyUtils; import org.tinygroup.commons.match.SimpleTypeMatcher; import org.tinygroup.commons.tools.StringUtil; import org.tinygroup.commons.tools.ValueUtil; import org.tinygroup.context.Context; import org.tinygroup.context.impl.ContextImpl; import org.tinygroup.context2object.util.Context2ObjectUtil; import org.tinygroup.event.Parameter; import org.tinygroup.flow.ComponentInterface; import org.tinygroup.flow.FlowExecutor; import org.tinygroup.flow.config.*; import org.tinygroup.flow.containers.ComponentContainers; import org.tinygroup.flow.exception.FlowRuntimeException; import org.tinygroup.flow.util.FlowElUtil; import org.tinygroup.format.Formater; import org.tinygroup.format.impl.ContextFormater; import org.tinygroup.format.impl.FormaterImpl; import org.tinygroup.i18n.I18nMessageFactory; import org.tinygroup.i18n.I18nMessages; import org.tinygroup.logger.LogLevel; import org.tinygroup.logger.Logger; import org.tinygroup.logger.LoggerFactory; import java.util.HashMap; import java.util.List; import java.util.Map; /** * ? * * @author luoguo */ public class FlowExecutorImpl implements FlowExecutor { private static final Logger LOGGER = LoggerFactory.getLogger(FlowExecutorImpl.class); private static Map<String, Class<?>> exceptionMap = new HashMap<String, Class<?>>(); private static transient Formater formater = new FormaterImpl(); private Map<String, Flow> flowIdMap = new HashMap<String, Flow>();// ?nameid??id? private I18nMessages i18nMessages = I18nMessageFactory.getI18nMessages(); private boolean change; // private ComponentContainers containers = new ComponentContainers(); static { formater.addFormatProvider("", new ContextFormater()); formater.addFormatProvider(Parameter.INPUT, new ContextFormater()); formater.addFormatProvider(Parameter.OUTPUT, new ContextFormater()); formater.addFormatProvider(Parameter.BOTH, new ContextFormater()); } public Map<String, Flow> getFlowIdMap() { return flowIdMap; } public void execute(String flowId, Context context) { execute(flowId, null, context); } public void execute(String flowId, String nodeId, Context context) { LOGGER.logMessage(LogLevel.INFO, "?[flowId:{0},nodeId:{1}]", flowId, nodeId); if (!getFlowIdMap().containsKey(flowId)) { LOGGER.log(LogLevel.ERROR, "flow.flowNotExist", flowId); throw new FlowRuntimeException("flow.flowNotExist", flowId); } Flow flow = getFlowIdMap().get(flowId); Node node = getNode(flow, nodeId); if (node != null) { logContext(context); checkInputParameter(flow, context); execute(flow, node, context); checkOutputParameter(flow, context); logContext(context); } LOGGER.logMessage(LogLevel.INFO, "?[flowId:{0},nodeId:{1}]", flowId, nodeId); } /** * nodeIdBegin begin?,? 1?0 2?0 * nodeIdend ?null ,?? * * @param flow * @param nodeId * @return */ private Node getNode(Flow flow, String nodeId) { if (DEFAULT_END_NODE.equals(nodeId)) { // end LOGGER.logMessage(LogLevel.INFO, "?[flowId:{0},nodeId:{1}]?,", flow.getId(), DEFAULT_END_NODE); return null; } if (nodeId == null) { // begin nodeId = DEFAULT_BEGIN_NODE; } if (DEFAULT_BEGIN_NODE.equals(nodeId) && flow.getNodes().size() == 0) { LOGGER.logMessage(LogLevel.INFO, "?,?[flowId:{0},nodeId:{1}]", flow.getId(), DEFAULT_BEGIN_NODE); return null; } Node node = flow.getNodeMap().get(nodeId); // begin?0 if (node == null && DEFAULT_BEGIN_NODE.equals(nodeId)) { node = flow.getNodes().get(0); } else if (node == null) {// ????begin LOGGER.log(LogLevel.ERROR, "flow.flowNodeNotExist", flow.getId(), nodeId); throw new FlowRuntimeException(i18nMessages.getMessage("flow.flowNodeNotExist", flow.getId(), nodeId)); } return node; } private void logContext(Context context) { if (LOGGER.isEnabled(LogLevel.DEBUG)) { LOGGER.logMessage(LogLevel.DEBUG, ""); logItemMap(context.getItemMap()); logSubContext(context.getSubContextMap()); LOGGER.logMessage(LogLevel.DEBUG, "?"); } } private void logSubContext(Map<String, Context> subContextMap) { LOGGER.logMessage(LogLevel.DEBUG, "?[{0}]"); if (subContextMap != null) { for (String key : subContextMap.keySet()) { logContext(subContextMap.get(key)); } } LOGGER.logMessage(LogLevel.DEBUG, "?[{0}]?"); } private void logItemMap(Map<String, Object> itemMap) { for (String key : itemMap.keySet()) { LOGGER.logMessage(LogLevel.DEBUG, "key: {0}, value: {1}", key, itemMap.get(key)); } } private static Class<?> getExceptionType(String name) { Class<?> exceptionType = exceptionMap.get(name); if (exceptionType == null) { try { exceptionType = Class.forName(name);// TODO:Loader? exceptionMap.put(name, exceptionType); } catch (ClassNotFoundException e) { throw new FlowRuntimeException(e); } } return exceptionType; } /** * ? * * @param flow * @param context * @return */ private Context getNewContext(Flow flow, Context context) { Context flowContext = null; if (context == null) { return null; } flowContext = context.getSubContextMap().get(flow.getId()); if (flowContext == null) { return getNewContext(flow, context.getParent()); } return flowContext; } /** * * * @param flow * ?? * @param node * ?end?? * @param context */ private void execute(Flow flow, Node node, Context context) { String nodeId = node.getId(); // ?id Context flowContext = context; try { LOGGER.logMessage(LogLevel.INFO, ":{}", nodeId); if (flow.isPrivateContext()) { // ?context? flowContext = getNewContext(flow, context); if (flowContext == null) { flowContext = new ContextImpl(); context.putSubContext(flow.getId(), flowContext); } } Component component = node.getComponent(); if (component != null) { ComponentInterface componentInstance = getComponentInstance(component.getName()); setProperties(node, componentInstance, flowContext); if (!nodeId.equals(DEFAULT_END_NODE)) { // ?? componentInstance.execute(flowContext); } LOGGER.logMessage(LogLevel.INFO, ":{}", nodeId); } else { LOGGER.logMessage(LogLevel.INFO, ":{}?", nodeId); } } catch (RuntimeException exception) { /** * ?? */ LOGGER.errorMessage("?[flow:{},node:{}]?", exception, flow.getId(), node.getId()); if (exceptionNodeProcess(flow, node, context, flowContext, exception)) { return; } // ???? Node exceptionNode = flow.getNodeMap().get(EXCEPTION_DEAL_NODE); if (exceptionNode != null && exceptionNodeProcess(flow, exceptionNode, context, flowContext, exception)) { return; // executeNextNode(flow, newContext, exceptionNode.getId()); } // ???? Flow exceptionProcessFlow = this.getFlow(EXCEPTION_DEAL_FLOW); if (exceptionProcessFlow != null) { exceptionNode = exceptionProcessFlow.getNodeMap().get(EXCEPTION_DEAL_NODE); if (exceptionNode != null && exceptionNodeProcess(exceptionProcessFlow, exceptionNode, context, flowContext, exception)) { return; } } throw exception; } if (nodeId != null && !nodeId.equals(DEFAULT_END_NODE)) { // ?????? String nextNodeId = node.getNextNodeId(context); if (nextNodeId == null) { int index = flow.getNodes().indexOf(node); if (index != flow.getNodes().size() - 1) { nextNodeId = flow.getNodes().get(index + 1).getId(); } else { nextNodeId = DEFAULT_END_NODE; } } LOGGER.logMessage(LogLevel.INFO, ":{}", nextNodeId); executeNextNode(flow, flowContext, nextNodeId); } } private void checkInputParameter(Flow flow, Context context) { StringBuffer buf = new StringBuffer(); if (flow.getInputParameters() != null) { for (Parameter parameter : flow.getInputParameters()) { if (parameter.isRequired()) {// // =============20130619begin================ // Object value = context.get(parameter.getName()); // if (value == null) {// // ClassNameObjectGenerator? // value = getObjectByGenerator(parameter, context); // if (value != null) {// ??? // context.put(parameter.getName(), value); // continue; // } // } Object value = Context2ObjectUtil.getObject(parameter, context, this.getClass().getClassLoader()); if (value != null) {// ??? context.put(parameter.getName(), value); continue; } // =============20130619end================ if (value == null) { buf.append("?<"); buf.append(parameter.getName()); buf.append(">?"); } } } if (buf.length() > 0) { // buf.insert(0, "?<" + flow.getId() + ">???"); // throw new FlowRuntimeException(buf.toString()); throw new FlowRuntimeException("flow.inParamNotExist", flow.getId(), buf.toString()); } } } // private Object getObjectByGenerator(Parameter parameter, Context context) // { // String collectionType = parameter.getCollectionType(); // if (generator == null) { // generator = SpringUtil.getBean( // GeneratorFileProcessor.CLASSNAME_OBJECT_GENERATOR_BEAN); // } // if (collectionType != null && !"".equals(collectionType)) { // return generator.getObjectCollection(parameter.getName(), // collectionType, parameter.getType(), context); // } else if (parameter.isArray()) { // return generator.getObjectArray(parameter.getName(), // parameter.getType(), context); // } // // return generator.getObject(parameter.getName(),parameter.getName(), // parameter.getType(), // context); // } private void checkOutputParameter(Flow flow, Context context) { StringBuffer buf = new StringBuffer(); if (flow.getOutputParameters() != null) { for (Parameter parameter : flow.getOutputParameters()) { if (parameter.isRequired()) {// Object value = context.get(parameter.getName()); if (value == null) { buf.append("?<"); buf.append(parameter.getName()); buf.append(">?"); } } } if (buf.length() > 0) { // buf.insert(0, "?<" + flow.getId() + ">???"); // throw new FlowRuntimeException(buf.toString()); throw new FlowRuntimeException("flow.outParamNotExist", flow.getId(), buf.toString()); } } } private boolean exceptionNodeProcess(Flow flow, Node node, Context context, Context newContext, Exception exception) { List<String> nextExceptionList = node.getNextExceptionList(); // 20130524??? for (int i = 0; i < nextExceptionList.size(); i++) { String exceptionName = nextExceptionList.get(i); if (dealException(exception, context, newContext, node, flow, exceptionName)) { return true; } Throwable t = exception.getCause(); while (t != null) { if (dealException(t, context, newContext, node, flow, exceptionName)) { return true; } t = t.getCause(); } } return false; } private boolean dealException(Throwable exception, Context context, Context newContext, Node node, Flow flow, String exceptionName) { if (getExceptionType(exceptionName).isInstance(exception)) {// ? String nextNode = node.getNextExceptionNodeMap().get(exceptionName); context.put(EXCEPTION_DEAL_FLOW, flow); context.put(EXCEPTION_DEAL_NODE_KEY, node); context.put(EXCEPTION_KEY, exception); executeNextNode(flow, newContext, nextNode); LOGGER.errorMessage("??:flow:{},node:{}", exception, flow.getId(), nextNode); return true; } return false; } private void executeNextNode(Flow flow, Context context, String nextNodeId) { String nextExecuteNodeId = nextNodeId; int index = nextNodeId.indexOf(':'); if (index > 0) { // newflowId:newnodeId String[] str = nextNodeId.split(":"); if (str.length > 1) { nextExecuteNodeId = str[1]; } else { nextExecuteNodeId = DEFAULT_BEGIN_NODE; } // ?? execute(str[0], nextExecuteNodeId, context); } else if (!DEFAULT_END_NODE.equals(nextNodeId)) { Node nextNode = flow.getNodeMap().get(nextNodeId); execute(flow, nextNode, context); } } /** * ?? * * @param node * @param componentInstance */ private void setProperties(Node node, ComponentInterface componentInstance, Context context) { Map<String, FlowProperty> properties = node.getComponent().getPropertyMap(); if (properties != null) { for (String name : properties.keySet()) { FlowProperty property = properties.get(name); String value = property.getValue(); Object object = null; // el?el?? if (FlowProperty.EL_TYPE.equals(property.getType())) { object = FlowElUtil.execute(value, context, this.getClass().getClassLoader()); } else {// ??? object = getObject(property.getType(), value, context); } try { PropertyUtils.setProperty(componentInstance, name, object); } catch (Exception e) { throw new FlowRuntimeException(e); } } } } private Object getObject(String type, String value, Context context) { String str = value; if (str instanceof String) { str = formater.format(context, str); } // ??,null Object o = null; if (str != null) { str = str.trim(); // type? if (StringUtil.isEmpty(type)) { o = SimpleTypeMatcher.matchType(str); } else { // type??type?????? o = ValueUtil.getValue(str, type); } } return o; } // protected Object getObjectByName(String name, Context context) { // Object object = getObject(name, context); // if (object == null) { // int index = name.indexOf('.'); // if (index == -1) { // object = context.get(name); // } else { // String k = name.substring(0, index); // String p = name.substring(index + 1); // object = context.get(k); // if (object != null) { // try { // object = PropertyUtils.getProperty(object, p); // } catch (Exception e) { // throw new FlowRuntimeException(e); // } // } // } // } // return object; // } public void assemble() { for (Flow flow : flowIdMap.values()) { flow.assemble(); } } public void addFlow(Flow flow) { if (flow.getId() != null && flowIdMap.get(flow.getId()) != null) { LOGGER.logMessage(LogLevel.ERROR, "flow:[id:{0}]??", flow.getId()); } if (flow.getName() != null && flowIdMap.get(flow.getName()) != null) { LOGGER.logMessage(LogLevel.ERROR, "flow:[name:{0}]??", flow.getName()); } if (flow.getId() != null) { LOGGER.logMessage(LogLevel.INFO, "flow:[id:{0}]", flow.getId()); flowIdMap.put(flow.getId(), flow); } if (flow.getName() != null) { LOGGER.logMessage(LogLevel.INFO, "flow:[Name:{0}]", flow.getName()); flowIdMap.put(flow.getName(), flow); } flow.setFlowExecutor(this); setChange(true); } public void removeFlow(Flow flow) { LOGGER.logMessage(LogLevel.INFO, "flow:[id:{0}]", flow.getId()); flowIdMap.remove(flow.getId()); LOGGER.logMessage(LogLevel.INFO, "flow:[name:{0}]", flow.getName()); flowIdMap.remove(flow.getName()); setChange(true); } public void removeFlow(String flowId) { Flow flow = getFlow(flowId); removeFlow(flow); } public Flow getFlow(String flowId) { return flowIdMap.get(flowId); } public void addComponents(ComponentDefines components) { containers.addComponents(components); } public void removeComponents(ComponentDefines components) { containers.removeComponents(components); } /** * ??? * * @param componentName * ??? * @return */ public ComponentInterface getComponentInstance(String componentName) { ComponentInterface componentInstance = null; if (!StringUtil.isBlank(componentName)) { componentInstance = containers.getComponentInstance(componentName); return componentInstance; } throw new FlowRuntimeException("flow.componentNotExist", componentName); // throw new FlowRuntimeException("??:" + componentName + "?"); } public Context getInputContext(Flow flow, Context context) { return getContext(flow.getInputParameters(), context); } private Context getContext(List<Parameter> parameters, Context context) { Context result = new ContextImpl(); if (parameters != null) { for (Parameter parameter : parameters) { result.put(parameter.getName(), context.get(parameter.getName())); } } return result; } public Context getOutputContext(Flow flow, Context context) { return getContext(flow.getOutputParameters(), context); } public void addComponent(ComponentDefine component) { containers.addComponent(component); } public void removeComponent(ComponentDefine component) { containers.removeComponent(component); } public ComponentDefine getComponentDefine(String componentName) { return containers.getComponentDefine(componentName); } public boolean isChange() { return change; } public void setChange(boolean change) { this.change = change; } public List<ComponentDefine> getComponentDefines() { return containers.getComponentDefines(); } }