Add base support for eclipse papyrus modeling
- First stage to add support for UI modeling via eclipse uml2 and papyrus frameworks. - Add new interface StateMachineModelFactory which is a central point of building machines models outside of a normal annotation/build classes. What this mean is a hook to config model so that machine can be defined via a model factory, instead of writing config based on normal adapter callbacks. - Integrate model config into an annotation model so that you can still use normal adapters but point those to model factory classes, which then allows external hooks for machine configuration. - New spring-statemachine-uml package which supports eclipse uml2/emf frameworks to define a machine config. - Relates to #193
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,8 @@ import org.springframework.statemachine.config.builders.StateMachineConfigBuilde
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineModelBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineModelConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionBuilder;
|
||||
@@ -36,12 +38,14 @@ import org.springframework.statemachine.config.common.annotation.ObjectPostProce
|
||||
*/
|
||||
public abstract class AbstractStateMachineConfigurerAdapter<S, E> implements StateMachineConfigurer<S, E> {
|
||||
|
||||
private StateMachineModelBuilder<S, E> modelBuilder;
|
||||
private StateMachineTransitionBuilder<S, E> transitionBuilder;
|
||||
private StateMachineStateBuilder<S, E> stateBuilder;
|
||||
private StateMachineConfigurationBuilder<S, E> configurationBuilder;
|
||||
|
||||
@Override
|
||||
public final void init(StateMachineConfigBuilder<S, E> config) throws Exception {
|
||||
config.setSharedObject(StateMachineModelBuilder.class, getStateMachineModelBuilder());
|
||||
config.setSharedObject(StateMachineTransitionBuilder.class, getStateMachineTransitionBuilder());
|
||||
config.setSharedObject(StateMachineStateBuilder.class, getStateMachineStateBuilder());
|
||||
config.setSharedObject(StateMachineConfigurationBuilder.class, getStateMachineConfigurationBuilder());
|
||||
@@ -51,6 +55,10 @@ public abstract class AbstractStateMachineConfigurerAdapter<S, E> implements Sta
|
||||
public void configure(StateMachineConfigBuilder<S, E> config) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineModelConfigurer<S, E> model) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineConfigurationConfigurer<S, E> config) throws Exception {
|
||||
}
|
||||
@@ -68,6 +76,15 @@ public abstract class AbstractStateMachineConfigurerAdapter<S, E> implements Sta
|
||||
return builder instanceof StateMachineConfigBuilder;
|
||||
}
|
||||
|
||||
protected final StateMachineModelBuilder<S, E> getStateMachineModelBuilder() throws Exception {
|
||||
if (modelBuilder != null) {
|
||||
return modelBuilder;
|
||||
}
|
||||
modelBuilder = new StateMachineModelBuilder<S, E>(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR, true);
|
||||
configure(modelBuilder);
|
||||
return modelBuilder;
|
||||
}
|
||||
|
||||
protected final StateMachineTransitionBuilder<S, E> getStateMachineTransitionBuilder() throws Exception {
|
||||
if (transitionBuilder != null) {
|
||||
return transitionBuilder;
|
||||
|
||||
@@ -23,6 +23,8 @@ import org.springframework.statemachine.config.builders.StateMachineConfigBuilde
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineModelBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineModelConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
|
||||
import org.springframework.statemachine.config.builders.StateMachineTransitionBuilder;
|
||||
@@ -75,6 +77,15 @@ public class StateMachineBuilder {
|
||||
builder = new StateMachineConfigBuilder<S, E>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure model.
|
||||
*
|
||||
* @return the state machine model configurer
|
||||
*/
|
||||
public StateMachineModelConfigurer<S, E> configureModel() {
|
||||
return adapter.modelBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure configuration.
|
||||
*
|
||||
@@ -144,12 +155,14 @@ public class StateMachineBuilder {
|
||||
private static class BuilderStateMachineConfigurerAdapter<S extends Object, E extends Object>
|
||||
implements StateMachineConfigurer<S, E> {
|
||||
|
||||
private StateMachineModelBuilder<S, E> modelBuilder;
|
||||
private StateMachineTransitionBuilder<S, E> transitionBuilder;
|
||||
private StateMachineStateBuilder<S, E> stateBuilder;
|
||||
private StateMachineConfigurationBuilder<S, E> configurationBuilder;
|
||||
|
||||
BuilderStateMachineConfigurerAdapter() {
|
||||
try {
|
||||
getStateMachineModelBuilder();
|
||||
getStateMachineTransitionBuilder();
|
||||
getStateMachineStateBuilder();
|
||||
getStateMachineConfigurationBuilder();
|
||||
@@ -160,6 +173,7 @@ public class StateMachineBuilder {
|
||||
|
||||
@Override
|
||||
public void init(StateMachineConfigBuilder<S, E> config) throws Exception {
|
||||
config.setSharedObject(StateMachineModelBuilder.class, getStateMachineModelBuilder());
|
||||
config.setSharedObject(StateMachineTransitionBuilder.class, getStateMachineTransitionBuilder());
|
||||
config.setSharedObject(StateMachineStateBuilder.class, getStateMachineStateBuilder());
|
||||
config.setSharedObject(StateMachineConfigurationBuilder.class, getStateMachineConfigurationBuilder());
|
||||
@@ -174,6 +188,10 @@ public class StateMachineBuilder {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineModelConfigurer<S, E> model) throws Exception {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineConfigurationConfigurer<S, E> config) throws Exception {
|
||||
}
|
||||
@@ -186,6 +204,15 @@ public class StateMachineBuilder {
|
||||
public void configure(StateMachineTransitionConfigurer<S, E> transitions) throws Exception {
|
||||
}
|
||||
|
||||
protected final StateMachineModelBuilder<S, E> getStateMachineModelBuilder() throws Exception {
|
||||
if (modelBuilder != null) {
|
||||
return modelBuilder;
|
||||
}
|
||||
modelBuilder = new StateMachineModelBuilder<S, E>(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR, true);
|
||||
configure(modelBuilder);
|
||||
return modelBuilder;
|
||||
}
|
||||
|
||||
protected final StateMachineTransitionBuilder<S, E> getStateMachineTransitionBuilder() throws Exception {
|
||||
if (transitionBuilder != null) {
|
||||
return transitionBuilder;
|
||||
@@ -209,7 +236,5 @@ public class StateMachineBuilder {
|
||||
configurationBuilder = new StateMachineConfigurationBuilder<S, E>(ObjectPostProcessor.QUIESCENT_POSTPROCESSOR, true);
|
||||
return configurationBuilder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* 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.springframework.statemachine.config.builders;
|
||||
|
||||
import org.springframework.statemachine.config.configurers.ModelConfigurer;
|
||||
import org.springframework.statemachine.config.model.StateMachineModelFactory;
|
||||
|
||||
/**
|
||||
* Data object used return and build data from a {@link ModelConfigurer}.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public class ModelData<S, E> {
|
||||
|
||||
private StateMachineModelFactory<S, E> factory;
|
||||
|
||||
/**
|
||||
* Instantiates a new model data.
|
||||
*
|
||||
* @param factory the factory
|
||||
*/
|
||||
public ModelData(StateMachineModelFactory<S, E> factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the factory.
|
||||
*
|
||||
* @return the factory
|
||||
*/
|
||||
public StateMachineModelFactory<S, E> getFactory() {
|
||||
return factory;
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,21 @@ package org.springframework.statemachine.config.builders;
|
||||
|
||||
import org.springframework.statemachine.config.StateMachineConfig;
|
||||
import org.springframework.statemachine.config.common.annotation.AbstractConfiguredAnnotationBuilder;
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationBuilder;
|
||||
import org.springframework.statemachine.config.model.ConfigurationData;
|
||||
import org.springframework.statemachine.config.model.StateMachineModel;
|
||||
import org.springframework.statemachine.config.model.StatesData;
|
||||
import org.springframework.statemachine.config.model.TransitionsData;
|
||||
|
||||
/**
|
||||
* {@link AnnotationBuilder} handling all shared builders which effectively contructs
|
||||
* full configuration for {@link StateMachineConfig}.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public class StateMachineConfigBuilder<S, E>
|
||||
extends
|
||||
AbstractConfiguredAnnotationBuilder<StateMachineConfig<S, E>, StateMachineConfigBuilder<S, E>, StateMachineConfigBuilder<S, E>> {
|
||||
@@ -28,17 +39,30 @@ public class StateMachineConfigBuilder<S, E>
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected StateMachineConfig<S, E> performBuild() throws Exception {
|
||||
// TODO: should prevent calling state/transition builder if model is given
|
||||
StateMachineModelBuilder<?, ?> modelBuilder = getSharedObject(StateMachineModelBuilder.class);
|
||||
StateMachineConfigurationBuilder<?, ?> configurationBuilder = getSharedObject(StateMachineConfigurationBuilder.class);
|
||||
StateMachineTransitionBuilder<?, ?> transitionBuilder = getSharedObject(StateMachineTransitionBuilder.class);
|
||||
StateMachineStateBuilder<?, ?> stateBuilder = getSharedObject(StateMachineStateBuilder.class);
|
||||
|
||||
// build config first as it's shared with transition builder
|
||||
ConfigurationData<S, E> config = (ConfigurationData<S, E>) configurationBuilder.build();
|
||||
transitionBuilder.setSharedObject(ConfigurationData.class, config);
|
||||
TransitionsData<S, E> transitions = (TransitionsData<S, E>) transitionBuilder.build();
|
||||
StatesData<S, E> states = (StatesData<S, E>) stateBuilder.build();
|
||||
StateMachineConfig<S, E> bean = new StateMachineConfig<S, E>(config, transitions, states);
|
||||
return bean;
|
||||
}
|
||||
ModelData<S, E> model = (ModelData<S, E>) modelBuilder.build();
|
||||
ConfigurationData<S, E> stateMachineConfigurationConfig = null;
|
||||
TransitionsData<S, E> transitions = null;
|
||||
StatesData<S, E> states = null;
|
||||
|
||||
if (model.getFactory() != null) {
|
||||
StateMachineModel<S,E> stateMachineModel = model.getFactory().build();
|
||||
transitions = stateMachineModel.getTransitionsData();
|
||||
states = stateMachineModel.getStatesData();
|
||||
}
|
||||
stateMachineConfigurationConfig = (ConfigurationData<S, E>) configurationBuilder.build();
|
||||
if (transitions == null) {
|
||||
transitionBuilder.setSharedObject(ConfigurationData.class, stateMachineConfigurationConfig);
|
||||
transitions = (TransitionsData<S, E>) transitionBuilder.build();
|
||||
}
|
||||
if (states == null) {
|
||||
states = (StatesData<S, E>) stateBuilder.build();
|
||||
}
|
||||
return new StateMachineConfig<S, E>(stateMachineConfigurationConfig, transitions, states);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,6 +29,14 @@ import org.springframework.statemachine.config.common.annotation.AnnotationConfi
|
||||
public interface StateMachineConfigurer<S, E> extends
|
||||
AnnotationConfigurer<StateMachineConfig<S, E>, StateMachineConfigBuilder<S, E>> {
|
||||
|
||||
/**
|
||||
* Callback for {@link StateMachineModelConfigurer}.
|
||||
*
|
||||
* @param model the {@link StateMachineModelConfigurer}
|
||||
* @throws Exception if configuration error happens
|
||||
*/
|
||||
void configure(StateMachineModelConfigurer<S, E> model) throws Exception;
|
||||
|
||||
/**
|
||||
* Callback for {@link StateMachineConfigurationConfigurer}.
|
||||
*
|
||||
@@ -52,5 +60,4 @@ public interface StateMachineConfigurer<S, E> extends
|
||||
* @throws Exception if configuration error happens
|
||||
*/
|
||||
void configure(StateMachineTransitionConfigurer<S, E> transitions) throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* 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.springframework.statemachine.config.builders;
|
||||
|
||||
import org.springframework.statemachine.config.common.annotation.AbstractConfiguredAnnotationBuilder;
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationBuilder;
|
||||
import org.springframework.statemachine.config.common.annotation.ObjectPostProcessor;
|
||||
import org.springframework.statemachine.config.configurers.DefaultModelConfigurer;
|
||||
import org.springframework.statemachine.config.configurers.ModelConfigurer;
|
||||
import org.springframework.statemachine.config.model.StateMachineModelFactory;
|
||||
|
||||
/**
|
||||
* {@link AnnotationBuilder} for {@link ModelData}.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public class StateMachineModelBuilder<S, E>
|
||||
extends AbstractConfiguredAnnotationBuilder<ModelData<S, E>, StateMachineModelConfigurer<S, E>, StateMachineModelBuilder<S, E>>
|
||||
implements StateMachineModelConfigurer<S, E> {
|
||||
|
||||
private StateMachineModelFactory<S, E> factory;
|
||||
|
||||
/**
|
||||
* Instantiates a new state machine model builder.
|
||||
*/
|
||||
public StateMachineModelBuilder() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new state machine model builder.
|
||||
*
|
||||
* @param objectPostProcessor the object post processor
|
||||
* @param allowConfigurersOfSameType the allow configurers of same type
|
||||
*/
|
||||
public StateMachineModelBuilder(ObjectPostProcessor<Object> objectPostProcessor,
|
||||
boolean allowConfigurersOfSameType) {
|
||||
super(objectPostProcessor, allowConfigurersOfSameType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new state machine model builder.
|
||||
*
|
||||
* @param objectPostProcessor the object post processor
|
||||
*/
|
||||
public StateMachineModelBuilder(ObjectPostProcessor<Object> objectPostProcessor) {
|
||||
super(objectPostProcessor);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ModelData<S, E> performBuild() throws Exception {
|
||||
return new ModelData<S, E>(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelConfigurer<S, E> withModel() throws Exception {
|
||||
return apply(new DefaultModelConfigurer<S, E>());
|
||||
}
|
||||
|
||||
public void setStateMachineModelFactory(StateMachineModelFactory<S, E> factory) {
|
||||
this.factory = factory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* 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.springframework.statemachine.config.builders;
|
||||
|
||||
import org.springframework.statemachine.config.configurers.ModelConfigurer;
|
||||
|
||||
/**
|
||||
* Configurer interface exposing model.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public interface StateMachineModelConfigurer<S, E> {
|
||||
|
||||
/**
|
||||
* Gets a configurer for model.
|
||||
*
|
||||
* @return {@link ModelConfigurer} for chaining
|
||||
* @throws Exception if configuration error happens
|
||||
*/
|
||||
ModelConfigurer<S, E> withModel() throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* 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.springframework.statemachine.config.configurers;
|
||||
|
||||
import org.springframework.statemachine.config.builders.ModelData;
|
||||
import org.springframework.statemachine.config.builders.StateMachineModelBuilder;
|
||||
import org.springframework.statemachine.config.builders.StateMachineModelConfigurer;
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.model.StateMachineModelFactory;
|
||||
|
||||
/**
|
||||
* Default implementation of a {@link ModelConfigurer}.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public class DefaultModelConfigurer<S, E>
|
||||
extends AnnotationConfigurerAdapter<ModelData<S, E>, StateMachineModelConfigurer<S, E>, StateMachineModelBuilder<S, E>>
|
||||
implements ModelConfigurer<S, E> {
|
||||
|
||||
private StateMachineModelFactory<S, E> factory;
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineModelBuilder<S, E> builder) throws Exception {
|
||||
builder.setStateMachineModelFactory(factory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelConfigurer<S, E> factory(StateMachineModelFactory<S, E> factory) {
|
||||
this.factory = factory;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* 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.springframework.statemachine.config.configurers;
|
||||
|
||||
import org.springframework.statemachine.config.builders.StateMachineModelConfigurer;
|
||||
import org.springframework.statemachine.config.common.annotation.AnnotationConfigurerBuilder;
|
||||
import org.springframework.statemachine.config.model.StateMachineModelFactory;
|
||||
|
||||
/**
|
||||
* Base {@code ModelConfigurer} interface for configuring state machine model.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public interface ModelConfigurer<S, E> extends
|
||||
AnnotationConfigurerBuilder<StateMachineModelConfigurer<S, E>> {
|
||||
|
||||
/**
|
||||
* Specify a state machine model factory.
|
||||
*
|
||||
* @param factory the state machine model factory
|
||||
* @return configurer for chaining
|
||||
*/
|
||||
ModelConfigurer<S, E> factory(StateMachineModelFactory<S, E> factory);
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* 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.springframework.statemachine.config.model;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.statemachine.action.Action;
|
||||
import org.springframework.statemachine.guard.Guard;
|
||||
|
||||
/**
|
||||
* Base implementation of a {@link StateMachineModelFactory} providing
|
||||
* some common grounds for various implementations.
|
||||
*
|
||||
* This factory is able to resolve {@link Action}s or {@link Guard}s either from
|
||||
* a {@link BeanFactory} if knows, or from manually registered instances. Manually
|
||||
* registered actions or guards are needed if those are not created as beans or if
|
||||
* whole state machine is working outside of an application context.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public abstract class AbstractStateMachineModelFactory<S, E> implements StateMachineComponentResolver<S, E>, BeanFactoryAware {
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
private final Map<String, Action<S, E>> registeredActions = new HashMap<>();
|
||||
private final Map<String, Guard<S, E>> registeredGuards = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register {@link Action} into factory with a given id.
|
||||
*
|
||||
* @param id the id
|
||||
* @param action the action
|
||||
*/
|
||||
public void registerAction(String id, Action<S, E> action) {
|
||||
registeredActions.put(id, action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register {@link Guard} into factory with a given id.
|
||||
*
|
||||
* @param id the id
|
||||
* @param guard the guard
|
||||
*/
|
||||
public void registerGuard(String id, Guard<S, E> guard) {
|
||||
registeredGuards.put(id, guard);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bean factory.
|
||||
*
|
||||
* @return the bean factory
|
||||
*/
|
||||
protected final BeanFactory getBeanFactory() {
|
||||
return beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve action.
|
||||
*
|
||||
* @param id the id
|
||||
* @return the action
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Action<S, E> resolveAction(String id) {
|
||||
Action<S, E> a = null;
|
||||
a = registeredActions.get(id);
|
||||
if (a == null && beanFactory != null) {
|
||||
a = beanFactory.getBean(id, Action.class);
|
||||
}
|
||||
if (a == null) {
|
||||
throw new RuntimeException("Can't resolve action with id " + id + " either from registered actions nor beanfactory");
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve guard.
|
||||
*
|
||||
* @param id the id
|
||||
* @return the guard
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Guard<S, E> resolveGuard(String id) {
|
||||
Guard<S, E> g = null;
|
||||
g = registeredGuards.get(id);
|
||||
if (g == null && beanFactory != null) {
|
||||
g = beanFactory.getBean(id, Guard.class);
|
||||
}
|
||||
if (g == null) {
|
||||
throw new RuntimeException("Can't resolve guard with id " + id + " either from registered guards nor beanfactory");
|
||||
}
|
||||
return g;
|
||||
}
|
||||
}
|
||||
@@ -64,6 +64,18 @@ public class StateData<S, E> {
|
||||
this(null, null, state, null, null, null, initial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new state data.
|
||||
*
|
||||
* @param parent the parent
|
||||
* @param region the region
|
||||
* @param state the state
|
||||
* @param initial the initial
|
||||
*/
|
||||
public StateData(Object parent, Object region, S state, boolean initial) {
|
||||
this(parent, region, state, null, null, null, initial);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new state data.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* 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.springframework.statemachine.config.model;
|
||||
|
||||
import org.springframework.statemachine.action.Action;
|
||||
import org.springframework.statemachine.guard.Guard;
|
||||
|
||||
/**
|
||||
* Strategy interface for registering and resolving state machine
|
||||
* components by their id's
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public interface StateMachineComponentResolver<S, E> {
|
||||
|
||||
/**
|
||||
* Register {@link Action} into factory with a given id.
|
||||
*
|
||||
* @param id the id
|
||||
* @param action the action
|
||||
*/
|
||||
void registerAction(String id, Action<S, E> action);
|
||||
|
||||
/**
|
||||
* Register {@link Guard} into factory with a given id.
|
||||
*
|
||||
* @param id the id
|
||||
* @param guard the guard
|
||||
*/
|
||||
void registerGuard(String id, Guard<S, E> guard);
|
||||
|
||||
/**
|
||||
* Resolve action.
|
||||
*
|
||||
* @param id the id
|
||||
* @return the action
|
||||
*/
|
||||
Action<S, E> resolveAction(String id);
|
||||
|
||||
/**
|
||||
* Resolve guard.
|
||||
*
|
||||
* @param id the id
|
||||
* @return the guard
|
||||
*/
|
||||
Guard<S, E> resolveGuard(String id);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* 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.springframework.statemachine.config.model;
|
||||
|
||||
/**
|
||||
* A generic builder interface for building {@link StateMachineModel}s.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
* @param <S> the type of state
|
||||
* @param <E> the type of event
|
||||
*/
|
||||
public interface StateMachineModelFactory<S, E> {
|
||||
|
||||
/**
|
||||
* Builds the state machine model.
|
||||
*
|
||||
* @return the state machine model
|
||||
*/
|
||||
StateMachineModel<S, E> build();
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Copyright 2016 the original author or authors.
|
||||
*
|
||||
* 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.springframework.statemachine.config.model;
|
||||
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.statemachine.AbstractStateMachineTests;
|
||||
import org.springframework.statemachine.StateContext;
|
||||
import org.springframework.statemachine.StateMachine;
|
||||
import org.springframework.statemachine.action.Action;
|
||||
import org.springframework.statemachine.config.EnableStateMachine;
|
||||
import org.springframework.statemachine.config.ObjectStateMachineFactory;
|
||||
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
|
||||
import org.springframework.statemachine.config.builders.StateMachineModelConfigurer;
|
||||
|
||||
public class StateMachineModelFactoryTests extends AbstractStateMachineTests {
|
||||
|
||||
@Test
|
||||
public void testResolvingFromContext() {
|
||||
context.register(Config1.class);
|
||||
context.refresh();
|
||||
|
||||
TestStateMachineModelFactory modelBuilder = new TestStateMachineModelFactory();
|
||||
modelBuilder.setBeanFactory(context);
|
||||
ObjectStateMachineFactory<String, String> factory = new ObjectStateMachineFactory<>(modelBuilder.build());
|
||||
|
||||
StateMachine<String,String> stateMachine = factory.getStateMachine();
|
||||
stateMachine.start();
|
||||
assertThat(stateMachine.getState().getIds(), contains("S1"));
|
||||
stateMachine.sendEvent("E1");
|
||||
assertThat(stateMachine.getState().getIds(), contains("S2"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromAnnotationConfig() {
|
||||
context.register(Config2.class);
|
||||
context.refresh();
|
||||
@SuppressWarnings("unchecked")
|
||||
StateMachine<String, String> stateMachine = context.getBean(StateMachine.class);
|
||||
|
||||
stateMachine.start();
|
||||
assertThat(stateMachine.getState().getIds(), contains("S1"));
|
||||
stateMachine.sendEvent("E1");
|
||||
assertThat(stateMachine.getState().getIds(), contains("S2"));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class Config1 {
|
||||
@Bean
|
||||
public Action<String, String> action1() {
|
||||
return new Action<String, String>() {
|
||||
@Override
|
||||
public void execute(StateContext<String, String> context) {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableStateMachine
|
||||
public static class Config2 extends StateMachineConfigurerAdapter<String, String> {
|
||||
|
||||
@Override
|
||||
public void configure(StateMachineModelConfigurer<String, String> model) throws Exception {
|
||||
model
|
||||
.withModel()
|
||||
.factory(modelFactory());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public StateMachineModelFactory<String, String> modelFactory() {
|
||||
return new TestStateMachineModelFactory();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Action<String, String> action1() {
|
||||
return new Action<String, String>() {
|
||||
@Override
|
||||
public void execute(StateContext<String, String> context) {
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static class TestStateMachineModelFactory implements StateMachineModelFactory<String, String>, BeanFactoryAware {
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@Override
|
||||
public StateMachineModel<String, String> build() {
|
||||
|
||||
Action<String, String> action1 = beanFactory.getBean("action1", Action.class);
|
||||
Collection<Action<String, String>> s2Actions = new ArrayList<>();
|
||||
s2Actions.add(action1);
|
||||
|
||||
ConfigurationData<String, String> configurationData = new ConfigurationData<>();
|
||||
|
||||
Collection<StateData<String, String>> stateData = new ArrayList<>();
|
||||
stateData.add(new StateData<String, String>("S1", true));
|
||||
stateData.add(new StateData<String, String>(null, null, "S2", null, s2Actions, null));
|
||||
StatesData<String, String> statesData = new StatesData<>(stateData);
|
||||
|
||||
Collection<TransitionData<String, String>> transitionData = new ArrayList<>();
|
||||
transitionData.add(new TransitionData<String, String>("S1", "S2", "E1"));
|
||||
TransitionsData<String, String> transitionsData = new TransitionsData<>(transitionData);
|
||||
|
||||
StateMachineModel<String, String> stateMachineModel = new DefaultStateMachineModel<>(configurationData, statesData, transitionsData);
|
||||
return stateMachineModel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AnnotationConfigApplicationContext buildContext() {
|
||||
return new AnnotationConfigApplicationContext();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user