/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package com.windowtester.swt;
import java.util.Set;
import org.eclipse.swt.widgets.Widget;
import abbot.finder.swt.Matcher;
import com.windowtester.finder.swt.BasicFinder2;
import com.windowtester.runtime.swt.internal.debug.LogHandler;
import com.windowtester.swt.mapper.IKeyGenerator;
import com.windowtester.swt.mapper.SmartKeyGenerator;
import com.windowtester.swt.mapper.WidgetRegistry;
/**
* A top-level service that maps widgets to String handles.
*
* @author Phil Quitslund
*/
public class WidgetMapper {
/** The backing widget registry */
private final WidgetRegistry _registry = new WidgetRegistry();
/** The finder used to retrieve widgets */
private abbot.finder.swt.WidgetFinder _finder = BasicFinder2.getDefault();
/** The KeyGenerator for generating new widget keys */
private final IKeyGenerator _keyGen;
/**
* Create an instance.
* @param keyGen - the key generator to use for generating new keys.
*/
public WidgetMapper(IKeyGenerator keyGen) {
_keyGen = keyGen;
}
/**
* Create an instance using the default key generator.
*/
public WidgetMapper() {
this(new SmartKeyGenerator());/** A default key generator, in case none is specified */
}
/**
* Finds the Widget associated with the given key.
* @param key - the key in question.
* @return the associated widget.
* @throws WidgetNotFoundException
* @throws MultipleWidgetsFoundException
*/
public Widget find(String key) throws WidgetNotFoundException, MultipleWidgetsFoundException {
WidgetLocator info = _registry.get(key);
if (info == null)
throw new UnregisteredKeyException();
Matcher m = WidgetLocatorService.getMatcher(info);
try {
return _finder.find(m);
} catch (abbot.finder.swt.WidgetNotFoundException wnfe) {
//replace/rethrow with our own exception
throw new WidgetNotFoundException(wnfe.getMessage());
} catch (abbot.finder.swt.MultipleWidgetsFoundException mwfe) {
//replace/rethrow with our own exception
throw new MultipleWidgetsFoundException(mwfe.getMessage());
}
}
/**
* Registers this info object, returning its associated key.
* @param info - the info object to register.
* @return the key associated with this info object
*/
public String register(WidgetLocator info) {
if (_registry.containsValue(info))
return _registry.getKey(info);
//if not already registered, generate a key and register
String key = null;
//if it's named, register its name as a key unless there's a conflict
String name = info.getData("name");
if (name != null && !_registry.containsKey(name))
key = name;
else
key = _keyGen.generate(info);
register(key, info);
return key;
}
/**
* Registers this key, info pair.
* @param key - the key to register.
* @param info - the associated info object.
*/
public void register(String key, WidgetLocator info) {
WidgetLocator old = _registry.add(key, info);
if (old != info) {
/*
* this case is no longer being treated as an exception.
* We'll log it nonetheless though.
*
*/
//log(new IllegalArgumentException("key registered twice with different values"));
log("key: " + key + " registered twice to different values (clobbering old value)");
}
}
/**
* Returns true if this map contains a mapping for the specified key.
* @param key - key whose presence in this map is to be tested.
* @return true if this mapper's registry contains a mapping for the specified key.
*/
public boolean containsKey(String key) {
return _registry.containsKey(key);
}
/**
* Get the locator associated with this key, or null if there is none.
* @param key - the key of interest
* @return the associated locator (or null)
*/
public WidgetLocator getLocator(String key) {
return _registry.get(key);
}
/**
* Returns a set view of the mappings contained in this mapper. Each element
* in the returned set is a Map.Entry. The set is backed by the mapper, so changes
* to the mapper are reflected in the set, and vice-versa. If the mapper is modified
* while an iteration over the set is in progress, the results of the iteration
* are undefined.
* @see WidgetRegistry#getEntries()
* @return a set view of the mappings contained in this map.
*/
public Set getMappings() {
return _registry.getEntries();
}
////////////////////////////////////////////////////////////////////////////
//
// Internal
//
////////////////////////////////////////////////////////////////////////////
private void log(String msg) {
LogHandler.log(msg);
}
/**
* Exception signaling that a widget was sought for a key that was not registered.
* @author Phil Quitslund
*/
public static final class UnregisteredKeyException extends RuntimeException {
private static final long serialVersionUID = -5996967689887211859L;
}
}