blob: 84897b8248ea41439c856c831b22c59d3305c14f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2019 Xored Software Inc and others.
* 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
* https://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Xored Software Inc - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.rcptt.tesla.recording.core.internal.ecl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.rcptt.ecl.core.Command;
import org.eclipse.rcptt.ecl.core.Pipeline;
import org.eclipse.rcptt.ecl.core.util.ScriptletFactory;
import org.eclipse.rcptt.tesla.core.protocol.ElementKind;
import org.eclipse.rcptt.tesla.core.protocol.IMLSelectData;
import org.eclipse.rcptt.tesla.core.protocol.IWindowProvider;
import org.eclipse.rcptt.tesla.core.protocol.SelectCommand;
import org.eclipse.rcptt.tesla.core.protocol.SelectData;
import org.eclipse.rcptt.tesla.core.protocol.raw.CommandToElementEntry;
import org.eclipse.rcptt.tesla.core.protocol.raw.Element;
import org.eclipse.rcptt.tesla.core.protocol.raw.TeslaScenario;
import org.eclipse.rcptt.tesla.core.utils.TeslaPathUtils;
import org.eclipse.rcptt.tesla.ecl.TeslaScriptletFactory;
import org.eclipse.rcptt.tesla.ecl.model.GetColumnHeader;
import org.eclipse.rcptt.tesla.ecl.model.GetEclipseWindow;
import org.eclipse.rcptt.tesla.ecl.model.GetPropertyTab;
import org.eclipse.rcptt.tesla.ecl.model.GetRegion;
import org.eclipse.rcptt.tesla.ecl.model.Selector;
import org.eclipse.rcptt.tesla.ecl.model.TeslaFactory;
import org.eclipse.rcptt.tesla.ecl.model.TeslaPackage;
import org.eclipse.rcptt.tesla.recording.core.ecl.ISelectorParserExtension;
import org.eclipse.rcptt.tesla.recording.core.ecl.TeslaRecordingPlugin;
import org.eclipse.rcptt.tesla.recording.core.ecl.parser.TeslaParserUtil;
import org.eclipse.rcptt.util.Base64;
public class TeslaSelectorParser extends TeslaScriptletFactory {
private static final String EXTENSION_ID = "org.eclipse.rcptt.tesla.recording.core.ecl.selectorExtension"; //$NON-NLS-1$
static final List<ISelectorParserExtension> extensions = new ArrayList<ISelectorParserExtension>();
static {
initExtensions();
}
private static void initExtensions() {
IConfigurationElement[] config = Platform.getExtensionRegistry()
.getConfigurationElementsFor(EXTENSION_ID);
try {
for (IConfigurationElement element : config) {
final Object extension = element
.createExecutableExtension("class"); //$NON-NLS-1$
if (extension instanceof ISelectorParserExtension) {
extensions.add((ISelectorParserExtension) extension);
}
}
} catch (CoreException e) {
TeslaRecordingPlugin.log("Error while get selector extension.", e); //$NON-NLS-1$
}
}
//
protected Map<String, Command> elements = new HashMap<String, Command>();
protected TeslaScenario scenario;
public TeslaSelectorParser(TeslaScenario scenario) {
this.scenario = scenario;
}
public void parse() {
init();
process();
}
protected void init() {
}
protected void process() {
List<CommandToElementEntry> entries = scenario.getElementMapping();
for (CommandToElementEntry entry : entries) {
org.eclipse.rcptt.tesla.core.protocol.raw.Command command = entry.getCommand();
if (command instanceof SelectCommand) {
String id = entry.getElements().get(0).getId();
Command e = element((SelectCommand) command, id);
if (e != null) {
save(id, e);
}
}
}
}
protected void save(String id, Command e) {
Command oldVal = elements.put(id, e);
if (oldVal != null && !EcoreUtil.equals(e, oldVal))
throw new IllegalArgumentException("Elements with duplicate id=" + id + " are detected");
}
protected Command element(SelectCommand command, String id) {
SelectData data = command.getData();
if (data.getKind().equals("CompositeRuler")) {
data.setKind(ElementKind.VerticalRuler.name());
}
if (data.getKind().equals("OverviewRuler")) {
data.setKind(ElementKind.RightRuler.name());
}
ElementKind kind = ElementKind.kindOf(data.getKind());
if (kind == null) {
throw new IllegalArgumentException("Null-kind control was detected");
}
if (kind == ElementKind.Item) {
List<Integer> indexes = data.getIndexes();
if (indexes == null || indexes.isEmpty()) {
Command selector = TeslaParserUtil.makeItem(data.getPath());
// index and after are not recorded for items, so skip them
Command parent = selectorOf(data.getParent());
if (parent != null) {
return makePipe(parent, selector);
}
return selector;
}
}
if (kind == ElementKind.Menu) {
Command selector = TeslaParserUtil.makeMenu(data.getPath(), data.getIndex());
// index and after are not recorded for menus, so skip them
Command parent = selectorOf(data.getParent());
if (parent != null) {
return makePipe(parent, selector);
}
return selector;
}
Selector selector = null;
if (kind == ElementKind.Custom) {
// Try get selector from extensions
for (ISelectorParserExtension extension : extensions) {
selector = extension.selector(
data.getKind(), data.getPattern(), data.getPath(), data.getIndexes());
if (selector != null) {
break;
}
}
}
if (selector == null) {
selector = selector(kind, data);
}
if (kind.equals(ElementKind.Region) && data instanceof IMLSelectData) {
selector = selector(kind, ((IMLSelectData) data).getImage(),
data.getIndexes());
}
if (selector == null)
return null;
selector.setId(id);
selector.setIndex(data.getIndex());
Command parent = selectorOf(data.getParent());
Command after = selectorOf(data.getAfter());
if (after instanceof Pipeline) {
if (parent != null) {
Command cutAfter = TeslaParserUtil.cut(after, parent);
if (cutAfter == null) {
// FIXME workaround for suspicious selectors bug
EList<Command> afterCommands = ((Pipeline) after)
.getCommands();
if (afterCommands.size() > 1) {
after = afterCommands.get(afterCommands.size() - 1);
}
} else {
after = cutAfter;
}
}
}
if (after != null) {
ScriptletFactory.bind(selector,
TeslaPackage.eINSTANCE.getSelector_After(), after);
}
if (parent != null) {
return makePipe(parent, selector);
}
return selector;
}
private Selector selector(ElementKind kind, byte[] image,
EList<Integer> indexes) {
switch (kind) {
case Region:
GetRegion region = makeRegion();
region.setImageURI("base64://");
region.setRawImage(Base64.encode(image));
region.setX(indexes.get(0));
region.setY(indexes.get(1));
return region;
}
return null;
}
protected Selector selector(ElementKind kind, SelectData data) {
String text = data.getPattern();
List<String> path = data.getPath();
List<Integer> indexes = data.getIndexes();
Integer index = data.getIndex();
switch (kind) {
case Button:
return makeButton(text);
case Canvas:
return makeCanvas();
case CBanner:
return makeCBanner();
case Combo:
return makeCombo();
case CoolBar:
return makeCoolbar();
case DiagramViewer:
return makeDiagramViewer(index);
case DiagramFigure:
if (path.size() == 2) {
String first = path.get(0);
String second = path.get(1);
if ("editpart".equals(first) && "address".equals(second)) {
return makeEditPart(indexes);
} else if ("editpart.source.connection".equals(first)
&& "address".equals(second)) {
return makeSourceConnection(indexes);
} else if ("editpart.feature".equals(first)) {
return makeEditPartByFeature(second, text);
} else if ("editpart".equals(first)
&& "customId".equals(second)) {
return makeEditPartByCustomId(text);
} else if ("editpart".equals(first)
&& "classname".equals(second)) {
return makeEditPartByClassName(text);
} else if ("handle".equals(first) && "class".equals(second)) {
return makeHandle(text);
} else if ("editpart".equals(first) && "name".equals(second)) {
return makeEditPartByName(text);
} else if ("editpart".equals(first) && "text".equals(second)) {
return makeEditPartByText(text);
} else if ("editpart.target.connection".equals(first)
&& "address".equals(second)) {
return makeTargetConnection(indexes);
} else if ("rawFigure".equals(first)
&& "address".equals(second)) {
if (indexes.size() > 0) {
int value = indexes.get(0);
switch (value) {
case -3:
// Popup bar
return makePopupBarItem(indexes);
case -2:
// Connection
return makeConnectionHandle(indexes);
}
}
return makeFigure(indexes);
}
}
throw new IllegalArgumentException("Unexpected figure path: "
+ path.toArray(new String[0]).toString());
case EclipseWindow:
if (index != null && index.intValue() != 0) {
return makeEclipseWindow(index.intValue());
}
return null; // do nothing
case QuickAccess:
return makeQuickAccess();
case Editor:
return makeEditor(text, data.getClassPattern(), index);
case TextViewer:
return makeTextViewer();
case VerticalRuler:
return makeVerticalRuler();
case VerticalColumn:
return makeRulerColumn(text);
case LeftRuler:
return makeLeftRuler();
case RightRuler:
return makeRightRuler();
case Expandable:
return makeExpandable(text);
case FormText:
return makeLabel(text);
case Group:
return makeGroup(text);
case Item:
if (indexes != null && !indexes.isEmpty()) {
// It's cell
if (indexes.size() != 2)
throw new IllegalArgumentException("Invalid cell selector");
return makeCell(indexes.get(1), indexes.get(0));
}
return makeItem(TeslaPathUtils.makePathFromList(path), null);
case Label:
return makeLabel(text);
case Link:
return makeLink(text);
case List:
return makeList();
case Menu:
return makeMenu(TeslaPathUtils.makePathFromList(path), index);
case PaletteViewer:
return makePaletteViewer();
case State:
return null;
case TabFolder:
return makeTabFolder();
case TabItem:
return makeTabItem(text);
case Table:
return makeTable();
case Text:
return makeEditbox();
case Toolbar:
return makeToolbar();
case Tree:
return makeTree();
case DateTime:
return makeDateTime();
case Slider:
return makeSlider();
case View:
return makeView(text);
case Window: {
if (path.size() == 2) {
String first = path.get(0);
String second = path.get(1);
if (IWindowProvider.FROM_PATH_MARK.equals(first)) {
return makeFromedWindow(second);
} else if (IWindowProvider.CLASS_PATH_MARK.equals(first)) {
return makeClassedWindow(second);
}
}
return makeWindow(text);
}
case PaletteEntry:
return paletteEntry(text);
case ColumnHeader:
return makeColumnHeader(text, index);
case PropertyTab:
return makePropertyTab(text);
case Custom:
return makeControl(data.getKind(), text);
default:
return makeControl(kind.name(), text);
}
}
private Selector makePropertyTab(String text) {
GetPropertyTab getPropertyTab = TeslaFactory.eINSTANCE
.createGetPropertyTab();
getPropertyTab.setText(text);
return getPropertyTab;
}
private Selector makeColumnHeader(String text, Integer index) {
GetColumnHeader getColumnHeader = TeslaFactory.eINSTANCE
.createGetColumnHeader();
getColumnHeader.setText(text);
getColumnHeader.setIndex(index);
return getColumnHeader;
}
public Command selectorOf(Element element) {
return selectorOf(element, true);
}
public Command selectorOf(Element element, boolean reduceEclipseWindow) {
if (element == null)
return null;
String id = element.getId();
Command selector = elements.get(id);
if (ElementKind.EclipseWindow.name().equals(element.getKind())
&& selector instanceof GetEclipseWindow
&& (((GetEclipseWindow) selector).getIndex() == null || ((GetEclipseWindow) selector)
.getIndex().intValue() == 0)) {
if (reduceEclipseWindow) {
return null;
}
}
if (selector == null) {
if (ElementKind.EclipseWindow.name().equals(element.getKind())) {
if (reduceEclipseWindow) {
return null;
}
return TeslaFactory.eINSTANCE.createGetEclipseWindow();
}
return TeslaScriptletFactory.controlNotFound();
}
if (element.getKind() != null
&& element.getKind().equals(ElementKind.Text.name())
&& element.getDescription() != null
&& element.getDescription().equals("quick-access"))
return TeslaFactory.eINSTANCE.createGetQuickAccess();
// eclipse 3.4 compatibility:
// EcoreUtil.copy raise exception if argument is null
return (Command) EcoreUtil.copy(selector);
}
public Element elementOf(SelectCommand command) {
for (CommandToElementEntry entry : scenario.getElementMapping()) {
if (command.equals(entry.getCommand())) {
return entry.getElements().get(0);
}
}
// Could not happen because element mapping contains all the selectors
// that scenario has
throw new AssertionError();
}
}