Use references in RepositoryTransition
- Refactor so that we can create RepositoryState in one place and then reference to it from JpaRepositoryTransition impls. - New common top class BaseRepositoryEntity for entities - Change RepositoryState and RepositoryTransition to be abstract classes instead of interfaces. - New custom StateMachineJackson2RepositoryPopulatorFactoryBean and StateMachineJackson2ResourceReader handling json refs. - Relates to #262
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
|
||||
/**
|
||||
* Generic base class for all entity classes.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
*/
|
||||
@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="_class")
|
||||
public abstract class BaseRepositoryEntity {
|
||||
}
|
||||
@@ -18,59 +18,59 @@ package org.springframework.statemachine.data;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Generic interface representing state entity.
|
||||
* Generic base class representing state entity.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
*/
|
||||
public interface RepositoryState {
|
||||
public abstract class RepositoryState extends BaseRepositoryEntity {
|
||||
|
||||
/**
|
||||
* Gets the parent state.
|
||||
*
|
||||
* @return the parent state
|
||||
*/
|
||||
String getParentState();
|
||||
public abstract String getParentState();
|
||||
|
||||
/**
|
||||
* Gets the machine id.
|
||||
*
|
||||
* @return the machine id
|
||||
*/
|
||||
String getMachineId();
|
||||
public abstract String getMachineId();
|
||||
|
||||
/**
|
||||
* Gets the state.
|
||||
*
|
||||
* @return the state
|
||||
*/
|
||||
String getState();
|
||||
public abstract String getState();
|
||||
|
||||
/**
|
||||
* Checks if is initial.
|
||||
*
|
||||
* @return true, if is initial
|
||||
*/
|
||||
boolean isInitial();
|
||||
public abstract boolean isInitial();
|
||||
|
||||
/**
|
||||
* Gets the state actions.
|
||||
*
|
||||
* @return the state actions
|
||||
*/
|
||||
Set<? extends RepositoryAction> getStateActions();
|
||||
public abstract Set<? extends RepositoryAction> getStateActions();
|
||||
|
||||
/**
|
||||
* Gets the entry actions.
|
||||
*
|
||||
* @return the entry actions
|
||||
*/
|
||||
Set<? extends RepositoryAction> getEntryActions();
|
||||
public abstract Set<? extends RepositoryAction> getEntryActions();
|
||||
|
||||
/**
|
||||
* Gets the exit actions.
|
||||
*
|
||||
* @return the exit actions
|
||||
*/
|
||||
Set<? extends RepositoryAction> getExitActions();
|
||||
public abstract Set<? extends RepositoryAction> getExitActions();
|
||||
}
|
||||
|
||||
@@ -175,8 +175,7 @@ public class RepositoryStateMachineModelFactory extends AbstractStateMachineMode
|
||||
guard = new SpelExpressionGuard<>(parser.parseExpression(repositoryGuard.getSpel()));
|
||||
}
|
||||
}
|
||||
|
||||
transitionData.add(new TransitionData<>(t.getSource(), t.getTarget(), t.getEvent(), actions, guard, kind != null ? kind : TransitionKind.EXTERNAL));
|
||||
transitionData.add(new TransitionData<>(t.getSource().getState(), t.getTarget().getState(), t.getEvent(), actions, guard, kind != null ? kind : TransitionKind.EXTERNAL));
|
||||
}
|
||||
TransitionsData<String, String> transitionsData = new TransitionsData<>(transitionData);
|
||||
|
||||
|
||||
@@ -20,59 +20,59 @@ import java.util.Set;
|
||||
import org.springframework.statemachine.transition.TransitionKind;
|
||||
|
||||
/**
|
||||
* Generic interface representing transition entity.
|
||||
* Generic base class representing transition entity.
|
||||
*
|
||||
* @author Janne Valkealahti
|
||||
*
|
||||
*/
|
||||
public interface RepositoryTransition {
|
||||
public abstract class RepositoryTransition extends BaseRepositoryEntity {
|
||||
|
||||
/**
|
||||
* Gets the machine id.
|
||||
*
|
||||
* @return the machine id
|
||||
*/
|
||||
String getMachineId();
|
||||
public abstract String getMachineId();
|
||||
|
||||
/**
|
||||
* Gets the source.
|
||||
*
|
||||
* @return the source
|
||||
*/
|
||||
String getSource();
|
||||
public abstract RepositoryState getSource();
|
||||
|
||||
/**
|
||||
* Gets the target.
|
||||
*
|
||||
* @return the target
|
||||
*/
|
||||
String getTarget();
|
||||
public abstract RepositoryState getTarget();
|
||||
|
||||
/**
|
||||
* Gets the event.
|
||||
*
|
||||
* @return the event
|
||||
*/
|
||||
String getEvent();
|
||||
public abstract String getEvent();
|
||||
|
||||
/**
|
||||
* Gets the actions.
|
||||
*
|
||||
* @return the actions
|
||||
*/
|
||||
Set<? extends RepositoryAction> getActions();
|
||||
public abstract Set<? extends RepositoryAction> getActions();
|
||||
|
||||
/**
|
||||
* Gets the guard.
|
||||
*
|
||||
* @return the guard
|
||||
*/
|
||||
RepositoryGuard getGuard();
|
||||
public abstract RepositoryGuard getGuard();
|
||||
|
||||
/**
|
||||
* Gets the transition kind.
|
||||
*
|
||||
* @return the transition kind
|
||||
*/
|
||||
TransitionKind getKind();
|
||||
public abstract TransitionKind getKind();
|
||||
}
|
||||
|
||||
@@ -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.data.support;
|
||||
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.data.repository.init.AbstractRepositoryPopulatorFactoryBean;
|
||||
import org.springframework.data.repository.init.ResourceReader;
|
||||
import org.springframework.data.repository.init.ResourceReaderRepositoryPopulator;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} to set up a {@link ResourceReaderRepositoryPopulator} with a {@link StateMachineJackson2ResourceReader}.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Janne Valkealahti
|
||||
*/
|
||||
public class StateMachineJackson2RepositoryPopulatorFactoryBean extends AbstractRepositoryPopulatorFactoryBean {
|
||||
|
||||
private ObjectMapper mapper;
|
||||
|
||||
/**
|
||||
* Configures the {@link ObjectMapper} to be used.
|
||||
*
|
||||
* @param mapper the new mapper
|
||||
*/
|
||||
public void setMapper(ObjectMapper mapper) {
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ResourceReader getResourceReader() {
|
||||
return new StateMachineJackson2ResourceReader(mapper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.data.support;
|
||||
|
||||
import static com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.repository.init.Jackson2ResourceReader;
|
||||
import org.springframework.data.repository.init.ResourceReader;
|
||||
import org.springframework.statemachine.data.BaseRepositoryEntity;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.ObjectReader;
|
||||
|
||||
/**
|
||||
* A {@link ResourceReader} using Jackson to read JSON into objects.
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @author Janne Valkealahti
|
||||
*/
|
||||
public class StateMachineJackson2ResourceReader implements ResourceReader {
|
||||
|
||||
/** The Constant DEFAULT_TYPE_KEY. */
|
||||
private static final String DEFAULT_TYPE_KEY = "_class";
|
||||
|
||||
/** The Constant DEFAULT_MAPPER. */
|
||||
private static final ObjectMapper DEFAULT_MAPPER = new ObjectMapper();
|
||||
|
||||
static {
|
||||
DEFAULT_MAPPER.configure(FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
}
|
||||
|
||||
/** The mapper. */
|
||||
private final ObjectMapper mapper;
|
||||
|
||||
/** The type key. */
|
||||
private String typeKey = DEFAULT_TYPE_KEY;
|
||||
|
||||
/**
|
||||
* Creates a new {@link Jackson2ResourceReader}.
|
||||
*/
|
||||
public StateMachineJackson2ResourceReader() {
|
||||
this(DEFAULT_MAPPER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Jackson2ResourceReader} using the given {@link ObjectMapper}.
|
||||
*
|
||||
* @param mapper the mapper
|
||||
*/
|
||||
public StateMachineJackson2ResourceReader(ObjectMapper mapper) {
|
||||
this.mapper = mapper == null ? DEFAULT_MAPPER : mapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the JSON document's key to lookup the type to instantiate the object. Defaults to
|
||||
* {@link Jackson2ResourceReader#DEFAULT_TYPE_KEY}.
|
||||
*
|
||||
* @param typeKey the new type key
|
||||
*/
|
||||
public void setTypeKey(String typeKey) {
|
||||
this.typeKey = typeKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object readFrom(Resource resource, ClassLoader classLoader) throws Exception {
|
||||
InputStream stream = resource.getInputStream();
|
||||
ObjectReader objectReader = mapper.readerFor(JsonNode.class);
|
||||
JsonNode node = objectReader.readTree(stream);
|
||||
objectReader = mapper.readerFor(BaseRepositoryEntity[].class);
|
||||
|
||||
if (node.isArray()) {
|
||||
List<Object> result = new ArrayList<Object>();
|
||||
BaseRepositoryEntity[] entitys = objectReader.readValue(node);
|
||||
result.addAll(Arrays.asList(entitys));
|
||||
return result;
|
||||
}
|
||||
|
||||
return readSingle(node, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the given {@link JsonNode} into an instance of the type encoded in it using the configured type key.
|
||||
*
|
||||
* @param node must not be {@literal null}.
|
||||
* @param classLoader the class loader
|
||||
* @return the object
|
||||
* @throws IOException Signals that an I/O exception has occurred.
|
||||
*/
|
||||
private Object readSingle(JsonNode node, ClassLoader classLoader) throws IOException {
|
||||
|
||||
JsonNode typeNode = node.findValue(typeKey);
|
||||
String typeName = typeNode == null ? null : typeNode.asText();
|
||||
|
||||
Class<?> type = ClassUtils.resolveClassName(typeName, classLoader);
|
||||
return mapper.readerFor(type).readValue(node);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user