package com.indyforge.foxnet.rmi.pattern.change.impl; import java.util.Collection; import java.util.LinkedList; import java.util.Queue; import com.indyforge.foxnet.rmi.Invocation; import com.indyforge.foxnet.rmi.Invoker; import com.indyforge.foxnet.rmi.RemoteInterfaces; import com.indyforge.foxnet.rmi.pattern.change.Change; import com.indyforge.foxnet.rmi.pattern.change.Changeable; import com.indyforge.foxnet.rmi.pattern.change.ChangeableQueue; /** * * @author Christopher Probst * * @param <T> */ @RemoteInterfaces(Changeable.class) public final class DefaultChangeableQueue<T> implements ChangeableQueue<T> { /* * Used to queue changes. */ private final Queue<Change<T>> changes = new LinkedList<Change<T>>(); /* * The changeable peer. */ private final Changeable<T> peer; public DefaultChangeableQueue(Changeable<T> peer) { if (peer == null) { throw new NullPointerException("peer"); } this.peer = peer; } /* * (non-Javadoc) * * @see * com.indyforge.foxnet.rmi.pattern.change.Changeable#applyChange(com.indyforge * .foxnet.rmi.pattern.change.Change) */ @Override public void applyChange(Change<T> change) { peer.applyChange(change); } /* * (non-Javadoc) * * @see * com.indyforge.foxnet.rmi.pattern.change.ChangeableQueue#applyChangeLater * (com.indyforge.foxnet.rmi.pattern.change.Change, java.util.Collection) */ @Override public void applyChangeLater(Change<T> change, Collection<Invocation> invocations) { // Lookup invoker Invoker invoker = Invoker.of(peer); if (invoker != null) { // Generate an invocation Invocation invocation = invoker.invoke("applyChange", change); // Add... ? if (invocations != null) { invocations.add(invocation); } } else { // Apply directly! peer.applyChange(change); } } /* * (non-Javadoc) * * @see com.indyforge.foxnet.rmi.pattern.change.ChangeableQueue# * applyQueuedChangesLater(java.util.Collection) */ @Override public void applyQueuedChangesLater(Collection<Invocation> invocations) { Change<T> change; while ((change = changes.poll()) != null) { applyChangeLater(change, invocations); } } /* * (non-Javadoc) * * @see * com.indyforge.foxnet.rmi.pattern.change.ChangeableQueue#applyQueuedChanges * () */ @Override public synchronized void applyQueuedChanges() { Change<T> change; while ((change = changes.poll()) != null) { applyChange(change); } } /* * (non-Javadoc) * * @see * com.indyforge.foxnet.rmi.pattern.change.ChangeableQueue#mergeQueuedChanges * () */ @Override public synchronized void mergeQueuedChanges() { // Check the size if (changes.size() > 1) { // Create a new composite change CompositeChange<T> compositeChange = new CompositeChange<T>(changes); // Remove all changes changes.clear(); // Offer the composite change changes.offer(compositeChange); } } /* * (non-Javadoc) * * @see * com.indyforge.foxnet.rmi.pattern.change.ChangeableQueue#separateQueuedChanges * () */ @Override public synchronized void separateQueuedChanges() { // Check the head if (changes.size() == 1 && changes.peek() instanceof CompositeChange) { // Remove composite change and add each change changes.addAll(((CompositeChange<T>) changes.poll()).changes()); } } /* * (non-Javadoc) * * @see * com.indyforge.foxnet.rmi.pattern.change.ChangeableQueue#queueChange(com * .indyforge.foxnet.rmi.pattern.change.Change, boolean) */ @Override public synchronized void queueChange(Change<T> change, boolean merge) { // Queue the change changes.offer(change); // Merge ? if (merge) { mergeQueuedChanges(); } } /* * (non-Javadoc) * * @see * com.indyforge.foxnet.rmi.pattern.change.ChangeableQueue#removeQueuedChanges * () */ @Override public synchronized void removeQueuedChanges() { // Clear all changes changes.clear(); } }