package mpi.eudico.client.annotator.commands;

import mpi.eudico.client.annotator.ElanLayoutManager;
import mpi.eudico.client.annotator.ElanLocale;
import mpi.eudico.client.annotator.ViewerManager2;
import mpi.eudico.client.annotator.timeseries.TSTrackManager;

import mpi.eudico.server.corpora.clom.Transcription;

import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

import java.util.Collection;
import java.util.Hashtable;
import java.util.Locale;
import java.util.Vector;

import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.KeyStroke;

/**
 * DOCUMENT ME!
 * $Id: ELANCommandFactory.java,v 1.16 2006/04/03 16:03:43 hasloe Exp $
 * @author $Author: hasloe $
 * @version $Revision: 1.16 $
 */
public class ELANCommandFactory {
	// all Hashtables have Transcription as their key
	private static Hashtable commandActionHash = new Hashtable();
	private static Hashtable undoCAHash = new Hashtable();
	private static Hashtable redoCAHash = new Hashtable();
	private static Hashtable commandHistoryHash = new Hashtable();

	//	private UndoCA undoCA = null;
	//	private RedoCA redoCA = null;
	//	private CommandHistory commandHistory;
	// the viewer manager for this document / frame
	//	public ViewerManager2 viewerManager = null;
	//	public ElanLayoutManager layoutManager = null;
	private static Hashtable viewerManagerHash = new Hashtable();
	private static Hashtable layoutManagerHash = new Hashtable();
	private static Hashtable trackManagerHash = new Hashtable();

	// root frame for dialogs
	//	public JFrame frame = null;
	private static Hashtable rootFrameHash = new Hashtable();
	
	// a table for the available languages 
	private static final Hashtable languages = new Hashtable();

	// list of commands/command actions

	/** Holds value of property DOCUMENT ME! */
	public static final String SET_TIER_NAME = "CommandActions.SetTierName";

	/** Holds value of property DOCUMENT ME! */
	public static final String CHANGE_TIER_DLG = "CommandActions.ChangeTier";

	/** Holds value of property DOCUMENT ME! */
	public static final String CHANGE_TIER = "CommandActions.ChangeTierAttributes";

	/** Holds value of property DOCUMENT ME! */
	public static final String ADD_TIER_DLG = "CommandActions.AddNewTier";

	/** Holds value of property DOCUMENT ME! */
	public static final String ADD_TIER = "CommandActions.AddTier";

	/** Holds value of property DOCUMENT ME! */
	public static final String DELETE_TIER = "CommandActions.DeleteTier";

	/** Holds value of property DOCUMENT ME! */
	public static final String DELETE_TIER_DLG = "CommandActions.DeleteTierDialog";

	/** Holds value of property DOCUMENT ME! */
	public static final String EDIT_TIER = "CommandActions.EditTier";
	
	public static final String IMPORT_TIERS = "CommandActions.ImportTiers";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String EDIT_TYPE = "CommandActions.EditType";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String ADD_TYPE_DLG = "CommandActions.AddNewTypeDialog";

	/** Holds value of property DOCUMENT ME! */
	public static final String CHANGE_TYPE_DLG = "CommandActions.ChangeTypeDialog";

	/** Holds value of property DOCUMENT ME! */
	public static final String DELETE_TYPE_DLG = "CommandActions.DeleteTypeDialog";

	/** Holds value of property DOCUMENT ME! */
	public static final String ADD_TYPE = "CommandActions.AddNewType";

	/** Holds value of property DOCUMENT ME! */
	public static final String CHANGE_TYPE = "CommandActions.ChangeType";

	/** Holds value of property DOCUMENT ME! */
	public static final String DELETE_TYPE = "CommandActions.DeleteType";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String ADD_CV = "CommandActions.AddCV";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String CHANGE_CV = "CommandActions.ChangeCV";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String DELETE_CV = "CommandActions.DeleteCV";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String REPLACE_CV = "CommandActions.ReplaceCV";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String ADD_CV_ENTRY = "CommandActions.AddCVEntry";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String CHANGE_CV_ENTRY = "CommandActions.ChangeCVEntry";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String DELETE_CV_ENTRY = "CommandActions.DeleteCVEntry";
	
	/** only for Command: String is currently not in the language files! */
	public static final String MOVE_CV_ENTRIES = "MoveEntries";
	
	/** only for Command: String is currently not in the language files! */
	public static final String REPLACE_CV_ENTRIES = "ReplaceEntries";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String EDIT_CV_DLG = "CommandActions.EditCV"; 

	/** Holds value of property DOCUMENT ME! */
	public static final String NEW_ANNOTATION = "Menu.Edit.NewAnnotation";

	/** Holds value of property DOCUMENT ME! */
	public static final String NEW_ANNOTATION_BEFORE = "Menu.Edit.NewAnnotationBefore";

	/** Holds value of property DOCUMENT ME! */
	public static final String NEW_ANNOTATION_AFTER = "Menu.Edit.NewAnnotationAfter";

	/** Holds value of property DOCUMENT ME! */
	public static final String MODIFY_ANNOTATION = "Menu.Edit.ModifyAnnotation";

	/** Holds value of property DOCUMENT ME! */
	public static final String MODIFY_ANNOTATION_DLG = "ModifyAnnotationDialog";

	/** Holds value of property DOCUMENT ME! */
	public static final String DELETE_ANNOTATION = "Menu.Edit.DeleteAnnotation";

	/** Holds value of property DOCUMENT ME! */
	public static final String MODIFY_ANNOTATION_TIME = "CommandActions.ModifyAnnotationTime";

	/** Holds value of property DOCUMENT ME! */
	public static final String MODIFY_GRAPHIC_ANNOTATION = "Menu.Edit.ModifyGraphicAnnotation";

	/** Holds value of property DOCUMENT ME! */
	public static final String MODIFY_GRAPHIC_ANNOTATION_DLG = "ModifyGraphicAnnotationDialog";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String SHIFT_ALL_DLG = "CommandActions.ShiftAllDialog";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String SHIFT_ALL_ANNOTATIONS = "Menu.Edit.ShiftAll";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String TOKENIZE_DLG = "Menu.Edit.Tokenize";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String TOKENIZE_TIER = "CommandActions.Tokenize";

	/** Holds value of property DOCUMENT ME! */
	public static final String SHOW_TIMELINE = "Menu.View.ShowTimeline";

	/** Holds value of property DOCUMENT ME! */
	public static final String SHOW_INTERLINEAR = "Menu.View.ShowInterlinear";

	/** Holds value of property DOCUMENT ME! */
	public static final String SHOW_MULTITIER_VIEWER = "Commands.ShowMultitierViewer";

	/** Holds value of property DOCUMENT ME! */
	public static final String GOTO_DLG = "Menu.Search.GoTo";

	/** Holds value of property DOCUMENT ME! */
	public static final String SEARCH_DLG = "Menu.Search.Find";

	/** Holds string for search in multiple files */
	public static final String SEARCH_MULTIPLE_DLG = "Menu.Search.Multiple";
	
	/** Holds string for structured search in multiple files */
	public static final String STRUCTURED_SEARCH_MULTIPLE_DLG = "Menu.Search.StructuredMultiple";
	
	/** Command action name of replacing matches with string */
	public static final String REPLACE = "CommandActions.Replace";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String TIER_DEPENDENCIES = "Menu.View.Dependencies";

	/** Holds value of property DOCUMENT ME! */
	public static final String SHORTCUTS = "Menu.View.Shortcuts";

	/** Holds value of property DOCUMENT ME! */
	public static final String ABOUT_DLG = "Menu.Help.About";

	/** Holds value of property DOCUMENT ME! */
	public static final String SYNC_MODE = "Menu.Options.SyncMode";

	/** Holds value of property DOCUMENT ME! */
	public static final String ANNOTATION_MODE = "Menu.Options.AnnotationMode";

	/** Holds value of property DOCUMENT ME! */
	public static final String BULLDOZER_MODE = "Menu.Options.BulldozerMode";

	/** Holds value of property DOCUMENT ME! */
	public static final String TIMEPROP_NORMAL = "Menu.Options.NormalPropagationMode";

	/** Holds value of property DOCUMENT ME! */
	public static final String SHIFT_MODE = "Menu.Options.ShiftMode";

	/** Holds value of property DOCUMENT ME! */
	public static final String SELECTION_MODE = "CommandActions.SelectionMode";

	/** Holds value of property DOCUMENT ME! */
	public static final String LOOP_MODE = "CommandActions.LoopMode";

	/** Holds value of property DOCUMENT ME! */
	public static final String CLEAR_SELECTION = "Menu.Play.ClearSelection";

	/** Holds value of property DOCUMENT ME! */
	public static final String PLAY_SELECTION = "Menu.Play.PlaySelection";

	/** Holds value of property DOCUMENT ME! */
	public static final String PLAY_AROUND_SELECTION = "CommandActions.PlayAroundSelection";

	/** Holds value of property DOCUMENT ME! */
	public static final String PLAY_AROUND_SELECTION_DLG =
		"CommandActions.PlayAroundSelectionDialog";
	
	public static final String PLAYBACK_TOGGLE_DLG = "CommandActions.PlaybackToggleDialog";
	
	public static final String PLAYBACK_TOGGLE = "PLAYBACK_TOGGLE";
	
	public static final String PLAYBACK_RATE_TOGGLE = "CommandActions.PlaybackRateToggle";
	
	public static final String PLAYBACK_VOLUME_TOGGLE = "CommandActions.PlaybackVolumeToggle";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String SET_PAL = "CommandActions.PAL";

	/** Holds value of property DOCUMENT ME! */
	public static final String SET_NTSC = "CommandActions.NTSC";

	/** Holds value of property DOCUMENT ME! */
	public static final String NEXT_FRAME = "Menu.Play.Next";

	/** Holds value of property DOCUMENT ME! */
	public static final String PREVIOUS_FRAME = "Menu.Play.Previous";

	/** Holds value of property DOCUMENT ME! */
	public static final String PLAY_PAUSE = "Menu.Play.PlayPause";

	/** Holds value of property DOCUMENT ME! */
	public static final String GO_TO_BEGIN = "Menu.Play.GoToBegin";

	/** Holds value of property DOCUMENT ME! */
	public static final String GO_TO_END = "Menu.Play.GoToEnd";

	/** Holds value of property DOCUMENT ME! */
	public static final String PREVIOUS_SCROLLVIEW = "Menu.Play.GoToPreviousScrollview";

	/** Holds value of property DOCUMENT ME! */
	public static final String NEXT_SCROLLVIEW = "Menu.Play.GoToNextScrollview";

	/** Holds value of property DOCUMENT ME! */
	public static final String PIXEL_LEFT = "Menu.Play.1PixelLeft";

	/** Holds value of property DOCUMENT ME! */
	public static final String PIXEL_RIGHT = "Menu.Play.1PixelRight";

	/** Holds value of property DOCUMENT ME! */
	public static final String SECOND_LEFT = "Menu.Play.1SecLeft";

	/** Holds value of property DOCUMENT ME! */
	public static final String SECOND_RIGHT = "Menu.Play.1SecRight";

	/** Holds value of property DOCUMENT ME! */
	public static final String SELECTION_BOUNDARY = "Menu.Play.ToggleCrosshairInSelection";

	/** Holds value of property DOCUMENT ME! */
	public static final String ACTIVE_ANNOTATION = "Commands.ActiveAnnotation";

	/** Holds value of property DOCUMENT ME! */
	public static final String PREVIOUS_ANNOTATION = "CommandActions.PreviousAnnotation";

	/** Holds value of property DOCUMENT ME! */
	public static final String NEXT_ANNOTATION = "CommandActions.NextAnnotation";

	/** Holds value of property DOCUMENT ME! */
	public static final String ANNOTATION_UP = "CommandActions.AnnotationUp";

	/** Holds value of property DOCUMENT ME! */
	public static final String ANNOTATION_DOWN = "CommandActions.AnnotationDown";

	/** Holds value of property DOCUMENT ME! */
	public static final String SET_LOCALE = "CommandActions.Language";

	/** Holds value of property DOCUMENT ME! */
	public static final String CATALAN = "CommandActions.Catalan";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String DUTCH = "CommandActions.Dutch";

	/** Holds value of property DOCUMENT ME! */
	public static final String ENGLISH = "CommandActions.English";
	
	public static final String SPANISH = "CommandActions.Spanish";
	
	public static final String SWEDISH = "CommandActions.Swedish";
	
	public static final String GERMAN ="CommandActions.German";
	
	public static final String PORTUGUESE = "CommandActions.Portuguese";
	public static final String FRENCH = "CommandActions.French";

	/** Holds value of property DOCUMENT ME! */
	public static final String SAVE = "Menu.File.Save";

	/** Holds value of property DOCUMENT ME! */
	public static final String SAVE_AS = "Menu.File.SaveAs";

	/** Holds value of property DOCUMENT ME! */
	public static final String SAVE_AS_TEMPLATE = "Menu.File.SaveAsTemplate";
	
	public static final String SAVE_SELECTION_AS_EAF = "Menu.File.SaveSelectionAsEAF";

	/** Holds value of property DOCUMENT ME! */
	public static final String STORE = "Commands.Store";

	/** Holds value of property DOCUMENT ME! */
	public static final String EXPORT_TAB = "Menu.File.Export.Tab";

	/** Holds value of property DOCUMENT ME! */
	public static final String EXPORT_TEX = "Menu.File.Export.TeX";

	/** Holds value of property DOCUMENT ME! */
	public static final String EXPORT_TIGER = "Menu.File.Export.Tiger";

	/** Holds value of property DOCUMENT ME! */
	public static final String EXPORT_QT_SUB = "Menu.File.Export.QtSub";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String EXPORT_SMIL = "Menu.File.Export.Smil";

	/** Holds value of property DOCUMENT ME! */
	public static final String EXPORT_SHOEBOX = "Menu.File.Export.Shoebox";

	/** Holds value of property DOCUMENT ME! */
	public static final String EXPORT_CHAT = "Menu.File.Export.CHAT";

	/** Holds value of property DOCUMENT ME! */
	public static final String EXPORT_MEDIA = "Menu.File.Export.Media";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String EXPORT_IMAGE_FROM_WINDOW = "Menu.File.Export.ImageFromWindow";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String BACKUP = "CommandActions.Backup";

	/** Holds value of property DOCUMENT ME! */
	public static final String BACKUP_NEVER = "Menu.File.Backup.Never";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String BACKUP_5 = "Menu.File.Backup.5";

	/** Holds value of property DOCUMENT ME! */
	public static final String BACKUP_10 = "Menu.File.Backup.10";

	/** Holds value of property DOCUMENT ME! */
	public static final String BACKUP_20 = "Menu.File.Backup.20";

	/** Holds value of property DOCUMENT ME! */
	public static final String BACKUP_30 = "Menu.File.Backup.30";

	/** Holds value of property DOCUMENT ME! */
	public static final String PRINT = "Menu.File.Print";

	/** Holds value of property DOCUMENT ME! */
	public static final String PREVIEW = "Menu.File.PrintPreview";

	/** Holds value of property DOCUMENT ME! */
	public static final String PAGESETUP = "Menu.File.PageSetup";

	/** Holds value of property DOCUMENT ME! */
	public static final String REDO = "Menu.Edit.Redo";

	/** Holds value of property DOCUMENT ME! */
	public static final String UNDO = "Menu.Edit.Undo";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String LINKED_FILES_DLG = "CommandActions.LinkedFilesDialog";
	
	/** Holds value of property DOCUMENT ME! */
	public static final String CHANGE_LINKED_FILES = "CommandActions.ChangeLinkedFiles";
	public static final String SEGMENTATION_DLG = "CommandActions.SegmentationDlg";
	public static final String ADD_SEGMENTATION = "CommandActions.AddSegmentation";
	
	public static final String FILTER_TIER = "CommandActions.FilterTier";
	public static final String FILTER_TIER_DLG = "CommandActions.FilterTierDlg";
	
	public static final String EXPORT_TRAD_TRANSCRIPT = "Menu.File.Export.TraditionalTransript";
	public static final String EXPORT_INTERLINEAR = "Menu.File.Export.Interlinear";
	public static final String REPARENT_TIER_DLG = "CommandActions.ReparentTierDialog";
	public static final String REPARENT_TIER = "CommandActions.ReparentTier";
	public static final String COPY_TIER = "CommandActions.CopyTier";
	public static final String COPY_TIER_DLG = "CommandActions.CopyTierDialog";
	public static final String MERGE_TRANSCRIPTIONS = "CommandActions.MergeTranscriptions";
	
	public static final String NEXT_ACTIVE_TIER = "CommandActions.NextActiveTier";
	public static final String PREVIOUS_ACTIVE_TIER = "CommandActions.PreviousActiveTier";
	public static final String ACTIVE_TIER = "ActiveTier";
	
	public static final String SYNTAX_VIEWER = "CommandActions.SyntaxViewer";
	
	public static final String PUBLISH_DOC = "Menu.P2P.PublishDocument";
	public static final String DISCOVER_DOC = "Menu.P2P.DiscoverDocument";
	public static final String EXT_TRACK_DATA = "CommandActions.ExtractTrackData";

	/** a list of commandactions that have a keyboard shortcut */
	private static final String[] commandConstants =
		{
			NEW_ANNOTATION,
			NEW_ANNOTATION_BEFORE,
			NEW_ANNOTATION_AFTER,
			MODIFY_ANNOTATION,
			MODIFY_ANNOTATION_TIME,
			DELETE_ANNOTATION,
			PREVIOUS_ANNOTATION,
			NEXT_ANNOTATION,
			ANNOTATION_UP,
			ANNOTATION_DOWN,
			ANNOTATION_MODE,
			SET_TIER_NAME,
			CHANGE_TIER_DLG,
			ADD_TIER_DLG,
			DELETE_TIER_DLG,
			PREVIOUS_ACTIVE_TIER,
			NEXT_ACTIVE_TIER,
			ADD_TYPE_DLG,
			CHANGE_TYPE_DLG,
			DELETE_TYPE_DLG,
			PLAY_PAUSE,
			PLAY_SELECTION,
			PLAY_AROUND_SELECTION,
			PLAY_AROUND_SELECTION_DLG,
			CLEAR_SELECTION,
			SELECTION_BOUNDARY,
			PIXEL_LEFT,
			PIXEL_RIGHT,
			PREVIOUS_FRAME,
			NEXT_FRAME,
			SECOND_LEFT,
			SECOND_RIGHT,
			PREVIOUS_SCROLLVIEW,
			NEXT_SCROLLVIEW,
			GO_TO_BEGIN,
			GO_TO_END,
			GOTO_DLG,
			SELECTION_MODE,
			LOOP_MODE,
			SHOW_TIMELINE,
			SHOW_INTERLINEAR,
			TIER_DEPENDENCIES,
			SHORTCUTS,
			ABOUT_DLG,
			SYNC_MODE,
			SET_PAL,
			SET_NTSC,
			SEARCH_DLG,
			SEARCH_MULTIPLE_DLG,
			STRUCTURED_SEARCH_MULTIPLE_DLG,
			SAVE,
			SAVE_AS,
			SAVE_AS_TEMPLATE,
			PRINT,
			PREVIEW,
			PAGESETUP,
			PLAYBACK_RATE_TOGGLE,
			PLAYBACK_VOLUME_TOGGLE };

	/*    public ELANCommandFactory(JFrame fr, ViewerManager2 vm, ElanLayoutManager lm) {
	   commandActions = new Hashtable();
	   commandHistory = new CommandHistory(CommandHistory.historySize);
	   frame = fr;
	   viewerManager = vm;
	   layoutManager = lm;
	   }
	 */
	
	static {
		languages.put(CATALAN, ElanLocale.CATALAN);
		languages.put(DUTCH, ElanLocale.DUTCH);
		languages.put(ENGLISH, ElanLocale.ENGLISH);
		languages.put(SPANISH, ElanLocale.SPANISH);
		languages.put(SWEDISH, ElanLocale.SWEDISH);
		languages.put(GERMAN, ElanLocale.GERMAN);
		languages.put(PORTUGUESE, ElanLocale.PORTUGUESE);
		languages.put(FRENCH, ElanLocale.FRENCH);
	}
	
	public static void addDocument(JFrame fr, ViewerManager2 vm, ElanLayoutManager lm) {
		Transcription t = vm.getTranscription();

		if (rootFrameHash.get(t) == null) {
			rootFrameHash.put(t, fr);
		}

		if (viewerManagerHash.get(t) == null) {
			viewerManagerHash.put(t, vm);
		}

		if (layoutManagerHash.get(t) == null) {
			layoutManagerHash.put(t, lm);
		}
	}

	/**
	 * DOCUMENT ME!
	 *
	 * @param vm DOCUMENT ME!
	 */
	public static void removeDocument(ViewerManager2 vm) {
		if (vm != null) {
			Transcription t = vm.getTranscription();

			commandActionHash.remove(t);
			undoCAHash.remove(t);
			redoCAHash.remove(t);
			commandHistoryHash.remove(t);
			viewerManagerHash.remove(t);
			layoutManagerHash.remove(t);
			rootFrameHash.remove(t);
			trackManagerHash.remove(t);
		}
	}

	/**
	 * DOCUMENT ME!
	 *
	 * @param forTranscription DOCUMENT ME!
	 *
	 * @return DOCUMENT ME!
	 */
	public static JFrame getRootFrame(Transcription forTranscription) {
		return (JFrame) (rootFrameHash.get(forTranscription));
	}

	// TEST METHOD FOR DEALING WITH JXTA MESSAGES

	/*    public static CommandAction getCommandAction(String transcriptionID, String caName) {
	   CommandAction ca = null;
	
	   if (transcriptionID.equals("fake")) {
	       Transcription t = null;
	
	       Set keySet = viewerManagerHash.keySet();
	
	       Iterator iter = keySet.iterator();
	       while (iter.hasNext()) {
	           t = (Transcription) iter.next();
	       }
	
	       if (t != null) {
	           ca = getCommandAction(t, caName);
	       } else {
	           System.out.println("no transcription found for id: " + transcriptionID);
	       }
	   }
	   return ca;
	   }
	 */
	public static ViewerManager2 getViewerManager(Transcription forTranscription) {
		return (ViewerManager2) (viewerManagerHash.get(forTranscription));
	}

	/**
	 * DOCUMENT ME!
	 *
	 * @param forTranscription DOCUMENT ME!
	 *
	 * @return DOCUMENT ME!
	 */
	public static ElanLayoutManager getLayoutManager(Transcription forTranscription) {
		return (ElanLayoutManager) (layoutManagerHash.get(forTranscription));
	}

	/**
	 * Creation of the a track manager is postponed until it is necessary: when at least 
	 * one time series source has been added.
	 * 
	 * @param forTranscription the document / transcription
	 * @param trackManager the manager for tracks and track sources
	 */
	public static void addTrackManager(Transcription forTranscription, TSTrackManager trackManager) {
		if (forTranscription != null && trackManager != null) {
			trackManagerHash.put(forTranscription, trackManager);		
		}
	}
	
	/**
	 * Returns the time series track manager for the transcription.
	 * 
	 * @param forTranscription the transcription
	 * @return the track manager or null
	 */
	public static TSTrackManager getTrackManager(Transcription forTranscription) {
		return (TSTrackManager) trackManagerHash.get(forTranscription);
	}

	/**
	 * DOCUMENT ME!
	 *
	 * @param tr DOCUMENT ME!
	 * @param caName DOCUMENT ME!
	 *
	 * @return DOCUMENT ME!
	 */
	public static CommandAction getCommandAction(Transcription tr, String caName) {
		CommandAction ca = null;

		if (commandActionHash.get(tr) == null) {
			commandActionHash.put(tr, new Hashtable());
		}

		if (commandHistoryHash.get(tr) == null) {
			commandHistoryHash.put(tr, new CommandHistory(CommandHistory.historySize));
		}

		ViewerManager2 viewerManager = (ViewerManager2) viewerManagerHash.get(tr);
		ElanLayoutManager layoutManager = (ElanLayoutManager) layoutManagerHash.get(tr);

		if (caName.equals(SET_TIER_NAME)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SET_TIER_NAME));

			if (ca == null) {
				ca = new SetTierNameCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SET_TIER_NAME, ca);
			}
		}
		else if (caName.equals(ADD_TIER_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(ADD_TIER_DLG));

			if (ca == null) {
				ca = new AddTierDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(ADD_TIER_DLG, ca);
			}
		}
		else if (caName.equals(CHANGE_TIER_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(CHANGE_TIER_DLG));

			if (ca == null) {
				ca = new ChangeTierDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(CHANGE_TIER_DLG, ca);
			}
		}
		else if (caName.equals(DELETE_TIER_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(DELETE_TIER_DLG));

			if (ca == null) {
				ca = new DeleteTierDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(DELETE_TIER_DLG, ca);
			}
		}
		else if (caName.equals(ADD_TYPE_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(ADD_TYPE_DLG));

			if (ca == null) {
				ca = new AddLingTypeDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(ADD_TYPE_DLG, ca);
			}
		}
		else if (caName.equals(CHANGE_TYPE_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(CHANGE_TYPE_DLG));

			if (ca == null) {
				ca = new ChangeLingTypeDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(CHANGE_TYPE_DLG, ca);
			}
		}
		else if (caName.equals(DELETE_TYPE_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(DELETE_TYPE_DLG));

			if (ca == null) {
				ca = new DeleteLingTypeDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(DELETE_TYPE_DLG, ca);
			}
		}
		else if (caName.equals(EDIT_CV_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(EDIT_CV_DLG));

			if (ca == null) {
				ca = new EditCVDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(EDIT_CV_DLG, ca);
			}
		}
		else if (caName.equals(NEW_ANNOTATION)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(NEW_ANNOTATION));

			if (ca == null) {
				ca = new NewAnnotationCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(NEW_ANNOTATION, ca);
			}
		}
		else if (caName.equals(NEW_ANNOTATION_BEFORE)) {
			ca =
				(CommandAction) (((Hashtable) commandActionHash.get(tr))
					.get(NEW_ANNOTATION_BEFORE));

			if (ca == null) {
				ca = new AnnotationBeforeCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(NEW_ANNOTATION_BEFORE, ca);
			}
		}
		else if (caName.equals(NEW_ANNOTATION_AFTER)) {
			ca =
				(CommandAction) (((Hashtable) commandActionHash.get(tr)).get(NEW_ANNOTATION_AFTER));

			if (ca == null) {
				ca = new AnnotationAfterCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(NEW_ANNOTATION_AFTER, ca);
			}
		}
		else if (caName.equals(MODIFY_ANNOTATION)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(MODIFY_ANNOTATION));

			if (ca == null) {
				ca = new ModifyAnnotationCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(MODIFY_ANNOTATION, ca);
			}
		}
		else if (caName.equals(DELETE_ANNOTATION)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(DELETE_ANNOTATION));

			if (ca == null) {
				ca = new DeleteAnnotationCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(DELETE_ANNOTATION, ca);
			}
		}
		else if (caName.equals(MODIFY_ANNOTATION_TIME)) {
			ca =
				(CommandAction) (((Hashtable) commandActionHash.get(tr))
					.get(MODIFY_ANNOTATION_TIME));

			if (ca == null) {
				ca = new ModifyAnnotationTimeCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(MODIFY_ANNOTATION_TIME, ca);
			}
		}
		else if (caName == MODIFY_GRAPHIC_ANNOTATION) {
			ca =
				(CommandAction) (((Hashtable) commandActionHash.get(tr))
					.get(MODIFY_GRAPHIC_ANNOTATION));

			if (ca == null) {
				ca = new ModifyGraphicAnnotationCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(MODIFY_GRAPHIC_ANNOTATION, ca);
			}
		}
		else if (caName == SHIFT_ALL_DLG) {
			ca = 
				(CommandAction) (((Hashtable) commandActionHash.get(tr))
								.get(SHIFT_ALL_DLG));
			if (ca == null) {
				ca = new ShiftAllAnnotationsDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SHIFT_ALL_DLG, ca);
			}
		}
		else if (caName == TOKENIZE_DLG) {
			ca =
				(CommandAction) (((Hashtable) commandActionHash.get(tr))
					.get(TOKENIZE_DLG));

			if (ca == null) {
				ca = new TokenizeDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(TOKENIZE_DLG, ca);
			}
		}		
		else if (caName.equals(SHOW_TIMELINE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SHOW_TIMELINE));

			if (ca == null) {
				ca = new ShowTimelineCA(viewerManager, layoutManager);
				((Hashtable) commandActionHash.get(tr)).put(SHOW_TIMELINE, ca);
			}
		}
		else if (caName.equals(SHOW_INTERLINEAR)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SHOW_INTERLINEAR));

			if (ca == null) {
				ca = new ShowInterlinearCA(viewerManager, layoutManager);
				((Hashtable) commandActionHash.get(tr)).put(SHOW_INTERLINEAR, ca);
			}
		}
		else if (caName.equals(SEARCH_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SEARCH_DLG));

			if (ca == null) {
				ca = new SearchDialogCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SEARCH_DLG, ca);
			}
		}
		else if (caName.equals(SEARCH_MULTIPLE_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SEARCH_MULTIPLE_DLG));

			if (ca == null) {
				ca = new SearchMultipleDialogCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SEARCH_MULTIPLE_DLG, ca);
			}
		}		    
		else if (caName.equals(GOTO_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(GOTO_DLG));

			if (ca == null) {
				ca = new GoToDialogCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(GOTO_DLG, ca);
			}
		}
		else if (caName.equals(TIER_DEPENDENCIES)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(TIER_DEPENDENCIES));

			if (ca == null) {
				ca = new TierDependenciesCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(TIER_DEPENDENCIES, ca);
			}
		}
		else if (caName.equals(SHORTCUTS)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SHORTCUTS));

			if (ca == null) {
				ca = new ShortcutsCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SHORTCUTS, ca);
			}
		}
		else if (caName.equals(ABOUT_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(ABOUT_DLG));

			if (ca == null) {
				ca = new AboutDialogCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(ABOUT_DLG, ca);
			}
		}
		else if (caName.equals(SYNC_MODE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SYNC_MODE));

			if (ca == null) {
				ca = new SyncModeCA(viewerManager, layoutManager);
				((Hashtable) commandActionHash.get(tr)).put(SYNC_MODE, ca);
			}
		}
		else if (caName.equals(ANNOTATION_MODE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(ANNOTATION_MODE));

			if (ca == null) {
				ca = new AnnotationModeCA(viewerManager, layoutManager);
				((Hashtable) commandActionHash.get(tr)).put(ANNOTATION_MODE, ca);
			}
		}
		else if (caName.equals(SELECTION_MODE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SELECTION_MODE));

			if (ca == null) {
				ca = new SelectionModeCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SELECTION_MODE, ca);
			}
		}
		else if (caName.equals(LOOP_MODE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(LOOP_MODE));

			if (ca == null) {
				ca = new LoopModeCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(LOOP_MODE, ca);
			}
		}
		else if (caName.equals(BULLDOZER_MODE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(BULLDOZER_MODE));

			if (ca == null) {
				ca = new BulldozerModeCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(BULLDOZER_MODE, ca);
			}
		}
		else if (caName.equals(TIMEPROP_NORMAL)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(TIMEPROP_NORMAL));

			if (ca == null) {
				ca = new NormalTimePropCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(TIMEPROP_NORMAL, ca);
			}
		}
		else if (caName.equals(SHIFT_MODE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SHIFT_MODE));

			if (ca == null) {
				ca = new ShiftModeCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SHIFT_MODE, ca);
			}
		}
		else if (caName.equals(SET_PAL)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SET_PAL));

			if (ca == null) {
				ca = new SetPALCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SET_PAL, ca);
			}
		}
		else if (caName.equals(SET_NTSC)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SET_NTSC));

			if (ca == null) {
				ca = new SetNTSCCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SET_NTSC, ca);
			}
		}
		else if (caName.equals(CLEAR_SELECTION)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(CLEAR_SELECTION));

			if (ca == null) {
				ca = new ClearSelectionCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(CLEAR_SELECTION, ca);
			}
		}
		else if (caName.equals(PLAY_SELECTION)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PLAY_SELECTION));

			if (ca == null) {
				ca = new PlaySelectionCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PLAY_SELECTION, ca);
			}
		}
		else if (caName.equals(PLAY_AROUND_SELECTION)) {
			ca =
				(CommandAction) (((Hashtable) commandActionHash.get(tr))
					.get(PLAY_AROUND_SELECTION));

			if (ca == null) {
				ca = new PlayAroundSelectionCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PLAY_AROUND_SELECTION, ca);
			}
		}
		else if (caName.equals(PLAY_AROUND_SELECTION_DLG)) {
			ca =
				(CommandAction) (((Hashtable) commandActionHash.get(tr))
					.get(PLAY_AROUND_SELECTION_DLG));

			if (ca == null) {
				ca = new SetPlayAroundSelectionDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PLAY_AROUND_SELECTION_DLG, ca);
			}
		}
		else if (caName.equals(NEXT_FRAME)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(NEXT_FRAME));

			if (ca == null) {
				ca = new NextFrameCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(NEXT_FRAME, ca);
			}
		}
		else if (caName.equals(PREVIOUS_FRAME)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PREVIOUS_FRAME));

			if (ca == null) {
				ca = new PreviousFrameCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PREVIOUS_FRAME, ca);
			}
		}
		else if (caName.equals(PLAY_PAUSE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PLAY_PAUSE));

			if (ca == null) {
				ca = new PlayPauseCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PLAY_PAUSE, ca);
			}
		}
		else if (caName.equals(GO_TO_BEGIN)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(GO_TO_BEGIN));

			if (ca == null) {
				ca = new GoToBeginCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(GO_TO_BEGIN, ca);
			}
		}
		else if (caName.equals(GO_TO_END)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(GO_TO_END));

			if (ca == null) {
				ca = new GoToEndCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(GO_TO_END, ca);
			}
		}
		else if (caName.equals(PREVIOUS_SCROLLVIEW)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PREVIOUS_SCROLLVIEW));

			if (ca == null) {
				ca = new PreviousScrollViewCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PREVIOUS_SCROLLVIEW, ca);
			}
		}
		else if (caName.equals(NEXT_SCROLLVIEW)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(NEXT_SCROLLVIEW));

			if (ca == null) {
				ca = new NextScrollViewCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(NEXT_SCROLLVIEW, ca);
			}
		}
		else if (caName.equals(PIXEL_LEFT)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PIXEL_LEFT));

			if (ca == null) {
				ca = new PixelLeftCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PIXEL_LEFT, ca);
			}
		}
		else if (caName.equals(PIXEL_RIGHT)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PIXEL_RIGHT));

			if (ca == null) {
				ca = new PixelRightCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PIXEL_RIGHT, ca);
			}
		}
		else if (caName.equals(SECOND_LEFT)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SECOND_LEFT));

			if (ca == null) {
				ca = new SecondLeftCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SECOND_LEFT, ca);
			}
		}
		else if (caName.equals(SECOND_RIGHT)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SECOND_RIGHT));

			if (ca == null) {
				ca = new SecondRightCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SECOND_RIGHT, ca);
			}
		}
		else if (caName.equals(SELECTION_BOUNDARY)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SELECTION_BOUNDARY));

			if (ca == null) {
				ca = new ActiveSelectionBoundaryCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SELECTION_BOUNDARY, ca);
			}
		}
		else if (caName.equals(PREVIOUS_ANNOTATION)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PREVIOUS_ANNOTATION));

			if (ca == null) {
				ca = new PreviousAnnotationCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PREVIOUS_ANNOTATION, ca);
			}
		}
		else if (caName.equals(NEXT_ANNOTATION)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(NEXT_ANNOTATION));

			if (ca == null) {
				ca = new NextAnnotationCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(NEXT_ANNOTATION, ca);
			}
		}
		else if (caName.equals(ANNOTATION_UP)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(ANNOTATION_UP));

			if (ca == null) {
				ca = new AnnotationUpCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(ANNOTATION_UP, ca);
			}
		}
		else if (caName.equals(ANNOTATION_DOWN)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(ANNOTATION_DOWN));

			if (ca == null) {
				ca = new AnnotationDownCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(ANNOTATION_DOWN, ca);
			}
		}
		else if (caName.equals(SAVE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SAVE));

			if (ca == null) {
				ca = new SaveCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SAVE, ca);
			}
		}
		else if (caName.equals(SAVE_AS)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SAVE_AS));

			if (ca == null) {
				ca = new SaveAsCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SAVE_AS, ca);
			}
		}
		else if (caName.equals(SAVE_AS_TEMPLATE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SAVE_AS_TEMPLATE));

			if (ca == null) {
				ca = new SaveAsTemplateCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SAVE_AS_TEMPLATE, ca);
			}
		}
		else if (caName.equals(SAVE_SELECTION_AS_EAF)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SAVE_SELECTION_AS_EAF));

			if (ca == null) {
				ca = new SaveSelectionAsEafCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SAVE_SELECTION_AS_EAF, ca);
			}
		}
		else if (caName.equals(BACKUP)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(BACKUP));

			if (ca == null) {
				ca = new BackupCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(BACKUP, ca);
			}
		}
		else if (caName.equals(BACKUP_NEVER)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(BACKUP_NEVER));

			if (ca == null) {
				ca = new BackupNeverCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(BACKUP_NEVER, ca);
			}
		}
		else if (caName.equals(BACKUP_5)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(BACKUP_5));

			if (ca == null) {
				ca = new Backup5CA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(BACKUP_5, ca);
			}
		}
		else if (caName.equals(BACKUP_10)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(BACKUP_10));

			if (ca == null) {
				ca = new Backup10CA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(BACKUP_10, ca);
			}
		}
		else if (caName.equals(BACKUP_20)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(BACKUP_20));

			if (ca == null) {
				ca = new Backup20CA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(BACKUP_20, ca);
			}
		}
		else if (caName.equals(BACKUP_30)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(BACKUP_30));

			if (ca == null) {
				ca = new Backup30CA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(BACKUP_30, ca);
			}
		}
		else if (caName.equals(PRINT)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PRINT));

			if (ca == null) {
				ca = new PrintCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PRINT, ca);
			}
		}
		else if (caName.equals(PREVIEW)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PREVIEW));

			if (ca == null) {
				ca = new PrintPreviewCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PREVIEW, ca);
			}
		}
		else if (caName.equals(PAGESETUP)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PAGESETUP));

			if (ca == null) {
				ca = new PageSetupCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PAGESETUP, ca);
			}
		}
		else if (caName.equals(EXPORT_TAB)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(EXPORT_TAB));

			if (ca == null) {
				ca = new ExportTabDelDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(EXPORT_TAB, ca);
			}
		}
		else if (caName.equals(EXPORT_TEX)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(EXPORT_TEX));

			if (ca == null) {
				ca = new ExportTeXDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(EXPORT_TEX, ca);
			}
		}
		else if (caName.equals(EXPORT_TIGER)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(EXPORT_TIGER));

			if (ca == null) {
				ca = new ExportTigerDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(EXPORT_TIGER, ca);
			}
		}
		else if (caName.equals(EXPORT_QT_SUB)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(EXPORT_QT_SUB));

			if (ca == null) {
				ca = new ExportQtSubCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(EXPORT_QT_SUB, ca);
			}
		}
		else if (caName.equals(EXPORT_SMIL)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(EXPORT_SMIL));

			if (ca == null) {
				ca = new ExportSmilCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(EXPORT_SMIL, ca);
			}
		}
		else if (caName.equals(EXPORT_SHOEBOX)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(EXPORT_SHOEBOX));

			if (ca == null) {
				ca = new ExportShoeboxCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(EXPORT_SHOEBOX, ca);
			}
		}
		else if (caName.equals(EXPORT_CHAT)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(EXPORT_CHAT));

			if (ca == null) {
				ca = new ExportCHATCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(EXPORT_CHAT, ca);
			}
		}
		else if (caName.equals(EXPORT_MEDIA)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(EXPORT_MEDIA));

			if (ca == null) {
				ca = new ExportMediaCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(EXPORT_MEDIA, ca);
			}
		}
		else if (caName.equals(EXPORT_IMAGE_FROM_WINDOW)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(EXPORT_IMAGE_FROM_WINDOW ));

			if (ca == null) {
				ca = new ExportImageFromWindowCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(EXPORT_IMAGE_FROM_WINDOW, ca);
			}
		}
		else if (caName.equals(ENGLISH)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(ENGLISH));

			if (ca == null) {
				ca = new SetLocaleCA(viewerManager, ENGLISH);
				((Hashtable) commandActionHash.get(tr)).put(ENGLISH, ca);
			}
		}
		else if (caName.equals(DUTCH)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(DUTCH));

			if (ca == null) {
				ca = new SetLocaleCA(viewerManager, DUTCH);
				((Hashtable) commandActionHash.get(tr)).put(DUTCH, ca);
			}
		}
		else if (caName.equals(CATALAN)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(CATALAN));

			if (ca == null) {
				ca = new SetLocaleCA(viewerManager, CATALAN);
				((Hashtable) commandActionHash.get(tr)).put(CATALAN, ca);
			}
		}
		else if (caName.equals(SPANISH)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SPANISH));

			if (ca == null) {
				ca = new SetLocaleCA(viewerManager, SPANISH);
				((Hashtable) commandActionHash.get(tr)).put(SPANISH, ca);
			}
		}
		else if (caName.equals(SWEDISH)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SWEDISH));

			if (ca == null) {
				ca = new SetLocaleCA(viewerManager, SWEDISH);
				((Hashtable) commandActionHash.get(tr)).put(SWEDISH, ca);
			}
		}
		else if (caName.equals(GERMAN)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(GERMAN));

			if (ca == null) {
				ca = new SetLocaleCA(viewerManager, GERMAN);
				((Hashtable) commandActionHash.get(tr)).put(GERMAN, ca);
			}
		}
		else if (caName.equals(PORTUGUESE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PORTUGUESE));

			if (ca == null) {
				ca = new SetLocaleCA(viewerManager, PORTUGUESE);
				((Hashtable) commandActionHash.get(tr)).put(PORTUGUESE, ca);
			}
		}
		else if (caName.equals(FRENCH)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(FRENCH));

			if (ca == null) {
				ca = new SetLocaleCA(viewerManager, FRENCH);
				((Hashtable) commandActionHash.get(tr)).put(FRENCH, ca);
			}
		}
		else if (caName.equals(PUBLISH_DOC)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PUBLISH_DOC));

			if (ca == null) {
				ca = new PublishDocumentCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PUBLISH_DOC, ca);
			}
		}
		else if (caName.equals(DISCOVER_DOC)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(DISCOVER_DOC));

			if (ca == null) {
				ca = new DiscoverDocumentCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(DISCOVER_DOC, ca);
			}
		}
		else if (caName.equals(LINKED_FILES_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(LINKED_FILES_DLG));

			if (ca == null) {
				ca = new LinkedFilesDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(LINKED_FILES_DLG, ca);
			}
		}
		else if (caName.equals(PLAYBACK_TOGGLE_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PLAYBACK_TOGGLE_DLG));
		
			if (ca == null) {
				ca = new SetPlaybackToggelDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PLAYBACK_TOGGLE_DLG, ca);
			}
		}
		else if (caName.equals(PLAYBACK_RATE_TOGGLE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PLAYBACK_RATE_TOGGLE));
		
			if (ca == null) {
				ca = new PlaybackRateToggleCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PLAYBACK_RATE_TOGGLE, ca);
			}
		}
		else if (caName.equals(PLAYBACK_VOLUME_TOGGLE)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PLAYBACK_VOLUME_TOGGLE));
		
			if (ca == null) {
				ca = new PlaybackVolumeToggleCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PLAYBACK_VOLUME_TOGGLE, ca);
			}
		}
		else if (caName.equals(SEGMENTATION_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SEGMENTATION_DLG));
		
			if (ca == null) {
				ca = new SegmentationDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(SEGMENTATION_DLG, ca);
			}
		}
		else if (caName.equals(FILTER_TIER_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(FILTER_TIER_DLG));
		
			if (ca == null) {
				ca = new FilterTierDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(FILTER_TIER_DLG, ca);
			}
		}
		else if (caName.equals(EXPORT_TRAD_TRANSCRIPT)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(EXPORT_TRAD_TRANSCRIPT));
		
			if (ca == null) {
				ca = new ExportTradTranscriptDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(EXPORT_TRAD_TRANSCRIPT, ca);
			}
		}
		else if (caName.equals(EXPORT_INTERLINEAR)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(EXPORT_INTERLINEAR));
		
			if (ca == null) {
				ca = new ExportInterlinearDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(EXPORT_INTERLINEAR, ca);
			}
		}
		else if (caName.equals(REPARENT_TIER_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(REPARENT_TIER_DLG));
		
			if (ca == null) {
				ca = new ReparentTierDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(REPARENT_TIER_DLG, ca);
			}
		}
		else if (caName.equals(COPY_TIER_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(COPY_TIER_DLG));
		
			if (ca == null) {
				ca = new CopyTierDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(COPY_TIER_DLG, ca);
			}
		}
		else if (caName.equals(NEXT_ACTIVE_TIER)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(NEXT_ACTIVE_TIER));
		
			if (ca == null) {
				ca = new NextActiveTierCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(NEXT_ACTIVE_TIER, ca);
			}
		}
		else if (caName.equals(PREVIOUS_ACTIVE_TIER)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(PREVIOUS_ACTIVE_TIER));
		
			if (ca == null) {
				ca = new PreviousActiveTierCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(PREVIOUS_ACTIVE_TIER, ca);
			}
		}
		else if (caName.equals(MERGE_TRANSCRIPTIONS)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(MERGE_TRANSCRIPTIONS));
		
			if (ca == null) {
				ca = new MergeTranscriptionDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(MERGE_TRANSCRIPTIONS, ca);
			}
		}	
		else if (caName.equals(SYNTAX_VIEWER)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(SYNTAX_VIEWER));
		
			if (ca == null) {				
					if(SyntaxViewerCommand.isEnabled()){
						ca = new SyntaxViewerCA(viewerManager);
						((Hashtable) commandActionHash.get(tr)).put(SYNTAX_VIEWER, ca);
					}				
			}
		}
		else if (caName.equals(STRUCTURED_SEARCH_MULTIPLE_DLG)) {
			ca = (CommandAction) (((Hashtable) commandActionHash.get(tr)).get(STRUCTURED_SEARCH_MULTIPLE_DLG));
		
			if (ca == null) {				
				ca = new StructuredSearchMultipleDlgCA(viewerManager);
				((Hashtable) commandActionHash.get(tr)).put(STRUCTURED_SEARCH_MULTIPLE_DLG, ca);				
			}
		}
		
					
		return ca;
	}

	/**
	 * DOCUMENT ME!
	 *
	 * @param tr DOCUMENT ME!
	 * @param cName DOCUMENT ME!
	 *
	 * @return DOCUMENT ME!
	 */
	public static Command createCommand(Transcription tr, String cName) {
		Command c = null;

		if (cName.equals(SET_TIER_NAME)) {
			c = new SetTierNameCommand(cName);
		}

		if (cName.equals(EDIT_TIER)) {
			c = new EditTierDlgCommand(cName);
		}
		else if (cName.equals(CHANGE_TIER)) {
			c = new ChangeTierAttributesCommand(cName);
		}
		else if (cName.equals(ADD_TIER_DLG)) {
			c = new AddTierDlgCommand(cName);
		}
		else if (cName.equals(ADD_TIER)) {
			c = new AddTierCommand(cName);
		}
		else if (cName.equals(DELETE_TIER)) {
			c = new DeleteTierCommand(cName);
		}
		else if (cName.equals(IMPORT_TIERS)) {
			c = new ImportTiersCommand(cName);
		}
		else if (cName.equals(EDIT_TYPE)) {
			c = new EditLingTypeDlgCommand(cName);
		}
		else if (cName.equals(ADD_TYPE)) {
			c = new AddTypeCommand(cName);
		}
		else if (cName.equals(CHANGE_TYPE)) {
			c = new ChangeTypeCommand(cName);
		}
		else if (cName.equals(DELETE_TYPE)) {
			c = new DeleteTypeCommand(cName);
		}
		else if (cName.equals(EDIT_CV_DLG)) {
			c = new EditCVDlgCommand(cName);
		}
		else if (cName.equals(ADD_CV)) {
			c = new AddCVCommand(cName);
		}
		else if (cName.equals(CHANGE_CV)) {
			c = new ChangeCVCommand(cName);
		}
		else if (cName.equals(DELETE_CV)) {
			c = new DeleteCVCommand(cName);
		}
		else if (cName.equals(REPLACE_CV)) {
			c = new ReplaceCVCommand(cName);
		}
		else if (cName.equals(ADD_CV_ENTRY)) {
			c = new AddCVEntryCommand(cName);
		}
		else if (cName.equals(CHANGE_CV_ENTRY)) {
			c = new ChangeCVEntryCommand(cName);
		}
		else if (cName.equals(DELETE_CV_ENTRY)) {
			c = new DeleteCVEntryCommand(cName);
		}
		else if (cName.equals(MOVE_CV_ENTRIES)) {
			c = new MoveCVEntriesCommand(cName);
		}
		else if (cName.equals(REPLACE_CV_ENTRIES)) {
			c = new ReplaceCVEntriesCommand(cName);
		}
		else if (cName.equals(NEW_ANNOTATION)) {
			c = new NewAnnotationCommand(cName);
		}
		else if (cName.equals(NEW_ANNOTATION_BEFORE)) {
			c = new AnnotationBeforeCommand(cName);
		}
		else if (cName.equals(NEW_ANNOTATION_AFTER)) {
			c = new AnnotationAfterCommand(cName);
		}
		else if (cName.equals(MODIFY_ANNOTATION_DLG)) {
			c = new ModifyAnnotationDlgCommand(cName);
		}
		else if (cName.equals(MODIFY_ANNOTATION)) {
			c = new ModifyAnnotationCommand(cName);
		}
		else if (cName.equals(DELETE_ANNOTATION)) {
			c = new DeleteAnnotationCommand(cName);
		}
		else if (cName.equals(MODIFY_ANNOTATION_TIME)) {
			c = new ModifyAnnotationTimeCommand(cName);
		}
		else if (cName == MODIFY_GRAPHIC_ANNOTATION_DLG) {
			c = new ModifyGraphicAnnotationDlgCommand(cName);
		}
		else if (cName == MODIFY_GRAPHIC_ANNOTATION) {
			c = new ModifyGraphicAnnotationCommand(cName);
		}
		else if (cName == SHIFT_ALL_ANNOTATIONS) {
			c = new ShiftAllAnnotationsCommand(cName);
		}
		else if (cName == SHIFT_ALL_DLG) {
			c = new ShiftAllAnnotationsDlgCommand(cName);
		}
		else if (cName == TOKENIZE_DLG) {
			c = new TokenizeDlgCommand(cName);
		}
		else if (cName == TOKENIZE_TIER) {
			c = new TokenizeCommand(cName);
		}
		else if (cName.equals(SHOW_MULTITIER_VIEWER)) {
			c = new ShowMultitierViewerCommand(cName);
		}
		else if (cName.equals(SEARCH_DLG)) {
			c = new SearchDialogCommand(cName);
		}
		else if (cName.equals(SEARCH_MULTIPLE_DLG)) {
			c = new SearchMultipleDialogCommand(cName);
		}
		else if(cName.equals(REPLACE)){
		    c = new ReplaceCommand(cName);
		}
		else if (cName.equals(GOTO_DLG)) {
			c = new GoToDialogCommand(cName);
		}
		else if (cName.equals(TIER_DEPENDENCIES)) {
			c = new TierDependenciesCommand(cName);
		}
		else if (cName.equals(SHORTCUTS)) {
			c = new ShortcutsCommand(cName);
		}
		else if (cName.equals(ABOUT_DLG)) {
			c = new AboutDialogCommand(cName);
		}
		else if (cName.equals(SYNC_MODE)) {
			c = new SyncModeCommand(cName);
		}
		else if (cName.equals(ANNOTATION_MODE)) {
			c = new AnnotationModeCommand(cName);
		}
		else if (cName.equals(SELECTION_MODE)) {
			c = new SelectionModeCommand(cName);
		}
		else if (cName.equals(LOOP_MODE)) {
			c = new LoopModeCommand(cName);
		}
		else if (cName.equals(BULLDOZER_MODE)) {
			c = new BulldozerModeCommand(cName);
		}
		else if (cName.equals(TIMEPROP_NORMAL)) {
			c = new NormalTimePropCommand(cName);
		}
		else if (cName.equals(SHIFT_MODE)) {
			c = new ShiftModeCommand(cName);
		}
		else if (cName.equals(SET_PAL)) {
			c = new SetMsPerFrameCommand(cName);
		}
		else if (cName.equals(SET_NTSC)) {
			c = new SetMsPerFrameCommand(cName);
		}
		else if (cName.equals(CLEAR_SELECTION)) {
			c = new ClearSelectionCommand(cName);
		}
		else if (cName.equals(PLAY_SELECTION)) {
			c = new PlaySelectionCommand(cName);
		}
		else if (cName.equals(PLAY_AROUND_SELECTION_DLG)) {
			c = new SetPlayAroundSelectionDlgCommand(cName);
		}
		else if (cName.equals(PLAY_AROUND_SELECTION)) {
			c = new SetPlayAroundSelectionCommand(cName);
		}
		else if (cName.equals(NEXT_FRAME)) {
			c = new NextFrameCommand(cName);
		}
		else if (cName.equals(PREVIOUS_FRAME)) {
			c = new PreviousFrameCommand(cName);
		}
		else if (cName.equals(PLAY_PAUSE)) {
			c = new PlayPauseCommand(cName);
		}
		else if (cName.equals(GO_TO_BEGIN)) {
			c = new GoToBeginCommand(cName);
		}
		else if (cName.equals(GO_TO_END)) {
			c = new GoToEndCommand(cName);
		}
		else if (cName.equals(PREVIOUS_SCROLLVIEW)) {
			c = new PreviousScrollViewCommand(cName);
		}
		else if (cName.equals(NEXT_SCROLLVIEW)) {
			c = new NextScrollViewCommand(cName);
		}
		else if (cName.equals(PIXEL_LEFT)) {
			c = new PixelLeftCommand(cName);
		}
		else if (cName.equals(PIXEL_RIGHT)) {
			c = new PixelRightCommand(cName);
		}
		else if (cName.equals(SECOND_LEFT)) {
			c = new SecondLeftCommand(cName);
		}
		else if (cName.equals(SECOND_RIGHT)) {
			c = new SecondRightCommand(cName);
		}
		else if (cName.equals(SELECTION_BOUNDARY)) {
			c = new ActiveSelectionBoundaryCommand(cName);
		}
		else if (cName.equals(ACTIVE_ANNOTATION)) {
			c = new ActiveAnnotationCommand(cName);
		}
		else if (cName.equals(STORE)) {
			c = new StoreCommand(cName);
		}
		else if (cName.equals(BACKUP)) {
			c = new SetBackupDelayCommand(cName);
		}
		else if (cName.equals(PRINT)) {
			c = new PrintCommand(cName);
		}
		else if (cName.equals(PREVIEW)) {
			c = new PrintPreviewCommand(cName);
		}
		else if (cName.equals(PAGESETUP)) {
			c = new PageSetupCommand(cName);
		}
		else if (cName.equals(EXPORT_TAB)) {
			c = new ExportTabDelDlgCommand(cName);
		}
		else if (cName.equals(EXPORT_TEX)) {
			c = new ExportTeXDlgCommand(cName);
		}
		else if (cName.equals(EXPORT_TIGER)) {
			c = new ExportTigerDlgCommand(cName);
		}
		else if (cName.equals(EXPORT_SMIL)){
			c = new ExportSmilCommand(cName);
		}		
		else if (cName.equals(EXPORT_QT_SUB)){
			c = new ExportQtSubCommand(cName);
		}		
		else if (cName.equals(EXPORT_MEDIA)){
			c = new ExportMediaCommand(cName);
		}
		else if (cName.equals(EXPORT_IMAGE_FROM_WINDOW)){
			c = new ExportImageFromWindowCommand(cName);
		}			
		else if (cName.equals(EXPORT_SHOEBOX)) {
			c = new ExportShoeboxCommand(cName);
		}
		else if (cName.equals(EXPORT_CHAT)) {
			c = new ExportCHATCommand(cName);
		}
		else if (cName.equals(SET_LOCALE)) {
			c = new SetLocaleCommand(cName);
		}
		else if (cName.equals(PUBLISH_DOC)) {
			c = new PublishDocumentCommand(cName);
		}
		else if (cName.equals(DISCOVER_DOC)) {
			c = new DiscoverDocumentCommand(cName);
		}
		else if (cName.equals(LINKED_FILES_DLG)) {
			c = new LinkedFilesDlgCommand(cName);
		}		
		else if (cName.equals(CHANGE_LINKED_FILES)) {
			c = new ChangeLinkedFilesCommand(cName);
		}
		else if (cName.equals(PLAYBACK_TOGGLE_DLG)) {
			c = new SetPlaybackToggleDlgCommand(cName);
		}
		else if (cName.equals(PLAYBACK_TOGGLE)) {
			c = new SetPlaybackToggleCommand(cName);
		}
		else if (cName.equals(PLAYBACK_RATE_TOGGLE)) {
			c = new PlaybackRateToggleCommand(cName);
		}
		else if (cName.equals(PLAYBACK_VOLUME_TOGGLE)) {
			c = new PlaybackVolumeToggleCommand(cName);
		}
		else if (cName.equals(SEGMENTATION_DLG)) {
			c = new SegmentationDlgCommand(cName);
		}
		else if (cName.equals(ADD_SEGMENTATION)) {
			c = new AddSegmentationCommand(cName);
		}
		else if (cName.equals(FILTER_TIER_DLG)) {
			c = new FilterTierDlgCommand(cName);
		}
		else if (cName.equals(FILTER_TIER)) {
			c = new FilterTierCommand(cName);
		}
		else if (cName.equals(EXPORT_TRAD_TRANSCRIPT)) {
			c = new ExportTradTranscriptDlgCommand(cName);
		}
		else if (cName.equals(EXPORT_INTERLINEAR)) {
			c = new ExportInterlinearDlgCommand(cName);
		}
		else if (cName.equals(REPARENT_TIER_DLG)) {
			c = new ReparentTierDlgCommand(cName);
		}
		else if (cName.equals(COPY_TIER_DLG)) {
			c = new CopyTierDlgCommand(cName);
		}
		else if (cName.equals(COPY_TIER) || cName.equals(REPARENT_TIER)) {
			c = new CopyTierCommand(cName);
		}
		else if (cName.equals(SAVE_SELECTION_AS_EAF)) {
			c = new SaveSelectionAsEafCommand(cName);
		}
		else if (cName.equals(ACTIVE_TIER)) {
			c = new ActiveTierCommand(cName);
		}
		else if (cName.equals(MERGE_TRANSCRIPTIONS)) {
			c = new MergeTranscriptionsDlgCommand(cName);
		}
		else if (cName.equals(SYNTAX_VIEWER)){
			c = new SyntaxViewerCommand(cName);
		}
		else if (cName.equals(STRUCTURED_SEARCH_MULTIPLE_DLG)){
			c = new StructuredSearchMultipleDlgCommand(cName);
		}
		else if (cName.equals(EXT_TRACK_DATA)) {
			c = new ExtractTrackDataCommand(cName);
		}
				
		if ((c != null) && (c instanceof UndoableCommand)) {
		    ((CommandHistory) commandHistoryHash.get(tr)).addCommand(c);
		}

		return c;
	}

	/**
	 * DOCUMENT ME!
	 *
	 * @param tr DOCUMENT ME!
	 *
	 * @return DOCUMENT ME!
	 */
	public static UndoCA getUndoCA(Transcription tr) {
		UndoCA undoCA = (UndoCA) undoCAHash.get(tr);

		if (undoCAHash.get(tr) == null) {
			undoCA =
				new UndoCA(
					((ViewerManager2) viewerManagerHash.get(tr)),
					((CommandHistory) commandHistoryHash.get(tr)));
			((CommandHistory) commandHistoryHash.get(tr)).setUndoCA(undoCA);

			undoCAHash.put(tr, undoCA);
		}

		return undoCA;
	}

	/**
	 * DOCUMENT ME!
	 *
	 * @param tr DOCUMENT ME!
	 *
	 * @return DOCUMENT ME!
	 */
	public static RedoCA getRedoCA(Transcription tr) {
		RedoCA redoCA = (RedoCA) redoCAHash.get(tr);

		if (redoCA == null) {
			redoCA =
				new RedoCA(
					((ViewerManager2) viewerManagerHash.get(tr)),
					((CommandHistory) commandHistoryHash.get(tr)));
			((CommandHistory) commandHistoryHash.get(tr)).setRedoCA(redoCA);

			redoCAHash.put(tr, redoCA);
		}

		return redoCA;
	}
	
	/**
	 * Returns the Locale for the specified key.
	 * 
	 * @param key a CommandAction language key
	 * @return the associated Locale, defaults to English
	 */
	public static Locale getLocaleForKey(Object key) {
		if (key != null) {
			Locale l = (Locale) languages.get(key);
			if (l != null) {
				return l;
			}
		}
		// default english
		return ElanLocale.ENGLISH;
	}

	/**
	 * Returns a Set view of the registered Locales.
	 * @return a Set view of the registered Locales
	 */
	public static Collection getLocales() {
	    return languages.values();
	}
	
	/**
	 * DOCUMENT ME!
	 *
	 * @param tr DOCUMENT ME!
	 *
	 * @return DOCUMENT ME!
	 */
	public static String[][] getShortCutText(Transcription tr) {
		Vector shortCuts = new Vector();
		Vector descriptions = new Vector();

		for (int i = 0; i < commandConstants.length; i++) {
			CommandAction ca = getCommandAction(tr, commandConstants[i]);
			KeyStroke acc = (KeyStroke) ca.getValue(Action.ACCELERATOR_KEY);

			if (acc != null) {
				String accString = convertAccKey(acc);
				String descString = (String) ca.getValue(Action.SHORT_DESCRIPTION);

				if (descString == null) {
					descString = "";
				}

				if (accString != null) {
					shortCuts.add(accString);
					descriptions.add(descString);
				}
			}
		}

		// add open, new, undo and redo manually
		String accString;
		String descString;
		accString = convertAccKey(KeyStroke.getKeyStroke(KeyEvent.VK_N, 
			Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
		descString = ElanLocale.getString("Menu.File.NewToolTip");

		if (accString != null) {
			shortCuts.add(accString);
			descriptions.add(descString);
		}

		accString = convertAccKey(KeyStroke.getKeyStroke(KeyEvent.VK_O, 
			Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
		descString = ElanLocale.getString("Menu.File.OpenToolTip");

		if (accString != null) {
			shortCuts.add(accString);
			descriptions.add(descString);
		}

		CommandAction ca = getUndoCA(tr);
		accString = convertAccKey((KeyStroke) ca.getValue(Action.ACCELERATOR_KEY));
		//descString = (String) ca.getValue(Action.NAME);
		descString = ElanLocale.getString("Menu.Edit.Undo");

		if (accString != null) {
			shortCuts.add(accString);
			descriptions.add(descString);
		}

		ca = getRedoCA(tr);
		accString = convertAccKey((KeyStroke) ca.getValue(Action.ACCELERATOR_KEY));
		//descString = (String) ca.getValue(Action.NAME);
		descString = ElanLocale.getString("Menu.Edit.Redo");

		if (accString != null) {
			shortCuts.add(accString);
			descriptions.add(descString);
		}

		accString = convertAccKey(KeyStroke.getKeyStroke(KeyEvent.VK_1, 
			ActionEvent.ALT_MASK + ActionEvent.SHIFT_MASK +
			Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
		accString = accString.substring(0, accString.length() - 2);
		shortCuts.add(accString);
		descriptions.add(ElanLocale.getString("MultiTierViewer.ShiftToolTip"));

		String[][] resultTable = new String[shortCuts.size()][2];

		for (int j = 0; j < shortCuts.size(); j++) {
			resultTable[j][0] = (String) shortCuts.elementAt(j);
			resultTable[j][1] = (String) descriptions.elementAt(j);
		}

		return resultTable;
	}

	//Input is something like: 'Keycode Ctrl+Alt+ShiftB-P'
	//Matching output: 'Ctrl+Alt+Shift+B'
	//
	//The order of Ctrl, Alt and Shift is always like this, regardless of the order
	//when the accelerator was made.
	public static String convertAccKey(KeyStroke acc) {
		// special case for the Mac
		if (System.getProperty("os.name").startsWith("Mac")) {
			return convertMacAccKey(acc);
		}
		String strAcc = "" + acc;
		
		//remove 'Keycode ' at begin and '-P' at end
		strAcc = strAcc.substring(8, strAcc.length() - 2);

		int indexShift = strAcc.indexOf("Shift");
		int indexAlt = strAcc.indexOf("Alt");
		int indexCtrl = strAcc.indexOf("Ctrl");

		String strAccEnd = "";

		//insert a '+' at the right position
		if (indexShift != -1) {
			strAccEnd = strAcc.substring(indexShift + 5);
			strAcc = strAcc.substring(0, indexShift + 5);
			strAcc = strAcc + "+";
			strAcc = strAcc + strAccEnd;
		}
		else if (indexAlt != -1) {
			strAccEnd = strAcc.substring(indexAlt + 3);
			strAcc = strAcc.substring(0, indexAlt + 3);
			strAcc = strAcc + "+";
			strAcc = strAcc + strAccEnd;
		}
		else if (indexCtrl != -1) {
			strAccEnd = strAcc.substring(indexCtrl + 4);
			strAcc = strAcc.substring(0, indexCtrl + 4);
			strAcc = strAcc + "+";
			strAcc = strAcc + strAccEnd;
		}

		return strAcc;
	}
	
	/**
	 * @see #convertAccKey(KeyStroke)
	 * @param acc the KeyStroke
	 * @return a String representation
	 */
	private static String convertMacAccKey(KeyStroke acc) {
		String strAcc = "" + acc;
		
		//mac sometimes gives 'Option' instead of 'Alt'
		//change this ??
		/*
		if (indexOption != -1) {
			String strTempEnd = strAcc.substring(indexOption + 6);
			strAcc = strAcc.substring(0, indexOption);
			strAcc = strAcc + "Alt";
			strAcc = strAcc + strTempEnd;
		}
		*/
		//remove 'Keycode ' at begin and '-P' at end
		strAcc = strAcc.substring(8, strAcc.length() - 2);
		int indexOption = strAcc.indexOf("Option");
		int indexCommand = strAcc.indexOf("Command");
		
		int indexShift = strAcc.indexOf("Shift");
		int indexAlt = strAcc.indexOf("Alt");
		int indexCtrl = strAcc.indexOf("Ctrl");

		String strAccEnd = "";

		//insert a '+' at the right position
		if (indexShift != -1) {
			strAccEnd = strAcc.substring(indexShift + 5);
			strAcc = strAcc.substring(0, indexShift + 5);
			strAcc = strAcc + "+" + strAccEnd;
		}
		else if (indexAlt != -1) {
			strAccEnd = strAcc.substring(indexAlt + 3);
			strAcc = strAcc.substring(0, indexAlt + 3);
			strAcc = strAcc + "+" + strAccEnd;
		}
		else if (indexOption != -1) {
			strAccEnd = strAcc.substring(indexAlt + 6);
			strAcc = strAcc.substring(0, indexAlt + 6);
			strAcc = strAcc + "+" + strAccEnd;
		}
		else if (indexCtrl != -1) {
			strAccEnd = strAcc.substring(indexCtrl + 4);
			strAcc = strAcc.substring(0, indexCtrl + 4);
			strAcc = strAcc + "+" + strAccEnd;
		}
		else if (indexCommand != -1) {
			strAccEnd = strAcc.substring(indexCommand + 7);
			strAcc = strAcc.substring(0, indexCommand + 7);
			strAcc = strAcc + "+" + strAccEnd;
		}

		return strAcc;
	}
}
