applied patch swf-784

This commit is contained in:
Keith Donald
2008-07-29 16:16:37 +00:00
parent 209ccc2fbb
commit e12e62d4bb
4 changed files with 82 additions and 65 deletions

View File

@@ -60,7 +60,7 @@ public class DefaultFlowModelHolder implements FlowModelHolder {
if (flowModel == null) {
assembleFlowModel();
} else {
if (flowModelBuilder.hasFlowModelChanged()) {
if (flowModelBuilder.hasFlowModelResourceChanged()) {
assembleFlowModel();
}
}
@@ -72,7 +72,7 @@ public class DefaultFlowModelHolder implements FlowModelHolder {
}
public boolean hasFlowModelChanged() {
return flowModelBuilder.hasFlowModelChanged();
return flowModelBuilder.hasFlowModelResourceChanged();
}
public synchronized void refresh() {

View File

@@ -69,16 +69,18 @@ public interface FlowModelBuilder {
*/
public void dispose() throws FlowModelBuilderException;
/**
* Returns true if the underlying flow model has changed since the last call to {@link #init()}.
* @return true if the flow model has changed
*/
public boolean hasFlowModelChanged();
/**
* Get the underlying flow model resource accessed to build this flow model. Returns null if this builder does not
* construct the flow model from a resource.
* @return the flow model resource
*/
public Resource getFlowModelResource();
/**
* Returns true if the underlying flow model resource has changed since the last call to {@link #init()}. Always
* returns false if the flow model is not build from a resource.
* @return true if the resource backing the flow model has changed
*/
public boolean hasFlowModelResourceChanged();
}

View File

@@ -75,10 +75,10 @@ public class XmlFlowModelBuilder implements FlowModelBuilder {
private Document document;
private FlowModel flowModel;
private long lastModifiedTimestamp;
private FlowModel flowModel;
/**
* Create a new XML flow model builder that will parse the XML document at the specified resource location and use
* the provided locator to access parent flow models.
@@ -111,7 +111,7 @@ public class XmlFlowModelBuilder implements FlowModelBuilder {
public void init() throws FlowModelBuilderException {
try {
document = documentLoader.loadDocument(resource);
lastModifiedTimestamp = resource.lastModified();
initLastModifiedTimestamp();
} catch (IOException e) {
throw new FlowModelBuilderException("Could not access the XML flow definition at " + resource, e);
} catch (ParserConfigurationException e) {
@@ -132,59 +132,11 @@ public class XmlFlowModelBuilder implements FlowModelBuilder {
mergeStates();
}
protected void mergeFlows() {
if (flowModel.getParent() != null) {
List parents = Arrays.asList(StringUtils.trimArrayElements(flowModel.getParent().split(",")));
for (Iterator it = parents.iterator(); it.hasNext();) {
String parentFlowId = (String) it.next();
if (StringUtils.hasText(parentFlowId)) {
try {
flowModel.merge(modelLocator.getFlowModel(parentFlowId));
} catch (NoSuchFlowModelException e) {
throw new FlowModelBuilderException("Unable to find flow '" + parentFlowId
+ "' to inherit from", e);
}
}
}
}
}
protected void mergeStates() {
if (flowModel.getStates() == null) {
return;
}
for (Iterator it = flowModel.getStates().iterator(); it.hasNext();) {
AbstractStateModel childState = (AbstractStateModel) it.next();
String parent = childState.getParent();
if (childState.getParent() != null) {
String flowId;
String stateId;
AbstractStateModel parentState = null;
if (!parent.contains("#")) {
throw new FlowModelBuilderException("Invalid parent syntax '" + parent
+ "', should take form 'flowId#stateId'");
}
flowId = parent.substring(0, parent.indexOf("#")).trim();
stateId = parent.substring(parent.indexOf("#") + 1).trim();
try {
parentState = modelLocator.getFlowModel(flowId).getStateById(stateId);
if (parentState == null) {
throw new FlowModelBuilderException("Unable to find state '" + stateId + "' in flow '" + flowId
+ "'");
}
childState.merge(parentState);
} catch (NoSuchFlowModelException e) {
throw new FlowModelBuilderException("Unable to find flow '" + flowId + "' to inherit from", e);
} catch (ClassCastException e) {
throw new FlowModelBuilderException("Parent state type '" + parentState.getClass().getName()
+ "' cannot be merged with state type '" + childState.getClass().getName() + "'", e);
}
}
}
}
public FlowModel getFlowModel() throws FlowModelBuilderException {
if (flowModel == null) {
throw new FlowModelBuilderException(
"The FlowModel must be built first -- called init() and build() before calling getFlowModel()");
}
return flowModel;
}
@@ -197,7 +149,10 @@ public class XmlFlowModelBuilder implements FlowModelBuilder {
return resource;
}
public boolean hasFlowModelChanged() {
public boolean hasFlowModelResourceChanged() {
if (lastModifiedTimestamp == -1) {
return false;
}
try {
long lastModified = resource.lastModified();
if (lastModified > lastModifiedTimestamp) {
@@ -230,6 +185,14 @@ public class XmlFlowModelBuilder implements FlowModelBuilder {
this.modelLocator = modelLocator;
}
private void initLastModifiedTimestamp() {
try {
lastModifiedTimestamp = resource.lastModified();
} catch (IOException e) {
lastModifiedTimestamp = -1;
}
}
private FlowModel parseFlow(Element element) {
FlowModel flow = new FlowModel();
flow.setAbstract(element.getAttribute("abstract"));
@@ -659,6 +622,58 @@ public class XmlFlowModelBuilder implements FlowModelBuilder {
return state;
}
private void mergeFlows() {
if (flowModel.getParent() != null) {
List parents = Arrays.asList(StringUtils.trimArrayElements(flowModel.getParent().split(",")));
for (Iterator it = parents.iterator(); it.hasNext();) {
String parentFlowId = (String) it.next();
if (StringUtils.hasText(parentFlowId)) {
try {
flowModel.merge(modelLocator.getFlowModel(parentFlowId));
} catch (NoSuchFlowModelException e) {
throw new FlowModelBuilderException("Unable to find flow '" + parentFlowId
+ "' to inherit from", e);
}
}
}
}
}
private void mergeStates() {
if (flowModel.getStates() == null) {
return;
}
for (Iterator it = flowModel.getStates().iterator(); it.hasNext();) {
AbstractStateModel childState = (AbstractStateModel) it.next();
String parent = childState.getParent();
if (childState.getParent() != null) {
String flowId;
String stateId;
AbstractStateModel parentState = null;
if (!parent.contains("#")) {
throw new FlowModelBuilderException("Invalid parent syntax '" + parent
+ "', should take form 'flowId#stateId'");
}
flowId = parent.substring(0, parent.indexOf("#")).trim();
stateId = parent.substring(parent.indexOf("#") + 1).trim();
try {
parentState = modelLocator.getFlowModel(flowId).getStateById(stateId);
if (parentState == null) {
throw new FlowModelBuilderException("Unable to find state '" + stateId + "' in flow '" + flowId
+ "'");
}
childState.merge(parentState);
} catch (NoSuchFlowModelException e) {
throw new FlowModelBuilderException("Unable to find flow '" + flowId + "' to inherit from", e);
} catch (ClassCastException e) {
throw new FlowModelBuilderException("Parent state type '" + parentState.getClass().getName()
+ "' cannot be merged with state type '" + childState.getClass().getName() + "'", e);
}
}
}
}
public String toString() {
return new ToStringCreator(this).append("resource", resource).toString();
}

View File

@@ -61,7 +61,7 @@ public class DefaultFlowModelHolderTests extends TestCase {
return null;
}
public boolean hasFlowModelChanged() {
public boolean hasFlowModelResourceChanged() {
return false;
}