package kvj.app.vimtouch.ext.manager;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.momodalo.app.vimtouch.Exec;
import org.kvj.bravo7.ipc.RemoteServicesCollector;
import org.kvj.vimtouch.BasePlugin;
import org.kvj.vimtouch.TransferableData;
import org.kvj.vimtouch.ext.FieldReaderException;
import org.kvj.vimtouch.ext.IncomingTransfer;
import org.kvj.vimtouch.ext.OutgoingTransfer;
import org.kvj.vimtouch.ext.Transferable;
import org.kvj.vimtouch.ext.manager.IntegrationError;
import org.kvj.vimtouch.ext.manager.IntegrationExtension;
import org.kvj.vimtouch.ext.manager.IntegrationExtensionException;
import android.content.Context;
import android.os.IBinder;
import android.util.Log;
public class IntegrationManager {
private static final String TAG = "Integration";
private Context ctx = null;
private IntegrationManager(Context ctx) {
this.ctx = ctx;
pluginCollector = new RemoteServicesCollector<BasePlugin>(ctx,
IntegrationExtension.PLUGIN_ACTION) {
@Override
public BasePlugin castAIDL(IBinder binder) {
return BasePlugin.Stub.asInterface(binder);
}
};
}
private static IntegrationManager instance = null;
public static IntegrationManager getInstance(Context ctx) {
if (null == instance) {
instance = new IntegrationManager(ctx);
}
return instance;
}
private RemoteServicesCollector<BasePlugin> pluginCollector = null;
private Map<String, IntegrationExtension<Transferable, Transferable>> extensions = new HashMap<String, IntegrationExtension<Transferable, Transferable>>();
private int nextEvent = 0;
@SuppressWarnings("unchecked")
public void addExtension(
IntegrationExtension<? extends Transferable, ? extends Transferable> ext) {
if (!extensions.containsValue(ext)) {
extensions.put(ext.getType(),
(IntegrationExtension<Transferable, Transferable>) ext);
}
}
public void removeExtension(
IntegrationExtension<Transferable, Transferable> ext) {
extensions.remove(ext.getType());
}
public String process(String type, String input) {
Transferable output = null;
try {
IntegrationExtension<Transferable, Transferable> ext = extensions
.get(type);
if (null == ext) {
return invokeRemoteExtension(type, input);
}
Transferable inp = ext.newInput();
IncomingTransfer it = new IncomingTransfer(input);
inp.readFrom(it);
try {
it.read();
} catch (FieldReaderException e) {
throw new IntegrationExtensionException(String.format(
"Parsing failed: %s", e.getMessage()));
}
output = ext.process(inp);
} catch (IntegrationExtensionException e) {
Log.w(TAG, "Error processing input:", e);
output = new IntegrationError(e.getMessage());
}
OutgoingTransfer ot = new OutgoingTransfer();
ot.beginWrite();
output.writeTo(ot);
ot.endWrite();
return ot.getBuffer().toString();
}
private String invokeRemoteExtension(String type, String input)
throws IntegrationExtensionException {
try {
List<BasePlugin> plugins = pluginCollector.getPlugins();
for (BasePlugin plugin : plugins) {
if (plugin.getName().equals(type)) {
// Found
TransferableData out = plugin.process(new TransferableData(
input));
return out.getData();
}
}
throw new IntegrationExtensionException(String.format(
"Extension '%s' not found", type));
} catch (Exception e) {
Log.w(TAG,
String.format("Error invoking remote plugin '%s':", type),
e);
throw new IntegrationExtensionException(e.getMessage());
}
}
public int nextEvent() {
return ++nextEvent;
}
public void sendEvent(int type, Transferable object) {
OutgoingTransfer ot = new OutgoingTransfer();
ot.beginWrite();
object.writeTo(ot);
ot.endWrite();
Exec.sendAndroidEvent(type, ot.getBuffer().toString());
}
public void stop() {
pluginCollector.stop();
}
}