blob: a83420c0a2de1577e5f3ae439ce03dae1183c3ef [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.commons.scxml2.invoke;
import java.io.IOException;
import java.io.Serializable;
import java.net.URL;
import java.util.Map;
import javax.xml.stream.XMLStreamException;
import org.apache.commons.scxml2.Context;
import org.apache.commons.scxml2.SCXMLExecutor;
import org.apache.commons.scxml2.SCXMLIOProcessor;
import org.apache.commons.scxml2.TriggerEvent;
import org.apache.commons.scxml2.env.SimpleSCXMLListener;
import org.apache.commons.scxml2.io.SCXMLReader;
import org.apache.commons.scxml2.model.ModelException;
import org.apache.commons.scxml2.model.SCXML;
/**
* A simple {@link Invoker} for SCXML documents. Invoked SCXML document
* may not contain external namespace elements, further invokes etc.
*/
public class SimpleSCXMLInvoker implements Invoker, Serializable {
/** Serial version UID. */
private static final long serialVersionUID = 1L;
/** Parent state ID. */
private String parentStateId;
/** Invoking parent SCXMLExecutor */
private SCXMLExecutor parentSCXMLExecutor;
/** The invoked state machine executor. */
private SCXMLExecutor executor;
/** Cancellation status. */
private boolean cancelled;
/**
* {@inheritDoc}.
*/
@Override
public String getInvokeId() {
return parentStateId;
}
/**
* {@inheritDoc}.
*/
@Override
public void setInvokeId(final String invokeId) {
this.parentStateId = invokeId;
this.cancelled = false;
}
/**
* {@inheritDoc}.
*/
@Override
public void setParentSCXMLExecutor(SCXMLExecutor parentSCXMLExecutor) {
this.parentSCXMLExecutor = parentSCXMLExecutor;
}
/**
* {@inheritDoc}.
*/
@Override
public SCXMLIOProcessor getChildIOProcessor() {
// not used
return executor;
}
/**
* {@inheritDoc}.
*/
@Override
public void invoke(final String source, final Map<String, Object> params)
throws InvokerException {
SCXML scxml;
try {
scxml = SCXMLReader.read(new URL(source));
} catch (ModelException me) {
throw new InvokerException(me.getMessage(), me.getCause());
} catch (IOException ioe) {
throw new InvokerException(ioe.getMessage(), ioe.getCause());
} catch (XMLStreamException xse) {
throw new InvokerException(xse.getMessage(), xse.getCause());
}
executor = new SCXMLExecutor(parentSCXMLExecutor);
try {
executor.setStateMachine(scxml);
}
catch (ModelException me) {
throw new InvokerException(me);
}
Context rootCtx = executor.getRootContext();
for (Map.Entry<String, Object> entry : params.entrySet()) {
rootCtx.setLocal(entry.getKey(), entry.getValue());
}
executor.addListener(scxml, new SimpleSCXMLListener());
try {
executor.go();
} catch (ModelException me) {
throw new InvokerException(me.getMessage(), me.getCause());
}
if (executor.getStatus().isFinal()) {
TriggerEvent te = new TriggerEvent("done.invoke."+parentStateId, TriggerEvent.SIGNAL_EVENT);
new AsyncTrigger(parentSCXMLExecutor, te).start();
}
}
/**
* {@inheritDoc}.
*/
@Override
public void parentEvent(final TriggerEvent evt)
throws InvokerException {
if (cancelled) {
return; // no further processing should take place
}
boolean doneBefore = executor.getStatus().isFinal();
executor.addEvent(evt);
if (!doneBefore && executor.getStatus().isFinal()) {
TriggerEvent te = new TriggerEvent("done.invoke."+parentStateId,TriggerEvent.SIGNAL_EVENT);
new AsyncTrigger(parentSCXMLExecutor, te).start();
}
}
/**
* {@inheritDoc}.
*/
@Override
public void cancel()
throws InvokerException {
cancelled = true;
executor.addEvent(new TriggerEvent("cancel.invoke."+parentStateId, TriggerEvent.CANCEL_EVENT));
}
}