boolean isStateInProductIllegal = false;
if ((!considerTransient)
|| ((!_isTransient(stateInThis)) && (!_isTransient(stateInArgument)))) {
// extend frontier from state in this automaton
ComponentPort outPort = stateInThis.outgoingPort;
Iterator transitions = outPort.linkedRelationList()
.iterator();
while (transitions.hasNext() && !isStateInProductIllegal) {
InterfaceAutomatonTransition transition = (InterfaceAutomatonTransition) transitions
.next();
State destinationInThis = transition.destinationState();
// get transitionLabel, transitionName and relation name
// for later use
String transitionLabel = transition.getLabel();
// remove ending "?", "!", or ";"
String transitionName = transitionLabel.substring(0,
transitionLabel.length() - 1);
// switch depending on type of transition
int transitionType = transition.getType();
if (transitionType == InterfaceAutomatonTransition._INPUT_TRANSITION) {
// case 1
if (_inputNames.contains(transitionName)) {
// case 1A. Add transition to product as input
// transition
State destinationInProduct = _addState(product,
destinationInThis, stateInArgument,
frontier);
_addTransition(product, this.getName(),
stateInProduct, destinationInProduct,
transitionLabel);
} else {
// case 1B. transition is shared in product
String outName = transitionName + "!";
Set destinationsInArgument = _getDestinationStates(
stateInArgument, outName);
if (!destinationsInArgument.isEmpty()) {
// case 1Ba. q has T output. Add T to
// product as internal transition
Iterator destinations = destinationsInArgument
.iterator();
while (destinations.hasNext()) {
State destinationInArgument = (State) destinations
.next();
State destinationInProduct = _addState(
product, destinationInThis,
destinationInArgument, frontier);
_addTransition(product, this.getName()
+ NAME_CONNECTOR
+ automaton.getName(),
stateInProduct,
destinationInProduct,
transitionName + ";");
}
} else {
// case 1Bb. q does not have T output.
// Transition cannot happen, ignore.
}
}
} else if (transitionType == InterfaceAutomatonTransition._OUTPUT_TRANSITION) {
// case 2. T is output for p.
if (_outputNames.contains(transitionName)) {
// case 2A. T is output of product. Add T to
// product as output transition
State destinationInProduct = _addState(product,
destinationInThis, stateInArgument,
frontier);
_addTransition(product, this.getName(),
stateInProduct, destinationInProduct,
transitionLabel);
} else {
// case 2B. transition is shared in product
String inName = transitionName + "?";
Set destinationsInArgument = _getDestinationStates(
stateInArgument, inName);
if (!destinationsInArgument.isEmpty()) {
// case 2Ba. q has T input. Need to add T
// to product as internal transition.
// However, to avoid adding this transition
// twice, leave the code that explores
// state q to add the transition
} else {
// case 2Bb. q does not have T input.
// stateInProduct is illegal
_illegalStates.add(stateInProduct);
isStateInProductIllegal = true;
}
}
} else if (transitionType == InterfaceAutomatonTransition._INTERNAL_TRANSITION) {
// case 3. T is internal for p. Add T to product
State destinationInProduct = _addState(product,
destinationInThis, stateInArgument,
frontier);
_addTransition(product, this.getName(),
stateInProduct, destinationInProduct,
transitionLabel);
} else {
throw new InternalErrorException(
"InterfaceAutomaton._computeProduct: "
+ "unrecognized transition type.");
}
} // end explore from state p
// extend frontier from state in the argument automaton
outPort = stateInArgument.outgoingPort;
transitions = outPort.linkedRelationList().iterator();
while (transitions.hasNext() && !isStateInProductIllegal) {
InterfaceAutomatonTransition transition = (InterfaceAutomatonTransition) transitions
.next();
State destinationInArgument = transition
.destinationState();
// get transitionLabel, transitionName and relation name
// for later use
String transitionLabel = transition.getLabel();
// remove ending "?", "!", or ";"
String transitionName = transitionLabel.substring(0,
transitionLabel.length() - 1);
// switch depending on type of transition
int transitionType = transition.getType();
if (transitionType == InterfaceAutomatonTransition._INPUT_TRANSITION) {
// case 1
if (_inputNames.contains(transitionName)) {
// case 1A. Add transition to product as input
// transition
State destinationInProduct = _addState(product,
stateInThis, destinationInArgument,
frontier);
_addTransition(product, automaton.getName(),
stateInProduct, destinationInProduct,
transitionLabel);
} else {
// case 1B. transition is shared in product
String outName = transitionName + "!";
Set destinationsInThis = _getDestinationStates(
stateInThis, outName);
if (!destinationsInThis.isEmpty()) {
// case 1Ba. p has T output. Add T to
// product as internal transition
Iterator destinations = destinationsInThis
.iterator();
while (destinations.hasNext()) {
State destinationInThis = (State) destinations
.next();
State destinationInProduct = _addState(
product, destinationInThis,
destinationInArgument, frontier);
_addTransition(product, this.getName()
+ NAME_CONNECTOR
+ automaton.getName(),
stateInProduct,
destinationInProduct,
transitionName + ";");
}
} else {
// case 1Bb. p does not have T output.
// Transition cannot happen, ignore.
}
}
} else if (transitionType == InterfaceAutomatonTransition._OUTPUT_TRANSITION) {
// case 2. T is output for q.
if (_outputNames.contains(transitionName)) {
// case 2A. T is output of product. Add T to
// product as output transition
State destinationInProduct = _addState(product,
stateInThis, destinationInArgument,
frontier);
_addTransition(product, automaton.getName(),
stateInProduct, destinationInProduct,
transitionLabel);
} else {
// case 2B. transition is shared in product
String inName = transitionName + "?";
Set destinationsInThis = _getDestinationStates(
stateInThis, inName);
if (!destinationsInThis.isEmpty()) {
// case 2Ba. p has T input. Need to add T
// to product as internal transition.
// However, to avoid adding this transition
// twice, leave the code that explores
// state p to add the transition
} else {
// case 2Bb. p does not have T input.
// stateInProduct is illegal
_illegalStates.add(stateInProduct);
isStateInProductIllegal = true;
}
}
} else if (transitionType == InterfaceAutomatonTransition._INTERNAL_TRANSITION) {
// case 3. T is internal for q. Add T to product
State destinationInProduct = _addState(product,
stateInThis, destinationInArgument,
frontier);
_addTransition(product, automaton.getName(),
stateInProduct, destinationInProduct,
transitionLabel);
} else {
throw new InternalErrorException(
"InterfaceAutomaton._computeProduct: "
+ "unrecognized transition type.");
}
} // end explore from state q
} else {
// one or both of stateInThis and stateInArgument are
// transient
if (_isTransient(stateInThis)
&& _isTransient(stateInArgument)) {
throw new IllegalActionException("Cannot compute "
+ "product since both states are transient: "
+ stateInThis.getName() + " and "
+ stateInArgument.getName());
}
if (_isTransient(stateInThis)) {
// extend frontier from transient state in this
// automaton
ComponentPort outPort = stateInThis.outgoingPort;
Iterator transitions = outPort.linkedRelationList()
.iterator();
while (transitions.hasNext()
&& !isStateInProductIllegal) {
InterfaceAutomatonTransition transition = (InterfaceAutomatonTransition) transitions
.next();
State destinationInThis = transition
.destinationState();
// get transitionLabel, transitionName and
// relation name for later use
String transitionLabel = transition.getLabel();
// remove ending "?", "!", or ";"
String transitionName = transitionLabel.substring(
0, transitionLabel.length() - 1);
// switch depending on type of transition
int transitionType = transition.getType();
if (transitionType == InterfaceAutomatonTransition._INPUT_TRANSITION) {
// case 1
throw new IllegalActionException("Transient "
+ "state " + stateInThis.getName()
+ " in " + getName() + " has input "
+ "transition " + transitionLabel);
} else if (transitionType == InterfaceAutomatonTransition._OUTPUT_TRANSITION) {
// case 2. T is output for p.
if (_outputNames.contains(transitionName)) {
// case 2A. T is output of product. Add T
// to product as output transition
State destinationInProduct = _addState(
product, destinationInThis,
stateInArgument, frontier);
_addTransition(product, this.getName(),
stateInProduct,
destinationInProduct,
transitionLabel);
} else {
// case 2B. transition is shared in product
String inName = transitionName + "?";
Set destinationsInArgument = _getDestinationStates(
stateInArgument, inName);
if (!destinationsInArgument.isEmpty()) {
// case 2Ba. q has T input. Add T to
// product as internal transition.
Iterator destinations = destinationsInArgument
.iterator();
while (destinations.hasNext()) {
State destinationInArgument = (State) destinations
.next();
State destinationInProduct = _addState(
product, destinationInThis,
destinationInArgument,
frontier);
_addTransition(product, this
.getName()
+ NAME_CONNECTOR
+ automaton.getName(),
stateInProduct,
destinationInProduct,
transitionName + ";");
}
} else {
// case 2Bb. q does not have T input.
// stateInProduct is illegal
_illegalStates.add(stateInProduct);
isStateInProductIllegal = true;
}
}
} else if (transitionType == InterfaceAutomatonTransition._INTERNAL_TRANSITION) {
// case 3. T is internal for p. Add T to product
State destinationInProduct = _addState(product,
destinationInThis, stateInArgument,
frontier);
_addTransition(product, this.getName(),
stateInProduct, destinationInProduct,
transitionLabel);
} else {
throw new InternalErrorException(
"InterfaceAutomaton._computeProduct: "
+ "unrecognized transition type.");
}
} // end explore from transient state p
} else {
// stateInArgument is transient.
// extend frontier from state in the argument automaton
ComponentPort outPort = stateInArgument.outgoingPort;
Iterator transitions = outPort.linkedRelationList()
.iterator();
while (transitions.hasNext()
&& !isStateInProductIllegal) {
InterfaceAutomatonTransition transition = (InterfaceAutomatonTransition) transitions