/
codebase/
codebase/area/
codebase/doc/
codebase/etc/
codebase/src/net/sourceforge/pain/data/trigger/
codebase/src/net/sourceforge/pain/logic/
codebase/src/net/sourceforge/pain/logic/affect/
codebase/src/net/sourceforge/pain/logic/event/
codebase/src/net/sourceforge/pain/logic/event/deploy/
codebase/src/net/sourceforge/pain/logic/event/guitool/
codebase/src/net/sourceforge/pain/logic/event/guitool/event/
codebase/src/net/sourceforge/pain/logic/fn/util/
codebase/src/net/sourceforge/pain/logic/trigger/
codebase/src/net/sourceforge/pain/logic/trigger/impl/
codebase/src/net/sourceforge/pain/network/console/
codebase/src/net/sourceforge/pain/network/console/telnet/
codebase/src/net/sourceforge/pain/network/guitool/
codebase/src/net/sourceforge/pain/plugin/
codebase/src/net/sourceforge/pain/plugin/command/
codebase/src/net/sourceforge/pain/plugin/reset/
codebase/src/net/sourceforge/pain/plugin/shutdown/
codebase/src/net/sourceforge/pain/plugin/social/
codebase/src/net/sourceforge/pain/util/
db/doc/javadoc/resources/
db/src/net/sourceforge/pain/util/
gui/
gui/lib/
gui/src/net/sourceforge/pain/tools/guitool/dbbrowse/
gui/src/net/sourceforge/pain/tools/guitool/dialog/
gui/src/net/sourceforge/pain/tools/guitool/menu/
gui/src/net/sourceforge/pain/tools/guitool/resources/
gui/src/net/sourceforge/pain/tools/guitool/resources/images/
gui/src/net/sourceforge/pain/tools/guitool/resources/images/explorer/
tests/
tests/src/
tests/src/net/sourceforge/pain/db/data/
package net.sourceforge.pain.plugin.command;


import net.sourceforge.pain.util.*;

import java.util.*;

public class CommandRegistry {

	private final HashMap prefixMapping = new HashMap(1024);
	final HashMap exactMapping = new HashMap(1024);
	private final HashMap commandNamesByClassName = new HashMap(1024);

	CommandRegistry() {
	}

	public LinkedHashMap findCommandsByPrefix(String prefix) {
		prefix = prefix.toLowerCase();
		PrefixEntry entry = (PrefixEntry) prefixMapping.get(prefix);
		if (entry == null) {
			return null;
		}
		return entry.commands;
	}

	public void registerCommand(TextCommand command) {
		final String name = command.name;
		if (exactMapping.containsKey(name)) {
			throw new IllegalArgumentException("command with this name already registered:" + name);
		}
		for (int i = 0; i < name.length(); i++) {
			String prefix = name.substring(0, i + 1);
			PrefixEntry entry = (PrefixEntry) prefixMapping.get(prefix);
			if (entry == null) {
				entry = new PrefixEntry();
				prefixMapping.put(prefix, entry);
			}
			entry.commands.put(name, command);
		}
		exactMapping.put(name, command);
		addToClassNameMapping(command);
	}

	private void addToClassNameMapping(TextCommand command) {
		HashSet commandNames = (HashSet) commandNamesByClassName.get(command.commandClassName);
		if (commandNames == null) {
			commandNames = new HashSet();
			commandNamesByClassName.put(command.commandClassName, commandNames);
		}
		commandNames.add(command.name);
	}

	public void unregisterCommand(String name) {
		name = name.toLowerCase();
		TextCommand command = (TextCommand) exactMapping.remove(name);
		if (command == null) {
			return;
		}
		for (int i = name.length(); i > 0; i--) {
			String prefix = name.substring(0, i);
			PrefixEntry entry = (PrefixEntry) prefixMapping.get(prefix);
			if (entry == null) {
				return;
			}
			entry.commands.remove(name);
			if (entry.commands.isEmpty()) {
				prefixMapping.remove(prefix);
			}
		}
		removeFromClassNameMapping(command);
	}

	private void removeFromClassNameMapping(TextCommand command) {
		HashSet commandNames = (HashSet) commandNamesByClassName.get(command.commandClassName);
		if (commandNames == null) {
			Log.warn("BUG:removeFromClassNameMapping: commandsNames is null");
			return;
		}
		commandNames.remove(command.name);
		if (commandNames.isEmpty()) {
			commandNamesByClassName.remove(command.commandClassName);
		}
	}


	public TextCommand findCommandByPrefix(String prefix) {
		LinkedHashMap commandsByPrefix = findCommandsByPrefix(prefix);
		if (commandsByPrefix == null || commandsByPrefix.isEmpty()) {
			return null;
		}
		return (TextCommand) commandsByPrefix.values().iterator().next();
	}

	public Set getAllCommandsForClassName(String className) {
		return (Set) commandNamesByClassName.get(className);
	}

	private static class PrefixEntry {
		LinkedHashMap commands = new LinkedHashMap();
	}

}