All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
tfw.tsm.Multiplexer Maven / Gradle / Ivy
package tfw.tsm;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import tfw.check.Argument;
import tfw.tsm.MultiplexerStrategy.MultiStateAccessor;
import tfw.tsm.ecd.EventChannelDescription;
import tfw.tsm.ecd.ObjectECD;
public class Multiplexer implements EventChannel {
private final MultiplexerStrategy multiStrategy;
/** The branch associated with this terminator. */
private MultiplexedBranch component = null;
/** The description of the single value event channel. */
final ObjectECD valueECD;
/** The state change rule for the sub-channels. */
private final StateChangeRule stateChangeRule;
/** The multiplexed value sink. */
final Sink multiSink;
/** The multiplexed value initiator source. */
public final MultiSource processorMultiSource;
/** The set of demultiplexing event channels. */
private final Map demultiplexedEventChannels =
new HashMap();
/**
* Creates a multiplexer with the specified value and multi-value event
* channels.
*
* @param multiplexerBranchName
* @param valueECD
* @param multiValueECD
*/
Multiplexer(
String multiplexerBranchName,
ObjectECD valueECD,
ObjectECD multiValueECD,
StateChangeRule stateChangeRule,
MultiplexerStrategy multiStrategy) {
Argument.assertNotNull(valueECD, "valueECD");
Argument.assertNotNull(multiValueECD, "multiValueECD");
Argument.assertNotNull(multiStrategy, "multiStrategy");
this.valueECD = valueECD;
this.stateChangeRule = stateChangeRule;
this.multiSink = new MultiSink(multiValueECD);
this.processorMultiSource = new MultiSource("Multiplexer Source[" + multiplexerBranchName + "]", multiValueECD);
this.multiStrategy = multiStrategy;
}
public class MultiSink extends Sink {
public MultiSink(ObjectECD ecd) {
super("MultiplexSink[" + ecd.getEventChannelName() + "]", ecd, true);
}
/**
* @see co2.ui.fw.Sink#stateChange()
*/
void stateChange() {
if (processorMultiSource.isStateSource()) {
return;
}
MultiStateAccessor stateAccessor = multiStrategy.toMultiStateAccessor(getState());
for (DemultiplexedEventChannel dm : Multiplexer.this.demultiplexedEventChannels.values()) {
Object state = stateAccessor.getState(dm.demultiplexSlotId);
if (state != null && stateChangeRule.isChange(dm.getPreviousCycleState(), state)) {
dm.setDeMultiState(state);
}
}
}
public Iterator getDemultiplexedEventChannels() {
return demultiplexedEventChannels.values().iterator();
}
}
class MultiSource extends ProcessorSource {
ArrayList pendingStateChanges = new ArrayList();
MultiSource(String name, EventChannelDescription ecd) {
super(name, ecd);
}
void setState(DemultiplexedEventChannel deMultiplexer) {
if (!pendingStateChanges.contains(deMultiplexer)) {
pendingStateChanges.add(deMultiplexer);
}
fire();
}
private int keyValueArraySize = 0;
private Object[] keys = new Object[keyValueArraySize];
private Object[] values = new Object[keyValueArraySize];
Object fire() {
if (pendingStateChanges.size() == 0) {
throw new IllegalStateException("No pending state changes to fire.");
}
keyValueArraySize = pendingStateChanges.size();
if (keys.length < keyValueArraySize) {
keys = new Object[keyValueArraySize];
values = new Object[keyValueArraySize];
}
for (int i = 0; i < keyValueArraySize; i++) {
DemultiplexedEventChannel dec = pendingStateChanges.get(i);
keys[i] = dec.demultiplexSlotId;
values[i] = dec.getState();
}
pendingStateChanges.clear();
Object multiState = null;
try {
multiState = Multiplexer.this.multiStrategy.addToMultiState(
eventChannel.getState(), keys, values, keyValueArraySize);
} catch (Exception e) {
throw new RuntimeException("ECD=" + ecd.getEventChannelName(), e);
}
eventChannel.setState(this, multiState, null);
getTreeComponent().getTransactionManager().addChangedEventChannel(eventChannel);
return multiState;
}
}
private EventChannel getDemultiplexedEventChannel(Object slotId) {
if (slotId == null) {
throw new IllegalArgumentException("slotId == null not allowed");
}
if (!demultiplexedEventChannels.containsKey(slotId)) {
Object currentSlotState = null;
/*
* TODO: If the multiSink is not connected, initial state is not
* handled properly.
*/
if (this.multiSink.isConnected()) {
Object multiState = getState();
MultiStateAccessor msa = this.multiStrategy.toMultiStateAccessor(multiState);
currentSlotState = msa.getState(slotId);
}
final Object defaultSlotState = this.multiStrategy.getDefaultSlotState();
Object initialSlotState = currentSlotState;
if (initialSlotState == null) {
initialSlotState = defaultSlotState;
}
DemultiplexedEventChannel dm =
new DemultiplexedEventChannel(this, slotId, initialSlotState, stateChangeRule);
/*
* if the initial slot state is non-null, make sure the state gets
* added to the multiplexed state.
*/
if (this.multiSink.isConnected() && currentSlotState == null && defaultSlotState != null) {
this.processorMultiSource.setState(dm);
}
dm.setTreeComponent(this.component);
demultiplexedEventChannels.put(slotId, dm);
}
return demultiplexedEventChannels.get(slotId);
}
TreeComponent getTreeComponent() {
return this.component;
}
void remove(DemultiplexedEventChannel deMultiplexer) {
if (demultiplexedEventChannels.remove(deMultiplexer.demultiplexSlotId) == null) {
throw new IllegalStateException("Demultiplexer not found attempting to remove demultiplexer for "
+ valueECD.getEventChannelName() + "["
+ deMultiplexer.demultiplexSlotId + "]");
}
}
/**
* @see tfw.tsm.EventChannel#add(tfw.tsm.Port)
*/
public void add(Port port) {
// Search for the multiplexed component...
Object slotId = component.getSlotId(port.getTreeComponent());
TreeComponent tc = port.getTreeComponent().getParent();
while (slotId == null && tc != null) {
slotId = component.getSlotId(tc);
tc = tc.getParent();
}
// if we didn't find a multiplexed component...
if (slotId == null) {
throw new IllegalArgumentException("The specified port, '"
+ port.ecd.getEventChannelName()
+ "', is not from a multiplexed component.\n" + " p.tc="
+ port.getTreeComponent() + " p.fqn="
+ port.getFullyQualifiedName());
}
getDemultiplexedEventChannel(slotId).add(port);
}
/**
* @see tfw.tsm.EventChannel#addDeferredStateChange(tfw.tsm.ProcessorSource)
*/
public void addDeferredStateChange(ProcessorSource source) {
throw new UnsupportedOperationException("Multiplexer does not participate directly in transactions.");
}
/**
* @see tfw.tsm.EventChannel#fire()
*/
public Object fire() {
throw new UnsupportedOperationException("Multiplexer does not participate directly in transactions.");
}
/**
* @see tfw.tsm.EventChannel#getParent()
*/
public TreeComponent getParent() {
return this.component;
}
/**
* @see tfw.tsm.EventChannel#getCurrentStateSource()
*/
public Source getCurrentStateSource() {
throw new UnsupportedOperationException("Multiplexer does not participate directly in transactions.");
}
/**
* @see tfw.tsm.EventChannel#getECD()
*/
public EventChannelDescription getECD() {
return valueECD;
}
/**
* @see tfw.tsm.EventChannel#getPreviousCycleState()
*/
public Object getPreviousCycleState() {
throw new UnsupportedOperationException("Multiplexer does not participate directly in transactions.");
}
/**
* @see tfw.tsm.EventChannel#getPreviousTransactionState()
*/
public Object getPreviousTransactionState() {
throw new UnsupportedOperationException("Multiplexer does not participate directly in transactions.");
}
public boolean isStateChanged() {
return false;
}
/**
* @see tfw.tsm.EventChannel#getState()
*/
public Object getState() {
return this.multiSink.eventChannel.getState();
}
/**
* @see tfw.tsm.EventChannel#isFireOnConnect()
*/
public boolean isFireOnConnect() {
throw new UnsupportedOperationException("Multiplexer does not participate directly in transactions.");
}
/**
* @see tfw.tsm.EventChannel#isRollbackParticipant()
*/
public boolean isRollbackParticipant() {
throw new UnsupportedOperationException("Multiplexer does not participate directly in transactions.");
}
/**
* @see tfw.tsm.EventChannel#remove(tfw.tsm.Port)
*/
public void remove(Port port) {
port.eventChannel.remove(port);
}
/**
* @see tfw.tsm.EventChannel#setState(tfw.tsm.Source, java.lang.Object,
* tfw.tsm.EventChannel)
*/
public void setState(Source source, Object state, EventChannel forwardingEventChannel) {
throw new UnsupportedOperationException("Multiplexer does not participate directly in transactions.");
}
/**
* @see tfw.tsm.EventChannel#setTreeComponent(tfw.tsm.TreeComponent)
*/
public void setTreeComponent(TreeComponent component) {
this.component = (MultiplexedBranch) component;
this.multiSink.setTreeComponent(component);
this.processorMultiSource.setTreeComponent(component);
}
/**
* @see tfw.tsm.EventChannel#synchronizeCycleState()
*/
public void synchronizeCycleState() {
throw new UnsupportedOperationException("Multiplexer does not participate directly in transactions.");
}
/**
* @see tfw.tsm.EventChannel#synchronizeTransactionState()
*/
public void synchronizeTransactionState() {
throw new UnsupportedOperationException("Multiplexer does not participate directly in transactions.");
}
}