blob: c8b8c4832244964254830ad35fe6560336433275 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2003 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ui.internal.commands;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;
import org.eclipse.swt.SWT;
public final class SequenceMachine {
public static SequenceMachine create() {
return new SequenceMachine();
}
private final static String LOCALE_SEPARATOR = "_"; //$NON-NLS-1$
private final static Locale SYSTEM_LOCALE = Locale.getDefault();
private final static String SYSTEM_PLATFORM = SWT.getPlatform();
static SortedMap buildPathMapForConfigurationMap(SortedMap configurationMap) {
SortedMap pathMap = new TreeMap();
Iterator iterator = configurationMap.keySet().iterator();
while (iterator.hasNext()) {
String id = (String) iterator.next();
if (id != null) {
Path path = getPathForConfiguration(id, configurationMap);
if (path != null)
pathMap.put(id, path);
}
}
return pathMap;
}
static SortedMap buildPathMapForScopeMap(SortedMap scopeMap) {
SortedMap pathMap = new TreeMap();
Iterator iterator = scopeMap.keySet().iterator();
while (iterator.hasNext()) {
String id = (String) iterator.next();
if (id != null) {
Path path = getPathForScope(id, scopeMap);
if (path != null)
pathMap.put(id, path);
}
}
return pathMap;
}
static Path getPathForConfiguration(String id, Map configurationMap) {
Path path = null;
if (id != null) {
List strings = new ArrayList();
while (id != null) {
if (strings.contains(id))
return null;
Configuration configuration = (Configuration) configurationMap.get(id);
if (configuration == null)
return null;
strings.add(0, id);
id = configuration.getParent();
}
path = Path.create(strings);
}
return path;
}
static Path getPathForLocale(String locale) {
Path path = null;
if (locale != null) {
List strings = new ArrayList();
locale = locale.trim();
if (locale.length() > 0) {
StringTokenizer st = new StringTokenizer(locale, LOCALE_SEPARATOR);
while (st.hasMoreElements()) {
String string = ((String) st.nextElement()).trim();
if (string != null)
strings.add(string);
}
}
path = Path.create(strings);
}
return path;
}
static Path getPathForPlatform(String platform) {
Path path = null;
if (platform != null) {
List strings = new ArrayList();
platform = platform.trim();
if (platform.length() > 0)
strings.add(platform);
path = Path.create(strings);
}
return path;
}
static Path getPathForScope(String id, Map scopeMap) {
Path path = null;
if (id != null) {
List strings = new ArrayList();
while (id != null) {
if (strings.contains(id))
return null;
Scope scope = (Scope) scopeMap.get(id);
if (scope == null)
return null;
strings.add(0, id);
id = scope.getParent();
}
path = Path.create(strings);
}
return path;
}
static Path getSystemLocale() {
return SYSTEM_LOCALE != null ? getPathForLocale(SYSTEM_LOCALE.toString()) : null;
}
static Path getSystemPlatform() {
return getPathForPlatform(SYSTEM_PLATFORM);
}
private Map commandMap;
private Map commandMapForMode;
private SortedSet sequenceBindingSet;
private String configuration;
private SortedMap configurationMap;
private SortedMap sequenceMap;
private SortedMap sequenceMapForMode;
private Sequence mode;
private SortedMap scopeMap;
private String[] scopes;
private boolean solved;
private SortedMap tree;
private SequenceMachine() {
super();
configurationMap = new TreeMap();
scopeMap = new TreeMap();
sequenceBindingSet = new TreeSet();
configuration = Util.ZERO_LENGTH_STRING;
scopes = new String[] { Util.ZERO_LENGTH_STRING };
mode = Sequence.create();
}
public Map getCommandMap() {
if (commandMap == null) {
solve();
commandMap = Collections.unmodifiableMap(SequenceNode.toCommandMap(getSequenceMap()));
}
return commandMap;
}
public Map getCommandMapForMode() {
if (commandMapForMode == null) {
solve();
SortedMap tree = SequenceNode.find(this.tree, mode);
if (tree == null)
tree = new TreeMap();
commandMapForMode = Collections.unmodifiableMap(SequenceNode.toCommandMap(getSequenceMapForMode()));
}
return commandMapForMode;
}
public SortedSet getSequenceBindingSet() {
return sequenceBindingSet;
}
public String getConfiguration() {
return configuration;
}
public SortedMap getConfigurationMap() {
return configurationMap;
}
public Sequence getFirstSequenceForCommand(String command)
throws IllegalArgumentException {
if (command == null)
throw new IllegalArgumentException();
SortedSet sequenceSet = (SortedSet) getCommandMap().get(command);
if (sequenceSet != null && !sequenceSet.isEmpty())
return (Sequence) sequenceSet.first();
return null;
}
public SortedMap getSequenceMap() {
if (sequenceMap == null) {
solve();
sequenceMap = Collections.unmodifiableSortedMap(SequenceNode.toSequenceMap(tree, Sequence.create()));
}
return sequenceMap;
}
public SortedMap getSequenceMapForMode() {
if (sequenceMapForMode == null) {
solve();
SortedMap tree = SequenceNode.find(this.tree, mode);
if (tree == null)
tree = new TreeMap();
sequenceMapForMode = Collections.unmodifiableSortedMap(SequenceNode.toSequenceMap(tree, mode));
}
return sequenceMapForMode;
}
public Sequence getMode() {
return mode;
}
public SortedMap getScopeMap() {
return scopeMap;
}
public String[] getScopes() {
return (String[]) scopes.clone();
}
public boolean setBindingSet(SortedSet sequenceBindingSet)
throws IllegalArgumentException {
if (sequenceBindingSet == null)
throw new IllegalArgumentException();
sequenceBindingSet = new TreeSet(sequenceBindingSet);
Iterator iterator = sequenceBindingSet.iterator();
while (iterator.hasNext())
if (!(iterator.next() instanceof SequenceBinding))
throw new IllegalArgumentException();
if (this.sequenceBindingSet.equals(sequenceBindingSet))
return false;
this.sequenceBindingSet = Collections.unmodifiableSortedSet(sequenceBindingSet);
invalidateTree();
return true;
}
public boolean setConfiguration(String configuration) {
if (configuration == null)
throw new IllegalArgumentException();
if (this.configuration.equals(configuration))
return false;
this.configuration = configuration;
invalidateSolution();
return true;
}
public boolean setConfigurationMap(SortedMap configurationMap)
throws IllegalArgumentException {
if (configurationMap == null)
throw new IllegalArgumentException();
configurationMap = new TreeMap(configurationMap);
Iterator iterator = configurationMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
if (!(entry.getKey() instanceof String) || !(entry.getValue() instanceof Path))
throw new IllegalArgumentException();
}
if (this.configurationMap.equals(configurationMap))
return false;
this.configurationMap = Collections.unmodifiableSortedMap(configurationMap);
invalidateTree();
return true;
}
public boolean setMode(Sequence mode)
throws IllegalArgumentException {
if (mode == null)
throw new IllegalArgumentException();
if (this.mode.equals(mode))
return false;
this.mode = mode;
invalidateMode();
return true;
}
public boolean setScopeMap(SortedMap scopeMap)
throws IllegalArgumentException {
if (scopeMap == null)
throw new IllegalArgumentException();
scopeMap = new TreeMap(scopeMap);
Iterator iterator = scopeMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
if (!(entry.getKey() instanceof String) || !(entry.getValue() instanceof Path))
throw new IllegalArgumentException();
}
if (this.scopeMap.equals(scopeMap))
return false;
this.scopeMap = Collections.unmodifiableSortedMap(scopeMap);
invalidateTree();
return true;
}
public boolean setScopes(String[] scopes)
throws IllegalArgumentException {
if (scopes == null || scopes.length == 0)
throw new IllegalArgumentException();
scopes = (String[]) scopes.clone();
for (int i = 0; i < scopes.length; i++)
if (scopes[i] == null)
throw new IllegalArgumentException();
if (Arrays.equals(this.scopes, scopes))
return false;
this.scopes = scopes;
invalidateSolution();
return true;
}
private void build() {
if (tree == null) {
tree = new TreeMap();
Iterator iterator = sequenceBindingSet.iterator();
while (iterator.hasNext()) {
SequenceBinding sequenceBinding = (SequenceBinding) iterator.next();
Path scope = (Path) scopeMap.get(sequenceBinding.getScope());
if (scope == null)
continue;
Path configuration = (Path) configurationMap.get(sequenceBinding.getConfiguration());
if (configuration == null)
continue;
List paths = new ArrayList();
paths.add(scope);
paths.add(configuration);
State scopeConfiguration = State.create(paths);
paths = new ArrayList();
paths.add(getPathForPlatform(sequenceBinding.getPlatform()));
paths.add(getPathForLocale(sequenceBinding.getLocale()));
State platformLocale = State.create(paths);
SequenceNode.add(tree, sequenceBinding, scopeConfiguration, platformLocale);
}
}
}
private void invalidateMode() {
commandMapForMode = null;
sequenceMapForMode = null;
}
private void invalidateSolution() {
solved = false;
commandMap = null;
sequenceMap = null;
invalidateMode();
}
private void invalidateTree() {
tree = null;
invalidateSolution();
}
private void solve() {
if (!solved) {
build();
State[] scopeConfigurations = new State[scopes.length];
Path configuration = (Path) configurationMap.get(this.configuration);
if (configuration == null)
configuration = Path.create();
for (int i = 0; i < scopes.length; i++) {
Path scope = (Path) scopeMap.get(scopes[i]);
if (scope == null)
scope = Path.create();
List paths = new ArrayList();
paths.add(scope);
paths.add(configuration);
scopeConfigurations[i] = State.create(paths);
}
List paths = new ArrayList();
paths.add(getSystemPlatform());
paths.add(getSystemLocale());
State platformLocale = State.create(paths);
SequenceNode.solve(tree, scopeConfigurations, new State[] { platformLocale } );
solved = true;
}
}
}