package org.bbssh.model;
import java.io.EOFException;
import java.util.Hashtable;
import java.util.Vector;
import net.rim.device.api.synchronization.SyncObject;
import org.bbssh.command.CommandConstants;
import org.bbssh.io.SyncBuffer;
import org.bbssh.keybinding.PersistableCommandFactory;
import org.bbssh.util.Logger;
public class MacroManager extends DefaultSyncCollection {
public static final long MACRO_GUID = 0xea72d52bcfa4f1fL; // org.bbssh.model.MacroManager
private static MacroManager me;
private Hashtable macroMap = new Hashtable();
private MacroManager() {
}
public void initialize() {
// @todo is loadData even needed? That will get called automatically on first use.
loadData();
}
public static synchronized MacroManager getInstance() {
if (me == null) {
me = new MacroManager();
}
return me;
}
public Macro getMacro(String name) {
return (Macro) macroMap.get(name);
}
public void addMacro(Macro macro) {
if (macroMap.containsKey(macro.getName())) {
return;
}
getDataVector().addElement(macro);
macroMap.put(macro.getName(), macro);
}
public void delMacro(String name) {
if (macroMap.containsKey(name)) {
Object m = macroMap.get(name);
macroMap.remove(name);
getDataVector().removeElement(m);
}
}
public boolean isExistingMacro(String name) {
return macroMap.containsKey(name);
}
public String getSyncName() {
return "BBSSH Macros";
}
public int getSyncVersion() {
return 1;
}
protected SyncObject convertImpl(SyncBuffer buffer, int version, int uID, boolean syncDirty) {
Macro m = new Macro(uID);
// @todo we can also make sync state dirty an interface member, and haev the caller
// do this.
m.setSyncStateDirty(syncDirty);
try {
m.setName(buffer.readNextStringField());
Vector v = m.getCommandVector();
if (version == 0) {
// version 0 is a simple thig - has name and text. Convert it to our new version
// which will just be a SendKeys command.
v.addElement(new PersistableCommandFactory(0, CommandConstants.SEND_TEXT, buffer
.readNextStringField()));
} else {
int count = buffer.readNextIntField();
while (count-- > 0) {
v.addElement(KeyBindingManager.readPersistableCommandFactory(buffer, uID, 0));
}
}
macroMap.put(m.getName(), m);
} catch (EOFException e) {
Logger.error("MacroManager.convertImpl received unexpected EOF while deserializing macros.");
}
return m;
}
protected boolean convertImpl(SyncObject object, SyncBuffer buffer, int version) {
// @todo - this *will* screw up any count that preceded thsi. We may need to have a verifyCount function:
// for each vector element check non-null and data type?
if (!(object instanceof Macro))
return false;
Macro m = (Macro) object;
// BEGIN VERSION 0 FIELDS
buffer.writeField(m.getName());
// buffer.writeField(m.getText());
// END VERSION 0 FIELDS
Vector v = m.getCommandVector();
int count = v.size();
buffer.writeField(count);
for (int x = 0; x < count; x++) {
KeyBindingManager.writePersistableCommandFactory((PersistableCommandFactory) v.elementAt(x), buffer);
}
return true;
}
public Vector getMacros() {
return getDataVector();
}
public Vector getTemporaryMacroNamesList() {
Vector v = getDataVector();
Vector out = new Vector(v.size());
// @todo - sorted?
int max = v.size();
for (int x = 0; x < max; x++) {
Object t = v.elementAt(x);
if (t == null) { // bad data - shouldn't happen, butlet's be safe.
v.removeElementAt(x);
x--; // hit this same index again.
continue;
}
out.addElement(((Macro) v.elementAt(x)).getName());
}
return out;
}
public long getPersistentStoreId() {
return MACRO_GUID;
}
public void resetState() {
macroMap.clear();
}
public Macro duplicateMacro(Macro m) {
Macro dup = new Macro(m);
int idx = 1;
String name = m.getName();
while (getMacro(name) != null) {
name = name + idx++;
// Make a reasonable attempt at a unique name before we give up
// and make a ridiculous attempt at a unique name.
if (idx > 10) {
// through somefluke, we COULD get stuck in a loophere if getInt kept returning us a value
// of 10 or less... but that's fairly unlikely.
name = name + dup.getUID();
}
}
dup.setName(name);
addMacro(dup);
return dup;
}
public boolean isSecureStoreRequired() {
return false;
}
}