package games.strategy.engine.message;
/**
* Very similar to RMI
*
* <p>
* Objects can be registered with a remote messenger under a public name and
* declared to implement a particular interface. Methods on this registered
* object can then be called on different vms.
* </p>
*
* <p>
* To call a method on the registered object, you get a remote reference to it using the
* getRemote(...) method. This returns an object that can be used and called
* as if it were the original implementor.
* </p>
*
* <p>
* The getRemote(...) method though may be called on a different vm than
* the registerRemote(...) method. In that case the calls on the return value of
* getRemote(...) will be routed to the implementor object passed to registerRemote(...)
* On VM A you have code like
* </p>
*
* <pre>
* RemoteName FOO = new RemoteName("Foo", IFoo.class);
* IFoo aFoo = new Foo();
* aRemoteMessenger.registerRemote(IFoo.class, aFoo, FOO);
* </pre>
*
* <p>
* After this runs, on VM B you can do
* </p>
*
* <pre>
* IFoo someFoo = anotherRemoteMessenger.getRemote(FOO);
* boolean rVal = someFoo.fee();
* if(rVal)
* ...
* </pre>
*
* <p>
* What will happen is that the fee() call in VM B will be invoked on aFoo in VM A.
* </p>
*
* <p>
* This is done using reflection and dynamic proxies (java.lang.reflect.Proxy)
* </p>
*
* <p>
* To avoid naming conflicts, it is advised to use the fully qualified java name and
* and a constant be used as the channel name. For example names should be in the form
* </p>
*
* <pre>
* "foo.fee.Fi.SomeConstant"
* </pre>
*
* <p>
* where SomeConstant is defined in the class foo.fee.Fi
* </p>
*
* <p>
* <b>Remotes and threading</b>
* </p>
*
* <p>
* Remotes are multithreaded. Method calls may arrive out of order that methods were called.
* </p>
*/
public interface IRemoteMessenger {
/**
* @param name
* the name the remote is registered under.
* @return a remote reference to the registered remote.
*/
IRemote getRemote(RemoteName name);
/**
* @param name
* the name the remote is registered under.
* @param ignoreResults
* whether we need to wait for the results or not
* @return a remote reference to the registered remote.
*/
IRemote getRemote(RemoteName name, boolean ignoreResults);
/**
* @param implementor
* An object that implements remoteInterface.
* @param name
* The name that implementor will be registered under.
*/
void registerRemote(Object implementor, RemoteName name);
/**
* Remove the remote registered under name.
*/
void unregisterRemote(String name);
/**
* Remove the remote registered under name.
*/
void unregisterRemote(RemoteName name);
boolean hasLocalImplementor(RemoteName name);
boolean isServer();
}