📄 xmlflowbuilder.java
字号:
else if (flowDef.isClassRef()) {
flow = getFlowServiceLocator().getFlow(flowDef.classRef);
}
else if (flowDef.shouldCreate()) {
flow = getFlowServiceLocator().createFlow(flowDef.clazz, flowDef.autowire);
}
else {
flow = getFlowServiceLocator().createFlow(flowDef.autowire);
}
flow.setId(element.getAttribute(ID_ATTRIBUTE));
flow.setProperties(parseProperties(element));
// set the flow under construction
setFlow(flow);
}
/**
* Parse the state definitions in the XML file and add them to the flow
* object we're constructing.
*/
protected void parseStateDefinitions() {
Element root = doc.getDocumentElement();
String startStateId = root.getAttribute(START_STATE_ATTRIBUTE);
// get the flow under construction
Flow flow = getFlow();
NodeList nodeList = root.getChildNodes();
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node instanceof Element) {
Element element = (Element)node;
if (ACTION_STATE_ELEMENT.equals(element.getNodeName())) {
parseAndAddActionState(flow, element);
}
else if (VIEW_STATE_ELEMENT.equals(element.getNodeName())) {
parseAndAddViewState(flow, element);
}
else if (DECISION_STATE_ELEMENT.equals(element.getNodeName())) {
parseAndAddDecisionState(flow, element);
}
else if (SUBFLOW_STATE_ELEMENT.equals(element.getNodeName())) {
parseAndAddSubFlowState(flow, element);
}
else if (END_STATE_ELEMENT.equals(element.getNodeName())) {
parseAndAddEndState(flow, element);
}
}
}
flow.setStartState(startStateId);
}
/**
* Parse a state definition from given element, returning given fallback state
* in case no other state object is identified.
*/
protected State parseStateDefinition(Element element, Class requiredStateType, State fallbackInstance) {
FlowArtifact stateDef = parseFlowArtifactDefinition(element);
State state;
if (stateDef.isBeanRef()) {
state = getFlowServiceLocator().getState(stateDef.bean);
}
else if (stateDef.isClassRef()) {
state = getFlowServiceLocator().getState(stateDef.classRef);
}
else if (stateDef.shouldCreate()) {
state = getFlowServiceLocator().createState(stateDef.clazz, stateDef.autowire);
}
else {
state = fallbackInstance;
}
Assert.isInstanceOf(requiredStateType, state,
"The state object for the '" + element.getAttribute(ID_ATTRIBUTE)
+ "' state definition should subclass '" + ClassUtils.getShortName(requiredStateType) + "'");
// parse any state entry actions
List entryElements = DomUtils.getChildElementsByTagName(element, ENTRY_ELEMENT);
if (!entryElements.isEmpty()) {
Element entryElement = (Element)entryElements.get(0);
state.setEntryAction(new CompositeAction(parseAnnotatedActions(entryElement)));
}
if (state instanceof TransitionableState) {
// parse any state exit actions
List exitElements = DomUtils.getChildElementsByTagName(element, EXIT_ELEMENT);
if (!exitElements.isEmpty()) {
Element exitElement = (Element)exitElements.get(0);
((TransitionableState)state).setExitAction(new CompositeAction(parseAnnotatedActions(exitElement)));
}
return state;
}
return state;
}
/**
* Parse given action state definition and add a corresponding state to
* given flow.
*/
protected void parseAndAddActionState(Flow flow, Element element) {
ActionState actionState = (ActionState)parseStateDefinition(element, ActionState.class, new ActionState());
actionState.setId(element.getAttribute(ID_ATTRIBUTE));
actionState.setFlow(flow);
actionState.addActions(parseAnnotatedActions(element));
actionState.addAll(parseTransitions(element));
actionState.setProperties(parseProperties(element));
}
/**
* Parse given view state definition and add a corresponding state to given
* flow.
*/
protected void parseAndAddViewState(Flow flow, Element element) {
ViewState viewState = (ViewState)parseStateDefinition(element, ViewState.class, new ViewState());
viewState.setId(element.getAttribute(ID_ATTRIBUTE));
viewState.setFlow(flow);
if (element.hasAttribute(VIEW_ATTRIBUTE)) {
ViewDescriptorCreator creator = (ViewDescriptorCreator)
fromStringTo(ViewDescriptorCreator.class).execute(element.getAttribute(VIEW_ATTRIBUTE));
viewState.setViewDescriptorCreator(creator);
}
viewState.addAll(parseTransitions(element));
viewState.setProperties(parseProperties(element));
}
/**
* Parse given decision state definition and add a corresponding state to given
* flow.
*/
protected void parseAndAddDecisionState(Flow flow, Element element) {
DecisionState decisionState = (DecisionState)parseStateDefinition(element, DecisionState.class, new DecisionState());
decisionState.setId(element.getAttribute(ID_ATTRIBUTE));
decisionState.setFlow(flow);
decisionState.addAll(parseIfs(element));
decisionState.setProperties(parseProperties(element));
}
/**
* Parse given sub flow state definition and add a corresponding state to
* given flow.
*/
protected void parseAndAddSubFlowState(Flow flow, Element element) {
SubflowState subflowState = (SubflowState)parseStateDefinition(element, SubflowState.class, new SubflowState());
subflowState.setId(element.getAttribute(ID_ATTRIBUTE));
subflowState.setFlow(flow);
subflowState.setSubflow(getFlowServiceLocator().getFlow(element.getAttribute(FLOW_ATTRIBUTE)));
subflowState.setAttributeMapper(parseAttributeMapper(element));
subflowState.addAll(parseTransitions(element));
subflowState.setProperties(parseProperties(element));
}
/**
* Parse given end state definition and add a corresponding state to given
* flow.
*/
protected void parseAndAddEndState(Flow flow, Element element) {
EndState endState = (EndState)parseStateDefinition(element, EndState.class, new EndState());
endState.setId(element.getAttribute(ID_ATTRIBUTE));
endState.setFlow(flow);
if (element.hasAttribute(VIEW_ATTRIBUTE)) {
ViewDescriptorCreator creator = (ViewDescriptorCreator)
fromStringTo(ViewDescriptorCreator.class).execute(element.getAttribute(VIEW_ATTRIBUTE));
endState.setViewDescriptorCreator(creator);
}
endState.setProperties(parseProperties(element));
}
/**
* Parse all annotated action definitions contained in given element.
*/
protected AnnotatedAction[] parseAnnotatedActions(Element element) {
List actions = new LinkedList();
List actionElements = DomUtils.getChildElementsByTagName(element, ACTION_ELEMENT);
Iterator it = actionElements.iterator();
while (it.hasNext()) {
actions.add(parseAnnotatedAction((Element)it.next()));
}
return (AnnotatedAction[])actions.toArray(new AnnotatedAction[actions.size()]);
}
/**
* Parse an annotated action definition and return the corresponding object.
*/
protected AnnotatedAction parseAnnotatedAction(Element element) {
AnnotatedAction action = new AnnotatedAction((Action)parseAction(element));
if (element.hasAttribute(NAME_ATTRIBUTE)) {
action.setName(element.getAttribute(NAME_ATTRIBUTE));
}
if (element.hasAttribute(METHOD_ATTRIBUTE)) {
// direct support for multi-actions
action.setProperty(MultiAction.DefaultActionExecuteMethodNameResolver.METHOD_PROPERTY,
element.getAttribute(METHOD_ATTRIBUTE));
}
parseAndAddProperties(element, action);
return action;
}
/**
* Parse an action definition and return the corresponding object.
*/
protected Action parseAction(Element element) throws FlowBuilderException {
FlowArtifact actionDef = parseFlowArtifactDefinition(element);
if (actionDef.isBeanRef()) {
return getFlowServiceLocator().getAction(actionDef.bean);
}
else if (actionDef.isClassRef()) {
return getFlowServiceLocator().getAction(actionDef.classRef);
}
else if (actionDef.shouldCreate()) {
return getFlowServiceLocator().createAction(actionDef.clazz, actionDef.autowire);
}
throw new FlowBuilderException(this, "Illegal action definition: '" + element + "'");
}
/**
* Parse all properties defined as nested elements of given element.
* Returns the properties as a map: the name of the property is the key, the
* associated value the value.
*/
protected Map parseProperties(Element element) {
MapAttributeSource properties = new MapAttributeSource();
parseAndAddProperties(element, properties);
return properties.getAttributeMap();
}
/**
* Parse all properties defined as nested elements of given element
* and add them to given set of properties.
*/
protected void parseAndAddProperties(Element element, MutableAttributeSource properties) {
List propertyElements = DomUtils.getChildElementsByTagName(element, PROPERTY_ELEMENT);
for (int i = 0; i < propertyElements.size(); i++) {
parseAndAddProperty((Element)propertyElements.get(i), properties);
}
}
/**
* Parse a property definition from given element and add the property
* to given set.
*/
protected void parseAndAddProperty(Element element, MutableAttributeSource properties) {
String name = element.getAttribute(NAME_ATTRIBUTE);
String value = null;
if (element.hasAttribute(VALUE_ATTRIBUTE)) {
value = element.getAttribute(VALUE_ATTRIBUTE);
}
else {
List valueElements = DomUtils.getChildElementsByTagName(element, VALUE_ELEMENT);
Assert.state(valueElements.size() == 1, "A property value should be specified for property '" + name + "'");
value = DomUtils.getTextValue((Element)valueElements.get(0));
}
properties.setAttribute(name, convertPropertyValue(element, value));
}
/**
* Do type conversion for given property value.
*/
protected Object convertPropertyValue(Element element, String stringValue) {
if (element.hasAttribute(TYPE_ATTRIBUTE)) {
ConversionExecutor executor = fromStringToAliased(element.getAttribute(TYPE_ATTRIBUTE));
if (executor != null) {
// convert string value to instance of aliased type
return executor.execute(stringValue);
}
else {
Class targetClass = (Class)fromStringTo(Class.class).execute(element.getAttribute(TYPE_ATTRIBUTE));
// convert string value to instance of target class
return fromStringTo(targetClass).execute(stringValue);
}
}
else {
return stringValue;
}
}
/**
* Find all transition definitions in given state definition and return a
* list of corresponding Transition objects.
*/
protected Transition[] parseTransitions(Element element) {
List transitions = new LinkedList();
List transitionElements = DomUtils.getChildElementsByTagName(element, TRANSITION_ELEMENT);
for (int i = 0; i < transitionElements.size(); i++) {
transitions.add(parseTransition((Element)transitionElements.get(i)));
}
return (Transition[])transitions.toArray(new Transition[transitions.size()]);
}
/**
* Parse a transition definition and return a corresponding Transition
* object.
*/
protected Transition parseTransition(Element element) {
FlowArtifact transitionDef = parseFlowArtifactDefinition(element);
Transition transition;
if (transitionDef.isBeanRef()) {
transition = getFlowServiceLocator().getTransition(transitionDef.bean);
}
else if (transitionDef.isClassRef()) {
transition = getFlowServiceLocator().getTransition(transitionDef.classRef);
}
else if (transitionDef.shouldCreate()) {
transition = getFlowServiceLocator().createTransition(transitionDef.clazz, transitionDef.autowire);
}
else {
transition = new Transition();
}
TransitionCriteria matchingCriteria = (TransitionCriteria)
fromStringTo(TransitionCriteria.class).execute(element.getAttribute(ON_ATTRIBUTE));
transition.setMatchingCriteria(matchingCriteria);
transition.setTargetStateId(element.getAttribute(TO_ATTRIBUTE));
transition.setExecutionCriteria(TransitionCriteriaChain.criteriaChainFor(parseAnnotatedActions(element)));
transition.setProperties(parseProperties(element));
return transition;
}
/**
* Find all "if" definitions in given state definition and return a
* list of corresponding Transition objects.
*/
protected Transition[] parseIfs(Element element) {
List transitions = new LinkedList();
List transitionElements = DomUtils.getChildElementsByTagName(element, IF_ELEMENT);
Iterator it = transitionElements.iterator();
while (it.hasNext()) {
transitions.addAll(Arrays.asList(parseIf((Element)it.next())));
}
return (Transition[])transitions.toArray(new Transition[transitions.size()]);
}
/**
* Parse an "if" transition definition and return a corresponding Transition
* object.
*/
protected Transition[] parseIf(Element element) {
TransitionCriteria criteria = (TransitionCriteria)
fromStringTo(TransitionCriteria.class).execute(element.getAttribute(TEST_ATTRIBUTE));
String trueStateId = element.getAttribute(THEN_ATTRIBUTE);
Transition thenTransition = new Transition(criteria, trueStateId);
String falseStateId = element.getAttribute(ELSE_ATTRIBUTE);
if (StringUtils.hasText(falseStateId)) {
Transition elseTransition = new Transition(TransitionCriteriaFactory.alwaysTrue(), falseStateId);
return new Transition[] { thenTransition, elseTransition };
}
else {
return new Transition[] { thenTransition };
}
}
/**
* Obtain an attribute mapper reference from given sub flow definition
* element and return the identified mapper, or null if no mapper is referenced.
*/
protected FlowAttributeMapper parseAttributeMapper(Element element) {
List attributeMapperElements = DomUtils.getChildElementsByTagName(element, ATTRIBUTE_MAPPER_ELEMENT);
if (attributeMapperElements.isEmpty()) {
return null;
}
else {
Element attributeMapperElement = (Element)attributeMapperElements.get(0);
FlowArtifact mapperDef = parseFlowArtifactDefinition(attributeMapperElement);
if (mapperDef.isBeanRef()) {
return getFlowServiceLocator().getFlowAttributeMapper(mapperDef.bean);
}
else if (mapperDef.isClassRef()) {
return getFlowServiceLocator().getFlowAttributeMapper(mapperDef.classRef);
}
else if (mapperDef.shouldCreate()) {
return getFlowServiceLocator().createFlowAttributeMapper(mapperDef.clazz, mapperDef.autowire);
}
else {
// inline definition of a mapping
ParameterizableFlowAttributeMapper attributeMapper = new ParameterizableFlowAttributeMapper();
List inputElements = DomUtils.getChildElementsByTagName(attributeMapperElement, INPUT_ELEMENT);
List inputMappings = new ArrayList(inputElements.size());
for (Iterator it = inputElements.iterator(); it.hasNext(); ) {
parseAndAddMapping((Element)it.next(), inputMappings);
}
attributeMapper.setInputMappings(inputMappings);
List outputElements = DomUtils.getChildElementsByTagName(attributeMapperElement, OUTPUT_ELEMENT);
List outputMappings = new ArrayList(outputElements.size());
for (Iterator it = outputElements.iterator(); it.hasNext(); ) {
parseAndAddMapping((Element)it.next(), outputMappings);
}
attributeMapper.setOutputMappings(outputMappings);
return attributeMapper;
}
}
}
/**
* Parse a single inline attribute mapping definition and add it to given map.
*/
protected void parseAndAddMapping(Element element, List mappings) {
String name = element.getAttribute(NAME_ATTRIBUTE);
String value = element.getAttribute(VALUE_ATTRIBUTE);
String as = element.getAttribute(AS_ATTRIBUTE);
String from = element.getAttribute(FROM_ATTRIBUTE);
String to = element.getAttribute(TO_ATTRIBUTE);
ConversionExecutor valueConverter = null;
if (StringUtils.hasText(from)) {
if (StringUtils.hasText(to)) {
valueConverter = getConversionService().
getConversionExecutor(getConversionService().getClassByAlias(from), getConversionService().getClassByAlias(to));
}
}
if (StringUtils.hasText(name)) {
// "name" allows you to specify the name of an attribute to map
if (StringUtils.hasText(as)) {
mappings.add(new Mapping(new FlowScopeExpression(name), ExpressionFactory.parsePropertyExpression(as), valueConverter));
}
else {
mappings.add(new Mapping(new FlowScopeExpression(name), ExpressionFactory.parsePropertyExpression(name), valueConverter));
}
}
else if (StringUtils.hasText(value)) {
// "value" allows you to specify the value that should get mapped using an expression
Assert.hasText(as, "The 'as' attribute is required with the 'value' attribute");
mappings.add(new Mapping(ExpressionFactory.parseExpression(value), ExpressionFactory.parsePropertyExpression(as), valueConverter));
}
else {
throw new FlowBuilderException(this, "Name or value is required in a mapping definition: " + element);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -