Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 133099 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/ToggleStructuredCommand.java (-41 / +41 lines)
Lines 16-99 Link Here
16
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.swt.widgets.Event;
17
import org.eclipse.swt.widgets.Event;
18
import org.eclipse.swt.widgets.Widget;
18
import org.eclipse.swt.widgets.Widget;
19
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
19
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
20
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
20
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
21
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
21
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
22
import org.w3c.dom.Node;
22
import org.w3c.dom.Node;
23
23
24
public abstract class ToggleStructuredCommand extends AbstractStructuredCommand {
24
public abstract class ToggleStructuredCommand extends AbstractStructuredCommand {
25
25
	protected boolean itemState;
26
	protected boolean itemState;
26
27
27
	/**
28
	/**
28
	 * @param wid
29
	 * @param wid
29
	 */
30
	 */
30
	public ToggleStructuredCommand(MacroCommandShell parent, WidgetIdentifier wid) {
31
	public ToggleStructuredCommand(MacroCommandShell parent) {
31
		super(parent, wid);
32
		super(parent);
32
	}
33
	}
33
	
34
34
	
35
	/**
35
	/**
36
	 * There are more incomming events, merge them appropriately
36
	 * There are more incomming events, merge them appropriately
37
	 * 
37
	 * 
38
	 * @param e The event to be merged with this command
38
	 * @param e
39
	 *            The event to be merged with this command
39
	 */
40
	 */
40
	public boolean mergeEvent(Event e) 
41
	public boolean mergeEvent(Event e) throws Exception {
41
	{
42
		ArrayList itemMatches = super.getItems();
42
		ArrayList itemMatches = super.getItems();
43
		
43
44
		if (e.item != null && itemState == getItemState(e.item))
44
		if (e.item != null && itemState == getItemState(e.item)) {
45
		{
46
			itemMatches.add(super.getItemAttributes(e.item));
45
			itemMatches.add(super.getItemAttributes(e.item));
47
			return true;
46
			return true;
48
		}
47
		}
49
		
48
50
		return false;
49
		return false;
51
	}
50
	}
52
	
51
53
	public void load(Node node, Hashtable lineTable) throws CoreException
52
	public void load(Node node, Hashtable lineTable) throws CoreException {
54
	{
53
		super.load(node,
55
		super.load(node, lineTable);
54
			lineTable);
56
		String att = MacroUtil.getAttribute(node, MacroConstants.VALUE_ATTRIBUTE);
55
		String att = MacroUtil.getAttribute(node,
57
		this.itemState = att!=null && att.equals(MacroConstants.TRUE_VALUE);
56
			MacroConstants.VALUE_ATTRIBUTE);
58
	}
57
		this.itemState = att != null && att.equals(MacroConstants.TRUE_VALUE);
59
	
58
	}
60
	protected void writeAdditionalAttributes(StringBuffer sb) 
59
61
	{
60
	protected void writeAdditionalAttributes(StringBuffer sb) {
62
		MacroUtil.addAttribute(sb, 
61
		MacroUtil.addAttribute(sb,
63
				new String[]{MacroConstants.VALUE_ATTRIBUTE}, 
62
			new String[] {MacroConstants.VALUE_ATTRIBUTE},
64
				new String[]{itemState?MacroConstants.TRUE_VALUE:MacroConstants.FALSE_VALUE}, 
63
			new String[] {itemState
65
				false, false);
64
				? MacroConstants.TRUE_VALUE
65
				: MacroConstants.FALSE_VALUE},
66
			false,
67
			false);
66
	}
68
	}
67
69
68
	
69
	public boolean getValue() {
70
	public boolean getValue() {
70
		return itemState;
71
		return itemState;
71
	}
72
	}
72
	
73
73
	/**
74
	/**
74
	 * Overwirte this method to indicate that if there are two toggle commands
75
	 * Overwirte this method to indicate that if there are two toggle commands with different values, then they are not the same.
75
	 * with different values, then they are not the same.
76
	 * 
76
	 * 
77
	 * @param obj The object that this object will be comapred against
77
	 * @param obj
78
	 *            The object that this object will be comapred against
78
	 */
79
	 */
79
	public boolean equals (Object obj)
80
	public boolean equals(Object obj) {
80
	{
81
		if (!(obj instanceof ToggleStructuredCommand) || !super.equals(obj))
81
		if (!(obj instanceof ToggleStructuredCommand) || !super.equals(obj))
82
			return false;
82
			return false;
83
				
83
84
		ToggleStructuredCommand compareWithObj = (ToggleStructuredCommand)obj;
84
		ToggleStructuredCommand compareWithObj = (ToggleStructuredCommand) obj;
85
		if (compareWithObj.getValue() == this.getValue())
85
		if (compareWithObj.getValue() == this.getValue())
86
			return true;
86
			return true;
87
		
87
88
		return false;
88
		return false;
89
	}
89
	}
90
		
90
91
	/**
91
	/**
92
	 * Returns the state of the item (e.g. whether it is check/unchecked, expanded/
92
	 * Returns the state of the item (e.g. whether it is check/unchecked, expanded/ collapsed, and etc...)
93
	 * collapsed, and etc...)
94
	 * 
93
	 * 
95
	 * @param item The item for which its state is being queried
94
	 * @param item
95
	 *            The item for which its state is being queried
96
	 * @return The state of the item
96
	 * @return The state of the item
97
	 */
97
	 */
98
	public abstract boolean getItemState (Widget item);
98
	public abstract boolean getItemState(Widget item);
99
}
99
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/MouseEventCommand.java (-119 / +116 lines)
Lines 11-177 Link Here
11
 *******************************************************************************/
11
 *******************************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.commands;
12
package org.eclipse.tptp.test.auto.gui.internal.commands;
13
13
14
import java.util.ArrayList;
15
import java.util.Hashtable;
14
import java.util.Hashtable;
16
15
17
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.core.runtime.CoreException;
18
import org.eclipse.core.runtime.IProgressMonitor;
17
import org.eclipse.core.runtime.IProgressMonitor;
19
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.SWT;
20
import org.eclipse.swt.graphics.Point;
19
import org.eclipse.swt.graphics.Point;
21
import org.eclipse.swt.widgets.Composite;
22
import org.eclipse.swt.widgets.Display;
20
import org.eclipse.swt.widgets.Display;
23
import org.eclipse.swt.widgets.Event;
21
import org.eclipse.swt.widgets.Event;
24
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
22
import org.eclipse.swt.widgets.Shell;
23
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
25
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
24
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
26
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
25
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
27
import org.eclipse.ui.PlatformUI;
26
import org.eclipse.ui.PlatformUI;
28
import org.w3c.dom.Node;
27
import org.w3c.dom.Node;
29
28
30
/**
29
/**
31
 * A concrete extension of PositionBasedCommand used to represent SWT.MouseUp and SWT.MouseDown
30
 * A concrete extension of PositionBasedCommand used to represent SWT.MouseUp
32
 * events.
31
 * and SWT.MouseDown and SWT.MouseMove events.
33
 * 
32
 * 
34
 * @author Ali Mehregani
33
 * @author Ali Mehregani
34
 * @author Alexander Nyssen (refactored and added mouse move event support)
35
 */
35
 */
36
public class MouseEventCommand extends PositionBasedCommand 
36
public class MouseEventCommand extends PositionBasedCommand {
37
{
37
38
	public static final String TYPE0 = "mouse-up";
38
	private Point coordinates; /* Keep track of the coordinates */
39
	public static final String TYPE1 = "mouse-down";
39
40
	public static final String TYPE2 = "mouse-click";
41
	
42
	private String type;			/* The type of this command (either TYPE0 or TYPE1) */
43
	private int button;				/* The mouse button that was pressed or released */
44
	private Point coordinates;		/* Keep track of the coordinates */
45
	
46
	private static Point lastCoordinates;
40
	private static Point lastCoordinates;
47
	
41
48
	public MouseEventCommand(MacroCommandShell parent) 
42
	public MouseEventCommand(MacroCommandShell parent) {
49
	{
43
		super(parent);
50
		super(parent, WidgetIdentifier.NULL_IDENTIFIER);		
51
	}
44
	}
52
45
53
	public String getType() 
46
	public void processEvent(Event event) throws Exception {
54
	{
47
		super.processEvent(event);
48
		coordinates = PlatformUI.getWorkbench().getDisplay()
49
				.getCursorLocation();
50
	}
51
52
	protected String determineType(Event e) {
53
		String type = null;
54
		if (e.type == SWT.MouseUp) {
55
			type = MOUSE_UP;
56
		} else if (e.type == SWT.MouseDown) {
57
			type = MOUSE_DOWN;
58
		} else if (e.type == SWT.MouseMove) {
59
			type = MOUSE_MOVE;
60
		}
55
		return type;
61
		return type;
56
	}
62
	}
57
63
58
	public void processEvent(Event e) 
64
	protected Integer determineDetail(Event e) {
59
	{
65
		if (e.button > 0) {
60
		coordinates = PlatformUI.getWorkbench().getDisplay().getCursorLocation();
66
			return new Integer(e.button);
61
		button = e.button;
67
		} else {
62
		
68
			return null;
63
		if (e.type == SWT.MouseUp)
69
		}
64
		{
70
	}
65
			/* Defect #: 110726 -- If the previous event was a mouse down event at the same
71
66
			 * exact location, then replace the two of them with the mouse click event */
72
	public boolean mergeEvent(Event e) throws Exception {
67
			ArrayList commands = getParent().getCommands();
73
		/*
68
			int commandSize;
74
		 * Defect #: 110726 -- If the previous event was a mouse down event at
69
			if (commands != null && (commandSize = commands.size()) > 0)
75
		 * the same exact location, then replace the two of them with the mouse
70
			{
76
		 * click event (ANy: As merging of position based commands is now
71
				Object lastCommand = commands.get(commandSize - 1);
77
		 * supported, this defect can be handled here more elegantly)
72
				if (lastCommand instanceof MouseEventCommand)
78
		 */
73
				{
79
		if (e.type == SWT.MouseUp
74
					Point lastCommandCoordinates = ((MouseEventCommand)lastCommand).getCoordinates();
80
				&& type != null
75
					if (lastCommandCoordinates.equals(coordinates))
81
				&& type.equals(MOUSE_DOWN)
76
					{
82
				&& coordinates != null
77
						type = TYPE2;
83
				&& coordinates.equals(PlatformUI.getWorkbench().getDisplay()
78
						commands.remove(commandSize - 1);
84
						.getCursorLocation())
79
						return;
85
				&& (detail == null || detail.intValue() == e.button)) {
80
					}
86
			type = MOUSE_CLICK;
81
				}				
87
			return true;
82
			}
88
		}
83
			
89
		// if the last command was a mouse move command, and this one as well,
84
			type = TYPE0;
90
		// the
85
		}
91
		// last may be ignored.
86
		else if (e.type == SWT.MouseDown)
92
		else if (e.type == SWT.MouseMove && type != null
87
			type = TYPE1;		
93
				&& type.equals(MOUSE_MOVE)) {
88
	}
94
			coordinates = PlatformUI.getWorkbench().getDisplay()
89
95
					.getCursorLocation();
90
	public int getDetail() 
96
			return true;
91
	{
97
		} else {
92
		return button;
98
			return super.mergeEvent(e);
99
		}
93
	}
100
	}
94
101
95
	public Event[] constructSWTEvents()
102
	public Event[] constructSWTEvents() {
96
	{
97
		Event[] mouseEvents;
103
		Event[] mouseEvents;
98
		if (type.equals(TYPE2))
104
		if (type.equals(MOUSE_CLICK))
99
			mouseEvents = new Event[2];
105
			mouseEvents = new Event[2];
100
		else
106
		else
101
			mouseEvents = new Event[1];
107
			mouseEvents = new Event[1];
102
		
108
103
		Event mouseUpEvent 	= new Event(), 
109
		if (type.equals(MOUSE_UP)) {
104
			  mouseDownEvent= new Event();
110
			mouseEvents[0] = new Event();
105
		
111
			mouseEvents[0].type = SWT.MouseUp;
106
		mouseUpEvent.type = SWT.MouseUp;
112
			mouseEvents[0].button = detail.intValue();
107
		mouseDownEvent.type = SWT.MouseDown;
113
		} else if (type.equals(MOUSE_DOWN)) {
108
		
114
			mouseEvents[0] = new Event();
109
		mouseUpEvent.button = button;
115
			mouseEvents[0].type = SWT.MouseDown;
110
		mouseDownEvent.button = button;
116
			mouseEvents[0].button = detail.intValue();
111
		
117
		} else if (type.equals(MOUSE_CLICK)) {
112
		if (type.equals(TYPE0))
118
			mouseEvents[0] = new Event();
113
			mouseEvents[0] = mouseUpEvent;
119
			mouseEvents[0].type = SWT.MouseDown;
114
		
120
			mouseEvents[0].button = detail.intValue();
115
		else if (type.equals(TYPE1))
121
			mouseEvents[1] = new Event();
116
			mouseEvents[0] = mouseDownEvent;
122
			mouseEvents[1].type = SWT.MouseUp;
117
		
123
			mouseEvents[1].button = detail.intValue();
118
		else if (type.equals(TYPE2))
124
		} else if (type.equals(MOUSE_MOVE)) {
119
		{
125
			mouseEvents[0] = new Event();
120
			mouseEvents[0] = mouseDownEvent;
126
			mouseEvents[0].type = SWT.MouseMove;
121
			mouseEvents[1] = mouseUpEvent;
127
			mouseEvents[0].x = coordinates.x;
128
			mouseEvents[0].y = coordinates.y;
122
		}
129
		}
123
				
130
124
		return mouseEvents;
131
		return mouseEvents;
125
	}
132
	}
126
	
127
133
128
	public void load(Node node, Hashtable lineTable) throws CoreException 
134
	public void load(Node node, Hashtable lineTable) throws CoreException {
129
	{
130
		super.load(node, lineTable);
135
		super.load(node, lineTable);
131
		
136
132
		type = MacroUtil.getAttribute(node, "type");
137
		// load coordinates
133
		int x = Integer.parseInt(MacroUtil.getAttribute(node, "x-coord"));
138
		int x = Integer.parseInt(MacroUtil.getAttribute(node, "x-coord"));
134
		int y = Integer.parseInt(MacroUtil.getAttribute(node, "y-coord"));
139
		int y = Integer.parseInt(MacroUtil.getAttribute(node, "y-coord"));
135
		button = Integer.parseInt(MacroUtil.getAttribute(node, "detail"));		
140
		coordinates = new Point(x, y);
136
		coordinates = new Point (x, y);
137
	}
141
	}
138
	
142
139
	public void write(int indent, StringBuffer sb, boolean close, boolean end)
143
	public void write(int indent, StringBuffer sb, boolean close, boolean end) {
140
	{
144
		super.write(indent, sb, false, false);
141
		super.write(indent, sb, close, end);
145
		MacroUtil.addAttribute(sb, new String[] {
142
		MacroUtil.addAttribute(sb, 
146
				MacroConstants.X_COORD_ATTRIBUTE,
143
				new String[] {			
147
				MacroConstants.Y_COORD_ATTRIBUTE, },
144
					MacroConstants.X_COORD_ATTRIBUTE,
148
				new String[] { String.valueOf(coordinates.x),
145
					MacroConstants.Y_COORD_ATTRIBUTE, 
149
						String.valueOf(coordinates.y), }, true, true);
146
				}, 
147
				new String[] {
148
					String.valueOf(coordinates.x),
149
					String.valueOf(coordinates.y),
150
				}
151
		, true, true);
152
	}
150
	}
153
	
151
154
	/**
152
	/**
155
	 * Plays back this command
153
	 * Plays back this command
156
	 */
154
	 */
157
	public boolean playback(Display display, Composite parent, IProgressMonitor monitor) throws CoreException 
155
	public boolean playback(final Display display, Shell parent,
158
	{		
156
			IProgressMonitor monitor) throws CoreException {
159
		/* It's important not to move the cursor if the last command had the same cursor position as this one */
157
		/*
160
		if (lastCoordinates == null || !lastCoordinates.equals(coordinates))
158
		 * It's important not to move the cursor if the last command had the
161
		{
159
		 * same cursor position as this one
160
		 */
161
		if (lastCoordinates == null || !lastCoordinates.equals(coordinates)) {
162
			display.setCursorLocation(coordinates.x, coordinates.y);
162
			display.setCursorLocation(coordinates.x, coordinates.y);
163
		}
163
		}
164
		lastCoordinates = coordinates;
164
		lastCoordinates = coordinates;
165
		return super.playback(display, parent, monitor);
165
		return super.playback(display, parent, monitor);
166
	}
166
	}
167
	
167
168
	public boolean equals (Object obj)
168
	public boolean equals(Object obj) {
169
	{
170
		if (!(obj instanceof MouseEventCommand))
169
		if (!(obj instanceof MouseEventCommand))
171
			return false;
170
			return false;
172
		
171
173
		MouseEventCommand mouseEvent = (MouseEventCommand)obj;
172
		MouseEventCommand mouseEvent = (MouseEventCommand) obj;
174
		if (this.type.equals(mouseEvent.getType()) && this.button == mouseEvent.getButton() && this.coordinates.equals(mouseEvent.getCoordinates()))
173
		if (this.type.equals(mouseEvent.getType())
174
				&& this.detail == mouseEvent.getDetail()
175
				&& this.coordinates.equals(mouseEvent.getCoordinates()))
175
			return true;
176
			return true;
176
		return false;
177
		return false;
177
	}
178
	}
Lines 180-191 Link Here
180
		return coordinates;
181
		return coordinates;
181
	}
182
	}
182
183
183
	public int getButton() {
184
	// TODO: This is ugly, it has to be removed
184
		return button;
185
	public static void init() {
185
	}
186
187
	public static void init()
188
	{
189
		lastCoordinates = null;
186
		lastCoordinates = null;
190
	}
187
	}
191
}
188
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/MacroCommandShell.java (-1493 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.commands;
12
13
import java.util.ArrayList;
14
import java.util.Hashtable;
15
import java.util.Vector;
16
17
import org.eclipse.core.runtime.CoreException;
18
import org.eclipse.core.runtime.IPath;
19
import org.eclipse.core.runtime.IProgressMonitor;
20
import org.eclipse.core.runtime.IStatus;
21
import org.eclipse.core.runtime.Path;
22
import org.eclipse.core.runtime.Status;
23
import org.eclipse.core.runtime.SubProgressMonitor;
24
import org.eclipse.jface.dialogs.MessageDialog;
25
import org.eclipse.jface.window.Window;
26
import org.eclipse.osgi.util.NLS;
27
import org.eclipse.swt.SWT;
28
import org.eclipse.swt.SWTException;
29
import org.eclipse.swt.custom.CCombo;
30
import org.eclipse.swt.custom.CTabFolder;
31
import org.eclipse.swt.custom.StyledText;
32
import org.eclipse.swt.graphics.Point;
33
import org.eclipse.swt.widgets.Button;
34
import org.eclipse.swt.widgets.Combo;
35
import org.eclipse.swt.widgets.Composite;
36
import org.eclipse.swt.widgets.Control;
37
import org.eclipse.swt.widgets.Display;
38
import org.eclipse.swt.widgets.Event;
39
import org.eclipse.swt.widgets.List;
40
import org.eclipse.swt.widgets.Listener;
41
import org.eclipse.swt.widgets.MenuItem;
42
import org.eclipse.swt.widgets.Shell;
43
import org.eclipse.swt.widgets.TabFolder;
44
import org.eclipse.swt.widgets.Table;
45
import org.eclipse.swt.widgets.Text;
46
import org.eclipse.swt.widgets.ToolItem;
47
import org.eclipse.swt.widgets.Tree;
48
import org.eclipse.swt.widgets.TreeItem;
49
import org.eclipse.swt.widgets.Widget;
50
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
51
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
52
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
53
import org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine;
54
import org.eclipse.tptp.test.auto.gui.internal.core.IPlayable;
55
import org.eclipse.tptp.test.auto.gui.internal.core.IUIObject;
56
import org.eclipse.tptp.test.auto.gui.internal.core.IWritable;
57
import org.eclipse.tptp.test.auto.gui.internal.core.VerificationMetaData;
58
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
59
import org.eclipse.tptp.test.auto.gui.internal.macro.AbstractMacroInstruction;
60
import org.eclipse.tptp.test.auto.gui.internal.macro.Macro;
61
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
62
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
63
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroObjectLocator;
64
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
65
import org.eclipse.tptp.test.auto.gui.internal.macro.UIObject;
66
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMine.IDCollisionException;
67
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMine.UIObjectNotFound;
68
import org.w3c.dom.Node;
69
import org.w3c.dom.NodeList;
70
71
/**
72
 * Keeps track of the macro commands while they are being captured.
73
 */
74
public class MacroCommandShell extends AbstractMacroInstruction
75
{
76
	/* The commands of this macro shell */
77
	private ArrayList commands;
78
79
	/* The expected return code */
80
	private int expectedReturnCode;
81
82
	/* The last event received */
83
	private transient Event lastEvent;
84
85
	/* The display object */
86
	private transient Display display;
87
88
	/* The shell that this macro command shell represents */
89
	private transient Shell shell;
90
	
91
	/* The reference id of the macro shell object */
92
	private String referenceId;
93
	
94
	/* The title of the shell that this macro command shell represents */
95
	private String shellTitle;
96
97
	private transient Window window;
98
	
99
	/* Indicates user interaction -- Set when a key up event is received */
100
	private transient boolean isKeyPressed;
101
102
	/* Indicates user interaction -- Set when a mouse up event is received */
103
	private transient boolean isMousePressed;
104
	
105
	/* Stores an event that is only acknowledged followed by user interaction. */
106
	private transient Event toBeAckEvent;
107
	
108
	/* Set when the stored event in toBeAckEvent is acknowledged */
109
	private transient boolean ackEvent;
110
111
	/* Set when there is a listener registered with this MacroCommandShell */
112
	private transient boolean isListenerRegistered;
113
114
	/* Stores the time for which a command was last created in */
115
	private long lastCommandCreationTime;
116
	
117
	/* A queue of nested shell waiting to be activated (this is used during playback) */ 
118
	private static Vector nestedShellQueue;
119
	
120
	/* Last index of the nested shell queue */ 
121
	private static int lastNestedShellInx;
122
	
123
	/* Stores the last command line executed */
124
	private static int lastCommandLineExecuted;
125
	
126
	/* Mutual lock used to block when a command is being executed.  This lock is used to forcefully wake up
127
	 * the thread that this object is running in if the command has caused a stall */
128
	private Boolean mutualLock;
129
130
	/* A mutual lock shared across multiple instances of this class -- It's general purpose is to lock shared static resources */
131
	private static Boolean mutualGlobalLock;
132
	
133
	/* The parent of this macro command shell.  This is null if this macro shell command is the root */
134
	private MacroCommandShell parent;
135
136
	/* The index of the command being executed -- this will correspond to the last command index if isComplete = true */
137
	private int currentCommandInx;
138
139
	/* Indicates if all the commands of this shell has been completed */
140
	private boolean isComplete;
141
	
142
	/* Indicates that the process needs to be interrupted -- due to an error */
143
	private static boolean interruptProcess;
144
	
145
	/* Set to true when process has been terminated */
146
	private static boolean processTerminated;
147
148
	/* The exception causing the interruption */
149
	private static Throwable interruptedException;
150
		
151
	/* A central container for all macro command operation being played */
152
	private static Vector macroCommandsBeingPlayed;
153
	
154
	/* A central container for all instances of this class */
155
	private static Vector macroCommandShellContainer;
156
	
157
	
158
	/* A central repository for all macro command shells */
159
	static
160
	{
161
		nestedShellQueue = new Vector();
162
		macroCommandsBeingPlayed = new Vector();
163
		macroCommandShellContainer = new Vector();
164
		mutualGlobalLock = new Boolean(true);
165
	}
166
	
167
168
	public MacroCommandShell(MacroCommandShell parent)
169
	{
170
		this(parent, null, null);
171
	}
172
173
	public MacroCommandShell(MacroCommandShell parent, Shell shell, WidgetIdentifier wid)
174
	{
175
		setWidgetId(wid);
176
		commands = new ArrayList();
177
		this.shell = shell;
178
		this.shellTitle = shell == null || shell.isDisposed() ? null : shell.getText();
179
		hookWindow(false);
180
		expectedReturnCode = -1;
181
		isListenerRegistered = false;
182
		mutualLock = new Boolean(true);
183
		this.parent = parent;
184
		isComplete = false;
185
		macroCommandShellContainer.add (this);		
186
	}
187
188
	private void hookWindow(boolean playback)
189
	{
190
		if (shell != null)
191
		{
192
			if (!playback)
193
				doHookWindow();
194
			else
195
				display.syncExec(new Runnable()
196
				{
197
					public void run()
198
					{
199
						doHookWindow();
200
					}
201
				});
202
		}
203
	}
204
205
	private void doHookWindow()
206
	{
207
		Object data = shell.getData();
208
		if (data != null && data instanceof Window)
209
			this.window = (Window) data;
210
	}
211
212
	
213
	/**
214
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.AbstractMacroInstruction#load(org.w3c.dom.Node, java.util.Hashtable)
215
	 */
216
	public void load(Node node, Hashtable lineTable) throws CoreException
217
	{
218
		super.load(node, lineTable);
219
220
		/* If the corresponding shell of this command is referenced then attempt to find
221
		 * the corresponding object in the object mine. */
222
		setCorrespondingObject(MacroObjectLocator.lookupReferenceId(null, node, lineTable));		
223
		boolean useObjectMine = getCorrespondingObject() != null;
224
		setWidgetId(new WidgetIdentifier(
225
				null,
226
				new Path(useObjectMine ? getCorrespondingObject().getObjectId() : MacroUtil.getAttribute(node, MacroConstants.ID_ATTRIBUTE)),
227
				useObjectMine ? getCorrespondingObject().getResolverId() : MacroUtil.getAttribute(node, MacroConstants.RESOLVER_ATTRIBUTE)));		
228
		String codeId = MacroUtil.getAttribute(node, MacroConstants.RETURN_CODE_ATTRIBUTE);
229
		if (codeId != null)
230
		{
231
			try
232
			{
233
				expectedReturnCode = new Integer(codeId).intValue();
234
			} catch (NumberFormatException e)
235
			{
236
			}
237
		}
238
		NodeList children = node.getChildNodes();
239
		for (int i = 0; i < children.getLength(); i++)
240
		{
241
			Node child = children.item(i);
242
			if (child.getNodeType() == Node.ELEMENT_NODE)
243
			{
244
				String name = child.getNodeName();
245
				if (name.equals(MacroConstants.COMMAND_ELEMENT))
246
					processCommand(child, lineTable);
247
				else if (name.equals(MacroConstants.SHELL_ELEMENT))
248
					processShell(child, lineTable);
249
			}
250
		}
251
	}
252
253
	/**
254
	 * Used to process the node that is passed in as argument, the lineTable hashtable indicates
255
	 * the range of line numbers that the node corresponds to in the macro script
256
	 *  
257
	 * @param node The node to be processed
258
	 * @param lineTable The line number range that the node corresponds to in the script.
259
	 */
260
	private void processCommand(Node node, Hashtable lineTable) throws CoreException
261
	{
262
		IUIObject commandObject = MacroObjectLocator.lookupReferenceId(getCorrespondingObject(), node, lineTable);
263
		boolean isObjectFound = commandObject != null;
264
		
265
		String cid = isObjectFound ? commandObject.getContextId() : MacroUtil.getAttribute(node, MacroConstants.CONTEXT_ID_ATTRIBUTE);
266
		String wid = isObjectFound ? commandObject.getObjectId() : MacroUtil.getAttribute(node, MacroConstants.WIDGET_ID_ATTRIBUTE);		
267
		String rid = isObjectFound ? commandObject.getResolverId() : MacroUtil.getAttribute(node, MacroConstants.RESOLVER_ATTRIBUTE);
268
		String type = MacroUtil.getAttribute(node, MacroConstants.TYPE_ATTRIBUTE);
269
		if (type == null)
270
			return;
271
		AbstractMacroCommand command = null;
272
		WidgetIdentifier wi = (wid != null && cid != null) ? new WidgetIdentifier(new Path(cid), new Path(wid), rid) : null;
273
		
274
		
275
		if (type.equals(ModifyCommand.TYPE))
276
			command = new ModifyCommand(this, wi);
277
		
278
		else if (type.equals(BooleanSelectionCommand.TYPE))
279
			command = new BooleanSelectionCommand(this, wi);
280
		
281
		else if (type.equals(StructuredSelectionCommand.ITEM_SELECT) || type.equals(StructuredSelectionCommand.DEFAULT_SELECT))
282
			command = new StructuredSelectionCommand(this, wi, type);
283
		
284
		else if (type.equals(ExpansionCommand.TYPE))
285
			command = new ExpansionCommand(this, wi);
286
		
287
		else if (type.equals(CheckCommand.TYPE))
288
			command = new CheckCommand(this, wi);
289
		
290
		else if (type.equals(FocusCommand.TYPE))
291
			command = new FocusCommand(this, wi);
292
		
293
		else if (type.equals(ChoiceSelectionCommand.TYPE))
294
			command = new ChoiceSelectionCommand(this, wi);
295
		
296
		else if (type.equals(WaitCommand.TYPE))
297
			command = new WaitCommand(this);
298
		
299
		/* The verification command */
300
		else if (type.equals(VerificationCommand.TYPE))
301
			command = new VerificationCommand(this, new VerificationMetaData());
302
		
303
		/* The close workbench part command */
304
		else if (type.equals(CloseWorkbenchPartCommand.TYPE))
305
			command = new CloseWorkbenchPartCommand(this, wi);
306
		
307
		/* Mouse events */
308
		else if (type.equals(MouseEventCommand.TYPE0) || type.equals(MouseEventCommand.TYPE1) || type.equals(MouseEventCommand.TYPE2))
309
			command = new MouseEventCommand (this);
310
		
311
		/* Key events */
312
		else if (type.equals(KeyEventCommand.TYPE0) || type.equals(KeyEventCommand.TYPE1) || type.equals(KeyEventCommand.TYPE2))
313
			command = new KeyEventCommand (this);
314
		
315
		if (command != null)
316
		{
317
			command.setCorrespondingObject(commandObject);		
318
			command.load(node, lineTable);			
319
			commands.add(command);
320
		}
321
	}
322
323
324
	private void processShell(Node node, Hashtable lineTable) throws CoreException
325
	{
326
		MacroCommandShell shell = new MacroCommandShell(this);
327
		shell.load(node, lineTable);
328
		commands.add(shell);
329
	}
330
331
332
	public void addCommandShell(MacroCommandShell cshell)
333
	{
334
		commands.add(cshell);
335
	}
336
337
	public void write(int indent, StringBuffer sb)
338
	{
339
		/* If this shell command doesn't have any commands, then exit */
340
		if (commands == null || commands.size() <= 0)
341
			return;
342
				
343
		/* <shell */
344
		MacroUtil.addElement(sb, indent, MacroConstants.SHELL_ELEMENT, false, false);
345
		boolean objectMineInUse = MacroManager.getInstance().isObjectMineOn() && getWidgetId().getReferenceId() != null;
346
		MacroUtil.addAttribute(sb, 
347
				new String[] {	MacroConstants.DESCRIPTIVE_ATTRIBUTE,
348
								MacroConstants.RESOLVER_ATTRIBUTE,
349
								MacroConstants.ID_ATTRIBUTE,
350
								MacroConstants.REFERENCE_ID_ATTRIBUTE,
351
								MacroConstants.RETURN_CODE_ATTRIBUTE},
352
				new String[] {	getDescriptiveField(),
353
								objectMineInUse ? null : getWidgetId().getResolverId(),
354
								objectMineInUse ? null : getWidgetId().getObjectId().toString(),
355
								objectMineInUse ? getWidgetId().getReferenceId() : null,
356
								String.valueOf(expectedReturnCode)}, false, true
357
		);
358
		int cindent = indent + 1;
359
		for (int i = 0; i < commands.size(); i++)
360
		{
361
			IWritable writable = (IWritable) commands.get(i);
362
			writable.writeStart(cindent, sb);
363
			writable.write(cindent, sb);
364
			writable.writeFinish(cindent, sb);
365
		}
366
		MacroUtil.addElement(sb, indent, MacroConstants.SHELL_ELEMENT, true, true);
367
	}
368
	
369
	public String getDescriptiveField()
370
	{
371
		return shellTitle == null ? null : MacroUtil.normalizeDescriptiveField(MacroUtil.boundSize(shellTitle, AbstractMacroCommand.DESCRIPTIVE_FIELD_BOUND));
372
	}
373
374
	public void addEvent(Event event)
375
	{
376
		if (event.widget instanceof Control)
377
		{
378
			if (((Control) event.widget).isVisible() == false)
379
				return;
380
		}
381
		
382
		AbstractMacroCommand command = null;
383
		if (event.detail == MacroManager.POSITION_BASED_EVENT)
384
			command = createPositionBasedCommand(event);
385
		else
386
			command = createCommand(event);
387
		
388
		if (command != null)
389
		{			
390
			AbstractMacroCommand lastCommand = getLastCommand();
391
			
392
			/* Take out the last command if it is a focus command and the command just passed in implicitly does a focus */ 
393
			if (lastCommand != null && 
394
					(lastCommand.getWidgetId() != null && lastCommand.getWidgetId().equals(command.getWidgetId()) && lastCommand.getType().equals(FocusCommand.TYPE) && isFocusCommand(command.getType())))
395
			{
396
				// focus followed by select or modify - focus implied
397
				commands.remove(lastCommand);
398
			}
399
			
400
			/* Modify the last event accordinggly */
401
			if (ackEvent)				
402
			{
403
				ackEvent = false;
404
				lastEvent = toBeAckEvent;
405
				toBeAckEvent = null;
406
			}
407
			else
408
			{
409
				lastEvent = event;
410
			}
411
			
412
			/* Add the artificial wait time if required */
413
			if (MacroManager.getInstance().isArtificialWaitOn() && lastCommandCreationTime > 0)
414
			{
415
				long currentTime = System.currentTimeMillis();
416
				long difference = currentTime - lastCommandCreationTime;
417
				command.setTimeDifference(difference);
418
			}
419
			
420
			lastCommandCreationTime = System.currentTimeMillis();
421
			
422
			/* Ali M.: The following block of code provides a workaround for a limitation that
423
			 * exists for CloseWorkbenchPartCommand.  We are only able to capture this event
424
			 * after the entire part has been disposed.  Things would be ideal if this event
425
			 * could be captured right after the user clicks on the close button of the part */			
426
			if (command instanceof CloseWorkbenchPartCommand)
427
			{
428
				int commandSize = commands.size();
429
				if (commandSize > 0)
430
				{
431
					/* If the last command corresponds to the message dialog that prompts the
432
					 * user to save an editor, then store it after the close command */
433
					Object lastCommandStored = commands.get(commandSize - 1);
434
					if (lastCommandStored instanceof MacroCommandShell &&													/* If the last stored command is a shell */ 
435
						((CloseWorkbenchPartCommand)command).getWidgetId().getContextId().equals(MacroConstants.EDITOR_VALUE) &&				/* If the part is an editor */
436
						((MacroCommandShell)lastCommandStored).getWidgetId().getObjectId().equals(MessageDialog.class.getName()))				/* If the shell is a MessageDialog */
437
						
438
					{						
439
						commands.add(commandSize - 1 , command);
440
						return;						
441
					}
442
				}
443
				
444
			}
445
			/* Added for defect 164197 in order to add an item-expansion to the parent whenever the 
446
			 * child is selected in a case where the parent has been pre-expanded.
447
			 * Liz D.
448
			 */
449
			if (command instanceof StructuredSelectionCommand && event.widget instanceof Tree){
450
				
451
				StructuredSelectionCommand s = (StructuredSelectionCommand)command;
452
				
453
				TreeItem[] items = (TreeItem [])s.getItemsForEvent(event);
454
				for (int i=0; i<items.length; i++)
455
				{
456
					TreeItem selectedItem = (TreeItem) items[i];
457
					
458
					while(selectedItem.getParentItem()!=null)
459
					{
460
						TreeItem parent = selectedItem.getParentItem();
461
						if (parent.getExpanded()== true)
462
						{//necessary so that we only apply this in the case where the parent is already expanded
463
							Event expansionEvent = new Event();
464
							expansionEvent.widget = parent;
465
							expansionEvent.item = parent;
466
							ExpansionCommand parentExpand = new ExpansionCommand(this, command.getWidgetId());
467
							parentExpand.processEvent(expansionEvent, true);
468
							commands.add(parentExpand);
469
						}
470
						selectedItem = parent;
471
					}// end while			
472
				}		
473
			}
474
						
475
			commands.add(command);}
476
		
477
	}
478
479
	
480
	/**
481
	 * Adds a wait command for as long as the last command is not already a wait (i.e.
482
	 * duplicate addition of wait commands are avoided through this method)
483
	 */
484
	public void addPause()
485
	{
486
		WaitCommand command = new WaitCommand(this);
487
		
488
		Object lastCommand = null;
489
		int commandSize = commands.size();
490
		boolean isLastCommandWait = false;
491
		
492
		if (commandSize <= 0)
493
			return;
494
		
495
		lastCommand = commands.get (commandSize - 1);
496
		int lastCmdInx = 2;
497
		
498
		/* Avoid MacroCommandShells that have no commands (since these will not be included 
499
		 * as part of the macro) */
500
		while (lastCommand instanceof MacroCommandShell && ((MacroCommandShell)lastCommand).getCommands().size() <= 0) 
501
		{
502
			if (commandSize - lastCmdInx >= 0)
503
				lastCommand = commands.get (commandSize - lastCmdInx);
504
			else
505
			{
506
				lastCommand = null;
507
				break;
508
			}
509
			
510
			lastCmdInx++;
511
		}
512
		
513
		AbstractMacroCommand lastMacroCommand = null;
514
		if (lastCommand instanceof AbstractMacroCommand)
515
			lastMacroCommand = (AbstractMacroCommand)lastCommand;
516
		
517
		isLastCommandWait = lastMacroCommand != null && lastMacroCommand.getType() == WaitCommand.TYPE;
518
		if (commands.size() > 0 && !isLastCommandWait)
519
		{
520
			commands.add(command);				
521
		}
522
	}
523
524
	public void addVerificationCommand (VerificationCommand command)
525
	{
526
		commands.add(command);
527
	}
528
	
529
	public void extractExpectedReturnCode()
530
	{
531
		if (window != null)
532
			expectedReturnCode = window.getReturnCode();
533
	}
534
535
	public boolean matchesReturnCode()
536
	{
537
		if (window != null)
538
		{
539
			return window.getReturnCode() == expectedReturnCode;
540
		}
541
		return true;
542
	}
543
544
	private boolean isFocusCommand(String type)
545
	{
546
		return type.equals(BooleanSelectionCommand.TYPE) || type.equals(StructuredSelectionCommand.ITEM_SELECT) || type.equals(StructuredSelectionCommand.DEFAULT_SELECT) || type.equals(ExpansionCommand.TYPE) || type.equals(CheckCommand.TYPE) || type.equals(ModifyCommand.TYPE);
547
	}
548
549
	/**
550
	 * Handles position-based events 
551
	 */
552
	protected AbstractMacroCommand createPositionBasedCommand (Event event)
553
	{
554
		AbstractMacroCommand command = null;
555
		
556
		switch (event.type)
557
		{
558
			case SWT.MouseUp:
559
			case SWT.MouseDown:
560
			case SWT.MouseDoubleClick:
561
				command = new MouseEventCommand (this);			
562
				break;
563
			
564
			case SWT.KeyUp:
565
			case SWT.KeyDown:
566
				command = new KeyEventCommand (this);
567
				break;
568
			
569
		}
570
		
571
		if (command != null)
572
			command.processEvent (event);
573
		return command;
574
	}
575
	
576
	
577
	/**
578
	 *  Handles object-based events
579
	 */
580
	protected AbstractMacroCommand createCommand(Event event)
581
	{	
582
		/* A quick way to get out if we're only getting key up or mouse events that have been detected before */
583
		if ((isKeyPressed && event.type == SWT.KeyUp) || (isMousePressed && event.type == SWT.MouseUp))
584
			return null;
585
		
586
		AbstractMacroCommand lastCommand = getLastCommand();
587
		if (lastEvent != null && lastEvent.widget != null && lastEvent.widget.equals(event.widget))
588
		{
589
			if (lastEvent.type == event.type || (lastEvent.type == SWT.Selection && event.type == SWT.DefaultSelection))
590
			{
591
				if (lastCommand != null && lastCommand.mergeEvent(event))
592
					return null;
593
			}
594
		}
595
				
596
		AbstractMacroCommand command = null;
597
		
598
		/* Check to see if we are a drop-down menu selection */
599
		if (lastCommand != null && lastCommand.getType() == BooleanSelectionCommand.TYPE && 
600
				((BooleanSelectionCommand)lastCommand).getDetail() == SWT.DROP_DOWN)
601
		{
602
			((BooleanSelectionCommand)lastCommand).setItemSelected (event);
603
			return null;
604
		}
605
				
606
		
607
		WidgetIdentifier wi = MacroUtil.getWidgetIdentifier(event.widget);		
608
		if (wi == null)
609
			wi = MacroUtil.getCustomEventIdentifier(event);				
610
		if (wi == null)
611
			return null;
612
		
613
		
614
		switch (event.type)
615
		{
616
			case SWT.Modify:				
617
				if (!isEditable(event.widget))
618
					return null;
619
				
620
				/* This block of code is used to avoid displaying the browse native dialog when the user clicks
621
				 * a browse button - it doesn't cover all cases */
622
				if (lastEvent != null && lastEvent.type == SWT.Selection && lastEvent.widget instanceof Button)
623
				{
624
					String text = ((Button)lastEvent.widget).getText();
625
					if (text != null)
626
					{
627
						text = text.replaceAll("\\&", "");
628
						text = text.toLowerCase();
629
						if (text.indexOf(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_BROWSE) != -1)
630
						{
631
							ArrayList commands = this.getCommands();
632
							int size = 0;
633
							if (commands != null && (size = commands.size()) > 0)
634
							{
635
								commands.remove(size - 1);					
636
								command = new ModifyCommand(this, MacroUtil.getWidgetIdentifier(event.widget));
637
								break;
638
							}
639
						}
640
					}				
641
				}
642
				
643
				/* Only acknowledge modifies that are followed by a key up event */
644
				toBeAckEvent = event;								
645
				break;
646
			
647
			case SWT.Selection:
648
			case SWT.DefaultSelection:
649
				command = createSelectionCommand(wi, event);				
650
				break;
651
			
652
			case SWT.FocusIn:
653
				/**
654
				 * Ali M.: While recording, the SWT display listener has the tendency to report
655
				 * focus events on controls that are actually not visible to the user.  When the
656
				 * macro is played back, the control cannot be located.  To avoid this problem
657
				 * we only acknowledge focus events that are followed by a mouse up or key up event (i.e.
658
				 * The user explicitly focuses on the control).
659
				 */
660
				toBeAckEvent = event;
661
				break;
662
			
663
			case SWT.Expand:
664
			case SWT.Collapse:
665
				command = new ExpansionCommand(this, wi);
666
				
667
				break;
668
				
669
			case SWT.KeyUp:
670
				isKeyPressed = true;	
671
				if (toBeAckEvent != null && toBeAckEvent.type == SWT.Modify)
672
				{
673
					command = new ModifyCommand(this, MacroUtil.getWidgetIdentifier(toBeAckEvent.widget));
674
					ackEvent = true;
675
					break;
676
				}
677
				
678
			case SWT.MouseUp:
679
				isMousePressed = true;	
680
				if (toBeAckEvent != null && toBeAckEvent.type == SWT.FocusIn)
681
				{
682
					command = new FocusCommand(this, MacroUtil.getWidgetIdentifier(toBeAckEvent.widget));
683
					ackEvent = true;
684
				}
685
				break;
686
			case Macro.WORKBENCH_PART_CLOSED:
687
				/* 110810 -- Create the close workbench command only if there is only one frame
688
				 * in our shell stack */
689
				if (MacroManager.getInstance().getCurrentMacro().getShellStackSize() == 1)
690
					command = new CloseWorkbenchPartCommand (this, wi); 
691
				break;
692
		}
693
		
694
		if (event.type != SWT.KeyUp)
695
			isKeyPressed = false;
696
		else if (event.type != SWT.MouseUp)
697
			isMousePressed = false;
698
		
699
		
700
		if (command != null)
701
		{
702
			/* Lookup the widget of this command.  If it already exists in our object mine, then
703
			 * have it referenced by setting the reference id of the command. */
704
			IObjectMine objectMine = MacroManager.getInstance().getObjectMine();
705
			IUIObject uiObject = null;
706
			WidgetIdentifier commandWidgetIdentifier = command.getWidgetId();
707
			boolean needsDescriptiveField = false;
708
			try
709
			{
710
				IUIObject activeObject = objectMine.getActiveObject();
711
				uiObject = objectMine.lookupUIObject(activeObject, commandWidgetIdentifier.getContextId() == null ? null : commandWidgetIdentifier.getContextId().toString(), commandWidgetIdentifier.getObjectId().toString());
712
				
713
				/* The object is not registered with the object mine - register it */
714
				if (uiObject == null)
715
				{
716
					needsDescriptiveField = true;
717
					uiObject = UIObject.createInstance(objectMine, command, activeObject);
718
					objectMine.registerObject(uiObject);
719
				}
720
				commandWidgetIdentifier.setReferenceId(uiObject.getReferenceId());				
721
			} 
722
			
723
			/* We can't afford to show an error message in case of an unexpected error during 
724
			 * registeration.  We'll ignore the error and not make use of the object mine. */
725
			catch (UIObjectNotFound e)
726
			{
727
				/* Should not happen */
728
			} catch (IDCollisionException e)
729
			{
730
				/* Should not happen */
731
			} catch (CoreException e)
732
			{
733
				/* Should not happen */
734
			}
735
						
736
			command.processEvent(event);
737
			
738
			if (needsDescriptiveField && uiObject != null)
739
			{
740
				uiObject.setDescriptive(command.getObjectClassName(event.widget) + (command.getDescriptiveField() == null ? MacroConstants.EMPTY_STRING : ": " + command.getDescriptiveField()));
741
			}
742
		}
743
		
744
		/* Ensure that redundant commands are not created */
745
		if (lastCommand != null && command != null && command.isRepeatRedundant() && command.equals(lastCommand))
746
		{
747
			return null;
748
		}
749
		return command;
750
	}
751
752
	private boolean isEditable(Widget widget)
753
	{
754
		if (widget instanceof Control)
755
		{
756
			Control control = (Control) widget;
757
			if (!control.isEnabled())
758
				return false;
759
			if (control instanceof Text)
760
				return ((Text) control).getEditable();
761
			if (control instanceof Combo || control instanceof CCombo)
762
				return ((control.getStyle() & SWT.READ_ONLY) == 0);
763
			if (control instanceof StyledText)
764
				return ((StyledText) control).getEditable();
765
		}
766
		return true;
767
	}
768
769
	private AbstractMacroCommand createSelectionCommand(WidgetIdentifier wid, Event event)
770
	{				
771
		if (event.widget instanceof MenuItem || event.widget instanceof ToolItem || (event.widget instanceof Button
772
				/* A CCombo will cause a button selection followed by a combo selection.  
773
				 * We need to ignore the button selection */
774
				&& !(event.widget instanceof Control && ((Control)event.widget).getParent() instanceof CCombo)))
775
		{						
776
			if (event.x != 0 || event.y != 0 || event.detail != 0)
777
				return new BooleanSelectionCommand(this, wid, new Point (event.x, event.y), event.detail);
778
			return new BooleanSelectionCommand(this, wid);			
779
		}
780
		
781
		if (event.widget instanceof Tree || event.widget instanceof Table || event.widget instanceof List)
782
		{
783
			if (event.detail == SWT.CHECK)
784
				return new CheckCommand(this, wid);
785
			String type = event.type == SWT.DefaultSelection ? StructuredSelectionCommand.DEFAULT_SELECT : StructuredSelectionCommand.ITEM_SELECT;
786
			return new StructuredSelectionCommand(this, wid, type);
787
		}
788
		
789
		if (event.widget instanceof TabFolder || event.widget instanceof CTabFolder)
790
			return new ChoiceSelectionCommand(this, wid);
791
		
792
		if (event.widget instanceof Combo || event.widget instanceof CCombo)
793
			return new ChoiceSelectionCommand(this, wid);
794
		
795
		return null;
796
	}
797
798
799
	private AbstractMacroCommand getLastCommand()
800
	{
801
		if (commands.size() > 0)
802
		{
803
			Object item = commands.get(commands.size() - 1);
804
			if (item instanceof AbstractMacroCommand)
805
				return (AbstractMacroCommand) item;
806
		}
807
		return null;
808
	}
809
810
	public boolean isDisposed()
811
	{
812
		return this.shell != null && this.shell.isDisposed();
813
	}
814
815
	public void close()
816
	{
817
		if (this.shell != null && !this.shell.isDisposed())
818
			this.shell.close();
819
	}
820
821
	public boolean tracks(Shell shell)
822
	{
823
		if (this.shell != null && this.shell.equals(shell))
824
			return true;
825
		return false;
826
	}
827
	
828
	public boolean playback(final Display display, Composite parent, final IProgressMonitor monitor) throws CoreException
829
	{		
830
		if (parent instanceof Shell)
831
		{
832
			this.shell = (Shell) parent;
833
			this.display = display;
834
			hookWindow(true);
835
		}
836
837
		NestedShell nestedShell = null;
838
		int commandSize = commands.size();
839
		monitor.beginTask("", commandSize);
840
		final int commandTimeOut;
841
		
842
		int potentialTimeoutValue = MacroManager.getInstance().getCommandTimeoutThreshold();
843
		if (MacroManager.getInstance().getCommandTimeoutThreshold() > 0)
844
			commandTimeOut = potentialTimeoutValue;
845
		else
846
			commandTimeOut = GlobalConstants.DEFAULT_COMMAND_TIME_OUT_PERIOD;
847
			
848
		for (int i = 0; i < commandSize; i++)
849
		{
850
			currentCommandInx = i;
851
			checkForInterruptions();							
852
			Object c = commands.get(i);
853
			final IPlayable playable = (IPlayable) c;
854
			
855
			/* If this is the last command of this macro command shell, then take out its entry in the shell queue */	
856
			if (isLastCommand(i))
857
			{
858
				if (getNestedShellQueue() != null && getNestedShellQueue().size() > 0)
859
				{
860
					if (lastNestedShellInx > 0)
861
						lastNestedShellInx--;
862
					removeNestedShell(0);
863
				}
864
			}
865
			
866
			/* If this command is a nested shell, then we need to wait until it completes before proceeding to the next command. */
867
			if (c instanceof MacroCommandShell)
868
			{
869
				MacroCommandShell nestedCommandShell = (MacroCommandShell)c;
870
				//System.out.println("NESTED SHELL WAIT: " + nestedCommandShell.getId());
871
				Object lastNestedCommand = null;
872
				Object currentNestedCommand = null;
873
				synchronized (nestedCommandShell)
874
				{
875
					/* Give each command in the nested shell a maximum of commandTimeOut to execute */
876
					while (!nestedCommandShell.isComplete() && (currentNestedCommand == null || lastNestedCommand != currentNestedCommand) && !interruptProcess)
877
					{
878
						try 
879
						{
880
							nestedCommandShell.wait(commandTimeOut);
881
							lastNestedCommand = currentNestedCommand;
882
							currentNestedCommand = nestedCommandShell.getCommandBeingExecuted();
883
						} catch (InterruptedException e) 
884
						{
885
							/* Handled by next set of code */
886
						}
887
					}
888
					
889
					/* Indicate an error if the nested shell never completed */
890
					if (!nestedCommandShell.isComplete())
891
					{							
892
						synchronized (mutualGlobalLock)
893
						{
894
							interruptProcess = true;
895
							if (interruptedException == null)
896
								interruptedException = new CoreException (new Status(IStatus.ERROR, GuiPlugin.getID(), 0, 
897
										NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_NEST_TOUT, nestedCommandShell.getWidgetId().getObjectId().toString()), null));
898
						}
899
						
900
						continue;	/* Interrupt the normal flow */
901
					}
902
					//System.out.println("NESTED SHELL FINISH: " + nestedCommandShell.getId());
903
				}
904
			}
905
			
906
			if (i < commandSize - 1)
907
			{
908
				/* Ali M.: We need to iterate through all the shell commands and register listeners
909
				 * before it's too late.  It's not sufficient to just register a listener with the 
910
				 * next command */
911
				int counter = 1;
912
				IPlayable next = (IPlayable) commands.get(i + counter);
913
				while (next instanceof MacroCommandShell)
914
				{					
915
					/* This command will open a new shell.  Add a listener before it is too late */
916
					MacroCommandShell nestedCommand = (MacroCommandShell) next;
917
					
918
					if (!nestedCommand.isListenerRegistered())
919
					{
920
						nestedShell = new NestedShell(display, nestedCommand, new SubProgressMonitor(monitor, 1));
921
						final NestedShell fnestedShell = nestedShell;
922
923
						
924
						/* If this is a child of the previous shell, then it takes precedence.  If it's a sibling, then it
925
						 * should go to the end of the queue. */
926
						nestedCommand.setListenerRegistered(true);
927
						if (nestedShellQueue.size() > 0 && ((NestedShell)nestedShellQueue.get(0)).isParent(nestedCommand))
928
						{
929
							addNestedShell(0, fnestedShell);
930
							lastNestedShellInx = 0;
931
						}
932
						else
933
						{
934
							if (nestedShellQueue.size() > 0)
935
								addNestedShell(++lastNestedShellInx, fnestedShell);
936
							else
937
								addNestedShell(fnestedShell);							
938
						}
939
						
940
						display.syncExec(new Runnable()
941
								{
942
									public void run()
943
									{
944
										//System.out.println("ADDED");
945
										display.addFilter(SWT.Activate, fnestedShell);
946
									}
947
								});						
948
					}
949
					counter++;
950
					next = (i + counter <= commandSize - 1 ? (IPlayable) commands.get(i + counter) : null);					
951
				}
952
			}
953
			if (playable instanceof AbstractMacroCommand)
954
			{			
955
				final boolean last = i == commandSize - 1;	
956
				
957
				
958
				class WakeUpOperaion implements Runnable
959
				{
960
					private AbstractMacroCommand command;
961
					private boolean invalidate;
962
					
963
					public WakeUpOperaion (AbstractMacroCommand command)
964
					{
965
						this.command = command;
966
						invalidate = false;
967
					}
968
					
969
					public void run() 
970
					{
971
						if (!invalidate && MacroCommandShell.lastCommandLineExecuted == command.getStartLine())
972
						{
973
							/* Ali M.: A command just timed-out.  We need to indicate the error 
974
							 * and wakeup the thread */
975
							synchronized (mutualGlobalLock)
976
							{
977
								interruptProcess = true;								
978
								if (interruptedException == null)
979
									interruptedException = new CoreException (new Status(IStatus.ERROR, GuiPlugin.getID(), 0, 
980
										NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_TIME_OUT, command.toString()), null));
981
							}
982
							
983
							synchronized (mutualLock)
984
							{
985
								mutualLock.notify();
986
							}
987
						}
988
					}
989
					
990
					public void invalidate()
991
					{
992
						this.invalidate = true;
993
					}
994
995
				}					
996
				WakeUpOperaion wakeupOpt = null;
997
				if (i < commandSize - 1)
998
				{				
999
					wakeupOpt = new WakeUpOperaion ((AbstractMacroCommand)playable);
1000
					final Runnable wakeupOperation = wakeupOpt;					
1001
					display.asyncExec(
1002
						new Runnable()
1003
						{
1004
							public void run() 
1005
							{
1006
								display.timerExec(commandTimeOut, wakeupOperation);
1007
							};
1008
							
1009
						}	
1010
					);
1011
				}
1012
					
1013
				
1014
				class RunCommandOperation implements Runnable
1015
				{
1016
					private boolean isComplete;
1017
					
1018
					public void run()
1019
					{ 
1020
						try 
1021
						{						
1022
							if (!macroCommandsBeingPlayed.contains(this))
1023
								macroCommandsBeingPlayed.add(this);
1024
							
1025
							lastCommandLineExecuted = ((AbstractMacroCommand)playable).getStartLine();
1026
							playInGUIThread(display, playable, last, monitor);	
1027
							
1028
							macroCommandsBeingPlayed.remove(this);
1029
							isComplete = true;
1030
							synchronized (mutualLock) 
1031
							{
1032
								mutualLock.notify();
1033
							}
1034
						}
1035
						catch (Throwable e) 
1036
						{					
1037
							macroCommandsBeingPlayed.remove(this);
1038
							synchronized (mutualGlobalLock)
1039
							{
1040
								interruptProcess = true;
1041
								if (interruptedException == null)
1042
									interruptedException = e;
1043
							}
1044
							isComplete = true;
1045
							synchronized (mutualLock)
1046
							{
1047
								mutualLock.notify();
1048
							}
1049
						} 
1050
					} 
1051
					
1052
					public boolean isComplete()
1053
					{
1054
						return isComplete;
1055
					}
1056
1057
				}
1058
				
1059
				RunCommandOperation runCommandOpt = new RunCommandOperation();
1060
				
1061
1062
				/* Run the command */
1063
				synchronized (mutualLock)
1064
				{					
1065
					new Thread(runCommandOpt).start();
1066
					long start = System.currentTimeMillis();
1067
					long wakeUpTime = start;
1068
					long timeToSleep = commandTimeOut;
1069
					try 
1070
					{
1071
						while (!runCommandOpt.isComplete() && timeToSleep > 0 && !interruptProcess)
1072
						{
1073
							//System.out.println("WAITING on command: " + playable);
1074
							mutualLock.wait(timeToSleep);
1075
							wakeUpTime = System.currentTimeMillis();
1076
							timeToSleep = timeToSleep - (wakeUpTime - start);
1077
						}
1078
					} catch (InterruptedException e) 
1079
					{
1080
						/* Doesn't need to be handled */
1081
					}
1082
					
1083
					/* Indicate an error if command didn't complete */
1084
					if (!runCommandOpt.isComplete())
1085
					{	
1086
						synchronized (mutualGlobalLock)
1087
						{
1088
							interruptProcess = true;
1089
							if (interruptedException == null)
1090
								interruptedException = new CoreException (new Status(IStatus.ERROR, GuiPlugin.getID(), 0, 
1091
										NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_TIME_OUT, playable.toString()), null));							
1092
						}
1093
					}	
1094
					/* Otherwise invalidate the wake up operation that was suppose to wake this
1095
					command up */
1096
					else if (wakeupOpt != null)
1097
						wakeupOpt.invalidate();
1098
					
1099
					//System.out.println("FINISHED WAITING on command: " + playable);
1100
				}
1101
								
1102
				monitor.worked(1);
1103
			} 			
1104
		}
1105
		
1106
		checkForInterruptions();
1107
		shell = null;
1108
		
1109
		/* We made it out alive -- mark this as complete and wake any parents that are waiting upon our completion */
1110
		isComplete = true;
1111
		synchronized(this)
1112
		{
1113
			this.notify();
1114
		}
1115
		
1116
		macroCommandShellContainer.remove(this);
1117
		return true;
1118
	}
1119
1120
1121
	private boolean isComplete() 
1122
	{	
1123
		return isComplete;
1124
	}
1125
1126
	private Object getCommandBeingExecuted() 
1127
	{
1128
		if (commands == null || currentCommandInx >= commands.size())
1129
			return null;
1130
		return commands.get(currentCommandInx);
1131
	}
1132
1133
	private void checkForInterruptions() throws CoreException
1134
	{
1135
		if (interruptProcess)
1136
		{	
1137
			/* Wake up all threads in case they are asleep */
1138
			if (!processTerminated)
1139
			{
1140
				processTerminated = true;
1141
				interruptOperation();				
1142
				MacroCommandShell.macroStopped();
1143
				MacroUtil.closeSecondaryShells(display);			
1144
			}
1145
						
1146
			for (int i = 0; i < macroCommandShellContainer.size(); i++)
1147
			{
1148
				synchronized (mutualLock)
1149
				{
1150
					mutualLock.notify();
1151
				}
1152
				
1153
				synchronized (macroCommandShellContainer.get(i))
1154
				{
1155
					macroCommandShellContainer.get(i).notify();
1156
				}
1157
			}
1158
			
1159
			/* Try to close all nested shells */
1160
			synchronized (mutualGlobalLock)
1161
			{
1162
				if (interruptedException instanceof CoreException)
1163
					throw (CoreException)interruptedException;
1164
				throw new CoreException (new Status(IStatus.ERROR, GuiPlugin.getID(), 0, interruptedException.getLocalizedMessage(), interruptedException));
1165
			}
1166
		}
1167
		
1168
	}
1169
1170
	/**
1171
	 * A helper method that walks through all macro command shells and 
1172
	 * interrupts their normal flow.
1173
	 */
1174
	private void interruptOperation() 
1175
	{
1176
		MacroCommandShell currentMacroShell = this;
1177
		while (currentMacroShell != null)
1178
		{
1179
			Boolean lock = currentMacroShell.mutualLock;
1180
			synchronized(lock)
1181
			{
1182
				lock.notify();
1183
			}
1184
			
1185
			currentMacroShell = currentMacroShell.getParent();
1186
		}
1187
		
1188
	}
1189
1190
	private boolean isLastCommand(int index) 
1191
	{
1192
		for (int i = index + 1; i < commands.size(); i++)
1193
		{
1194
			if (commands.get(i) instanceof AbstractMacroCommand)
1195
				return false;
1196
		}
1197
		return true;
1198
	}
1199
1200
	private void playInGUIThread(final Display display, final IPlayable playable, boolean last, final IProgressMonitor monitor) throws CoreException
1201
	{
1202
		final CoreException[] ex = new CoreException[1];
1203
1204
		Runnable runnable = new Runnable()
1205
		{
1206
			public void run()
1207
			{
1208
				try
1209
				{						
1210
					boolean status = playable.playback(display, MacroCommandShell.this.shell, monitor);
1211
					
1212
					/* Something went wrong playing this item */
1213
					if (!status)
1214
						ex[0] = createPlaybackException(playable, null);
1215
					else
1216
						MacroUtil.processDisplayEvents(display);
1217
				} 
1218
				catch (ClassCastException e)
1219
				{
1220
					ex[0] = createPlaybackException(playable, e);
1221
				} 
1222
				catch (CoreException e)
1223
				{
1224
					ex[0] = e;
1225
				}
1226
				catch (SWTException e)
1227
				{
1228
					/* Don't handle */
1229
				}
1230
				catch (Throwable error)
1231
				{
1232
					ex[0] = createPlaybackException(playable, error);
1233
				}
1234
			}
1235
		};
1236
1237
		if (playable instanceof WaitCommand)
1238
		{
1239
			playable.playback(display, this.shell, monitor);
1240
		} 
1241
		else
1242
		{
1243
			display.syncExec(runnable);			
1244
		}
1245
					
1246
		try
1247
		{
1248
			Thread.sleep(100);
1249
		} catch (InterruptedException e)
1250
		{
1251
		}
1252
1253
		if (ex[0] != null)
1254
			throw ex[0];
1255
				
1256
	}
1257
1258
	private CoreException createPlaybackException(IPlayable playable, Throwable th)
1259
	{
1260
		IStatus status = new Status(IStatus.ERROR, "org.eclipse.pde.ui.tests", IStatus.OK, NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_COMMAND, playable.toString()), th);
1261
		return new CoreException(status);
1262
	}
1263
	
1264
	
1265
	public ArrayList getCommands()
1266
	{
1267
		return commands;
1268
	}
1269
1270
	public boolean isListenerRegistered() {
1271
		return isListenerRegistered;
1272
	}
1273
1274
	public void setListenerRegistered(boolean isListenerRegistered) {
1275
		this.isListenerRegistered = isListenerRegistered;
1276
	}
1277
1278
	public static Vector getNestedShellQueue() 
1279
	{
1280
		return nestedShellQueue;
1281
	}
1282
	
1283
	public static void addNestedShell(int inx, NestedShell nestedShell)
1284
	{
1285
		synchronized (nestedShellQueue)
1286
		{
1287
			if (inx >= 0)
1288
				nestedShellQueue.add(inx, nestedShell);
1289
			else
1290
				nestedShellQueue.add(nestedShell);
1291
		}
1292
	}
1293
	
1294
	private static void addNestedShell(NestedShell fnestedShell) 
1295
	{
1296
		addNestedShell (-1, fnestedShell);		
1297
	}
1298
	
1299
	
1300
	public static void removeNestedShell(int inx)
1301
	{
1302
		synchronized (nestedShellQueue)
1303
		{
1304
			nestedShellQueue.remove(inx);
1305
		}
1306
	}
1307
	
1308
	
1309
	public static void initializeForNewPlay()
1310
	{
1311
		nestedShellQueue.clear();
1312
		lastNestedShellInx = 0;
1313
		interruptProcess = false;
1314
		processTerminated = false;
1315
		interruptedException = null;
1316
		MouseEventCommand.init();
1317
		macroCommandsBeingPlayed.clear();
1318
		macroCommandShellContainer.clear();
1319
	}
1320
1321
	public Shell getShell() {
1322
		return shell;
1323
	}
1324
	
1325
	public void writeStart(int indent, StringBuffer sb)
1326
	{
1327
		/* Doesn't need to be implemented */		
1328
	}
1329
1330
	public void writeFinish(int indent, StringBuffer sb)
1331
	{
1332
		/* Doesn't need to be implemented */	
1333
	}
1334
1335
	public MacroCommandShell getParent() {
1336
		return parent;
1337
	}
1338
1339
	public void setParent(MacroCommandShell parent) {
1340
		this.parent = parent;
1341
	}
1342
1343
	public static void macroStopped() 
1344
	{
1345
		/* Walk through nested shell listeners and remove them if any exists */
1346
		final Display display = GuiPlugin.getDefault().getWorkbench().getDisplay();
1347
		display.syncExec(new Runnable(){
1348
1349
			public void run() {
1350
				for (int i = 0, nestedShellListenerSize = nestedShellQueue.size(); i < nestedShellListenerSize; i++)
1351
				{
1352
					display.removeFilter(SWT.Activate, (NestedShell)nestedShellQueue.get(i));	
1353
				}				
1354
			}
1355
		});					
1356
	}
1357
1358
	public static Vector getMacroCommandsBeingPlayed() {
1359
		return macroCommandsBeingPlayed;
1360
	}
1361
		
1362
	public String getReferenceId()
1363
	{
1364
		return referenceId;
1365
	}
1366
1367
	public void setReferenceId(String referenceId)
1368
	{
1369
		this.referenceId = referenceId;
1370
	}
1371
	
1372
	
1373
	private static class NestedShell implements Listener, Runnable
1374
	{
1375
		private MacroCommandShell cshell;
1376
1377
		private Display display;
1378
1379
		private Shell nshell;
1380
1381
		private boolean released;
1382
1383
		private CoreException exception;
1384
1385
		private IProgressMonitor monitor;
1386
1387
		private boolean served;		
1388
				
1389
		public NestedShell(Display display, MacroCommandShell cshell, IProgressMonitor monitor)
1390
		{
1391
			this.display = display;
1392
			this.cshell = cshell;
1393
			this.monitor = monitor;
1394
		}
1395
1396
		public void handleEvent(Event e)
1397
		{
1398
			try
1399
			{
1400
				if (e.widget instanceof Shell)
1401
				{
1402
					// shell activated
1403
					Shell shell = (Shell) e.widget;
1404
					IPath path = new Path(MacroUtil.getShellId(shell, null).toString());
1405
					String sid = path.toString();
1406
					
1407
					/* Debug */
1408
					//System.out.println();
1409
					//System.out.println(sid + " : " + cshell.getId());
1410
					//if (MacroCommandShell.getNestedShellQueue() != null && MacroCommandShell.getNestedShellQueue().size() > 0)
1411
						//System.out.println("Is Served: " + ((NestedShell)MacroCommandShell.getNestedShellQueue().get(0)).isServed());
1412
					//System.out.println(this + " : " + MacroCommandShell.getNestedShellQueue().get(0));
1413
					//System.out.println();  
1414
					
1415
					if (sid.equals(cshell.getWidgetId().getObjectId().toString()) && 
1416
									(MacroCommandShell.getNestedShellQueue() == null || 
1417
									MacroCommandShell.getNestedShellQueue().size() <= 0 || 
1418
									(!((NestedShell)MacroCommandShell.getNestedShellQueue().get(0)).isServed() && this.equals(MacroCommandShell.getNestedShellQueue().get(0)))))
1419
					{
1420
						//System.out.println("REMOVED FILTER: " + cshell.getId());
1421
						shell.getDisplay().removeFilter(SWT.Activate, this);
1422
						released = true;
1423
						this.nshell = shell;
1424
						
1425
						/* We need to start this in a separate thread.  MacroCommandShells should not be played in UI threads (otherwise wait commands
1426
						 * will not work properly) */					
1427
						this.setServed(true);
1428
						new Thread(this).start();					
1429
					}
1430
				}
1431
			}
1432
			catch (Throwable t)
1433
			{
1434
				//System.out.println("REMOVED filter");
1435
				/* Something unexpected has happened -- Remove this listener */
1436
				e.display.removeFilter(SWT.Activate, this);
1437
			}
1438
		}
1439
1440
		public void setServed(boolean served) 
1441
		{
1442
			this.served = served;			
1443
		}
1444
		
1445
		public boolean isServed()
1446
		{
1447
			return served;
1448
		}
1449
1450
		public boolean getResult()
1451
		{
1452
			return cshell.matchesReturnCode();
1453
		}
1454
1455
		public boolean isReleased()
1456
		{
1457
			return released;
1458
		}
1459
1460
		public void run()
1461
		{
1462
			try
1463
			{				
1464
				cshell.playback(display, nshell, monitor);					
1465
			} 
1466
			catch (CoreException e)
1467
			{
1468
				synchronized (mutualGlobalLock)
1469
				{
1470
					interruptProcess = true;
1471
					if (interruptedException == null)
1472
						interruptedException = e;
1473
				}
1474
				
1475
				synchronized (cshell.mutualLock)
1476
				{
1477
					cshell.mutualLock.notify();
1478
				}
1479
			}
1480
		}
1481
1482
		public CoreException getException()
1483
		{
1484
			return exception;
1485
		}
1486
1487
		public boolean isParent(MacroCommandShell macroCommandShell) 
1488
		{
1489
			return macroCommandShell.getParent().equals(cshell);			
1490
		}
1491
	}
1492
	
1493
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/AbstractStructuredCommand.java (-383 / +401 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 17-27 Link Here
17
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.core.runtime.CoreException;
18
import org.eclipse.core.runtime.IProgressMonitor;
18
import org.eclipse.core.runtime.IProgressMonitor;
19
import org.eclipse.hyades.test.common.util.XMLUtil;
19
import org.eclipse.hyades.test.common.util.XMLUtil;
20
import org.eclipse.swt.widgets.Composite;
21
import org.eclipse.swt.widgets.Display;
20
import org.eclipse.swt.widgets.Display;
22
import org.eclipse.swt.widgets.Event;
21
import org.eclipse.swt.widgets.Event;
23
import org.eclipse.swt.widgets.Item;
22
import org.eclipse.swt.widgets.Item;
24
import org.eclipse.swt.widgets.List;
23
import org.eclipse.swt.widgets.List;
24
import org.eclipse.swt.widgets.Shell;
25
import org.eclipse.swt.widgets.Table;
25
import org.eclipse.swt.widgets.Table;
26
import org.eclipse.swt.widgets.TableItem;
26
import org.eclipse.swt.widgets.TableItem;
27
import org.eclipse.swt.widgets.Tree;
27
import org.eclipse.swt.widgets.Tree;
Lines 30-96 Link Here
30
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
30
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
31
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
31
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
32
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
32
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
33
import org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine;
33
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
34
import org.eclipse.tptp.test.auto.gui.internal.core.IUIObject;
35
import org.eclipse.tptp.test.auto.gui.internal.core.IWidgetId;
36
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
37
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
34
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
38
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
35
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
39
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroObjectLocator;
40
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
36
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
41
import org.eclipse.tptp.test.auto.gui.internal.macro.UIObject;
37
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptor;
42
import org.eclipse.tptp.test.auto.gui.internal.resolvers.PrimitiveWidgetId;
38
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine;
39
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
40
import org.eclipse.tptp.test.auto.gui.internal.uiobject.PrimitiveUIObjectIdentifier;
41
import org.eclipse.tptp.test.auto.gui.internal.uiobject.UIObject;
42
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.UIObjectResolver;
43
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.deresolvingsupport.UIObjectDeprecatedDeresolvingSupport;
43
import org.w3c.dom.Node;
44
import org.w3c.dom.Node;
44
import org.w3c.dom.NodeList;
45
import org.w3c.dom.NodeList;
45
46
46
/**
47
/**
47
 * An abstract structured command that other commands can optionally
48
 * An abstract structured command that other commands can optionally extend.
48
 * extend.
49
 * 
49
 * 
50
 * @author Ali Mehregani
50
 * @author Ali Mehregani
51
 * @author Alexander Nyssen
51
 */
52
 */
52
public abstract class AbstractStructuredCommand extends AbstractMacroCommand
53
public abstract class AbstractStructuredCommand extends ObjectBasedCommand {
53
{
54
54
	/** 
55
	/**
55
	 * The items that are associated with the structured selection.  The list contains 
56
	 * The items that are associated with the structured selection. The list
56
	 * Hashtable entries with the following content:
57
	 * contains Hashtable entries with the following content: KEY = XML
57
	 * KEY = XML attribute of the item
58
	 * attribute of the item VALUE = The value of the attribute
58
	 * VALUE = The value of the attribute
59
	 */
59
	 */
60
	protected ArrayList items;
60
	protected ArrayList items;
61
	
61
62
	
63
	/**
62
	/**
64
	 * The constructor
63
	 * The constructor
65
	 * 
64
	 * 
66
	 * @param parent The parent macro command shell owning this command
65
	 * @param parent
67
	 * @param wid The widget identifier
66
	 *            The parent macro command shell owning this command
67
	 * @param wid
68
	 *            The widget identifier
68
	 */
69
	 */
69
	public AbstractStructuredCommand(MacroCommandShell parent, WidgetIdentifier wid)
70
	public AbstractStructuredCommand(MacroCommandShell parent) {
70
	{
71
		super(parent);
71
		super(parent, wid);
72
		items = new ArrayList();
72
		items = new ArrayList();
73
	}
73
	}
74
74
75
	/**
75
	/**
76
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand#mergeEvent(org.eclipse.swt.widgets.Event)
76
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand#mergeEvent(org.eclipse.swt.widgets.Event)
77
	 */
77
	 */
78
	public boolean mergeEvent(Event e)
78
	public boolean mergeEvent(Event e) throws Exception {
79
	{
80
		items.clear();
79
		items.clear();
81
		processEvent(e);
80
		doProcessEvent(e);
82
		return true;
81
		return true;
83
	}
82
	}
84
83
85
	
86
	/**
84
	/**
87
	 * Returns the items that are embedded in the event passed in
85
	 * Returns the items that are embedded in the event passed in
88
	 * 
86
	 * 
89
	 * @param event The event
87
	 * @param event
88
	 *            The event
90
	 * @return The items of the event
89
	 * @return The items of the event
91
	 */
90
	 */
92
	protected Object[] getItemsForEvent(Event event)
91
	protected Object[] getItemsForEvent(Event event) {
93
	{
94
		Widget item = null;
92
		Widget item = null;
95
		if (event.item != null)
93
		if (event.item != null)
96
			item = event.item;
94
			item = event.item;
Lines 101-346 Link Here
101
		return null;
99
		return null;
102
	}
100
	}
103
101
104
	
105
	/**
102
	/**
106
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand#processEvent(org.eclipse.swt.widgets.Event)
103
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand#processEvent(org.eclipse.swt.widgets.Event)
107
	 */
104
	 */
108
	public void processEvent(Event event)
105
	public void doProcessEvent(Event event) {
109
	{
110
		Object[] eventItems = getItemsForEvent(event);
106
		Object[] eventItems = getItemsForEvent(event);
111
		boolean isWidget = eventItems instanceof Widget[];
107
		boolean isWidget = eventItems instanceof Widget[];
112
		boolean isString = false;
108
		boolean isString = false;
113
		
109
114
		if (!isWidget)
110
		if (!isWidget)
115
			isString = eventItems instanceof String[];
111
			isString = eventItems instanceof String[];
116
112
117
113
		/*
118
		/* Populate the items instance variable according to the items of the event */		
114
		 * Populate the items instance variable according to the items of the
119
		if (eventItems != null)
115
		 * event
120
		{
116
		 */
117
		if (eventItems != null) {
121
			/* For every embedded item */
118
			/* For every embedded item */
122
			for (int i = 0; i < eventItems.length; i++)
119
			for (int i = 0; i < eventItems.length; i++) {
123
			{
124
				Map attributeValuePairs = null;
120
				Map attributeValuePairs = null;
125
				
121
126
				if (isWidget)
122
				if (isWidget) {
127
				{
123
					attributeValuePairs = getItemAttributes((Widget) eventItems[i]);
128
					attributeValuePairs = getItemAttributes((Widget)eventItems[i]);
124
				} else if (isString) {
129
				}
125
					attributeValuePairs = getItemAttributes(null,
130
				else if (isString)
126
							new PrimitiveUIObjectIdentifier(
131
				{
127
									(String) eventItems[i]));
132
					attributeValuePairs = getItemAttributes(null, new PrimitiveWidgetId((String)eventItems[i]));
133
				}
128
				}
134
129
135
				if (attributeValuePairs != null)
130
				if (attributeValuePairs != null) {
136
				{
137
					items.add(attributeValuePairs);
131
					items.add(attributeValuePairs);
138
				}
132
				}
139
			}
133
			}
140
		}
134
		}
141
		
135
142
		super.findDescriptiveField(eventItems);
136
		super.findDescriptiveField(eventItems);
143
	}
137
	}
144
138
145
146
	/**
139
	/**
147
	 * Returns the item attributes that will be used to find and resolve the item
140
	 * Returns the item attributes that will be used to find and resolve the
148
	 * that is associated with this structured command.
141
	 * item that is associated with this structured command.
149
	 * 
142
	 * 
150
	 * @param item The item
143
	 * @param item
151
	 * @return A map indicating the item attributes and values; null if the item can't be resolved.
144
	 *            The item
152
	 */
145
	 * @return A map indicating the item attributes and values; null if the item
153
	protected Map getItemAttributes(Widget item)
146
	 *         can't be resolved.
154
	{
147
	 */
155
		MacroManager macroManager = MacroManager.getInstance();		
148
	protected Map getItemAttributes(Widget item) {
156
		IWidgetId id = macroManager.resolveWidget(item, null, MacroUtil.newCounter());
149
		IUIObjectIdentifier id = null;
157
		if (id == null)
150
		try {
158
		{
151
			id = UIObjectResolver.resolve(null, new UIObject(item));
152
		} catch (CoreException e) {
153
			e.printStackTrace();
154
		}
155
		if (id == null) {
159
			id = getDefaultItemAttributes(item);
156
			id = getDefaultItemAttributes(item);
160
		}
157
		}
161
		
158
162
		if (id != null)
159
		if (id != null) {
163
		{			
164
			return getItemAttributes(item, id);
160
			return getItemAttributes(item, id);
165
		}
161
		}
166
				
162
167
		return null;
168
	}
169
	
170
	
171
	private IWidgetId getDefaultItemAttributes(Widget item)
172
	{
173
		Object data = item.getData();
174
		
175
		String idStr = MacroConstants.EMPTY_STRING;
176
		if (data != null)
177
			idStr = data.getClass().getName();
178
		
179
		/* Append index to id if it's a table or a tree item */
180
		if (item instanceof TreeItem)
181
		{
182
			TreeItem treeItem = (TreeItem)item;
183
			idStr = idStr + findTreeItemInx(treeItem, MacroConstants.EMPTY_STRING);
184
		}
185
		else if (item instanceof TableItem)
186
		{
187
			TableItem tableItem = (TableItem)item;
188
			idStr = idStr + tableItem.getParent().indexOf(tableItem);
189
		}
190
		if (idStr.length() > 0)
191
			return new PrimitiveWidgetId(idStr);
192
		
193
		return null;
163
		return null;
194
	}
164
	}
195
165
196
	/**
166
	/**
197
	 * Returns the item attributes that will be used to find and resolve the item
167
	 * Returns the item attributes that will be used to find and resolve the
198
	 * that is associated with this structured command.
168
	 * item that is associated with this structured command.
199
	 * 
169
	 * 
200
	 * @param item The item
170
	 * @param item
201
	 * @param id The item id
171
	 *            The item
202
	 * @return A map indicating the item attributes and values; null if the item can't be resolved.
172
	 * @param id
173
	 *            The item id
174
	 * @return A map indicating the item attributes and values; null if the item
175
	 *         can't be resolved.
203
	 */
176
	 */
204
	protected Map getItemAttributes(Widget item, IWidgetId id)
177
	private Map getItemAttributes(Widget item, IUIObjectIdentifier id) {
205
	{
206
		Hashtable attributeValuePair = new Hashtable();
178
		Hashtable attributeValuePair = new Hashtable();
207
		attributeValuePair.put(MacroConstants.PATH_ATTRIBUTE, id);
179
		attributeValuePair.put(MacroConstants.WIDGET_ID_ATTRIBUTE, id);
208
		
180
209
		IUIObject uiObject = findItemInObjectMine (item, id);
181
		MacroObjectDescriptor uiObject = findItemInObjectMine(item, id);
210
		if (uiObject != null)
182
		if (uiObject != null) {
211
		{
183
			attributeValuePair.put(MacroConstants.REFERENCE_ID_ATTRIBUTE,
212
			attributeValuePair.put(MacroConstants.REFERENCE_ID_ATTRIBUTE, uiObject.getReferenceId());
184
					uiObject.getReferenceId());
213
		}
185
		}
214
			
186
215
		if (id.getResolverId() != null)
187
		if (id.getResolverId() != null) {
216
		{
188
			attributeValuePair.put(MacroConstants.RESOLVER_ID_ATTRIBUTE, id
217
			attributeValuePair.put(MacroConstants.RESOLVER_ATTRIBUTE, id.getResolverId());
189
					.getResolverId());
218
		}
190
		}
219
		return attributeValuePair;
191
		return attributeValuePair;
220
	}
192
	}
221
	
222
193
223
	/**
194
	/**
224
	 * Attempts to find an item in the current object mine.  If it's not found,
195
	 * Attempts to find an item in the current object mine. If it's not found,
225
	 * then it is registered.
196
	 * then it is registered.
226
	 * 
197
	 * 
227
	 * @param item The item
198
	 * @param item
228
	 * @param id The item id
199
	 *            The item
200
	 * @param id
201
	 *            The item id
229
	 * @return The object or null if it cannot be found or registered.
202
	 * @return The object or null if it cannot be found or registered.
230
	 */
203
	 */
231
	private IUIObject findItemInObjectMine (Widget item, IWidgetId id)
204
	private MacroObjectDescriptor findItemInObjectMine(Widget item,
232
	{
205
			IUIObjectIdentifier id) {
233
		/* Determine if the item is already registered with the object mine */
206
		if (useObjectMine()) {
234
		IObjectMine objectMine = MacroManager.getInstance().getObjectMine();
207
			/* Determine if the item is already registered with the object mine */
235
		IUIObject activeObject = getCorrespondingObject();
208
			MacroObjectDescriptorMine objectMine = MacroManager.getInstance()
236
		IUIObject objectItem = null;
209
					.getObjectMine();
237
		if (activeObject != null)
210
			MacroObjectDescriptor activeObject = getCorrespondingMacroObjectDescriptor();
238
		{
211
			MacroObjectDescriptor objectItem = null;
239
			objectItem = objectMine.lookupUIObject(activeObject, null, id.toString());
212
			if (activeObject != null) {
240
			/* It's not registered, register the object */
213
				objectItem = objectMine.lookupMacroObjectDescriptor(
241
			if (objectItem == null)
214
						activeObject, null, id.getWidgetId(), id.getObjectId());
242
			{
215
				/* It's not registered, register the object */
243
				objectItem = new UIObject(activeObject);
216
				if (objectItem == null) {
244
				objectItem.setObjectId(id.toString());
217
					objectItem = new MacroObjectDescriptor(activeObject);
245
				objectItem.setReferenceId(objectMine.getUniqueReferenceId());
218
					((MacroObjectDescriptor) objectItem).setWidgetId(id
246
				objectItem.setResolver(id.getResolverId());
219
							.getWidgetId());
247
				String descriptiveField = getObjectClassName(item);
220
					((MacroObjectDescriptor) objectItem).setResolver(id
248
				if (descriptiveField == null)
221
							.getResolverId());
249
					descriptiveField = MacroConstants.EMPTY_STRING;
222
					((MacroObjectDescriptor) objectItem).setObjectId(id
250
				String itemText = getText(item);
223
							.getObjectId());
251
				descriptiveField += itemText == null ? MacroConstants.EMPTY_STRING :  ": " + itemText;	
224
					String descriptiveField = getObjectClassName(item);
252
				objectItem.setDescriptive (XMLUtil.useXMLSymbols(MacroUtil.normalizeDescriptiveField(MacroUtil.boundSize(descriptiveField, DESCRIPTIVE_FIELD_BOUND))));
225
					if (descriptiveField == null)
253
				objectItem.setParent(activeObject);
226
						descriptiveField = MacroConstants.EMPTY_STRING;
254
				try
227
					String itemText = getText(item);
255
				{
228
					descriptiveField += itemText == null ? MacroConstants.EMPTY_STRING
256
					objectMine.registerObject(objectItem);
229
							: ": " + itemText;
257
				} catch (Exception e)
230
					((MacroObjectDescriptor) objectItem).setDescriptive(XMLUtil
258
				{
231
							.useXMLSymbols(MacroUtil
259
					objectItem = null;
232
									.normalizeDescriptiveField(MacroUtil
260
					
233
											.boundSize(descriptiveField,
261
					/* We can't show an error message because it will distrupt the record session, instead print to error stream */
234
													DESCRIPTIVE_FIELD_BOUND))));
262
					System.err.println(AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE_REG);
235
					((MacroObjectDescriptor) objectItem)
263
					e.printStackTrace();
236
							.setParent(activeObject);
237
					try {
238
						objectMine
239
								.registerObject((MacroObjectDescriptor) objectItem);
240
					} catch (Exception e) {
241
						objectItem = null;
242
243
						/*
244
						 * We can't show an error message because it will
245
						 * distrupt the record session, instead print to error
246
						 * stream
247
						 */
248
						System.err
249
								.println(AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE_REG);
250
						e.printStackTrace();
251
					}
264
				}
252
				}
265
			}
253
			}
254
255
			return objectItem;
256
		} else {
257
			return null;
266
		}
258
		}
267
		
268
		return objectItem;
269
	}
259
	}
270
	
260
271
	
272
	/**
261
	/**
273
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.AbstractMacroInstruction#getCorrespondingObject()
262
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.AbstractMacroInstruction#getCorrespondingMacroObjectDescriptor()
274
	 */
263
	 */
275
	public IUIObject getCorrespondingObject ()
264
	public MacroObjectDescriptor getCorrespondingMacroObjectDescriptor() {
276
	{
265
		if (super.getCorrespondingMacroObjectDescriptor() != null)
277
		if (super.getCorrespondingObject() != null)
266
			return super.getCorrespondingMacroObjectDescriptor();
278
			return super.getCorrespondingObject();
267
279
		
268
		MacroObjectDescriptorMine objectMine = MacroManager.getInstance()
280
		IObjectMine objectMine = MacroManager.getInstance().getObjectMine();
269
				.getObjectMine();
281
		IUIObject activeObject = objectMine.getActiveObject();
270
		MacroObjectDescriptor activeObject = objectMine.getActiveObject();
282
		String contextId = getWidgetId().getContextId() == null ? null : getWidgetId().getContextId().toString();
271
283
		super.setCorrespondingObject(activeObject == null ? null : objectMine.lookupUIObject(activeObject, contextId, getWidgetId().getObjectId().toString()));
272
		if (useObjectMine() && getMacroObjectIdentifier() != null) {
284
		
273
			String contextId = (getMacroObjectIdentifier()
285
		return super.getCorrespondingObject();
274
					.getContextIdentifier() == null) ? null
275
					: getMacroObjectIdentifier().getContextIdentifier()
276
							.toString();
277
			super
278
					.setCorrespondingMacroObjectDescriptor(activeObject == null ? null
279
							: objectMine.lookupMacroObjectDescriptor(
280
									activeObject, contextId,
281
									getMacroObjectIdentifier()
282
											.getObjectIdentifier()
283
											.getWidgetId(),
284
									getMacroObjectIdentifier()
285
											.getObjectIdentifier()
286
											.getObjectId()));
287
		}
288
289
		return super.getCorrespondingMacroObjectDescriptor();
286
	}
290
	}
287
	
291
288
	/**
292
	/**
289
	 * Returns the tree item index in the form of N1|N2|N2|...|Nn where
293
	 * Returns the tree item index in the form of N1|N2|N2|...|Nn where Ni
290
	 * Ni corresponds to the item index in the tree.
294
	 * corresponds to the item index in the tree.
291
	 * 
295
	 * 
292
	 * @param treeItem The tree item
296
	 * @param treeItem
293
	 * @param currentInx The current index
297
	 *            The tree item
298
	 * @param currentInx
299
	 *            The current index
294
	 * @return A string representation of the index.
300
	 * @return A string representation of the index.
295
	 */
301
	 */
296
	private String findTreeItemInx(TreeItem treeItem, String currentInx) 
302
	private static String findTreeItemInx(TreeItem treeItem, String currentInx) {
297
	{	
298
		if (currentInx != null && currentInx.length() > 0)
303
		if (currentInx != null && currentInx.length() > 0)
299
			currentInx = "|" + currentInx;		
304
			currentInx = "|" + currentInx;
300
		
305
301
		/* We're not the root */
306
		/* We're not the root */
302
		if (treeItem.getParentItem() != null)
307
		if (treeItem.getParentItem() != null) {
303
		{
304
			TreeItem parentItem = treeItem.getParentItem();
308
			TreeItem parentItem = treeItem.getParentItem();
305
			currentInx = parentItem.indexOf(treeItem) + "|" + currentInx;
309
			currentInx = parentItem.indexOf(treeItem) + "|" + currentInx;
306
			return findTreeItemInx(parentItem, currentInx);
310
			return findTreeItemInx(parentItem, currentInx);
307
		}
311
		}
308
		/* Otherwise we are the root */
312
		/* Otherwise we are the root */
309
		int index = treeItem.getParent().indexOf(treeItem);
313
		int index = treeItem.getParent().indexOf(treeItem);
310
		return index + currentInx;			
314
		return index + currentInx;
315
	}
316
317
	private static Item findItem(Item[] children, IUIObjectIdentifier widgetId) {
318
		for (int i = 0; i < children.length; i++) {
319
			IUIObjectIdentifier defaultAttributes = getDefaultItemAttributes(children[i]);
320
			if (UIObjectDeprecatedDeresolvingSupport.foundWidget(children[i],
321
					widgetId)
322
					|| defaultAttributes.getWidgetId().equals(
323
							widgetId.getWidgetId()))
324
				return children[i];
325
326
			/* We need to do a recursive search in the case of a tree */
327
			if (children instanceof TreeItem[]) {
328
				TreeItem treeItem = (TreeItem) children[i];
329
				int ccount = treeItem.getItemCount();
330
				if (ccount > 0) {
331
					/* Test the item's children */
332
					Item citem = findItem(treeItem.getItems(), widgetId);
333
					if (citem != null)
334
						return citem;
335
				}
336
			}
337
		}
338
		return null;
339
	}
340
341
	private static IUIObjectIdentifier getDefaultItemAttributes(Widget item) {
342
		Object data = item.getData();
343
344
		String idStr = MacroConstants.EMPTY_STRING;
345
		if (data != null)
346
			idStr = data.getClass().getName();
347
348
		/* Append index to id if it's a table or a tree item */
349
		if (item instanceof TreeItem) {
350
			TreeItem treeItem = (TreeItem) item;
351
			idStr = idStr
352
					+ findTreeItemInx(treeItem, MacroConstants.EMPTY_STRING);
353
		} else if (item instanceof TableItem) {
354
			TableItem tableItem = (TableItem) item;
355
			idStr = idStr + tableItem.getParent().indexOf(tableItem);
356
		}
357
		if (idStr.length() > 0)
358
			return new PrimitiveUIObjectIdentifier(idStr);
359
360
		return null;
311
	}
361
	}
312
362
313
	
314
	/**
363
	/**
315
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand#load(org.w3c.dom.Node, java.util.Hashtable)
364
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand#load(org.w3c.dom.Node,
365
	 *      java.util.Hashtable)
316
	 */
366
	 */
317
	public void load(Node node, Hashtable lineTable) throws CoreException
367
	public void load(Node node, Hashtable lineTable) throws CoreException {
318
	{
319
		super.load(node, lineTable);
368
		super.load(node, lineTable);
320
		NodeList children = node.getChildNodes();
369
		NodeList children = node.getChildNodes();
321
		for (int i = 0; i < children.getLength(); i++)
370
		for (int i = 0; i < children.getLength(); i++) {
322
		{
323
			Node child = children.item(i);
371
			Node child = children.item(i);
324
			if (child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals(MacroConstants.ITEM_ELEMENT))
372
			if (child.getNodeType() == Node.ELEMENT_NODE
325
			{				
373
					&& child.getNodeName().equals(MacroConstants.ITEM_ELEMENT)) {
326
				/* First check to see if a reference id is available */
374
				/* First check to see if a reference id is available */
327
				String attribute = MacroConstants.REFERENCE_ID_ATTRIBUTE;
375
				String attribute = MacroConstants.REFERENCE_ID_ATTRIBUTE;
328
				String attributeValue = MacroUtil.getAttribute(child, attribute);
376
				String attributeValue = MacroUtil
329
				
377
						.getAttribute(child, attribute);
330
				/* If a reference id is not available, then check the path attribute */
378
331
				if (attributeValue == null)
379
				/*
332
				{
380
				 * If a reference id is not available, then check the path
333
					attribute = MacroConstants.PATH_ATTRIBUTE;
381
				 * attribute
382
				 */
383
				if (attributeValue == null) {
384
					attribute = MacroConstants.WIDGET_ID_ATTRIBUTE;
334
					attributeValue = MacroUtil.getAttribute(child, attribute);
385
					attributeValue = MacroUtil.getAttribute(child, attribute);
335
				}
386
				}
336
							
387
337
				if (attributeValue != null)
388
				if (attributeValue != null) {
338
				{
339
					Hashtable itemData = new Hashtable();
389
					Hashtable itemData = new Hashtable();
340
					itemData.put(attribute, attributeValue);
390
					itemData.put(attribute, attributeValue);
341
					String resolverId = MacroUtil.getAttribute(child, MacroConstants.RESOLVER_ATTRIBUTE);
391
					String resolverId = MacroUtil.getAttribute(child,
392
							MacroConstants.RESOLVER_ID_ATTRIBUTE);
342
					if (resolverId != null)
393
					if (resolverId != null)
343
						itemData.put(MacroConstants.RESOLVER_ATTRIBUTE, resolverId);
394
						itemData.put(MacroConstants.RESOLVER_ID_ATTRIBUTE,
395
								resolverId);
344
					items.add(itemData);
396
					items.add(itemData);
345
				}
397
				}
346
			}
398
			}
Lines 350-626 Link Here
350
	/**
402
	/**
351
	 * Sub-classes can optionally overwrite this method to write additional
403
	 * Sub-classes can optionally overwrite this method to write additional
352
	 * attributes to command.
404
	 * attributes to command.
353
	 *  
405
	 * 
354
	 * @param sb The string buffer that the attributes should be written to.
406
	 * @param sb
407
	 *            The string buffer that the attributes should be written to.
355
	 */
408
	 */
356
	protected void writeAdditionalAttributes(StringBuffer sb)
409
	protected void writeAdditionalAttributes(StringBuffer sb) {
357
	{
358
	}
410
	}
359
411
360
	
361
	/**
412
	/**
362
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand#write(int, java.lang.StringBuffer)
413
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand#write(int,
414
	 *      java.lang.StringBuffer)
363
	 */
415
	 */
364
	public void write(int indent, StringBuffer sb) 
416
	public void write(int indent, StringBuffer sb) {
365
	{
366
		super.write(indent, sb);
417
		super.write(indent, sb);
367
		writeAdditionalAttributes(sb);
418
		writeAdditionalAttributes(sb);
368
		sb.append(MacroConstants.CLOSE_ANGLE_BRACKET);
419
		sb.append(MacroConstants.CLOSE_ANGLE_BRACKET);
369
		sb.append(GlobalConstants.LINE_SEPARATOR);
420
		sb.append(GlobalConstants.LINE_SEPARATOR);
370
						
421
371
		int cindent = indent + 1;
422
		int cindent = indent + 1;
372
		boolean isObjectMineOn = MacroManager.getInstance().isObjectMineOn();
423
		boolean isObjectMineOn = MacroManager.getInstance().isObjectMineOn();
373
		for (int i = 0; i < items.size(); i++)
424
		for (int i = 0; i < items.size(); i++) {
374
		{
425
			Map itemData = (Map) items.get(i);
375
			Map itemData = (Map)items.get(i);
426
			if (itemData != null) {
376
			if (itemData != null)
427
				String referenceId = (String) itemData
377
			{
428
						.get(MacroConstants.REFERENCE_ID_ATTRIBUTE);
378
				String referenceId = (String)itemData.get(MacroConstants.REFERENCE_ID_ATTRIBUTE);
429
				String itemId = itemData
379
				String itemId = itemData.get(MacroConstants.PATH_ATTRIBUTE).toString();
430
						.get(MacroConstants.WIDGET_ID_ATTRIBUTE).toString();
380
				boolean useReferenceId = isObjectMineOn && referenceId != null;
431
				boolean useReferenceId = isObjectMineOn && referenceId != null;
381
				MacroUtil.addElement(sb, cindent, MacroConstants.ITEM_ELEMENT, false, false);
432
				MacroUtil.addElement(sb, cindent, MacroConstants.ITEM_ELEMENT,
382
				MacroUtil.addAttribute(sb, 
433
						false, false);
383
						new String[]{
434
				MacroUtil.addAttribute(sb, new String[] {
384
							useReferenceId ? MacroConstants.REFERENCE_ID_ATTRIBUTE : MacroConstants.PATH_ATTRIBUTE, 
435
						useReferenceId ? MacroConstants.REFERENCE_ID_ATTRIBUTE
385
							MacroConstants.RESOLVER_ATTRIBUTE
436
								: MacroConstants.WIDGET_ID_ATTRIBUTE,
386
									}, 
437
						MacroConstants.RESOLVER_ID_ATTRIBUTE }, new String[] {
387
						new String[]{
438
						useReferenceId ? referenceId : itemId,
388
							useReferenceId ? referenceId : itemId,
439
						useReferenceId ? null : (String) itemData
389
							useReferenceId ? null : (String)itemData.get(MacroConstants.RESOLVER_ATTRIBUTE)
440
								.get(MacroConstants.RESOLVER_ID_ATTRIBUTE) },
390
									}, true, true);
441
						true, true);
391
			}			
442
			}
392
		}
443
		}
393
		MacroUtil.addElement(sb, indent, MacroConstants.COMMAND_ELEMENT, true, true);		
444
		MacroUtil.addElement(sb, indent, MacroConstants.COMMAND_ELEMENT, true,
445
				true);
394
	}
446
	}
395
447
396
	/**
448
	/**
397
	 * Used to play the structured command collectively for all the discovered matches.
449
	 * Used to play the structured command collectively for all the discovered
398
	 * 
450
	 * matches.
399
	 * @param widget The widget
451
	 * 
400
	 * @param matches The matches discovered
452
	 * @param widget
401
	 */
453
	 *            The widget
402
	protected abstract void playStructuredCommand(Widget widget, Object[] matches);
454
	 * @param matches
403
	
455
	 *            The matches discovered
404
	
456
	 */
405
	/**
457
	protected abstract void playStructuredCommand(Widget widget,
406
	 * Some events require to be played as matches are discovered.  (e.g. an expansion command
458
			Object[] matches);
407
	 * requires to be played for each discovered item in order for successive children to be found)
408
	 * It's recommended that either playStructuredCommandForFoundMatch or playStructuredCommand be implemented
409
	 * by clients, eventhough both methods will be invoked.
410
	 *
411
	 * @param widget The widget
412
	 * @param matches The match discovered
413
	 */
414
	protected abstract void playStructuredCommandForFoundMatch(Widget widget, Object match);
415
	
416
	
417
	public final boolean playback(Display display, Composite parent, IProgressMonitor monitor) throws CoreException
418
	{
419
		CommandTarget[] targets = MacroObjectLocator.locateCommandTarget(parent, getWidgetId(), getStartLine());
420
459
421
		if (targets == null)
460
	/**
461
	 * Some events require to be played as matches are discovered. (e.g. an
462
	 * expansion command requires to be played for each discovered item in order
463
	 * for successive children to be found) It's recommended that either
464
	 * playStructuredCommandForFoundMatch or playStructuredCommand be
465
	 * implemented by clients, eventhough both methods will be invoked.
466
	 * 
467
	 * @param widget
468
	 *            The widget
469
	 * @param matches
470
	 *            The match discovered
471
	 */
472
	protected abstract void playStructuredCommandForFoundMatch(Widget widget,
473
			Object match);
474
475
	public final boolean doPlayback(Display display, Shell parent,
476
			IProgressMonitor monitor) throws CoreException {
477
		if (macroObject == null)
422
			return false;
478
			return false;
423
		
479
424
		for (int i = 0; i < targets.length; i++)
480
		// for (int i = 0; i < targets.length; i++) {
425
		{
481
		setFocus(macroObject);
426
			targets[i].setFocus();
482
427
			
483
		/*
428
			/* https://bugs.eclipse.org/bugs/show_bug.cgi?id=147766: A process display event causes the target widget to sometimes
484
		 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=147766: A process
429
			 * be disposed.  
485
		 * display event causes the target widget to sometimes be disposed.
430
			 * MacroUtil.processDisplayEvents(display);	*/
486
		 * MacroUtil.processDisplayEvents(display);
431
			Widget widget = targets[i].getWidget();
487
		 */
432
488
		Widget widget = macroObject.getUIObject().getWidget();
433
			if (widget == null || widget.isDisposed())
489
434
				continue;
490
		if (widget == null || widget.isDisposed())
435
491
			return false;// continue;
436
			Object[] matches = findMatches(widget);
492
437
				
493
		Object[] matches = findMatches(widget);
438
			/* If we failed to locate the item, then continue */
494
439
			if (matches != null && items.size() != matches.length)
495
		/* If we failed to locate the item, then continue */
440
				continue;
496
		if (matches != null && items.size() != matches.length)
441
				
497
			return false;// continue;
442
			playStructuredCommand(widget, matches);
498
443
			return true;
499
		playStructuredCommand(widget, matches);
444
		}
500
		return true;
445
		
501
		// }
446
		return false;
502
503
		// return false;
447
	}
504
	}
448
505
449
	protected Object[] findMatches(Widget widget) throws CoreException
506
	protected Object[] findMatches(Widget widget) throws CoreException {
450
	{
451
		if (widget instanceof Tree)
507
		if (widget instanceof Tree)
452
			return findMatches((Tree)widget);
508
			return findMatches((Tree) widget);
453
		else if (widget instanceof Table)
509
		else if (widget instanceof Table)
454
			return findMatches((Table)widget);
510
			return findMatches((Table) widget);
455
		else if (widget instanceof List)
511
		else if (widget instanceof List)
456
			return findMatches ((List) widget);
512
			return findMatches((List) widget);
457
		
513
458
		return null;
514
		return null;
459
	}
515
	}
460
516
461
	private String[] findMatches(List list) throws CoreException
517
	private String[] findMatches(List list) throws CoreException {
462
	{
463
		String[] children = list.getItems();
518
		String[] children = list.getItems();
464
		ArrayList matches = new ArrayList();
519
		ArrayList matches = new ArrayList();
465
		for (int i = 0; i < items.size(); i++)
520
		for (int i = 0; i < items.size(); i++) {
466
		{
467
			String itemId = findObjectId(i).toString();
521
			String itemId = findObjectId(i).toString();
468
			int itemInx = list.indexOf(itemId);
522
			int itemInx = list.indexOf(itemId);
469
			if (itemInx >= 0 && itemInx < children.length)
523
			if (itemInx >= 0 && itemInx < children.length) {
470
			{
524
				playStructuredCommandForFoundMatch(list, children[itemInx]);
471
				playStructuredCommandForFoundMatch (list, children[itemInx]);
472
				matches.add(children[itemInx]);
525
				matches.add(children[itemInx]);
473
			}
526
			}
474
		}
527
		}
475
		return (String[]) matches.toArray(new String[matches.size()]);
528
		return (String[]) matches.toArray(new String[matches.size()]);
476
	}
529
	}
477
	
478
530
479
	private TreeItem[] findMatches(Tree tree) throws CoreException
531
	private TreeItem[] findMatches(Tree tree) throws CoreException {
480
	{
481
		TreeItem[] children = tree.getItems();
532
		TreeItem[] children = tree.getItems();
482
		ArrayList matches = new ArrayList();
533
		ArrayList matches = new ArrayList();
483
		for (int i = 0; i < items.size(); i++)
534
		for (int i = 0; i < items.size(); i++) {
484
		{
535
			IUIObjectIdentifier currentWidgetId = findObjectId(i);
485
			IWidgetId currentWidgetId = findObjectId(i);
536
			Item item = findItem(children, currentWidgetId);
486
			String itemId = currentWidgetId.toString();
537
			if (item != null) {
487
			Item item = findItem(children, currentWidgetId.getResolverId(), itemId);
538
				playStructuredCommandForFoundMatch(tree, item);
488
			if (item != null)
489
			{
490
				playStructuredCommandForFoundMatch (tree, item);
491
				matches.add(item);
539
				matches.add(item);
492
			}
540
			}
493
		}
541
		}
494
		return (TreeItem[]) matches.toArray(new TreeItem[matches.size()]);
542
		return (TreeItem[]) matches.toArray(new TreeItem[matches.size()]);
495
	}
543
	}
496
544
497
	private TableItem[] findMatches(Table table) throws CoreException
545
	private TableItem[] findMatches(Table table) throws CoreException {
498
	{
499
		TableItem[] elements = table.getItems();
546
		TableItem[] elements = table.getItems();
500
		ArrayList matches = new ArrayList();
547
		ArrayList matches = new ArrayList();
501
548
502
		for (int i = 0; i < items.size(); i++)
549
		for (int i = 0; i < items.size(); i++) {
503
		{
550
			IUIObjectIdentifier currentWidgetId = findObjectId(i);
504
			IWidgetId currentWidgetId = findObjectId(i);
551
			Item item = findItem(elements, currentWidgetId);
505
			String itemId = currentWidgetId.toString();
552
			if (item != null) {
506
			Item item = findItem(elements, currentWidgetId.getResolverId(), itemId);
553
				playStructuredCommandForFoundMatch(table, item);
507
			if (item != null)
508
			{
509
				playStructuredCommandForFoundMatch (table, item);
510
				matches.add(item);
554
				matches.add(item);
511
			}
555
			}
512
		}
556
		}
513
		return (TableItem[]) matches.toArray(new TableItem[matches.size()]);
557
		return (TableItem[]) matches.toArray(new TableItem[matches.size()]);
514
	}
558
	}
515
559
516
	
517
	/**
560
	/**
518
	 * Returns the object id of the inx-th item associated with this
561
	 * Returns the object id of the inx-th item associated with this structured
519
	 * structured command.
562
	 * command.
520
	 * 
563
	 * 
521
	 * @param inx The index of the item
564
	 * @param inx
565
	 *            The index of the item
522
	 * @return The object id
566
	 * @return The object id
523
	 * 
567
	 * 
524
	 * @throws CoreException If an error occurrs while attempting to find the object
568
	 * @throws CoreException
569
	 *             If an error occurrs while attempting to find the object
525
	 */
570
	 */
526
	protected IWidgetId findObjectId(int inx) throws CoreException
571
	protected IUIObjectIdentifier findObjectId(int inx) throws CoreException {
527
	{
528
		Hashtable itemData = null;
572
		Hashtable itemData = null;
529
		if (inx < 0 || inx >= items.size() || (itemData = (Hashtable)items.get(inx)) == null)
573
		if (inx < 0 || inx >= items.size()
530
			AutoGUIUtil.throwCoreException(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_ITEM, getStartLine());
574
				|| (itemData = (Hashtable) items.get(inx)) == null)
531
		
575
			AutoGUIUtil.throwCoreException(
576
					AutoGUIMessages.AUTO_GUI_ERROR_MACRO_ITEM, getStartLine());
577
532
		Object itemObjectId = null;
578
		Object itemObjectId = null;
533
		PrimitiveWidgetId widgetId = null;
579
		PrimitiveUIObjectIdentifier widgetId = null;
534
		if ((itemObjectId = itemData.get(MacroConstants.PATH_ATTRIBUTE)) != null)
580
		if ((itemObjectId = itemData.get(MacroConstants.WIDGET_ID_ATTRIBUTE)) != null) {
535
		{
581
			widgetId = new PrimitiveUIObjectIdentifier(itemObjectId.toString(),
536
			widgetId = new PrimitiveWidgetId(itemObjectId.toString());
582
					(String) itemData.get(MacroConstants.RESOLVER_ID_ATTRIBUTE));
537
			widgetId.setResolverId((String)itemData.get(MacroConstants.RESOLVER_ATTRIBUTE));
538
			return widgetId;
583
			return widgetId;
539
		}
584
		}
540
		
585
541
		String referenceId = (String)itemData.get(MacroConstants.REFERENCE_ID_ATTRIBUTE);
586
		String referenceId = (String) itemData
587
				.get(MacroConstants.REFERENCE_ID_ATTRIBUTE);
542
		if (referenceId == null)
588
		if (referenceId == null)
543
			return new PrimitiveWidgetId(MacroConstants.EMPTY_STRING);
589
			return new PrimitiveUIObjectIdentifier(MacroConstants.EMPTY_STRING);
544
		
590
545
		IObjectMine objectMine = MacroManager.getInstance().getObjectMine();
591
		MacroObjectDescriptorMine objectMine = MacroManager.getInstance()
592
				.getObjectMine();
546
		if (objectMine == null)
593
		if (objectMine == null)
547
			AutoGUIUtil.throwCoreException(AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE_T, getStartLine());
594
			AutoGUIUtil.throwCoreException(
548
			
595
					AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE_T,
549
		IUIObject parentObject = getCorrespondingObject();
596
					getStartLine());
550
		IUIObject itemObject = null;
597
598
		MacroObjectDescriptor parentObject = getCorrespondingMacroObjectDescriptor();
599
		MacroObjectDescriptor itemObject = null;
551
		if (parentObject != null)
600
		if (parentObject != null)
552
			itemObject = MacroManager.getInstance().getObjectMine().lookupUIObject(parentObject, referenceId);
601
			itemObject = MacroManager.getInstance().getObjectMine()
553
		
602
					.lookupMacroObjectDescriptor(parentObject, referenceId);
554
		
555
		if (itemObject == null || (itemObjectId = itemObject.getObjectId()) == null)
556
			return new PrimitiveWidgetId(MacroConstants.EMPTY_STRING);
557
		
558
		itemData.put(MacroConstants.PATH_ATTRIBUTE, itemObjectId);
559
		widgetId = new PrimitiveWidgetId(itemObjectId.toString());
560
		widgetId.setResolverId(itemObject.getResolverId());
561
		return widgetId;
562
	}
563
	
564
	
565
	private Item findItem(Item[] children, String resolverId, String itemId)
566
	{
567
		for (int i = 0; i < children.length; i++)
568
		{
569
			if (MacroObjectLocator.foundWidget(children[i], resolverId, itemId) || getDefaultItemAttributes(children[i]).equals(itemId))
570
				return children[i];
571
603
572
			/* We need to do a recursive search in the case of a tree */
604
		if (itemObject == null
573
			if (children instanceof TreeItem[])
605
				|| (itemObjectId = itemObject.getWidgetId()) == null)
574
			{
606
			return new PrimitiveUIObjectIdentifier(MacroConstants.EMPTY_STRING);
575
				TreeItem treeItem = (TreeItem)children[i];
607
576
				int ccount = treeItem.getItemCount();
608
		itemData.put(MacroConstants.WIDGET_ID_ATTRIBUTE, itemObjectId);
577
				if (ccount > 0)
609
		widgetId = new PrimitiveUIObjectIdentifier(itemObjectId.toString(),
578
				{
610
				itemObject.getResolverId());
579
					/* Test the item's children */
611
		return widgetId;
580
					Item citem = findItem(treeItem.getItems(), resolverId, itemId);
581
					if (citem != null)
582
						return citem;				
583
				}
584
			}
585
		}
586
		return null;
587
	}
612
	}
588
613
589
	
590
	/**
614
	/**
591
	 * Returns the items that this command must match
615
	 * Returns the items that this command must match
592
	 * 
616
	 * 
593
	 * @return Matched items
617
	 * @return Matched items
594
	 */
618
	 */
595
	protected ArrayList getItems() 
619
	protected ArrayList getItems() {
596
	{
597
		return items;
620
		return items;
598
	}
621
	}
599
	
622
600
	
623
	public boolean equals(Object obj) {
601
	public boolean equals (Object obj)
602
	{
603
		boolean equalState = super.equals(obj);
624
		boolean equalState = super.equals(obj);
604
		if (!equalState)
625
		if (!equalState)
605
			return false;
626
			return false;
606
		
627
607
		AbstractStructuredCommand compareWithObj = (AbstractStructuredCommand)obj;
628
		AbstractStructuredCommand compareWithObj = (AbstractStructuredCommand) obj;
608
		if (compareWithObj.getItems().size() != items.size())
629
		if (compareWithObj.getItems().size() != items.size())
609
			return false;
630
			return false;
610
		
631
611
		/* For each item */
632
		/* For each item */
612
		for (int i = 0, objectCount = items.size(); i < objectCount; i++)
633
		for (int i = 0, objectCount = items.size(); i < objectCount; i++) {
613
		{
634
			try {
614
			try
615
			{
616
				if (!compareWithObj.findObjectId(i).equals(findObjectId(i)))
635
				if (!compareWithObj.findObjectId(i).equals(findObjectId(i)))
617
					return false;
636
					return false;
618
			} catch (CoreException e)
637
			} catch (CoreException e) {
619
			{
620
				return false;
638
				return false;
621
			}
639
			}
622
		}
640
		}
623
		
641
624
		return true;
642
		return true;
625
	}
643
	}
626
644
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/WindowCommandTarget.java (-36 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.commands;
12
13
import org.eclipse.jface.window.Window;
14
import org.eclipse.swt.widgets.Widget;
15
16
public class WindowCommandTarget extends CommandTarget {
17
	/**
18
	 * @param widget
19
	 * @param context
20
	 */
21
	public WindowCommandTarget(Widget widget, Window window) {
22
		super(widget, window);
23
	}
24
	
25
	Window getWindow() {
26
		return (Window)getContext();
27
	}
28
29
	/* (non-Javadoc)
30
	 * @see org.eclipse.ui.macro.CommandTarget#ensureVisible()
31
	 */
32
	public void ensureVisible() {
33
		Window window = getWindow();
34
		window.getShell().setActive();
35
	}
36
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/CloseWorkbenchPartCommand.java (-40 / +54 lines)
Lines 14-25 Link Here
14
import org.eclipse.core.runtime.CoreException;
14
import org.eclipse.core.runtime.CoreException;
15
import org.eclipse.core.runtime.IProgressMonitor;
15
import org.eclipse.core.runtime.IProgressMonitor;
16
import org.eclipse.core.runtime.Path;
16
import org.eclipse.core.runtime.Path;
17
import org.eclipse.swt.widgets.Composite;
17
import org.eclipse.osgi.util.NLS;
18
import org.eclipse.swt.widgets.Display;
18
import org.eclipse.swt.widgets.Display;
19
import org.eclipse.swt.widgets.Event;
19
import org.eclipse.swt.widgets.Event;
20
import org.eclipse.swt.widgets.Shell;
21
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
22
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
20
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
23
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
21
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
24
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
22
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
25
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
26
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
27
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObjectIdentifier;
23
import org.eclipse.ui.IEditorPart;
28
import org.eclipse.ui.IEditorPart;
24
import org.eclipse.ui.IEditorReference;
29
import org.eclipse.ui.IEditorReference;
25
import org.eclipse.ui.IViewPart;
30
import org.eclipse.ui.IViewPart;
Lines 32-106 Link Here
32
 * 
37
 * 
33
 * @author Ali Mehregani
38
 * @author Ali Mehregani
34
 */
39
 */
35
public class CloseWorkbenchPartCommand extends AbstractMacroCommand 
40
public class CloseWorkbenchPartCommand extends ObjectBasedCommand {
36
{
41
37
	public static final String TYPE = "close-workbenchpart";
42
	public static final String TYPE = IMacroCommand.CLOSE_WORKBENCHPART;
38
	
43
39
	public CloseWorkbenchPartCommand(MacroCommandShell parent, WidgetIdentifier widgetId)
44
	public CloseWorkbenchPartCommand(MacroCommandShell parent) {
40
	{
45
		super(parent);
41
		super(parent, widgetId);		
42
	}
46
	}
43
47
44
	public String getType() 
48
	public String getType() {
45
	{
46
		return TYPE;
49
		return TYPE;
47
	}
50
	}
51
	
52
	protected final void preProcessEvent(Event event) throws CoreException {
53
		IMacroObjectIdentifier macroObjectIdentifier = MacroUtil.getCustomEventIdentifier(event);
54
		if(macroObjectIdentifier == null){
55
			IWorkbenchPart part = (IWorkbenchPart) event.data;
56
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_OBJECT_RESOLVE, part));
57
		}
58
		setMacroObjectIdentifier(macroObjectIdentifier);
59
	}
48
60
49
	public void processEvent(Event e) 
61
	public void doProcessEvent(Event e) {
50
	{
62
		setDescriptiveField(((IWorkbenchPart) e.data).getTitle());
51
		setDescriptiveField(((IWorkbenchPart)e.data).getTitle());
52
	}
63
	}
53
64
54
	public void write(int indent, StringBuffer sb) 
65
	public void write(int indent, StringBuffer sb) {
55
	{
66
		super.write(indent,
56
		super.write(indent, sb, true, true);	
67
			sb,
68
			true,
69
			true);
57
	}
70
	}
71
	
72
	public boolean playback(Display display, Shell parent, IProgressMonitor monitor) throws CoreException {
73
		String partType = getMacroObjectIdentifier().getContextIdentifier().toString();
74
		String partId = getMacroObjectIdentifier().getObjectIdentifier().getWidgetId();
58
75
59
	public boolean playback(Display display, Composite parent, IProgressMonitor monitor) throws CoreException 
60
	{
61
		String partType = getWidgetId().getContextId().toString();
62
		String partId = getWidgetId().getObjectId().toString();
63
		
64
		boolean isView = partType.equals(MacroConstants.VIEW_VALUE);
76
		boolean isView = partType.equals(MacroConstants.VIEW_VALUE);
65
		IEditorReference[] editorReferences = null;
77
		IEditorReference[] editorReferences = null;
66
		IViewReference[] viewReferences = null;
78
		IViewReference[] viewReferences = null;
67
		
79
68
		IWorkbenchPage activePage = GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage();
80
		IWorkbenchPage activePage = GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage();
69
		String editorPartId = null;
81
		String editorPartId = null;
70
		String editorInputName = null;
82
		String editorInputName = null;
71
		
83
72
		/* Try to locate the part */
84
		/* Try to locate the part */
73
		if (isView)
85
		if (isView) {
74
		{
75
			viewReferences = activePage.getViewReferences();
86
			viewReferences = activePage.getViewReferences();
76
		}
87
		}
77
		else
88
		else {
78
		{
79
			editorReferences = activePage.getEditorReferences();
89
			editorReferences = activePage.getEditorReferences();
80
			Path partIdPath = new Path(partId);
90
			Path partIdPath = new Path(partId);
81
			editorPartId = partIdPath.segment(0);
91
			editorPartId = partIdPath.segment(0);
82
			editorInputName = partIdPath.segment(1);
92
			editorInputName = partIdPath.segment(1);
83
		}
93
		}
84
		
94
85
		IWorkbenchPart desiredPart = null;
95
		IWorkbenchPart desiredPart = null;
86
		for (int i = 0; i < (isView ? viewReferences.length : editorReferences.length); i++)
96
		for (int i = 0; i < (isView
87
		{
97
			? viewReferences.length
88
			if (isView ? viewReferences[i].getId().equals(partId) : (editorReferences[i].getId().equals(editorPartId) && editorReferences[i].getEditorInput().getName().equals(editorInputName)))
98
			: editorReferences.length); i++) {
89
			{
99
			if (isView
90
				desiredPart = (isView ? (IWorkbenchPart)viewReferences[i].getView(false) : (IWorkbenchPart)editorReferences[i].getEditor(false));
100
				? viewReferences[i].getId().equals(partId)
101
				: (editorReferences[i].getId().equals(editorPartId) && editorReferences[i].getEditorInput().getName().equals(editorInputName))) {
102
				desiredPart = (isView
103
					? (IWorkbenchPart) viewReferences[i].getView(false)
104
					: (IWorkbenchPart) editorReferences[i].getEditor(false));
91
				break;
105
				break;
92
			}
106
			}
93
		}
107
		}
94
		
108
95
		/* Close the part if we found it */
109
		/* Close the part if we found it */
96
		if (desiredPart != null)
110
		if (desiredPart != null) {
97
		{
98
			if (isView)
111
			if (isView)
99
				activePage.hideView((IViewPart)desiredPart);
112
				activePage.hideView((IViewPart) desiredPart);
100
			else
113
			else
101
				activePage.closeEditor((IEditorPart)desiredPart, true);
114
				activePage.closeEditor((IEditorPart) desiredPart,
115
					true);
102
		}
116
		}
103
		
117
104
		return true;
118
		return true;
105
	}
119
	}
106
120
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/WaitCommand.java (-115 / +95 lines)
Lines 20-30 Link Here
20
import org.eclipse.core.runtime.jobs.IJobManager;
20
import org.eclipse.core.runtime.jobs.IJobManager;
21
import org.eclipse.core.runtime.jobs.Job;
21
import org.eclipse.core.runtime.jobs.Job;
22
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
22
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
23
import org.eclipse.swt.widgets.Composite;
24
import org.eclipse.swt.widgets.Display;
23
import org.eclipse.swt.widgets.Display;
25
import org.eclipse.swt.widgets.Event;
24
import org.eclipse.swt.widgets.Event;
25
import org.eclipse.swt.widgets.Shell;
26
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
26
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
27
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
27
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
28
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
28
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
29
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
29
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
30
import org.w3c.dom.Node;
30
import org.w3c.dom.Node;
Lines 32-127 Link Here
32
/**
32
/**
33
 * <p>
33
 * <p>
34
 * The purpose of this command is to provide a waiting mechanism so as to avoid
34
 * The purpose of this command is to provide a waiting mechanism so as to avoid
35
 * racing conditions that may cause a test case to fail when the underlying functionality
35
 * racing conditions that may cause a test case to fail when the underlying
36
 * works as expected.
36
 * functionality works as expected.
37
 * </p>
37
 * </p>
38
 * 
38
 * 
39
 * <p>
39
 * <p>
40
 * The command has a dual behaviour depending on whether the waitTime field is set or not.  If
40
 * The command has a dual behaviour depending on whether the waitTime field is
41
 * this field is set, then this command will cause the caller thread to wait 'waitTime' milliseconds.  
41
 * set or not. If this field is set, then this command will cause the caller
42
 * If the field is not set, then the command will cause the caller thread to wait until all 
42
 * thread to wait 'waitTime' milliseconds. If the field is not set, then the
43
 * non-system Eclipse jobs are completed.
43
 * command will cause the caller thread to wait until all non-system Eclipse
44
 * </p>  
44
 * jobs are completed.
45
 * </p>
45
 */
46
 */
46
public class WaitCommand extends AbstractMacroCommand
47
public class WaitCommand extends AbstractMacroCommand {
47
{
48
48
	public static final String TYPE = "wait";	
49
	public static final String TYPE = IMacroCommand.WAIT;
49
50
50
	/* The amount of waiting time.  If this field is set, then this command behaves differently */
51
	/*
52
	 * The amount of waiting time. If this field is set, then this command
53
	 * behaves differently
54
	 */
51
	private long waitTime;
55
	private long waitTime;
52
	
56
53
	private static class JobListener extends JobChangeAdapter
57
	private static class JobListener extends JobChangeAdapter {
54
	{
58
55
		private int counter = 0;
59
		private int counter = 0;
56
60
57
		private IProgressMonitor monitor;
61
		private IProgressMonitor monitor;
58
62
59
		private Thread t;
63
		private Thread t;
60
64
61
		public JobListener(IProgressMonitor monitor, Thread t, int number)
65
		public JobListener(IProgressMonitor monitor, Thread t, int number) {
62
		{
63
			this.counter = number;
66
			this.counter = number;
64
			this.monitor = monitor;
67
			this.monitor = monitor;
65
			this.t = t;
68
			this.t = t;
66
		}
69
		}
67
70
68
		private synchronized void change(int increment)
71
		private synchronized void change(int increment) {
69
		{
70
			this.counter += increment;
72
			this.counter += increment;
71
			if (counter == 0)
73
			if (counter == 0) {
72
			{
73
				monitor.subTask("");
74
				monitor.subTask("");
74
				synchronized (t)
75
				synchronized (t) {
75
				{
76
					t.interrupt();
76
					t.interrupt();
77
				}
77
				}
78
			}
78
			}
79
		}
79
		}
80
80
81
		public void running(IJobChangeEvent event)
81
		public void running(IJobChangeEvent event) {
82
		{
83
			Job job = event.getJob();
82
			Job job = event.getJob();
84
			if (!job.isSystem())
83
			if (!job.isSystem())
85
				change(1);
84
				change(1);
86
		}
85
		}
87
86
88
		public void done(IJobChangeEvent event)
87
		public void done(IJobChangeEvent event) {
89
		{
90
			Job job = event.getJob();
88
			Job job = event.getJob();
91
			if (!job.isSystem())
89
			if (!job.isSystem())
92
				change(-1);
90
				change(-1);
93
		}
91
		}
94
	}
92
	}
95
93
96
97
	/**
94
	/**
98
	 * A chance to build the meta-data of this verification command
95
	 * A chance to build the meta-data of this verification command
99
	 */
96
	 */
100
	public void load(Node node, Hashtable lineTable) throws CoreException 
97
	public void load(Node node, Hashtable lineTable) throws CoreException {
101
	{
102
		super.load(node, lineTable);
98
		super.load(node, lineTable);
103
				
99
104
		String waitTime = MacroUtil.getAttribute(node, MacroConstants.TIME_TO_WAIT_ATTRIBUTE);
100
		String waitTime = MacroUtil.getAttribute(node,
105
		
101
				MacroConstants.TIME_TO_WAIT_ATTRIBUTE);
106
		if (waitTime != null && waitTime.length() > 0)
102
107
		{
103
		if (waitTime != null && waitTime.length() > 0) {
108
			try
104
			try {
109
			{
110
				long timeToWait = Long.parseLong(waitTime);
105
				long timeToWait = Long.parseLong(waitTime);
111
				if (timeToWait > 0)
106
				if (timeToWait > 0)
112
					this.waitTime = timeToWait;
107
					this.waitTime = timeToWait;
113
			}
108
			} catch (NumberFormatException nfe) {
114
			catch (NumberFormatException nfe)
115
			{
116
				nfe.printStackTrace();
109
				nfe.printStackTrace();
117
			}
110
			}
118
		}
111
		}
119
	}
112
	}
120
	
121
113
122
	public WaitCommand(MacroCommandShell parent)
114
	public WaitCommand(MacroCommandShell parent) {
123
	{
115
		super(parent);
124
		super(parent, WidgetIdentifier.NULL_IDENTIFIER);
125
	}
116
	}
126
117
127
	/*
118
	/*
Lines 129-136 Link Here
129
	 * 
120
	 * 
130
	 * @see org.eclipse.ui.macro.MacroCommand#getType()
121
	 * @see org.eclipse.ui.macro.MacroCommand#getType()
131
	 */
122
	 */
132
	public String getType()
123
	public String getType() {
133
	{
134
		return TYPE;
124
		return TYPE;
135
	}
125
	}
136
126
Lines 139-146 Link Here
139
	 * 
129
	 * 
140
	 * @see org.eclipse.ui.macro.MacroCommand#processEvent(org.eclipse.swt.widgets.Event)
130
	 * @see org.eclipse.ui.macro.MacroCommand#processEvent(org.eclipse.swt.widgets.Event)
141
	 */
131
	 */
142
	public void processEvent(Event e)
132
	public void processEvent(Event e) {
143
	{
144
	}
133
	}
145
134
146
	/*
135
	/*
Lines 149-278 Link Here
149
	 * @see org.eclipse.ui.macro.IWritable#write(java.lang.String,
138
	 * @see org.eclipse.ui.macro.IWritable#write(java.lang.String,
150
	 *      java.io.PrintWriter)
139
	 *      java.io.PrintWriter)
151
	 */
140
	 */
152
	public void write(int indent, StringBuffer sb)
141
	public void write(int indent, StringBuffer sb) {
153
	{		
142
		/*
154
		/* Don't print out this wait command if it happens to be the last command in the macro shell OR
143
		 * Don't print out this wait command if it happens to be the last
155
		 * the next command following it is a macro command shell */
144
		 * command in the macro shell OR the next command following it is a
145
		 * macro command shell
146
		 */
156
		ArrayList commands = getParent().getCommands();
147
		ArrayList commands = getParent().getCommands();
157
		int commandSize = commands.size();
148
		int commandSize = commands.size();
158
		if ((commandSize > 0 && this == commands.get(commandSize - 1)) || isNextCommandShell(commands))
149
		if ((commandSize > 0 && this == commands.get(commandSize - 1))
150
				|| isNextCommandShell(commands))
159
			return;
151
			return;
160
		
152
161
		
153
		MacroUtil.addElement(sb, indent, MacroConstants.COMMAND_ELEMENT, false,
162
		MacroUtil.addElement(sb, indent, MacroConstants.COMMAND_ELEMENT, false, false);
154
				false);
163
		MacroUtil.addAttribute(sb, 
155
		MacroUtil.addAttribute(sb, new String[] {
164
				new String[] {MacroConstants.DESCRIPTIVE_ATTRIBUTE,
156
				MacroConstants.DESCRIPTIVE_ATTRIBUTE,
165
							  MacroConstants.TYPE_ATTRIBUTE,
157
				MacroConstants.TYPE_ATTRIBUTE,
166
							  MacroConstants.TIME_TO_WAIT_ATTRIBUTE}, 
158
				MacroConstants.TIME_TO_WAIT_ATTRIBUTE }, new String[] {
167
				new String[] {MacroUtil.boundSize(getDescriptiveField(), AbstractMacroCommand.DESCRIPTIVE_FIELD_BOUND),
159
				MacroUtil.boundSize(getDescriptiveField(),
168
							  getType(),
160
						AbstractMacroCommand.DESCRIPTIVE_FIELD_BOUND),
169
							  waitTime > 0 ? String.valueOf(waitTime) : null}, true, true);		
161
				getType(), waitTime > 0 ? String.valueOf(waitTime) : null },
162
				true, true);
170
	}
163
	}
171
164
172
	private boolean isNextCommandShell(ArrayList commands) 
165
	private boolean isNextCommandShell(ArrayList commands) {
173
	{
174
		int index = -1;
166
		int index = -1;
175
		
167
176
		int commandCount = commands.size();
168
		int commandCount = commands.size();
177
		for (int i = 0; i < commandCount; i++) 
169
		for (int i = 0; i < commandCount; i++) {
178
		{
170
			if (this == commands.get(i)) {
179
			if (this == commands.get(i))
180
			{
181
				index = i;
171
				index = i;
182
				break;
172
				break;
183
			}			
173
			}
184
		}
174
		}
185
		
175
186
		if (index + 1 < commandCount)
176
		if (index + 1 < commandCount)
187
			return commands.get(index + 1) instanceof MacroCommandShell;
177
			return commands.get(index + 1) instanceof MacroCommandShell;
188
		return false;
178
		return false;
189
	}
179
	}
190
180
191
192
	/*
181
	/*
193
	 * (non-Javadoc)
182
	 * (non-Javadoc)
194
	 * 
183
	 * 
195
	 * @see org.eclipse.ui.macro.IPlayable#playback(org.eclipse.swt.widgets.Composite)
184
	 * @see org.eclipse.ui.macro.IPlayable#playback(org.eclipse.swt.widgets.Composite)
196
	 */
185
	 */
197
	public boolean playback(Display display, Composite parent, IProgressMonitor monitor) throws CoreException
186
	public boolean playback(Display display, Shell parent,
198
	{
187
			IProgressMonitor monitor) throws CoreException {
199
		
188
200
		if (waitTime > 0)
189
		if (waitTime > 0) {
201
		{
190
			try {
202
			try
203
			{
204
				Thread.sleep(waitTime);
191
				Thread.sleep(waitTime);
205
			}
192
			} catch (InterruptedException e) {
206
			catch (InterruptedException e)
207
			{
208
				/* Doesn't need to be handled */
193
				/* Doesn't need to be handled */
209
			}
194
			}
210
			return true;
195
			return true;
211
		}
196
		}
212
		
197
213
		
214
		IJobManager jobManager = Platform.getJobManager();
198
		IJobManager jobManager = Platform.getJobManager();
215
		int nrunning = getNumberOfRunningJobs(jobManager);
199
		int nrunning = getNumberOfRunningJobs(jobManager);
216
		if (nrunning == 0)
200
		if (nrunning == 0) {
217
		{
218
			return true;
201
			return true;
219
		}
202
		}
220
		String message = AutoGUIMessages.AUTO_GUI_MACRO_WAITING;
203
		String message = AutoGUIMessages.AUTO_GUI_MACRO_WAITING;
221
		JobListener listener = new JobListener(monitor, Thread.currentThread(), nrunning);
204
		JobListener listener = new JobListener(monitor, Thread.currentThread(),
205
				nrunning);
222
		jobManager.addJobChangeListener(listener);
206
		jobManager.addJobChangeListener(listener);
223
		monitor.subTask(message);
207
		monitor.subTask(message);
224
		
208
225
		final long INCREMENT_WAIT = 2000;
209
		final long INCREMENT_WAIT = 2000;
226
		final int MAX_INCREMENT_NUM = 5;
210
		final int MAX_INCREMENT_NUM = 5;
227
		try
211
		try {
228
		{
229
			int counter = 0;
212
			int counter = 0;
230
			
213
231
			/* Let's wait in increments of INCREMENT_WAIT milliseconds for a maximum of INCREMENT_WAIT * MAX_INCREMENT_NUM  milliseconds*/
214
			/*
232
			while (counter < MAX_INCREMENT_NUM)
215
			 * Let's wait in increments of INCREMENT_WAIT milliseconds for a
233
			{
216
			 * maximum of INCREMENT_WAIT * MAX_INCREMENT_NUM milliseconds
234
				Thread.sleep(INCREMENT_WAIT);						
217
			 */
218
			while (counter < MAX_INCREMENT_NUM) {
219
				Thread.sleep(INCREMENT_WAIT);
235
				if (getNumberOfRunningJobs(jobManager) == 0)
220
				if (getNumberOfRunningJobs(jobManager) == 0)
236
					break;				
221
					break;
237
				counter++;
222
				counter++;
238
			}
223
			}
239
			
224
240
		}
225
		} catch (InterruptedException e) {
241
		catch (InterruptedException e)
242
		{
243
		}
226
		}
244
		jobManager.removeJobChangeListener(listener);
227
		jobManager.removeJobChangeListener(listener);
245
		return true;
228
		return true;
246
	}
229
	}
247
230
248
	private int getNumberOfRunningJobs(IJobManager manager)
231
	private int getNumberOfRunningJobs(IJobManager manager) {
249
	{
250
		int count = 0;
232
		int count = 0;
251
		Job[] jobs = manager.find(null);
233
		Job[] jobs = manager.find(null);
252
		for (int i = 0; i < jobs.length; i++)
234
		for (int i = 0; i < jobs.length; i++) {
253
		{
254
			if (!jobs[i].isSystem() && jobs[i].getState() == Job.RUNNING)
235
			if (!jobs[i].isSystem() && jobs[i].getState() == Job.RUNNING)
255
				count++;
236
				count++;
256
		}
237
		}
257
		return count;
238
		return count;
258
	}
239
	}
259
240
260
	public void setWaitTime(long difference) 
241
	public void setWaitTime(long difference) {
261
	{
262
		this.waitTime = difference;
242
		this.waitTime = difference;
263
	}
243
	}
264
	
244
265
	/**
245
	/**
266
	 * Overwrite this method so that a custom descriptive field can be specified.
246
	 * Overwrite this method so that a custom descriptive field can be
267
	 * The format of the descriptive field is "<WAIT_TIME> seconds"
247
	 * specified. The format of the descriptive field is "<WAIT_TIME> seconds"
268
	 * 
248
	 * 
269
	 * @return The descriptive field.
249
	 * @return The descriptive field.
270
	 */
250
	 */
271
	public String getDescriptiveField()
251
	public String getDescriptiveField() {
272
	{
273
		if (waitTime > 0)
252
		if (waitTime > 0)
274
			return (((double)waitTime) / 1000.0)  + " " + AutoGUIMessages.TST_SUITE_AUTO_MACRO_SECONDS;
253
			return (((double) waitTime) / 1000.0) + " "
275
		
254
					+ AutoGUIMessages.TST_SUITE_AUTO_MACRO_SECONDS;
255
276
		return null;
256
		return null;
277
	}
257
	}
278
}
258
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/EditorCommandTarget.java (-38 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.commands;
12
13
import org.eclipse.swt.widgets.Widget;
14
import org.eclipse.ui.IEditorPart;
15
import org.eclipse.ui.IWorkbenchPage;
16
17
public class EditorCommandTarget extends CommandTarget {
18
	/**
19
	 * @param widget
20
	 * @param context
21
	 */
22
	public EditorCommandTarget(Widget widget, IEditorPart editor) {
23
		super(widget, editor);
24
	}
25
	
26
	public IEditorPart getEditor() {
27
		return (IEditorPart)getContext();
28
	}
29
30
	/* (non-Javadoc)
31
	 * @see org.eclipse.ui.macro.CommandTarget#ensureVisible()
32
	 */
33
	public void ensureVisible() {
34
		IEditorPart editor = getEditor();
35
		IWorkbenchPage page = editor.getEditorSite().getPage();
36
		page.activate(editor);
37
	}
38
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/CheckCommand.java (-44 / +41 lines)
Lines 17-106 Link Here
17
import org.eclipse.swt.widgets.Tree;
17
import org.eclipse.swt.widgets.Tree;
18
import org.eclipse.swt.widgets.TreeItem;
18
import org.eclipse.swt.widgets.TreeItem;
19
import org.eclipse.swt.widgets.Widget;
19
import org.eclipse.swt.widgets.Widget;
20
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
20
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
21
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
21
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
22
22
23
public class CheckCommand extends ToggleStructuredCommand 
23
public class CheckCommand extends ToggleStructuredCommand {
24
{
24
25
	public static final String TYPE = "item-check";
25
	public static final String TYPE = IMacroCommand.ITEM_CHECK;
26
26
	/**
27
	/**
27
	 * @param wid
28
	 * @param wid
28
	 */
29
	 */
29
	public CheckCommand(MacroCommandShell parent, WidgetIdentifier wid) {
30
	public CheckCommand(MacroCommandShell parent) {
30
		super(parent, wid);
31
		super(parent);
31
	}
32
	}
32
	
33
33
	public String getType() {
34
	public String getType() {
34
		return TYPE;
35
		return TYPE;
35
	}
36
	}
36
	
37
37
	public void processEvent(Event event) 
38
	public void doProcessEvent(Event event) {
38
	{
39
		super.doProcessEvent(event);
39
		super.processEvent(event);
40
		
40
		Widget item = event.item;
41
		Widget item = event.item;
41
		itemState = getItemState (item);
42
		itemState = getItemState(item);
42
	}
43
	}
43
	
44
44
	public boolean getItemState(Widget item)
45
	public boolean getItemState(Widget item) {
45
	{		
46
		if (item instanceof TreeItem)
46
		if (item instanceof TreeItem)
47
			return ((TreeItem)item).getChecked();
47
			return ((TreeItem) item).getChecked();
48
		else if (item instanceof TableItem)
48
		else if (item instanceof TableItem)
49
			return ((TableItem)item).getChecked();
49
			return ((TableItem) item).getChecked();
50
		
50
51
		return false;
51
		return false;
52
	}
52
	}
53
	
53
54
	protected void playStructuredCommand(Widget widget, Object[] matches) 
54
	protected void playStructuredCommand(Widget widget, Object[] matches) {
55
	{
56
		boolean isTree = widget instanceof Tree;
55
		boolean isTree = widget instanceof Tree;
57
		boolean isTable = false;
56
		boolean isTable = false;
58
		if (!isTree)
57
		if (!isTree)
59
			isTable = widget instanceof Table;
58
			isTable = widget instanceof Table;
60
		
59
61
		if (!isTree && !isTable)
60
		if (!isTree && !isTable)
62
			return;
61
			return;
63
		
62
64
		Event selectionEvent = null;
63
		Event selectionEvent = null;
65
		
64
66
		for (int i=0; i<matches.length; i++) 
65
		for (int i = 0; i < matches.length; i++) {
67
		{
68
			selectionEvent = constructSelectionEvent(widget);
66
			selectionEvent = constructSelectionEvent(widget);
69
			
67
70
			if ((widget.getStyle() & SWT.CHECK) != 0)
68
			if ((widget.getStyle() & SWT.CHECK) != 0)
71
				selectionEvent.detail = SWT.CHECK;
69
				selectionEvent.detail = SWT.CHECK;
72
			selectionEvent.item = (Widget)matches[i];
70
			selectionEvent.item = (Widget) matches[i];
73
			
71
74
			if (isTree)
72
			if (isTree)
75
				((TreeItem)matches[i]).setChecked(getValue());
73
				((TreeItem) matches[i]).setChecked(getValue());
76
			else
74
			else
77
				((TableItem)matches[i]).setChecked(getValue());
75
				((TableItem) matches[i]).setChecked(getValue());
78
			
76
79
			/* Send the selection event */
77
			/* Send the selection event */
80
			widget.notifyListeners(SWT.Selection, selectionEvent);
78
			widget.notifyListeners(SWT.Selection,
79
				selectionEvent);
81
			MacroUtil.processDisplayEvents(widget.getDisplay());
80
			MacroUtil.processDisplayEvents(widget.getDisplay());
82
		}
81
		}
83
		
82
84
	}
83
	}
85
	
84
86
	/**
85
	/**
87
	 * Clients will often expect a selection event to be sent.
86
	 * Clients will often expect a selection event to be sent. This helper method is used to construct a selection event.
88
	 * This helper method is used to construct a selection event.
89
	 * 
87
	 * 
90
	 * @param widget The widget that will be used to send out the event.
88
	 * @param widget
91
	 * @return The event. 
89
	 *            The widget that will be used to send out the event.
90
	 * @return The event.
92
	 */
91
	 */
93
	private Event constructSelectionEvent(Widget widget)
92
	private Event constructSelectionEvent(Widget widget) {
94
	{
95
		Event event = new Event();
93
		Event event = new Event();
96
		event.display = widget.getDisplay();
94
		event.display = widget.getDisplay();
97
		event.widget = widget;
95
		event.widget = widget;
98
		event.type = SWT.Selection;		
96
		event.type = SWT.Selection;
99
		return event;
97
		return event;
100
	}
98
	}
101
99
102
	protected void playStructuredCommandForFoundMatch(Widget widget, Object match) 
100
	protected void playStructuredCommandForFoundMatch(Widget widget, Object match) {
103
	{
104
		/* Deosn't need to be implemented */
101
		/* Deosn't need to be implemented */
105
	}
102
	}
106
103
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/ViewCommandTarget.java (-34 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.commands;
12
13
import org.eclipse.swt.widgets.Widget;
14
import org.eclipse.ui.IViewPart;
15
import org.eclipse.ui.IWorkbenchPage;
16
17
public class ViewCommandTarget extends CommandTarget {
18
	public ViewCommandTarget(Widget widget, IViewPart view) {
19
		super(widget, view);
20
	}
21
	
22
	public IViewPart getView() {
23
		return (IViewPart)getContext();
24
	}
25
26
	/* (non-Javadoc)
27
	 * @see org.eclipse.ui.macro.CommandTarget#ensureVisible()
28
	 */
29
	public void ensureVisible() {
30
		IViewPart view = getView();
31
		IWorkbenchPage page = view.getViewSite().getPage();
32
		page.activate(view);
33
	}
34
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/CommandTarget.java (-43 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.commands;
12
13
import org.eclipse.swt.widgets.*;
14
import org.eclipse.swt.widgets.Widget;
15
16
public class CommandTarget {
17
	private Widget widget;
18
	private Object context;
19
	
20
	public CommandTarget(Widget widget, Object context) {
21
		this.widget = widget;
22
		this.context = context;
23
	}
24
25
	public void ensureVisible() {
26
	}
27
	
28
	public Widget getWidget() {
29
		return widget;
30
	}
31
	public Object getContext() {
32
		return context;
33
	}
34
	public void setFocus() {
35
		ensureVisible();
36
		Display display = widget.getDisplay();
37
		if (widget instanceof Control) {
38
			Control c = (Control)widget;
39
			if (!c.equals(display.getFocusControl()))
40
				c.setFocus();
41
		}
42
	}
43
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/ExpansionCommand.java (-34 / +45 lines)
Lines 15-79 Link Here
15
import org.eclipse.swt.widgets.Tree;
15
import org.eclipse.swt.widgets.Tree;
16
import org.eclipse.swt.widgets.TreeItem;
16
import org.eclipse.swt.widgets.TreeItem;
17
import org.eclipse.swt.widgets.Widget;
17
import org.eclipse.swt.widgets.Widget;
18
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
18
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
19
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObjectIdentifier;
19
20
20
public class ExpansionCommand extends ToggleStructuredCommand {
21
public class ExpansionCommand extends ToggleStructuredCommand {
21
	public static final String TYPE = "item-expand";
22
23
	public static final String TYPE = IMacroCommand.ITEM_EXPAND;
24
22
	/**
25
	/**
23
	 * @param wid
26
	 * @param wid
24
	 */
27
	 */
25
	public ExpansionCommand(MacroCommandShell parent, WidgetIdentifier wid) {
28
	public ExpansionCommand(MacroCommandShell parent) {
26
		super(parent, wid);
29
		super(parent);
30
	}
31
32
	public ExpansionCommand(MacroCommandShell parent,
33
			IMacroObjectIdentifier identifier) {
34
		super(parent);
35
		setMacroObjectIdentifier(identifier);
27
	}
36
	}
28
	
37
29
	public void processEvent(Event event) {
38
	public void doProcessEvent(Event event) {
30
		super.processEvent(event);
39
		super.doProcessEvent(event);
31
		Widget item = event.item;
40
		Widget item = event.item;
32
		itemState = getItemState (item);
41
		itemState = getItemState(item);
33
	}
42
	}
34
	
43
35
	/* Added for defect 164197*/
44
	/* Added for defect 164197 */
36
	
45
37
	public void processEvent(Event event, boolean preferredState)
46
	public void doProcessEvent(Event event, boolean preferredState) {
38
	{
47
		super.doProcessEvent(event);
39
		super.processEvent(event);
48
40
		itemState = preferredState;
49
		itemState = preferredState;
41
	}
50
	}
42
	public boolean getItemState(Widget item)
51
43
	{		
52
	public void setItemState(boolean state) {
53
		this.itemState = state;
54
	}
55
56
	public boolean getItemState(Widget item) {
44
		if (item instanceof TreeItem)
57
		if (item instanceof TreeItem)
45
			return !((TreeItem)item).getExpanded();
58
			return !((TreeItem) item).getExpanded();
46
		
59
47
		return false;
60
		return false;
48
	}
61
	}
49
62
50
	protected void playStructuredCommand(Widget widget, Object[] matches) 
63
	protected void playStructuredCommand(Widget widget, Object[] matches) {
51
	{
52
		/* Doesn't need to be implemented */
64
		/* Doesn't need to be implemented */
53
	}
65
	}
54
	
66
55
	protected void playStructuredCommandForFoundMatch(Widget widget, Object match) 
67
	protected void playStructuredCommandForFoundMatch(Widget widget,
56
	{
68
			Object match) {
57
		if (!(widget instanceof Tree))
69
		if (!(widget instanceof Tree))
58
			return;
70
			return;
59
		
71
60
		TreeItem treeItem = (TreeItem)match;
72
		TreeItem treeItem = (TreeItem) match;
61
		treeItem.setExpanded(getValue());
73
		treeItem.setExpanded(getValue());
62
		fireEvent(widget, treeItem);		
74
		fireEvent(widget, treeItem);
63
	}
75
	}
64
	
76
65
	
77
	private void fireEvent(Widget widget, Widget item) {
66
	private void fireEvent(Widget widget, Widget item) 
67
	{
68
		Event event = new Event();
78
		Event event = new Event();
69
		event.type = getValue()?SWT.Expand:SWT.Collapse;
79
		event.type = getValue() ? SWT.Expand : SWT.Collapse;
70
		event.widget = widget;
80
		event.widget = widget;
71
		event.item= item;
81
		event.item = item;
72
		widget.notifyListeners(event.type, event);
82
		widget.notifyListeners(event.type, event);
73
	}
83
	}
74
84
75
	
85
	/*
76
	/* (non-Javadoc)
86
	 * (non-Javadoc)
87
	 * 
77
	 * @see org.eclipse.ui.macro.SelectionCommand#getKind()
88
	 * @see org.eclipse.ui.macro.SelectionCommand#getKind()
78
	 */
89
	 */
79
	public String getType() {
90
	public String getType() {
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/WizardCommandTarget.java (-29 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.commands;
12
13
import org.eclipse.jface.window.Window;
14
import org.eclipse.jface.wizard.WizardDialog;
15
import org.eclipse.swt.widgets.Widget;
16
17
public class WizardCommandTarget extends WindowCommandTarget {
18
	/**
19
	 * @param widget
20
	 * @param window
21
	 */
22
	public WizardCommandTarget(Widget widget, Window window) {
23
		super(widget, window);
24
	}
25
26
	public WizardDialog getWizardDialog() {
27
		return (WizardDialog)getWindow();
28
	}
29
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/VerificationCommand.java (-297 / +473 lines)
Lines 13-18 Link Here
13
13
14
import java.io.File;
14
import java.io.File;
15
import java.lang.reflect.Constructor;
15
import java.lang.reflect.Constructor;
16
import java.net.MalformedURLException;
16
import java.net.URL;
17
import java.net.URL;
17
import java.util.Hashtable;
18
import java.util.Hashtable;
18
import java.util.StringTokenizer;
19
import java.util.StringTokenizer;
Lines 25-398 Link Here
25
import org.eclipse.jdt.core.IJavaProject;
26
import org.eclipse.jdt.core.IJavaProject;
26
import org.eclipse.jface.dialogs.MessageDialog;
27
import org.eclipse.jface.dialogs.MessageDialog;
27
import org.eclipse.osgi.util.NLS;
28
import org.eclipse.osgi.util.NLS;
28
import org.eclipse.swt.SWT;
29
import org.eclipse.swt.widgets.Composite;
30
import org.eclipse.swt.widgets.Display;
29
import org.eclipse.swt.widgets.Display;
31
import org.eclipse.swt.widgets.Event;
30
import org.eclipse.swt.widgets.Event;
32
import org.eclipse.swt.widgets.Shell;
31
import org.eclipse.swt.widgets.Shell;
33
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
32
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
34
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
33
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
35
import org.eclipse.tptp.test.auto.gui.internal.core.VerifHookClassLoader;
34
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
36
import org.eclipse.tptp.test.auto.gui.internal.core.VerificationMetaData;
37
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
38
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
35
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
39
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
36
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
40
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroObjectLocator;
41
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
37
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
38
import org.eclipse.tptp.test.auto.gui.internal.macro.ModeConstants;
39
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObjectIdentifier;
40
import org.eclipse.tptp.test.auto.gui.internal.macroobject.resolver.MacroObjectResolver;
42
import org.eclipse.tptp.test.auto.gui.internal.runner.AutoGUIVerificationHook;
41
import org.eclipse.tptp.test.auto.gui.internal.runner.AutoGUIVerificationHook;
42
import org.eclipse.tptp.test.auto.gui.internal.util.VerificationHookClassLoader;
43
import org.eclipse.ui.IEditorPart;
43
import org.eclipse.ui.IEditorPart;
44
import org.eclipse.ui.IViewPart;
44
import org.eclipse.ui.IViewPart;
45
import org.w3c.dom.Node;
45
import org.w3c.dom.Node;
46
46
47
48
/**
47
/**
49
 * The following command is inserted for every verification hook that the 
48
 * The following command is inserted for every verification hook that the user
50
 * user inserts for a particular test case.  An instance of this class can
49
 * inserts for a particular test case. An instance of this class can only be
51
 * only be created through constructInstance(Event). <br/>
50
 * created through constructInstance(Event). <br/> In order for clients to be
52
 * In order for clients to be able to write or playback this command they must
51
 * able to write or playback this command they must meet the following
53
 * meet the following pre-conditions.
52
 * pre-conditions.
54
 * 
53
 * 
55
 * <ul>
54
 * <ul>
56
 * 	<li> test suite must be set using setTestSuite </li>
55
 * <li> test suite must be set using setTestSuite </li>
57
 * 	<li> verification hook must be set using setVerificationHook </li>
56
 * <li> verification hook must be set using setVerificationHook </li>
58
 * </ul>
57
 * </ul>
59
 * 
58
 * 
60
 * @author Ali Mehregani
59
 * @author Ali Mehregani
60
 * @author Alexander Nyssen (refactored to be a normal object based command and
61
 *         use the new resolving mechanism)
61
 */
62
 */
62
public class VerificationCommand extends AbstractMacroCommand
63
public class VerificationCommand extends ObjectBasedCommand {
63
{	
64
64
	/* The type of this command */
65
	/* The type of this command */
65
	public static final String TYPE = "verification";
66
	public static final String TYPE = IMacroCommand.VERIFICATION;
67
68
	/* The possible types */
69
	public static final byte EDITOR = 0x01;
70
	public static final byte VIEW = 0x02;
71
	public static final byte SHELL = 0x03;
72
73
	/* The location is the plugin that contains the hook source code */
74
	private String location;
75
76
	/* The resource is the class name containing the hook */
77
	private String resource;
78
79
	/* The hook is the method name representing the verification point */
80
	private String hook;
81
82
	/* The focus type indicates whether the type of context being retrieved */
83
	private byte focusType;
84
85
	private Class contextClass;
86
87
	private Class widgetClass;
88
89
	private Class objectClass;
90
91
	/*
92
	 * flag to indicate if additionally to the context id, an object id should
93
	 * be used as verification hook target
94
	 */
95
	private boolean extendedScope = false;
66
96
67
	/* This instance variable is updated if at any point there is an error 
68
	 * creating an instance of this class through constructInstance.  This can
69
	 * be null if no errors are to be reported */
70
	private static String error;
71
	
72
	/* The meta data required by this verification command */
73
	private VerificationMetaData metaData;
74
	
75
	/* To be acknowledged events */
76
	private static WidgetIdentifier toBeAck;
77
	
78
	/**
97
	/**
79
	 * The constructor 
98
	 * The constructor
80
	 * 
99
	 * 
81
	 * @param metaData The meta data that this verification command uses to write
100
	 * @param metaData
82
	 * or play back itself.
101
	 *            The meta data that this verification command uses to write or
102
	 *            play back itself.
83
	 */
103
	 */
84
	public VerificationCommand (MacroCommandShell parent, VerificationMetaData metaData)
104
	public VerificationCommand(MacroCommandShell parent) {
85
	{
105
		super(parent);
86
		super(parent, WidgetIdentifier.NULL_IDENTIFIER);			/* The widget id is irrelevant in the verification command.  This is just a dummy command */
87
		this.metaData = metaData;
88
	}
106
	}
89
107
90
	public String getType()
108
	public String getType() {
91
	{
92
		return TYPE;
109
		return TYPE;
93
	}
110
	}
94
111
95
	public void processEvent(Event e)
112
	/**
96
	{
113
	 * {@inheritDoc}
114
	 * 
115
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.IMacroCommand#processEvent(org.eclipse.swt.widgets.Event)
116
	 */
117
	public void doProcessEvent(Event event) {
118
		focusType = findFocusType(getMacroObjectIdentifier()
119
				.getContextIdentifier());
120
		contextClass = findContextClass(getMacroObjectIdentifier()
121
				.getContextIdentifier());
122
		widgetClass = macroObject.getUIObject().getWidget().getClass();
123
		if (macroObject.getUIObject().getObject() != null) {
124
			objectClass = macroObject.getUIObject().getObject().getClass();
125
		}
97
	}
126
	}
98
127
99
	/**
128
	/**
100
	 * A chance to build the meta-data of this verification command
129
	 * A chance to build the meta-data of this verification command
101
	 */
130
	 */
102
	public void load(Node node, Hashtable lineTable) 
131
	public void load(Node node, Hashtable lineTable) throws CoreException {
103
	{
132
		super.load(node, lineTable);
104
		/* Bind the source location */
133
105
		super.bindSourceLocation(node, lineTable);
134
		// String contextId = MacroUtil.getAttribute(node,
106
		
135
		// "contextId");
107
		/* Construct the meta data here */
136
		focusType = findFocusType(getMacroObjectIdentifier()
108
		VerificationMetaData metaData = getMetaData();
137
				.getContextIdentifier());
109
		
138
		contextClass = findContextClass(getMacroObjectIdentifier()
110
		String contextId = MacroUtil.getAttribute(node, "contextId");
139
				.getContextIdentifier());
111
		metaData.setContextId(contextId);
140
		location = MacroUtil.getAttribute(node, "location");
112
		metaData.setFocusType(MacroUtil.findFocusType(contextId));
141
		resource = MacroUtil.getAttribute(node, "resource");
113
		metaData.setLocation(MacroUtil.getAttribute(node, "location"));
142
		hook = MacroUtil.getAttribute(node, "hook");
114
		metaData.setResource(MacroUtil.getAttribute(node, "resource"));
143
		// if the hook has more than one parameter, we are in extended scope
115
		metaData.setHook(MacroUtil.getAttribute(node, "hook"));
144
		// mode
116
	}
145
		setExtendedScope(hook.indexOf(';') != hook.lastIndexOf(";"));
117
	
146
		// if we are in extended mode, we have to load the object class.
118
	
147
		if (isExtendedScope()) {
119
	/**
148
			widgetClass = findWidgetClass(hook);
120
	 * Invoked when this writable object is ready to be written to
149
			objectClass = findObjectClass(hook);
121
	 * a print writer.
150
		}
122
	 */
151
	}
123
	public void write(int indent, StringBuffer sb)
152
124
	{
153
	/**
125
		if (!metaData.isComplete())
154
	 * {@inheritDoc}
126
			return;
155
	 * 
127
		
156
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.ObjectBasedCommand#loadMacroObjectIdentifier(org.w3c.dom.Node,
128
		/* If the default package is selected for a verification hook class, 
157
	 *      java.util.Hashtable)
129
		 * it is often prefixed with a '.'  This needs to be taken out before
158
	 */
159
	protected void loadMacroObjectIdentifier(Node node, Hashtable lineTable)
160
			throws CoreException {
161
		// let the super implementation try (in case we are in extended mode,
162
		// this should build a valid descriptor)
163
		super.loadMacroObjectIdentifier(node, lineTable);
164
165
		// if we are not in extended mode, just set the context id
166
		if (getMacroObjectIdentifier() == null) {
167
			String cid = MacroUtil.getAttribute(node,
168
					MacroConstants.CONTEXT_ID_ATTRIBUTE);
169
			setMacroObjectIdentifier(new MacroObjectIdentifier(cid, null));
170
		}
171
	}
172
173
	/**
174
	 * {@inheritDoc}
175
	 * 
176
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.ObjectBasedCommand#writeMacroObjectIdentifier(int,
177
	 *      java.lang.StringBuffer, boolean, boolean)
178
	 */
179
	protected void writeMacroObjectIdentifier(int indent, StringBuffer sb,
180
			boolean close, boolean end) {
181
		if (isExtendedScope()) {
182
			// write the normal triple (contextID, objectID, resolverID)
183
			super.writeMacroObjectIdentifier(indent, sb, close, end);
184
		} else {
185
			// only write the context id
186
			MacroUtil.addAttribute(sb,
187
					new String[] { MacroConstants.CONTEXT_ID_ATTRIBUTE },
188
					new String[] { getMacroObjectIdentifier()
189
							.getContextIdentifier() }, close, end);
190
		}
191
	}
192
193
	/**
194
	 * Invoked when this writable object is ready to be written to a print
195
	 * writer.
196
	 */
197
	public void write(int indent, StringBuffer sb) {
198
		// let the super implementation write the element, we will just add our
199
		// attributes
200
		super.write(indent, sb);
201
		/*
202
		 * If the default package is selected for a verification hook class, it
203
		 * is often prefixed with a '.' This needs to be taken out before
130
		 * written as part of the macro
204
		 * written as part of the macro
131
		 */
205
		 */
132
		String resource = metaData.getResource();
206
		if (resource != null && resource.length() > 0
133
		if (resource != null && resource.length() > 0 && resource.charAt(0) == '.')
207
				&& resource.charAt(0) == '.')
134
			resource = resource.substring(1);
208
			resource = resource.substring(1);
135
		
209
136
		MacroUtil.addElement(sb, indent, MacroConstants.COMMAND_ELEMENT, false, false);
210
		MacroUtil.addAttribute(sb, new String[] {
137
		MacroUtil.addAttribute(sb, 
211
		/*
138
				new String[] {MacroConstants.TYPE_ATTRIBUTE,
212
		 * MacroConstants.TYPE_ATTRIBUTE, MacroConstants.CONTEXT_ID_ATTRIBUTE,
139
							  MacroConstants.CONTEXT_ID_ATTRIBUTE,
140
							  MacroConstants.LOCATION_ATTRIBUTE,
141
							  MacroConstants.RESOURCE_ATTRIBUTE,
142
							  MacroConstants.HOOK_ATTRIBUTE},
143
				new String[] {getType(),
144
							  metaData.getContextId(),
145
							  metaData.getLocation(),
146
							  resource,
147
							  metaData.getHook()}, true, true);		
148
	}
149
150
	
151
	/**
152
	 * This doesn't involve any UI actions.  Playing back the verification command will
153
	 * simply run the verification hook.
154
	 * @throws CoreException 
155
	 */
156
	public boolean playback(Display display, Composite parent, IProgressMonitor monitor) throws CoreException
157
	{
158
		/* Phases:
159
		 * 	1. Load the necessary class
160
		 * 	2. Do the method look up on the hook entry
161
		 * 	3. If valid:
162
		 * 		4. Load its context (i.e. View/Editor/etc...)
163
		 * 		5. Invoke the hook with the context  		
164
		 */
213
		 */
165
			
214
		MacroConstants.LOCATION_ATTRIBUTE, MacroConstants.RESOURCE_ATTRIBUTE,
215
				MacroConstants.HOOK_ATTRIBUTE }, new String[] {/*
216
																 * getType(),
217
																 * metaData.getContextId(),
218
																 */
219
		location, resource, hook }, true, true);
220
221
	}
222
223
	/**
224
	 * {@inheritDoc}
225
	 * 
226
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.ObjectBasedCommand#useObjectMine()
227
	 */
228
	protected boolean useObjectMine() {
229
		// verification commands do never use the object mine (why?)
230
		return false;
231
	}
232
233
	private Class findWidgetClass(String hook) {
234
		// parse the hook signature to retrieve the class name of the widget
235
		// class
236
		String className = hook.substring(hook.indexOf(";Q") + 2, hook.indexOf(
237
				";", hook.indexOf(";Q") + 2));
238
		try {
239
			return loadClass(className);
240
		} catch (Exception e) {
241
			return null;
242
		}
243
	}
244
245
	private Class findObjectClass(String hook) {
246
		// see if we have also an object parameter
247
		String className = hook.substring(hook.indexOf(";Q",
248
				hook.indexOf(";Q") + 2) + 2, hook.lastIndexOf(";"));
249
		try {
250
			return loadClass(className);
251
		} catch (Exception e) {
252
			return null;
253
		}
254
	}
255
256
	private Class loadClass(String className) throws MalformedURLException,
257
			CoreException, ClassNotFoundException {
166
		String classPath = System.getProperty("java.class.path");
258
		String classPath = System.getProperty("java.class.path");
167
		try
259
		Vector reqPlugins = null;
168
		{			
260
169
			Vector reqPlugins = null;
261
		/*
170
						
262
		 * If we happen to run in the quick run mode, then we need to explicitly
171
			
263
		 * modify the class path ourself.
172
			/* If we happen to run in the quick run mode, then we need to explicitly modify the
264
		 */
173
			 * class path ourself. */
265
		if (MacroManager.getInstance().getGlobalState() == ModeConstants.QUICK_RUN_MODE) {
174
			if (MacroManager.getInstance().getGlobalState() == MacroManager.QUICK_RUN_MODE)
266
			/* The project is expected to be a java project */
175
			{
267
			IJavaProject javaProject = AutoGUIUtil.findJavaProject(location);
176
				/* The project is expected to be a java project */
268
177
				IJavaProject javaProject = AutoGUIUtil.findJavaProject(metaData.getLocation());
269
			/*
178
270
			 * We need to add the output folder of all the java projects in our
179
				/* We need to add the output folder of all the java projects in our workspace to the classpath */
271
			 * workspace to the classpath
180
				classPath += AutoGUIUtil.appendWSProjOutputFolder(classPath);
272
			 */
181
				
273
			classPath += AutoGUIUtil.appendWSProjOutputFolder(classPath);
182
				if (javaProject != null && javaProject.exists())
274
183
				{					
275
			if (javaProject != null && javaProject.exists()) {
184
					/* Add the classpath entries of the project */										
276
				/* Add the classpath entries of the project */
185
					reqPlugins = new Vector(5);					
277
				reqPlugins = new Vector(5);
186
					classPath += AutoGUIUtil.findDependencies (javaProject, reqPlugins, true);
278
				classPath += AutoGUIUtil.findDependencies(javaProject,
187
				}
279
						reqPlugins, true);
188
			}
189
			
190
			/* Otherwise we're running in execution mode.  We'll still need to resolve the dependencies of the plugin
191
			 * containing the test suite.  If any exists, then it would have been registerd with the MacroManager. */
192
			else
193
			{
194
				reqPlugins = MacroManager.getInstance().getDependecies();
195
			}
196
			
197
			StringTokenizer st = new StringTokenizer (classPath, File.pathSeparator);
198
			Vector urlsVec = new Vector(10);
199
			
200
			/* https://bugs.eclipse.org/bugs/show_bug.cgi?id=136157 */
201
			final String PREFIX = "file:";
202
			
203
			while (st.hasMoreTokens())
204
			{
205
				String curURL = st.nextToken();
206
				
207
				/* The URL class loader will require all directories to end with a forward slash */
208
				if (!curURL.endsWith(".jar") && !curURL.endsWith("/"))
209
					curURL += "/";								
210
				
211
				urlsVec.add(new URL(PREFIX + curURL));
212
			}
280
			}
213
			
281
		}
214
			/* Construct the urls */
282
215
			URL[] urls = new URL[urlsVec.size()];
283
		/*
216
			for (int i = 0; i < urls.length; i++)
284
		 * Otherwise we're running in execution mode. We'll still need to
217
			{
285
		 * resolve the dependencies of the plugin containing the test suite. If
218
				urls[i] = (URL) urlsVec.get(i);
286
		 * any exists, then it would have been registerd with the MacroManager.
287
		 */
288
		else {
289
			reqPlugins = MacroManager.getInstance().getDependecies();
290
		}
291
292
		StringTokenizer st = new StringTokenizer(classPath, File.pathSeparator);
293
		Vector urlsVec = new Vector(10);
294
295
		/* https://bugs.eclipse.org/bugs/show_bug.cgi?id=136157 */
296
		final String PREFIX = "file:";
297
298
		while (st.hasMoreTokens()) {
299
			String curURL = st.nextToken();
300
301
			/*
302
			 * The URL class loader will require all directories to end with a
303
			 * forward slash
304
			 */
305
			if (!curURL.endsWith(".jar") && !curURL.endsWith("/"))
306
				curURL += "/";
307
308
			urlsVec.add(new URL(PREFIX + curURL));
309
		}
310
311
		/* Construct the urls */
312
		URL[] urls = new URL[urlsVec.size()];
313
		for (int i = 0; i < urls.length; i++) {
314
			urls[i] = (URL) urlsVec.get(i);
315
		}
316
317
		ClassLoader customClassLoader = new VerificationHookClassLoader(urls,
318
				this.getClass().getClassLoader(), reqPlugins);
319
		return Class.forName(className, true, customClassLoader);
320
	}
321
322
	/**
323
	 * This doesn't involve any UI actions. Playing back the verification
324
	 * command will simply run the verification hook.
325
	 * 
326
	 * @throws CoreException
327
	 */
328
	public boolean playback(Display display, Shell parent,
329
			IProgressMonitor monitor) throws CoreException {
330
		/*
331
		 * Phases: 1. Load the necessary class 2. Do the method look up on the
332
		 * hook entry 3. If valid: 4. Load its context (i.e. View/Editor/etc...)
333
		 * 5. Invoke the hook with the context
334
		 */
335
		try {
336
			Class verifyHookClass = loadClass(resource);
337
338
			if (isExtendedScope()) {
339
				macroObject = MacroObjectResolver.deresolve(getParent()
340
						.getShell(), getMacroObjectIdentifier());
219
			}
341
			}
220
		
342
221
			
343
			Object[] args = isExtendedScope() ? (macroObject.getUIObject()
222
			ClassLoader customClassLoader = new VerifHookClassLoader (urls, this.getClass().getClassLoader(), reqPlugins);
344
					.getObject() != null ? new Object[3] : new Object[2])
223
			Class verifyHookClass = Class.forName(metaData.getResource(), true, customClassLoader);
345
					: new Object[1];
224
346
			String contextId = new Path(getMacroObjectIdentifier()
225
			Object[] args = new Object[1];
347
					.getContextIdentifier()).segment(1);
226
			String contextId = new Path(metaData.getContextId()).segment(1);
348
227
			
349
			if (focusType == VIEW) {
228
			if (metaData.getFocusType() == VerificationMetaData.VIEW)
350
				IViewPart view = MacroUtil.locateView(display.getActiveShell(),
229
			{
351
						contextId);
230
				IViewPart view = MacroObjectLocator.locateView(display.getActiveShell(), contextId, getStartLine());
231
				args[0] = view;
352
				args[0] = view;
232
			}
353
			} else if (focusType == EDITOR) {
233
			else if (metaData.getFocusType() == VerificationMetaData.EDITOR)
354
				IEditorPart editor = MacroUtil.locateEditor(display
234
			{
355
						.getActiveShell(), contextId, null);
235
				IEditorPart editor = MacroObjectLocator.locateEditor(display.getActiveShell(), contextId, getStartLine(), null);
236
				args[0] = editor;
356
				args[0] = editor;
237
			}
357
			} else if (focusType == SHELL) {
238
			else if (metaData.getFocusType() == VerificationMetaData.SHELL)
239
			{
240
				Shell shell = getParent().getShell();
358
				Shell shell = getParent().getShell();
241
				args[0] = shell;
359
				args[0] = shell;
242
			}
360
			}
243
			
361
362
			if (isExtendedScope()) {
363
				args[1] = macroObject.getUIObject().getWidget();
364
				if (macroObject.getUIObject().getObject() != null) {
365
					args[2] = macroObject.getUIObject().getObject();
366
				}
367
			}
368
244
			/* Construct the test case */
369
			/* Construct the test case */
245
			HyadesTestSuite testSuite = new HyadesTestSuite();
370
			HyadesTestSuite testSuite = new HyadesTestSuite();
246
			Constructor constructor = verifyHookClass.getConstructor(new Class[] {String.class, Class[].class, Object[].class});
371
			Constructor constructor = verifyHookClass
247
			
372
					.getConstructor(new Class[] { String.class, Class[].class,
248
			String testMethodName = MacroUtil.findMethodName(metaData);
373
							Object[].class });
249
			Class[] testMethodParams = MacroUtil.findParameterType(metaData);
374
250
			AutoGUIVerificationHook verificationHook = (AutoGUIVerificationHook) constructor.newInstance(new Object[] {testMethodName,testMethodParams , args});
375
			String testMethodName = findMethodName(hook);
251
			verificationHook.setTestInvocationId("invocation-id-" + System.currentTimeMillis());
376
377
			Class[] testMethodParams = isExtendedScope() ? (macroObject
378
					.getUIObject().getObject() != null ? new Class[] {
379
					getContextClass(), getWidgetClass(), getObjectClass() }
380
					: new Class[] { getContextClass(), getWidgetClass() })
381
					: new Class[] { getContextClass() };
382
			AutoGUIVerificationHook verificationHook = (AutoGUIVerificationHook) constructor
383
					.newInstance(new Object[] { testMethodName,
384
							testMethodParams, args });
385
			verificationHook.setTestInvocationId("invocation-id-"
386
					+ System.currentTimeMillis());
252
			testSuite.addTest(verificationHook);
387
			testSuite.addTest(verificationHook);
253
			
388
254
			/* If we are running in quick mode, then report verification test methods that are missing */
389
			/*
255
			if (MacroManager.getInstance().getGlobalState() == MacroManager.QUICK_RUN_MODE)
390
			 * If we are running in quick mode, then report verification test
256
			{
391
			 * methods that are missing
257
				try
392
			 */
258
				{
393
			if (MacroManager.getInstance().getGlobalState() == ModeConstants.QUICK_RUN_MODE) {
259
					verificationHook.getClass().getMethod(testMethodName, testMethodParams);
394
				try {
260
				}
395
					verificationHook.getClass().getMethod(testMethodName,
261
				catch (NoSuchMethodException e)
396
							testMethodParams);
262
				{
397
				} catch (NoSuchMethodException e) {
263
					AutoGUIUtil.showMessage(AutoGUIMessages.AUTO_GUI_ERROR_VER_METHOD_NF_T,
398
					AutoGUIUtil
264
											NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_VER_METHOD_NF, new String[] {testMethodName, String.valueOf(getStartLine())}),
399
							.showMessage(
265
											MessageDialog.WARNING);
400
									AutoGUIMessages.AUTO_GUI_ERROR_VER_METHOD_NF_T,
401
									NLS
402
											.bind(
403
													AutoGUIMessages.AUTO_GUI_ERROR_VER_METHOD_NF,
404
													new String[] {
405
															testMethodName,
406
															String
407
																	.valueOf(getStartLine()) }),
408
									MessageDialog.WARNING);
266
				}
409
				}
267
			}
410
			}
268
			MacroManager.getInstance().getRunner().runVerificaitonHook(testSuite);
411
			MacroManager.getInstance().getRunner().runVerificationHook(
269
			
412
					testSuite);
413
270
			return true;
414
			return true;
271
			
415
272
		}
416
		} catch (ClassNotFoundException e) {
273
		catch (ClassNotFoundException e)
417
			e.printStackTrace();
274
		{
418
			/*
275
			/* The class was not found.  The classpath should have been set by the deployment adapter 
419
			 * The class was not found. The classpath should have been set by
276
			 * (JavaExecutionDeploymentAdapter) and the file should have been transferred to the
420
			 * the deployment adapter (JavaExecutionDeploymentAdapter) and the
277
			 * system's temporary directory.  This is an internal error */			
421
			 * file should have been transferred to the system's temporary
278
			String[] args = {metaData.getResource(), metaData.getHook(), classPath};
422
			 * directory. This is an internal error
279
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_VER_CLASS_NOT_F, args), super.getStartLine(), e);
423
			 */
280
		}
424
			String[] args = { resource, hook };
281
		catch (InstantiationException e)
425
			AutoGUIUtil.throwCoreException(NLS.bind(
282
		{
426
					AutoGUIMessages.AUTO_GUI_ERROR_VER_CLASS_NOT_F, args),
283
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_VER_INSTANTIATE, metaData.getResource()), super.getStartLine(), e);
427
					super.getStartLine(), e);			
284
		}
428
		} catch (CoreException e) {
285
		catch (CoreException e)
429
			e.printStackTrace();
286
		{
430
			String[] args = {
287
			String[] args = {metaData.getContextId(), metaData.getHook()}; 
431
					getMacroObjectIdentifier().getContextIdentifier(), hook };
288
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_VER_CONTEXT, args), super.getStartLine());
432
			AutoGUIUtil.throwCoreException(NLS.bind(
289
		}
433
					AutoGUIMessages.AUTO_GUI_ERROR_VER_CONTEXT, args), super
290
		catch (IllegalArgumentException e)
434
					.getStartLine());
291
		{
435
		} catch (InstantiationException e) {
292
			AutoGUIUtil.throwCoreException(AutoGUIMessages.AUTO_GUI_ERROR_VER_ARG_EXCEPT, super.getStartLine());
436
			e.printStackTrace();
293
		}
437
			AutoGUIUtil.throwCoreException(NLS.bind(
294
		catch (Exception e)
438
					AutoGUIMessages.AUTO_GUI_ERROR_VER_INSTANTIATE, resource),
295
		{ 
439
					super.getStartLine(), e);
296
			AutoGUIUtil.throwCoreException(AutoGUIUtil.getOriginOfException(e), super.getStartLine(), e);
440
		} catch (IllegalArgumentException e) {
441
			e.printStackTrace();
442
			AutoGUIUtil.throwCoreException(
443
					AutoGUIMessages.AUTO_GUI_ERROR_VER_ARG_EXCEPT, super
444
							.getStartLine());
445
		} catch (Exception e) {
446
			e.printStackTrace();
447
			AutoGUIUtil.throwCoreException(AutoGUIUtil.getOriginOfException(e),
448
					super.getStartLine(), e);
297
		}
449
		}
298
		
450
299
		return false;
451
		return false;
300
	}
452
	}
301
453
454
	/**
455
	 * Given a context id, return the focus type.
456
	 * 
457
	 * @param contextId
458
	 *            The id of the context
459
	 * @return The type of the context (i.e. focus type). -1 is returned if the
460
	 *         focus type is not recognized.
461
	 */
462
	public static byte findFocusType(String contextId) {
463
		if (contextId.startsWith(MacroConstants.VIEW_VALUE + "/"))
464
			return VIEW;
465
		else if (contextId.startsWith(MacroConstants.EDITOR_VALUE + "/"))
466
			return EDITOR;
467
		else if (contextId.startsWith(MacroConstants.SHELL_VALUE + "/"))
468
			return SHELL;
302
469
303
470
		return -1;
471
	}
304
472
305
	/**
473
	/**
306
	 * Returns an instance of this class based an event.  The returned value is null
474
	 * Find the method name corresponding the verification hook
307
	 * if an error occurs while constructing the instance.  Check the value returned
308
	 * by getError to determine the error that has occurred.
309
	 * 
475
	 * 
310
	 * @param event The event
476
	 * @param metaData
311
	 * @return An instance of this class
477
	 * @return
312
	 */
478
	 */
313
	public synchronized static VerificationCommand constructInstance (MacroCommandShell parent, Event event)
479
	public static String findMethodName(String hook) {
314
	{
480
		String methodName = hook;
315
		VerificationCommand instance = null;
481
316
		
482
		if (methodName == null || methodName.length() <= 0)
317
		error = ""; 
318
		if (MacroUtil.isIgnorableEvent(event))
319
		{
320
			error = "";			/* We don't want to report anything */
321
			return null;
483
			return null;
322
		}
484
323
		
485
		int index = methodName.indexOf(':');
324
		try
486
		if (index != -1)
325
		{
487
			return methodName.substring(0, index);
326
			/* Ignore all command except for a focus in command */
488
327
			switch (event.type)
489
		return methodName;
328
			{				
490
	}
329
				case SWT.Activate:
491
330
				case SWT.Selection:
492
	/**
331
				case SWT.FocusIn:
493
	 * Find the parameter types of the verificaiton hook
332
					
494
	 * 
333
					WidgetIdentifier widgetID = MacroUtil.getVerificationContextIdentifier(event);
495
	 * @param metaData
334
					String path = (widgetID == null ? "" : widgetID.getFullyQualifiedPath().toString());
496
	 * @return
335
					
497
	 */
336
					if (MacroUtil.findFocusType(path) == -1)
498
	private Class findContextClass(String contextId) {
337
					{
499
		Class param = null;
338
						error = AutoGUIMessages.AUTO_GUI_ERROR_VER_NOT_SUPP_CON;
500
		byte focusType = findFocusType(contextId);
339
						break;
501
		if (focusType == EDITOR)
340
					}
502
			param = IEditorPart.class;
341
										
503
		else if (focusType == VIEW)
342
					/* We only acknowledge after there is a mouse up event */
504
			param = IViewPart.class;
343
					toBeAck = widgetID;
505
		else if (focusType == SHELL)
344
					break;
506
			param = Shell.class;
345
					
507
346
				case SWT.MouseUp:					
508
		return param;
347
509
	}
348
					if (toBeAck == null)
510
349
						break;
511
	/**
350
					
512
	 * Return the class name containing the verification point that this meta
351
					/* Build the verification meta data -- we only know the context id and the focus type at this point */
513
	 * data points to.
352
					VerificationMetaData metaData = new VerificationMetaData();
514
	 * 
353
					String contextId = toBeAck.getContextId().toString();
515
	 * @param metaData
354
					metaData.setContextId(contextId);
516
	 *            The verification point's meta data
355
					metaData.setFocusType(MacroUtil.findFocusType(contextId));
517
	 * @return The class name. null is returned if it can't be determined
356
					
518
	 */
357
					/* Create the verification command instance */
519
	public static String getClassName(String resource) {
358
					instance = new VerificationCommand (parent, metaData);
520
		String className = resource;
359
					break;
521
360
					
522
		if (className == null || className.length() <= 0)
361
				default:
362
					toBeAck = null;
363
					error = AutoGUIMessages.AUTO_GUI_ERROR_VER_WRONG_EVENT;
364
			}
365
			
366
			return instance;
367
		} 
368
		catch (Exception e)
369
		{
370
			error = e.getMessage();
371
			e.printStackTrace();
372
			return null;
523
			return null;
373
		}
524
525
		int index = className.lastIndexOf('.');
526
		if (index != -1)
527
			return className.substring(index + 1, className.length());
528
		return className;
374
	}
529
	}
375
530
376
	
531
	public void setLocation(String location) {
377
	public static String getError()
532
		this.location = location;
378
	{
379
		return error;
380
	}
533
	}
381
534
382
	public static void setError(String error)
535
	public void setResource(String resource) {
383
	{
536
		this.resource = resource;
384
		VerificationCommand.error = error;
385
	}
537
	}
386
538
387
	public VerificationMetaData getMetaData()
539
	public void setHook(String hook) {
388
	{
540
		this.hook = hook;
389
		return metaData;
390
	}
541
	}
391
542
392
	public void setMetaData(VerificationMetaData metaData)
543
	public Class getObjectClass() {
393
	{
544
		return objectClass;
394
		this.metaData = metaData;
545
	}
546
547
	public Class getWidgetClass() {
548
		return widgetClass;
549
	}
550
551
	public Class getContextClass() {
552
		return contextClass;
553
	}
554
555
	public String getLocation() {
556
		return location;
395
	}
557
	}
396
	
397
}
398
558
559
	public String getResource() {
560
		return resource;
561
	}
562
563
	public String getHook() {
564
		return hook;
565
	}
566
567
	public boolean isExtendedScope() {
568
		return extendedScope;
569
	}
570
571
	public void setExtendedScope(boolean extendedScope) {
572
		this.extendedScope = extendedScope;
573
	}
574
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/KeyEventCommand.java (-113 / +91 lines)
Lines 11-172 Link Here
11
 *******************************************************************************/
11
 *******************************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.commands;
12
package org.eclipse.tptp.test.auto.gui.internal.commands;
13
13
14
import java.util.ArrayList;
15
import java.util.Hashtable;
14
import java.util.Hashtable;
16
15
17
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.core.runtime.CoreException;
18
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.SWT;
19
import org.eclipse.swt.widgets.Event;
18
import org.eclipse.swt.widgets.Event;
19
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
20
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
20
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
21
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
21
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
22
import org.w3c.dom.Node;
22
import org.w3c.dom.Node;
23
23
24
/**
24
/**
25
 * A concrete extension of PositionBasedCommand that is used to represent SWT.KeyUp
25
 * A concrete extension of PositionBasedCommand that is used to represent
26
 * and SWT.KeyDown events.
26
 * SWT.KeyUp and SWT.KeyDown events.
27
 * 
27
 * 
28
 * @author Ali Mehregani
28
 * @author Ali Mehregani
29
 * @author Alexander Nyssen (refactoring)
29
 */
30
 */
30
public class KeyEventCommand extends PositionBasedCommand 
31
public class KeyEventCommand extends PositionBasedCommand {
31
{
32
32
	public static String TYPE0 = "key-up";
33
	private boolean isCharSet; /*
33
	public static String TYPE1 = "key-down";
34
								 * Set when the character field of event is used
34
	public static String TYPE2 = "key-press";
35
								 * as opposed to the keyCode
35
	
36
								 */
36
	private String type; 		/* The type of the event (either TYPE0 or TYPE1) */
37
37
	private int button;			/* The key pressed or released */ 
38
	public KeyEventCommand(MacroCommandShell parent) {
38
	private boolean isCharSet;	/* Set when the character field of event is used as opposed to 
39
		super(parent);
39
								   the keyCode */
40
	public KeyEventCommand(MacroCommandShell parent) 
41
	{
42
		super(parent, null);
43
	}
40
	}
44
41
45
	public String getType()
42
	public String getType() {
46
	{
47
		return type;
43
		return type;
48
	}
44
	}
49
45
50
	public void processEvent(Event e) 
46
	public boolean mergeEvent(Event e) throws Exception {
51
	{
47
		/*
52
		if (e.character > 0)
48
		 * Defect #: 110726 -- Make the key events consistent with the mouse
53
		{
49
		 * event and introduce a notion of key-press
54
			button =  e.character;
50
		 */
55
			isCharSet = true;
51
		if (e.type == SWT.KeyUp && type != null && type.equals(KEY_DOWN)
52
				&& isCharSet(e) ? isCharSet && detail.intValue() == e.character
53
				: !isCharSet && detail.intValue() == e.keyCode) {
54
55
			type = KEY_PRESS;
56
			return true;
56
		}
57
		}
57
		else if (e.keyCode > 0)
58
		return false;
58
			button = e.keyCode;
59
	}
59
		
60
60
		if (e.type == SWT.KeyUp)
61
	private boolean isCharSet(Event e) {
61
		{
62
		return e.character > 0;
62
			/* Defect #: 110726 -- Make the key events consistent with the mouse event and 
63
	}
63
			 * introduce a notion of key-press */			
64
64
			ArrayList commands = getParent().getCommands();
65
	protected Integer determineDetail(Event e) {
65
			int commandSize;
66
		Integer detail = null;
66
			if (commands != null && (commandSize = commands.size()) > 0)
67
		if (e.character > 0) {
67
			{
68
			detail = new Integer(e.character);
68
				Object lastCommand = commands.get(commandSize - 1);
69
69
				if (lastCommand instanceof KeyEventCommand)
70
		} else if (e.keyCode > 0) {
70
				{
71
			detail = new Integer(e.keyCode);
71
					int lastButton = ((KeyEventCommand)lastCommand).getButton();
72
		}
72
					boolean lastIsCharSet = ((KeyEventCommand)lastCommand).isCharSet();
73
		return detail;
73
					if (button == lastButton && isCharSet == lastIsCharSet)
74
	}
74
					{
75
75
						type = TYPE2;
76
	protected String determineType(Event e) {
76
						commands.remove(commandSize - 1);
77
		String type = null;
77
						return;
78
		if (e.type == SWT.KeyUp) {
78
					}
79
			type = KEY_UP;
79
				}				
80
		} else if (e.type == SWT.KeyDown) {
80
			}
81
			type = KEY_DOWN;
81
			
82
			type = TYPE0;
83
			type = TYPE0;
84
		}
82
		}
85
		else if (e.type == SWT.KeyDown)
83
		return type;
86
			type = TYPE1;
87
	}
84
	}
88
	
85
89
	public void load(Node node, Hashtable lineTable) throws CoreException
86
	public void processEvent(Event e) throws Exception {
90
	{
87
		super.processEvent(e);
88
89
		isCharSet = e.character > 0;
90
	}
91
92
	public void load(Node node, Hashtable lineTable) throws CoreException {
91
		super.load(node, lineTable);
93
		super.load(node, lineTable);
92
		
94
93
		type = MacroUtil.getAttribute(node, "type");
95
		if (MacroConstants.TRUE_VALUE.equals(MacroUtil.getAttribute(node,
94
		button = Integer.parseInt(MacroUtil.getAttribute(node, "detail"));
96
				"ischarset")))
95
		if (MacroConstants.TRUE_VALUE.equals(MacroUtil.getAttribute(node, "ischarset")))
96
			isCharSet = true;
97
			isCharSet = true;
97
	}
98
	}
98
	
99
99
	public void write(int indent, StringBuffer sb, boolean close, boolean end)
100
	public void write(int indent, StringBuffer sb, boolean close, boolean end) {
100
	{		
101
		super.write(indent, sb, false, false);
101
		super.write(indent, sb, close, end);
102
		MacroUtil.addAttribute(sb,
102
		MacroUtil.addAttribute(sb, 
103
				new String[] { MacroConstants.IS_CHAR_SET_ATTRIBUTE },
103
				new String[] {MacroConstants.IS_CHAR_SET_ATTRIBUTE}, 
104
				new String[] { String.valueOf(isCharSet) }, true, true);
104
				new String[] {String.valueOf(isCharSet)}, true, true);		
105
	}
106
	
107
108
	public int getDetail()
109
	{
110
		return button;
111
	}
105
	}
112
106
113
	public Event[] constructSWTEvents() 
107
	public Event[] constructSWTEvents() {
114
	{
115
		Event[] events;
108
		Event[] events;
116
		
109
117
		if (type.equals(TYPE2))
110
		if (type.equals(KEY_PRESS))
118
			events = new Event[2];
111
			events = new Event[2];
119
		else
112
		else
120
			events = new Event[1];
113
			events = new Event[1];
121
		
114
122
		Event keyUpEvent = new Event(), keyDownEvent = new Event();
115
		Event keyUpEvent = new Event(), keyDownEvent = new Event();
123
		keyUpEvent.type = SWT.KeyUp;
116
		keyUpEvent.type = SWT.KeyUp;
124
		keyDownEvent.type = SWT.KeyDown;
117
		keyDownEvent.type = SWT.KeyDown;
125
		
118
126
		if (isCharSet)
119
		if (isCharSet) {
127
		{
120
			keyUpEvent.character = (char) detail.intValue();
128
			keyUpEvent.character = (char) button;
121
			keyDownEvent.character = (char) detail.intValue();
129
			keyDownEvent.character = (char) button;
122
		} else {
130
		}
123
			keyUpEvent.keyCode = detail.intValue();
131
		else
124
			keyDownEvent.keyCode = detail.intValue();
132
		{
133
			keyUpEvent.keyCode = button;
134
			keyDownEvent.keyCode = button;			
135
		}
125
		}
136
		
126
137
		
127
		if (type.equals(KEY_UP))
138
		if (type.equals(TYPE0))
139
			events[0] = keyUpEvent;
128
			events[0] = keyUpEvent;
140
		else if (type.equals(TYPE1))
129
		else if (type.equals(KEY_DOWN))
141
			events[0] = keyDownEvent;		
130
			events[0] = keyDownEvent;
142
		else if (type.equals(TYPE2))
131
		else if (type.equals(KEY_PRESS)) {
143
		{
144
			events[0] = keyDownEvent;
132
			events[0] = keyDownEvent;
145
			events[1] = keyUpEvent;
133
			events[1] = keyUpEvent;
146
		}
134
		}
147
		
135
148
		return events;		
136
		return events;
149
	}
137
	}
150
	
138
151
	public boolean equals (Object obj)
139
	public boolean equals(Object obj) {
152
	{
153
		if (!(obj instanceof KeyEventCommand))
140
		if (!(obj instanceof KeyEventCommand))
154
			return false;
141
			return false;
155
		
142
156
		KeyEventCommand keyEvent = (KeyEventCommand)obj;
143
		KeyEventCommand keyEvent = (KeyEventCommand) obj;
157
		if (this.type.equals(keyEvent.getType()) && this.button == keyEvent.getButton())
144
		if (this.type.equals(keyEvent.getType())
145
				&& this.detail == keyEvent.getDetail())
158
			return true;
146
			return true;
159
		return false;
147
		return false;
160
	}
148
	}
161
149
162
	private int getButton() 
163
	{
164
		return button;
165
	}
166
	
167
	private boolean isCharSet()
168
	{
169
		return isCharSet;
170
	}
171
172
}
150
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/ChoiceSelectionCommand.java (-197 / +274 lines)
Lines 14-259 Link Here
14
14
15
import org.eclipse.core.runtime.CoreException;
15
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.core.runtime.IProgressMonitor;
16
import org.eclipse.core.runtime.IProgressMonitor;
17
import org.eclipse.core.runtime.Path;
17
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.SWT;
18
import org.eclipse.swt.custom.CCombo;
19
import org.eclipse.swt.custom.CCombo;
19
import org.eclipse.swt.custom.CTabFolder;
20
import org.eclipse.swt.custom.CTabFolder;
20
import org.eclipse.swt.custom.CTabItem;
21
import org.eclipse.swt.custom.CTabItem;
21
import org.eclipse.swt.widgets.Combo;
22
import org.eclipse.swt.widgets.Combo;
22
import org.eclipse.swt.widgets.Composite;
23
import org.eclipse.swt.widgets.Display;
23
import org.eclipse.swt.widgets.Display;
24
import org.eclipse.swt.widgets.Event;
24
import org.eclipse.swt.widgets.Event;
25
import org.eclipse.swt.widgets.Item;
25
import org.eclipse.swt.widgets.Item;
26
import org.eclipse.swt.widgets.Shell;
26
import org.eclipse.swt.widgets.TabFolder;
27
import org.eclipse.swt.widgets.TabFolder;
27
import org.eclipse.swt.widgets.TabItem;
28
import org.eclipse.swt.widgets.TabItem;
28
import org.eclipse.swt.widgets.Widget;
29
import org.eclipse.swt.widgets.Widget;
29
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
30
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
30
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
31
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
31
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
32
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroObjectLocator;
33
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
32
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
33
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObject;
34
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObjectIdentifier;
35
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObject;
36
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObjectIdentifier;
37
import org.eclipse.tptp.test.auto.gui.internal.macroobject.resolver.MacroObjectResolver;
38
import org.eclipse.tptp.test.auto.gui.internal.uiobject.PrimitiveUIObjectIdentifier;
39
import org.eclipse.tptp.test.auto.gui.internal.uiobject.UIObject;
34
import org.w3c.dom.Node;
40
import org.w3c.dom.Node;
35
41
36
37
/**
42
/**
38
 * A choice selection command represents a user selection of an item from
43
 * A choice selection command represents a user selection of an item from a set
39
 * a set of items present.  For example, selecting a specific tab from a tab 
44
 * of items present. For example, selecting a specific tab from a tab group or
40
 * group or an item from a combo box.
45
 * an item from a combo box.
41
 * 
46
 * 
42
 * @author Ali Mehregani
47
 * @author Ali Mehregani
48
 * @author Alexander Nyssen (complete refactoring to use new widget resolving
49
 *         mechanism)
43
 */
50
 */
44
public class ChoiceSelectionCommand extends AbstractMacroCommand
51
public class ChoiceSelectionCommand extends SingleSelectionCommand {
45
{
52
46
	public static final String TYPE = "choice-select";
53
	public static final String TYPE = IMacroCommand.CHOICE_SELECT;
47
54
48
	/** Widget types */
55
	// ANy: this field is only needed for backwards compatibility issues
49
	private static final byte WIDGET_TYPE_TAB_FOLDER = 0x00;
56
	private String choiceId = null;
50
	private static final byte WIDGET_TYPE_CTAB_FOLDER = 0x01;
57
51
	private static final byte WIDGET_TYPE_COMBO = 0x02;
58
	// /** Widget types */
52
	private static final byte WIDGET_TYPE_CCOMBO = 0x03;	
59
	// private static final byte WIDGET_TYPE_TAB_FOLDER = 0x00;
53
	
60
	// private static final byte WIDGET_TYPE_CTAB_FOLDER = 0x01;
54
	private Object choiceId;
61
	// private static final byte WIDGET_TYPE_COMBO = 0x02;
55
62
	// private static final byte WIDGET_TYPE_CCOMBO = 0x03;
56
	public ChoiceSelectionCommand(MacroCommandShell parent, WidgetIdentifier wid)
63
57
	{
64
	public ChoiceSelectionCommand(MacroCommandShell parent) {
58
		super(parent, wid);
65
		super(parent);
59
	}
66
	}
60
67
61
	public String getType()
68
	public String getType() {
62
	{
63
		return TYPE;
69
		return TYPE;
64
	}
70
	}
65
71
66
	public void processEvent(Event e)
72
	protected IMacroObject locateMacroObject(Event event) {
67
	{	
73
		// find the selected item
68
		choiceId = resolveChoiceId(e.widget, e.item, MacroUtil.newCounter());
74
		boolean isCombo = event.widget instanceof Combo;
69
		
75
		boolean isCCombo = event.widget instanceof CCombo;
70
		boolean isCombo = e.widget instanceof Combo;
76
71
		boolean isCCombo = e.widget instanceof CCombo;
77
		Combo combo = isCombo ? (Combo) event.widget : null;
72
		
78
		CCombo ccombo = isCCombo ? (CCombo) event.widget : null;
73
		Combo combo = isCombo ? (Combo)e.widget : null;
79
		Object item = isCombo ? combo.getItem(combo.getSelectionIndex())
74
		CCombo ccombo = isCCombo ? (CCombo)e.widget : null;
80
				: (isCCombo ? (Object) ccombo.getItem(ccombo
75
		Object item = isCombo ? combo.getItem(combo.getSelectionIndex()) : (isCCombo ? (Object)ccombo.getItem(ccombo.getSelectionIndex()) : e.item);
81
						.getSelectionIndex()) : event.item);
76
		
82
77
		choiceId = choiceId == null ? computeDefaultChoiceId(e.widget, item) : choiceId;
83
		// if the item is itself a widget it can be resolved without its parent
78
			
84
		// widget, e.g. in case of a TabItem or CTabItem
79
		if (isCombo || isCCombo)
85
		if (item != null && item instanceof Widget) {
80
		{
86
			return new MacroObject(new UIObject((Widget) item));
81
			setDescriptiveField(isCombo ? combo.getItem(combo.getSelectionIndex()) : ccombo.getItem(ccombo.getSelectionIndex()));
87
		} else {
88
			return new MacroObject(new UIObject(event.widget, item));
82
		}
89
		}
83
		else
90
	}
84
		{
91
92
	// @Override
93
	// protected void writeMacroObject(int indent, StringBuffer sb, boolean
94
	// close,
95
	// boolean end) {
96
	//		
97
	// // remove the trailing path fragment and store it separately (for
98
	// // backwards compatibility)
99
	// MacroObjectIdentifier identifier = (MacroObjectIdentifier)
100
	// getMacroObjectIdentifier();
101
	// String originalContextId = identifier.getContextIdentifier();
102
	// String originalObjectId = identifier.getObjectIdentifier()
103
	// .getObjectId();
104
	// String resolverId = identifier.getObjectIdentifier().getResolverId();
105
	// String choiceId = new Path(originalObjectId).removeFirstSegments(1)
106
	// .toString();
107
	//		
108
	// setMacroObjectIdentifier(new MacroObjectIdentifier(originalContextId,
109
	// new PrimitiveUIObjectIdentifier(new Path(originalObjectId).segment(0)
110
	// .toString(), resolverId)));
111
	//		
112
	// super.writeMacroObject(indent, sb, false, false);
113
	//		
114
	// setMacroObjectIdentifier(identifier);
115
	//
116
	// MacroUtil.addAttribute(sb,
117
	// new String[] { MacroConstants.CHOICE_ID_ATTRIBUTE },
118
	// new String[] { choiceId == null || choiceId.equals("") ? null
119
	// : choiceId.toString() }, close, end);
120
	// }
121
122
	protected void loadMacroObjectIdentifier(Node node, Hashtable lineTable)
123
			throws CoreException {
124
		super.loadMacroObjectIdentifier(node, lineTable);
125
126
		// for backwards compatibility, the choice id is read (if present) and
127
		// appended to the macro object identifier
128
		MacroObjectIdentifier identifier = (MacroObjectIdentifier) getMacroObjectIdentifier();
129
130
		// ANy: added for backwards compatibility, in case we have a macro that
131
		// still has the choice id attribute stored
132
		choiceId = MacroUtil.getAttribute(node,
133
				MacroConstants.CHOICE_ID_ATTRIBUTE);
134
	}
135
136
	public void doProcessEvent(Event e) {
137
		if (e.widget instanceof Combo || e.widget instanceof CCombo) {
138
			setDescriptiveField(e.widget instanceof Combo ? ((Combo) e.widget)
139
					.getItem(((Combo) e.widget).getSelectionIndex())
140
					: ((CCombo) e.widget).getItem(((CCombo) e.widget)
141
							.getSelectionIndex()));
142
		} else {
85
			findDescriptiveField(e.item);
143
			findDescriptiveField(e.item);
86
		}
144
		}
87
	}
145
	}
88
146
89
	private Object resolveChoiceId (Widget widget, Object item, int[] resolverIndex)
147
	// public void load(Node node, Hashtable lineTable) throws CoreException {
90
	{		
148
	// super.load(node, lineTable);
91
		return MacroManager.getInstance().resolveWidget(widget, item, getWidgetId().getResolverId(), resolverIndex); 
149
	// String choiceId = MacroUtil.getAttribute(node,
92
	}
150
	// MacroConstants.CHOICE_ID_ATTRIBUTE);
93
	
151
	// }
94
	
152
	//
95
	private Object computeDefaultChoiceId(Widget widget, Object item)
153
96
	{
154
	// public void write(int indent, StringBuffer sb) {
97
		int index = -1;
155
	// super.write(indent, sb);
98
		boolean isCombo = widget instanceof Combo;
156
	// MacroUtil.addAttribute(sb,
99
		boolean isCCombo = isCombo ? false : widget instanceof CCombo;		
157
	// new String[] { MacroConstants.CHOICE_ID_ATTRIBUTE },
100
		if (isCombo || isCCombo)
158
	// new String[] { choiceId == null ? null : choiceId.toString() },
101
		{
159
	// true, true);
102
			Combo combo = isCombo ? ((Combo)widget) : null;
160
	// }
103
			CCombo ccombo = isCCombo ? ((CCombo)widget) : null;
161
104
			
162
	public boolean playback(Display display, Shell parent,
105
			index = isCombo ? combo.indexOf((String)item) : ccombo.indexOf((String)item);
163
			IProgressMonitor monitor) throws CoreException {
106
		}
164
		IMacroObjectIdentifier identifier = getMacroObjectIdentifier();
107
		else
165
		// backwards compatibility issues
108
		{	
166
		if (choiceId != null && !choiceId.equals("")) {
109
			boolean isTabFolder = widget instanceof TabFolder;
167
			// we need to deresolve here to decide wether we have an identifier
110
			boolean isCTabFolder = isTabFolder ? false : widget instanceof CTabFolder;
168
			// for a Combo (CCombo) or a TabFolder (CTabFolder)
111
			if (isTabFolder || isCTabFolder)
169
			IMacroObject macroObject = MacroObjectResolver.deresolve(
112
			{
170
					getParent().getShell(), identifier);
113
				index = isTabFolder ? ((TabFolder)widget).indexOf((TabItem)item) : ((CTabFolder)widget).indexOf((CTabItem)item);
171
			if (macroObject.getUIObject().getWidget() instanceof Combo
172
					|| macroObject.getUIObject().getWidget() instanceof CCombo) {
173
				// set the enhanced identifier that used the object id to denote
174
				// the String item on the Combo or CCombo
175
				setMacroObjectIdentifier(new MacroObjectIdentifier(identifier
176
						.getContextIdentifier(),
177
						new PrimitiveUIObjectIdentifier(identifier
178
								.getObjectIdentifier().getWidgetId(), choiceId,
179
								identifier.getObjectIdentifier()
180
										.getResolverId())));
181
			} else if (macroObject.getUIObject().getWidget() instanceof TabFolder
182
					|| macroObject.getUIObject().getWidget() instanceof CTabFolder) {
183
				// compute a new macro object identifier, the old one points to
184
				// the tabFolder
185
				String contextId = new Path(MacroConstants.TAB_VALUE).append(
186
						MacroObjectIdentifier
187
								.serializeMacroObjectIdentifier(identifier))
188
						.toString();
189
				String widgetId = choiceId;
190
				setMacroObjectIdentifier(new MacroObjectIdentifier(contextId,
191
						new PrimitiveUIObjectIdentifier(widgetId, identifier
192
								.getObjectIdentifier().getResolverId())));
114
			}
193
			}
115
		}
194
		}
116
		
195
		return super.playback(display, parent, monitor);
117
		if (index != -1)
196
	}
118
			return "item#" + index;
197
119
		return null;
198
	public boolean doPlayback(Display display, Shell parent,
120
	}
199
			IProgressMonitor monitor) throws CoreException {
121
200
122
	public void load(Node node, Hashtable lineTable) throws CoreException
201
		// deresolve the macro object (using the old path format (the choice id
123
	{
202
		// was kept separately before) -> locating a child with the given item
124
		super.load(node, lineTable);
203
		// suffix does not work yet)
125
		choiceId = MacroUtil.getAttribute(node, MacroConstants.CHOICE_ID_ATTRIBUTE);
204
		// Path path = new Path(getMacroObjectIdentifier().getObjectIdentifier()
126
	}
205
		// .getObjectId());
127
206
		// String oldObjectId = path.segmentCount() > 1 ?
128
	public void write(int indent, StringBuffer sb)
207
		// path.removeLastSegments(
129
	{
208
		// 1).toString() : path.toString();
130
		super.write(indent, sb);
209
131
		MacroUtil.addAttribute(sb, 
210
		// IMacroObject target = MacroObjectResolver.deresolve(parent,
132
				new String[] {MacroConstants.CHOICE_ID_ATTRIBUTE}, 
211
		// getMacroObjectIdentifier());
133
				new String[] {choiceId == null ? null : choiceId.toString()}, 
212
		// // new MacroObjectIdentifier(getMacroObjectIdentifier()
134
				true, true);
213
		// .getContextIdentifier(),
135
	}
214
		// new PrimitiveUIObjectIdentifier(oldObjectId,
136
215
		// getMacroObjectIdentifier()
137
	public boolean playback(Display display, Composite parent, IProgressMonitor monitor) throws CoreException
216
		// .getObjectIdentifier()
138
	{
217
		// .getResolverId())));
139
		CommandTarget[] targets = MacroObjectLocator.locateCommandTarget(parent, getWidgetId(), getStartLine());
218
140
		if (targets == null)
219
		if (macroObject == null) {
141
			return false;
220
			return false;
142
		
143
		CommandTarget target = targets[0];
144
		target.setFocus();
145
		Widget widget = target.getWidget();
146
		if (widget instanceof TabFolder)
147
		{
148
			doSelect(WIDGET_TYPE_TAB_FOLDER, widget);
149
		}
150
		else if (widget instanceof CTabFolder)
151
		{
152
			doSelect(WIDGET_TYPE_CTAB_FOLDER, widget);
153
		}
154
		else if (widget instanceof Combo)
155
		{
156
			doSelect(WIDGET_TYPE_COMBO, widget);
157
		}
158
		else if (widget instanceof CCombo)
159
		{
160
			doSelect(WIDGET_TYPE_CCOMBO, (CCombo) widget);
161
		}
221
		}
162
		
222
223
		setFocus(macroObject);
224
		doSelect(macroObject);
225
163
		return true;
226
		return true;
164
	}
227
	}
165
	
228
166
	
229
	protected void doSelect(IMacroObject target) {
167
	private void doSelect(byte widgetType, Widget widget)
230
		Widget widget = target.getUIObject().getWidget();
168
	{
231
		Object object = target.getUIObject().getObject();
169
		Object[] items = null;
232
170
		switch (widgetType)
233
		Widget parent = null;
171
		{
234
		Item item = null;
172
			case WIDGET_TYPE_TAB_FOLDER:
235
173
				items = ((TabFolder)widget).getItems();
236
		if (widget instanceof Combo) {
174
				break;
237
			Combo combo = (Combo) widget;
175
			case WIDGET_TYPE_CTAB_FOLDER:
238
			combo.select(combo.indexOf((String) object));
176
				items = ((CTabFolder)widget).getItems();
239
			parent = combo;
177
				break;
240
		} else if (widget instanceof CCombo) {
178
			case WIDGET_TYPE_COMBO:
241
			CCombo combo = (CCombo) widget;
179
				items = ((Combo)widget).getItems();
242
			combo.select(combo.indexOf((String) object));
180
				break;
243
			parent = combo;
181
			case WIDGET_TYPE_CCOMBO:
244
		}
182
				items = ((CCombo)widget).getItems();
245
		// TabItems and CTabItems are widgets themselves, so when selecting,
183
				break;		
246
		// they have to be passed into the event as item
184
		}
247
		else if (widget instanceof TabItem) {
185
				
248
			TabItem tabItem = (TabItem) widget;
186
		Object widgetId = null;
249
			TabFolder tabFolder = tabItem.getParent();
187
		int[] resolverIndex = MacroUtil.newCounter();
250
			tabFolder.setSelection(tabItem);
188
		boolean foundItem = false;
251
			parent = tabFolder;
189
		for (int i = 0; !foundItem && i < items.length; i++)
252
			item = tabItem;
190
		{
253
		} else if (widget instanceof CTabItem) {
191
			while (!foundItem && (widgetId = resolveChoiceId(widget, items[i], resolverIndex)) != null)
254
			CTabItem tabItem = (CTabItem) widget;
192
			{
255
			CTabFolder tabFolder = tabItem.getParent();
193
				foundItem = foundItem (widgetType, widget, items[i], widgetId, i);
256
			tabFolder.setSelection(tabItem);
194
			}	
257
			parent = tabFolder;
195
			
258
			item = tabItem;
196
			if (foundItem)
197
				break;
198
			resolverIndex[0] = 0;
199
			foundItem = foundItem (widgetType, widget, items[i], computeDefaultChoiceId(widget, items[i]), i);
200
		}
259
		}
201
	}
202
260
203
	private boolean foundItem(byte widgetType, Widget widget, Object item, Object itemId, int index)
261
		/*
204
	{
262
		 * Ali M.: A set selection is not enough for Eclipse forms. We have to
205
		if (itemId != null && itemId.equals(choiceId))
263
		 * send out a selection event
206
		{
264
		 */
207
			switch(widgetType)
265
		Event selectionEvent = new Event();
208
			{
266
		selectionEvent.type = SWT.Selection;
209
				case WIDGET_TYPE_TAB_FOLDER: 
267
		selectionEvent.widget = parent;
210
					((TabFolder)widget).setSelection(index);
268
		selectionEvent.display = parent.getDisplay();
211
					break;
269
		selectionEvent.item = item;
212
				case WIDGET_TYPE_CTAB_FOLDER:
270
		widget.notifyListeners(SWT.Selection, selectionEvent);
213
					((CTabFolder)widget).setSelection(index);
271
		MacroUtil.processDisplayEvents(selectionEvent.display);
214
					break;
272
	}
215
				case WIDGET_TYPE_COMBO:
273
216
					((Combo)widget).select(index);
274
	// private void doSelect(byte widgetType, Widget widget) {
217
					break;
275
	// Object[] items = null;
218
				case WIDGET_TYPE_CCOMBO:
276
	// switch (widgetType) {
219
					((CCombo)widget).select(index);
277
	// case WIDGET_TYPE_TAB_FOLDER:
220
					break;
278
	// items = ((TabFolder) widget).getItems();
221
			}
279
	// break;
222
				
280
	// case WIDGET_TYPE_CTAB_FOLDER:
223
			/* Ali M.: A set selection is not enough for Eclipse forms.  We have to send out a selection event */
281
	// items = ((CTabFolder) widget).getItems();
224
			Event selectionEvent = new Event();
282
	// break;
225
			selectionEvent.type = SWT.Selection;
283
	// case WIDGET_TYPE_COMBO:
226
			selectionEvent.widget = widget;
284
	// items = ((Combo) widget).getItems();
227
			selectionEvent.display = widget.getDisplay();
285
	// break;
228
			selectionEvent.item = item instanceof Item ? (Item)item : null;
286
	// case WIDGET_TYPE_CCOMBO:
229
			widget.notifyListeners(SWT.Selection, selectionEvent);
287
	// items = ((CCombo) widget).getItems();
230
			MacroUtil.processDisplayEvents(selectionEvent.display);
288
	// break;
231
			
289
	// }
232
			return true;
290
	//
233
		}				
291
	// // tries to determine the item by querying all resolves
234
		
292
	// IUIObjectIdentifier widgetId = null;
293
	// boolean foundItem = false;
294
	// for (int i = 0; !foundItem && i < items.length; i++) {
295
	// while (!foundItem
296
	// && ((widgetId = MacroObjectResolver.resolve(new MacroObject(new
297
	// UIObject(widget, items[i]))).getObjectIdentifier()) != null)) {
298
	// foundItem = itemId != null
299
	// && itemId.equals(getMacroObjectIdentifier()
300
	// .getObjectIdentifier())
301
	//					
302
	// }
303
	//
304
	// if (foundItem)
305
	// break;
306
	// // foundItem = foundItem(widgetType, widget, items[i],
307
	// // computeDefaultChoiceId(widget, items[i]), i);
308
	// }
309
	// }
310
311
	public boolean mergeEvent(Event e) throws Exception {
235
		return false;
312
		return false;
236
	}
313
	}
237
	
314
238
	
315
	public void write(int indent, StringBuffer sb, boolean close, boolean end) {
239
	public boolean mergeEvent(Event e)
316
		super.write(indent, sb, true, true);
240
	{
241
		return false;
242
	}
317
	}
243
	
318
244
	/**
319
	/**
245
	 * Overwrite this method in order to indicate that two choice commands that have
320
	 * Overwrite this method in order to indicate that two choice commands that
246
	 * different choice ids are not the same
321
	 * have different choice ids are not the same
247
	 */
322
	 */
248
	public boolean equals (Object obj)
323
	public boolean equals(Object obj) {
249
	{
250
		if (!(obj instanceof ChoiceSelectionCommand) || !super.equals(obj))
324
		if (!(obj instanceof ChoiceSelectionCommand) || !super.equals(obj))
251
			return false;
325
			return false;
252
		
326
253
		ChoiceSelectionCommand compareWithObj = (ChoiceSelectionCommand)obj;
327
		return true;
254
		if ((this.choiceId != null && this.choiceId.equals(compareWithObj.choiceId)) || (this.choiceId == null && compareWithObj.choiceId == null))
328
		// ChoiceSelectionCommand compareWithObj = (ChoiceSelectionCommand) obj;
255
			return true;
329
		// if ((this.choiceId != null && this.choiceId
256
		
330
		// .equals(compareWithObj.choiceId))
257
		return false;
331
		// || (this.choiceId == null && compareWithObj.choiceId == null))
332
		// return true;
333
		//
334
		// return false;
258
	}
335
	}
259
}
336
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/IMacroCommand.java (-45 / +65 lines)
Lines 11-101 Link Here
11
package org.eclipse.tptp.test.auto.gui.internal.commands;
11
package org.eclipse.tptp.test.auto.gui.internal.commands;
12
12
13
import org.eclipse.swt.widgets.Event;
13
import org.eclipse.swt.widgets.Event;
14
import org.eclipse.tptp.test.auto.gui.internal.core.IMacroInstruction;
14
import org.eclipse.tptp.test.auto.gui.internal.macro.IMacroInstruction;
15
15
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
16
16
17
/**
17
/**
18
 * Represents a macro command that can be included as part of the
18
 * Represents a macro command that can be included as part of the macro script
19
 * macro script or played back to perform a UI interaction. 
19
 * or played back to perform a UI interaction.
20
 * 
20
 * 
21
 * @author Ali Mehregani
21
 * @author Ali Mehregani
22
 * @author Alexander Nyssen
22
 */
23
 */
23
public interface IMacroCommand extends IMacroInstruction
24
public interface IMacroCommand extends IMacroInstruction {
24
{	
25
	/* command type constants */
26
	public static final String VERIFICATION = "verification";
27
	public static final String WAIT = "wait";
28
	public static final String MODIFY = "modify";
29
	public static final String SELECT = "select";
30
	public static final String ITEM_CHECK = "item-check";
31
	public static final String CHOICE_SELECT = "choice-select";
32
	public static final String CLOSE_WORKBENCHPART = "close-workbenchpart";
33
	public static final String ITEM_EXPAND = "item-expand";
34
	public static final String FOCUS = "focus";
35
	public static final String KEY_UP = "key-up";
36
	public static final String KEY_DOWN = "key-down";
37
	public static final String KEY_PRESS = "key-press";
38
	public static final String MOUSE_UP = "mouse-up";
39
	public static final String MOUSE_DOWN = "mouse-down";
40
	public static final String MOUSE_MOVE = "mouse-move";
41
	public static final String MOUSE_CLICK = "mouse-click";
42
	public static final String DEFAULT_SELECT = "default-select";
43
	public static final String ITEM_SELECT = "item-select";
44
45
	/** The bound for the value of descriptive fields */
46
	public static final int DESCRIPTIVE_FIELD_BOUND = 50;
47
25
	/**
48
	/**
26
	 * Returns the type of this command
49
	 * Returns the type of this command
27
	 *  
50
	 * 
28
	 * @return The type
51
	 * @return The type
29
	 */
52
	 */
30
	public String getType();
53
	public String getType();
31
	
54
32
	
33
	/**
55
	/**
34
	 * Allows this command to process the corresponding event. 
56
	 * Allows this command to process the corresponding event.
35
	 * 
57
	 * 
36
	 * @param event The event that awaits processing
58
	 * @param event
59
	 *            The event that awaits processing
37
	 */
60
	 */
38
	public void processEvent(Event event);
61
	public void processEvent(Event event) throws Exception;
39
	
62
40
	
41
	/**
63
	/**
42
	 * If this command occurs consecutively, then this method
64
	 * If this command occurs consecutively, then this method gives this command
43
	 * gives this command a chance to merge mutliple commands
65
	 * a chance to merge mutliple commands together to reduce the overhead.
44
	 * together to reduce the overhead.
45
	 * 
66
	 * 
46
	 * @param event The event that caused the creation of a consecutive
67
	 * @param event
47
	 * command of this type.
68
	 *            The event that caused the creation of a consecutive command of
69
	 *            this type.
48
	 * 
70
	 * 
49
	 * @return true if the command is merged; false otherwise.
71
	 * @return true if the command is merged; false otherwise.
72
	 * @throws Exception
73
	 *             TODO
50
	 */
74
	 */
51
	public boolean mergeEvent(Event e);
75
	public boolean mergeEvent(Event e) throws Exception;
52
	
76
53
	
77
	/**
54
	/**
78
	 * Returns the descriptive field of this command. The descriptive field is a
55
	 * Returns the descriptive field of this command.  The descriptive field
79
	 * human readable label that allows users to easily identify the purpose of
56
	 * is a human readable label that allows users to easily identify the 
80
	 * this command.
57
	 * purpose of this command.
58
	 * 
81
	 * 
59
	 * @return The descriptive field
82
	 * @return The descriptive field
60
	 */
83
	 */
61
	public String getDescriptiveField();
84
	public String getDescriptiveField();
62
	
85
63
	
64
	/**
86
	/**
65
	 * Sets the descriptive field of this command.  The descriptive field
87
	 * Sets the descriptive field of this command. The descriptive field is a
66
	 * is a human readable label that allows users to easily identify the 
88
	 * human readable label that allows users to easily identify the purpose of
67
	 * purpose of this command.
89
	 * this command.
68
	 * 
90
	 * 
69
	 * @param descriptiveField The descriptive field
91
	 * @param descriptiveField
92
	 *            The descriptive field
70
	 */
93
	 */
71
	public void setDescriptiveField(String descriptiveField);
94
	public void setDescriptiveField(String descriptiveField);
72
	
95
73
	
74
	/**
96
	/**
75
	 * Returns the parent of this command.
97
	 * Returns the parent of this command.
76
	 * 
98
	 * 
77
	 * @return The parent
99
	 * @return The parent
78
	 */
100
	 */
79
	public MacroCommandShell getParent();
101
	public MacroCommandShell getParent();
80
	
102
81
	
82
	/**
103
	/**
83
	 * Sets the parent of this command.
104
	 * Sets the parent of this command.
84
	 * 
105
	 * 
85
	 * @param parent The parent 
106
	 * @param parent
107
	 *            The parent
86
	 */
108
	 */
87
	public void setParent(MacroCommandShell parent);
109
	public void setParent(MacroCommandShell parent);
88
	
110
89
	
90
	/**
111
	/**
91
	 * Returns false if executing this command just after it has already been executed 
112
	 * Returns false if executing this command just after it has already been
92
	 * will have a different output.  (e.g. Two focus commands that are identical are 
113
	 * executed will have a different output. (e.g. Two focus commands that are
93
	 * redundant but two button selections are not); otherwise true should be returned.
114
	 * identical are redundant but two button selections are not); otherwise
115
	 * true should be returned.
94
	 * 
116
	 * 
95
	 * @return A flag indicating if repeats of this command are redundant.
117
	 * @return A flag indicating if repeats of this command are redundant.
96
	 */ 
118
	 */
97
	public boolean isRepeatRedundant();
119
	public boolean isRepeatRedundant();
98
120
99
}
121
}
100
101
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/ModifyCommand.java (-103 / +92 lines)
Lines 18-73 Link Here
18
import org.eclipse.swt.custom.CCombo;
18
import org.eclipse.swt.custom.CCombo;
19
import org.eclipse.swt.custom.StyledText;
19
import org.eclipse.swt.custom.StyledText;
20
import org.eclipse.swt.widgets.Combo;
20
import org.eclipse.swt.widgets.Combo;
21
import org.eclipse.swt.widgets.Composite;
22
import org.eclipse.swt.widgets.Display;
21
import org.eclipse.swt.widgets.Display;
23
import org.eclipse.swt.widgets.Event;
22
import org.eclipse.swt.widgets.Event;
23
import org.eclipse.swt.widgets.Shell;
24
import org.eclipse.swt.widgets.Text;
24
import org.eclipse.swt.widgets.Text;
25
import org.eclipse.swt.widgets.Widget;
25
import org.eclipse.swt.widgets.Widget;
26
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
26
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
27
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
27
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
28
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
28
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
29
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroObjectLocator;
30
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
29
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
31
import org.w3c.dom.Node;
30
import org.w3c.dom.Node;
32
import org.w3c.dom.NodeList;
31
import org.w3c.dom.NodeList;
33
32
34
public class ModifyCommand extends AbstractMacroCommand {
33
public class ModifyCommand extends ObjectBasedCommand {
35
	
34
36
	public static final String TYPE = "modify";
35
	public static final String TYPE = IMacroCommand.MODIFY;
37
	public static final String CDATA_OPEN = "<![CDATA[";
36
	public static final String CDATA_OPEN = "<![CDATA[";
38
	public static final String CDATA_CLOSE = "]]>";
37
	public static final String CDATA_CLOSE = "]]>";
39
38
40
	private String text;
39
	private String text;
41
	
40
42
	public ModifyCommand(MacroCommandShell parent, WidgetIdentifier wid) {
41
	public ModifyCommand(MacroCommandShell parent) {
43
		super(parent, wid);
42
		super(parent);
44
	}
43
	}
45
44
46
	public String getType() {
45
	public String getType() {
47
		return TYPE;
46
		return TYPE;
48
	}
47
	}
49
48
50
	public boolean mergeEvent(Event e) {
49
	public boolean mergeEvent(Event e) throws Exception {
51
		return doProcessEvent(e);
50
		try {
52
	}
51
			doProcessEvent(e);
53
52
			return true;
54
	public void processEvent(Event e) {
53
		} catch (Exception exception) {
55
		doProcessEvent(e);
54
			return false;
55
		}
56
	}
56
	}
57
57
58
	public void load(Node node, Hashtable lineTable) throws CoreException
58
	public void load(Node node, Hashtable lineTable) throws CoreException {
59
	{
60
		super.load(node, lineTable);
59
		super.load(node, lineTable);
61
60
62
		NodeList children = node.getChildNodes();
61
		NodeList children = node.getChildNodes();
63
		for (int i=0; i<children.getLength(); i++) {
62
		for (int i = 0; i < children.getLength(); i++) {
64
			Node child = children.item(i);
63
			Node child = children.item(i);
65
			if (child.getNodeType()==Node.TEXT_NODE) {
64
			if (child.getNodeType() == Node.TEXT_NODE) {
66
				text = child.getNodeValue().trim();
65
				text = child.getNodeValue().trim();
67
				break;
66
				break;
68
			}
67
			}
69
		}
68
		}
70
		
69
71
		/* If in case the text is null, then set it to an empty string */
70
		/* If in case the text is null, then set it to an empty string */
72
		if (text == null)
71
		if (text == null)
73
			text = "";
72
			text = "";
Lines 75-188 Link Here
75
			text = convertHTMLCodeToChar(text);
74
			text = convertHTMLCodeToChar(text);
76
	}
75
	}
77
76
78
	private boolean doProcessEvent(Event e) {
77
	protected void doProcessEvent(Event e) throws CoreException {
78
		findDescriptiveField(e.widget);
79
		String text = extractText(e.widget);
79
		String text = extractText(e.widget);
80
		if (text != null) {
80
		if (text != null) {
81
			this.text = text;
81
			this.text = text;
82
			return true;
83
		}
82
		}
84
		return false;
85
	}
83
	}
86
84
87
	private String extractText(Widget widget) 
85
	private String extractText(Widget widget) {
88
	{		
89
		String widgetText = null;
86
		String widgetText = null;
90
		if (widget instanceof Text)	
87
		if (widget instanceof Text)
91
			widgetText = ((Text) widget).getText();
88
			widgetText = ((Text) widget).getText();
92
		
89
93
		else if (widget instanceof Combo)
90
		else if (widget instanceof Combo)
94
			widgetText = ((Combo) widget).getText();
91
			widgetText = ((Combo) widget).getText();
95
		
92
96
		else if (widget instanceof CCombo)
93
		else if (widget instanceof CCombo)
97
			widgetText = ((CCombo) widget).getText();
94
			widgetText = ((CCombo) widget).getText();
98
		
95
99
		else if (widget instanceof StyledText)
96
		else if (widget instanceof StyledText)
100
			widgetText = ((StyledText) widget).getText();
97
			widgetText = ((StyledText) widget).getText();
101
		
98
102
		if (widgetText != null)
99
		if (widgetText != null)
103
			return convertSpaces(widgetText);
100
			return convertSpaces(widgetText);
104
		
101
105
		return null;
102
		return null;
106
	}
103
	}
107
104
108
	/**
105
	/**
109
	 * Convert leading and trailing spaces to their respective HTML code.  This is so
106
	 * Convert leading and trailing spaces to their respective HTML code. This
110
	 * that the user inserted spaces are not lost after a trim operation.
107
	 * is so that the user inserted spaces are not lost after a trim operation.
111
	 */
108
	 */
112
	public String convertSpaces (String input)
109
	public String convertSpaces(String input) {
113
	{
114
		String convertedString = "";
110
		String convertedString = "";
115
		char[] inputCharacters = input.toCharArray();
111
		char[] inputCharacters = input.toCharArray();
116
		
112
117
		/* Convert leading spaces */
113
		/* Convert leading spaces */
118
		boolean validCharacterReached = false;
114
		boolean validCharacterReached = false;
119
		String htmlCode;
115
		String htmlCode;
120
		int i = 0;
116
		int i = 0;
121
		for (; i < inputCharacters.length && !validCharacterReached; i++)
117
		for (; i < inputCharacters.length && !validCharacterReached; i++) {
122
		{			
118
			htmlCode = convertCharacter(inputCharacters[i]);
123
			htmlCode = convertCharacter (inputCharacters[i]);
124
			if (htmlCode == null)
119
			if (htmlCode == null)
125
				break;
120
				break;
126
			convertedString += htmlCode;
121
			convertedString += htmlCode;
127
		}
122
		}
128
		convertedString += input.substring(i).trim();
123
		convertedString += input.substring(i).trim();
129
		
124
130
		/* Convert trailing spaces */
125
		/* Convert trailing spaces */
131
		String trailingSpaces = "";
126
		String trailingSpaces = "";
132
		for (i = inputCharacters.length - 1; i >= 0; i--)
127
		for (i = inputCharacters.length - 1; i >= 0; i--) {
133
		{
128
			htmlCode = convertCharacter(inputCharacters[i]);
134
			htmlCode = convertCharacter (inputCharacters[i]);
135
			if (htmlCode == null)
129
			if (htmlCode == null)
136
				break;
130
				break;
137
			trailingSpaces = htmlCode + trailingSpaces;
131
			trailingSpaces = htmlCode + trailingSpaces;
138
		}
132
		}
139
		convertedString += trailingSpaces;		
133
		convertedString += trailingSpaces;
140
		return convertedString;
134
		return convertedString;
141
	}
135
	}
142
	
136
143
	
137
	public String convertCharacter(char character) {
144
	public String convertCharacter (char character)
138
		switch (character) {
145
	{
139
		case '\t':
146
		switch (character)
140
			return "&#09;";
147
		{
141
		case '\n':
148
			case '\t':
142
			return "&#10;";
149
				return "&#09;";
143
		case '\r':
150
			case '\n':
144
			return "&#13;";
151
				return  "&#10;";
145
		case ' ':
152
			case '\r':
146
			return "&#32;";
153
				return "&#13;";
147
		default:
154
			case ' ':
148
			return null;
155
				return "&#32;";
149
		}
156
			default:
150
	}
157
				return null;						
151
158
		}
152
	private String convertHTMLCodeToChar(String input) {
159
	}
160
	
161
	private String convertHTMLCodeToChar(String input) 
162
	{		
163
		String normalizedString = "";
153
		String normalizedString = "";
164
		String inputCloned = input;
154
		String inputCloned = input;
165
		int currentHTMLCodeInx;
155
		int currentHTMLCodeInx;
166
		final int HTML_LENGTH_CODE = 5;
156
		final int HTML_LENGTH_CODE = 5;
167
		
157
168
		while ((currentHTMLCodeInx = inputCloned.indexOf("&#"))!= -1)
158
		while ((currentHTMLCodeInx = inputCloned.indexOf("&#")) != -1) {
169
		{
170
			int totalHTMLCodeLen = currentHTMLCodeInx + HTML_LENGTH_CODE;
159
			int totalHTMLCodeLen = currentHTMLCodeInx + HTML_LENGTH_CODE;
171
			if (totalHTMLCodeLen > inputCloned.length())
160
			if (totalHTMLCodeLen > inputCloned.length())
172
				break;
161
				break;
173
			
162
174
			String htmlCode = inputCloned.substring(currentHTMLCodeInx, totalHTMLCodeLen);
163
			String htmlCode = inputCloned.substring(currentHTMLCodeInx,
164
					totalHTMLCodeLen);
175
			String htmlChar = convertCodeToChar(htmlCode);
165
			String htmlChar = convertCodeToChar(htmlCode);
176
			normalizedString +=  inputCloned.substring(0, currentHTMLCodeInx) + htmlChar;
166
			normalizedString += inputCloned.substring(0, currentHTMLCodeInx)
167
					+ htmlChar;
177
			inputCloned = inputCloned.substring(totalHTMLCodeLen);
168
			inputCloned = inputCloned.substring(totalHTMLCodeLen);
178
		}
169
		}
179
		normalizedString += inputCloned;
170
		normalizedString += inputCloned;
180
		
171
181
		return normalizedString;
172
		return normalizedString;
182
	}
173
	}
183
	
174
184
	private String convertCodeToChar(String htmlCode) 
175
	private String convertCodeToChar(String htmlCode) {
185
	{
186
		if (htmlCode.equals("&#09;"))
176
		if (htmlCode.equals("&#09;"))
187
			return "\t";
177
			return "\t";
188
		else if (htmlCode.equals("&#10;"))
178
		else if (htmlCode.equals("&#10;"))
Lines 195-232 Link Here
195
			return htmlCode;
185
			return htmlCode;
196
	}
186
	}
197
187
198
	public void write(int indent, StringBuffer sb) 
188
	public void write(int indent, StringBuffer sb) {
199
	{
200
		/* Ignore this command if it's corrupted */
189
		/* Ignore this command if it's corrupted */
201
		if (getWidgetId() == null || text == null || text.length() <= 0)
190
		if (getMacroObjectIdentifier() == null || text == null
191
				|| text.length() <= 0)
202
			return;
192
			return;
203
193
204
		super.write(indent, sb, false, true);
194
		super.write(indent, sb, false, true);
205
		if (text != null) 
195
		if (text != null) {
206
		{
207
			MacroUtil.addIndent(sb, indent);
196
			MacroUtil.addIndent(sb, indent);
208
			sb.append(CDATA_OPEN);
197
			sb.append(CDATA_OPEN);
209
			sb.append(text);
198
			sb.append(text);
210
			sb.append(CDATA_CLOSE);
199
			sb.append(CDATA_CLOSE);
211
			sb.append(GlobalConstants.LINE_SEPARATOR);
200
			sb.append(GlobalConstants.LINE_SEPARATOR);
212
		}
201
		}
213
		MacroUtil.addElement(sb, indent, MacroConstants.COMMAND_ELEMENT, true, true);
202
		MacroUtil.addElement(sb, indent, MacroConstants.COMMAND_ELEMENT, true,
203
				true);
214
	}
204
	}
215
205
216
	public boolean playback(Display display, Composite parent, 
206
	public boolean doPlayback(Display display, Shell parent,
217
			IProgressMonitor monitor) throws CoreException 
207
			IProgressMonitor monitor) throws CoreException {
218
	{
208
219
		
209
		if (parent.isDisposed())
220
		if (parent.isDisposed()) 
221
			return false;
210
			return false;
222
		
211
223
		CommandTarget[] targets = MacroObjectLocator.locateCommandTarget(parent, getWidgetId(), getStartLine());
212
		if (macroObject != null) {
224
		CommandTarget target = targets[0];
213
			setFocus(macroObject);
225
		if (target != null) 
214
			Widget widget = macroObject.getUIObject().getWidget();
226
		{
215
227
			target.setFocus();
228
			Widget widget = target.getWidget();
229
			
230
			if (widget instanceof Text)
216
			if (widget instanceof Text)
231
				((Text) widget).setText(text);
217
				((Text) widget).setText(text);
232
			else if (widget instanceof Combo)
218
			else if (widget instanceof Combo)
Lines 234-256 Link Here
234
			else if (widget instanceof CCombo)
220
			else if (widget instanceof CCombo)
235
				((CCombo) widget).setText(text);
221
				((CCombo) widget).setText(text);
236
			else if (widget instanceof StyledText)
222
			else if (widget instanceof StyledText)
237
				((StyledText)widget).setText(text);
223
				((StyledText) widget).setText(text);
238
			
224
239
			/* Ali M.: Some classes explicitly listen for a selection before a modification is made */			
225
			/*
226
			 * Ali M.: Some classes explicitly listen for a selection before a
227
			 * modification is made
228
			 */
240
			Event event = new Event();
229
			Event event = new Event();
241
			event.display = display;
230
			event.display = display;
242
			event.widget = widget;
231
			event.widget = widget;
243
			event.type = SWT.Selection;
232
			event.type = SWT.Selection;
244
			widget.notifyListeners(SWT.Selection, event);
233
			widget.notifyListeners(SWT.Selection, event);
245
			MacroUtil.processDisplayEvents(display);	
234
			MacroUtil.processDisplayEvents(display);
246
			
235
247
			/* Send out a modify command to notify modify listeners */
236
			/* Send out a modify command to notify modify listeners */
248
			event.type = SWT.Modify;			
237
			event.type = SWT.Modify;
249
			widget.notifyListeners(SWT.Modify, event);
238
			widget.notifyListeners(SWT.Modify, event);
250
			MacroUtil.processDisplayEvents(display);
239
			MacroUtil.processDisplayEvents(display);
251
			
240
252
		}		
241
		}
253
		
242
254
		return true;
243
		return true;
255
	}
244
	}
256
}
245
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/PositionBasedCommand.java (-45 / +52 lines)
Lines 11-56 Link Here
11
 *******************************************************************************/
11
 *******************************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.commands;
12
package org.eclipse.tptp.test.auto.gui.internal.commands;
13
13
14
import java.util.Hashtable;
15
14
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.core.runtime.CoreException;
15
import org.eclipse.core.runtime.IProgressMonitor;
17
import org.eclipse.core.runtime.IProgressMonitor;
16
import org.eclipse.swt.widgets.Composite;
17
import org.eclipse.swt.widgets.Display;
18
import org.eclipse.swt.widgets.Display;
18
import org.eclipse.swt.widgets.Event;
19
import org.eclipse.swt.widgets.Event;
19
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
20
import org.eclipse.swt.widgets.Shell;
21
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
20
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
22
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
21
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
23
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
24
import org.w3c.dom.Node;
22
25
23
/**
26
/**
24
 * An abstract representation of position-based commands
27
 * An abstract representation of position-based commands
25
 * 
28
 * 
26
 * @author Ali Mehregani
29
 * @author Ali Mehregani
30
 * @author Alexander Nyssen (refactoring)
27
 */
31
 */
28
public abstract class PositionBasedCommand extends AbstractMacroCommand 
32
public abstract class PositionBasedCommand extends AbstractMacroCommand {
29
{
30
33
31
	public PositionBasedCommand(MacroCommandShell parent, WidgetIdentifier wi) 
34
	protected String type = null;
32
	{
35
	protected Integer detail = null;
33
		super(parent, wi);
36
	
37
	public PositionBasedCommand(MacroCommandShell parent) {
38
		super(parent);
34
	}
39
	}
40
	
41
	protected abstract String determineType(Event e);
42
	
43
	protected abstract Integer determineDetail(Event e);
35
44
36
	/**
45
	public void processEvent(Event event) throws Exception {
37
	 * The type of the event
46
		this.type = determineType(event);
38
	 */
47
		this.detail = determineDetail(event);
39
	public abstract String getType();
48
	}
40
	
49
	
41
	/**
50
	public String getType() {
42
	 * A chance for the command to process the original SWT event
51
		return type;
43
	 */
52
	}
44
	public abstract void processEvent(Event e);
45
	
53
	
46
	/**
54
	public Integer getDetail() {
47
	 * Returns a field that is required to complete the string serialization of the
55
		return detail;
48
	 * command.
56
	}
49
	 * 
50
	 * @return A detail field (for mouse events it corresponds to the button pressed/released and
51
	 * for key events it corresponds to the key pressed/released
52
	 */
53
	public abstract int getDetail();
54
57
55
	/**
58
	/**
56
	 * Constructs the SWT event that will be played back
59
	 * Constructs the SWT event that will be played back
Lines 58-96 Link Here
58
	 * @return The SWT event
61
	 * @return The SWT event
59
	 */
62
	 */
60
	public abstract Event[] constructSWTEvents();
63
	public abstract Event[] constructSWTEvents();
61
	
64
62
	
63
	/**
65
	/**
64
	 * String serialize this event
66
	 * String serialize this event
65
	 */
67
	 */
66
	public void write(int indent, StringBuffer sb, boolean close, boolean end)
68
	public void write(int indent, StringBuffer sb, boolean close, boolean end) {
67
	{
69
		MacroUtil.addElement(sb,
68
		MacroUtil.addElement(sb, indent, MacroConstants.COMMAND_ELEMENT, false, false);		
70
			indent,
69
		MacroUtil.addAttribute(sb, 
71
			MacroConstants.COMMAND_ELEMENT,
70
				new String[] {			
72
			false,
71
					MacroConstants.TYPE_ATTRIBUTE,
73
			false);
72
					MacroConstants.DETAIL_ATTRIBUTE, 
74
		MacroUtil.addAttribute(sb,
73
				}, 
75
			new String[] {MacroConstants.TYPE_ATTRIBUTE, MacroConstants.DETAIL_ATTRIBUTE},
74
				new String[] {
76
			new String[] {getType(), detail != null ? String.valueOf(detail) : null},
75
					getType(),
77
			false,
76
					String.valueOf(getDetail()),
78
			false);
77
				}
79
	}
78
		, false, false);
80
	
81
	public void load(Node node, Hashtable lineTable) throws CoreException {
82
		super.load(node, lineTable);
83
84
		type = MacroUtil.getAttribute(node, "type");
85
		if(MacroUtil.getAttribute(node, "detail") != null){
86
			detail = new Integer(MacroUtil.getAttribute(node, "detail"));
87
		}
79
	}
88
	}
80
89
81
	/**
90
	/**
82
	 * Plays back this command
91
	 * Plays back this command
83
	 */
92
	 */
84
	public boolean playback(final Display display, Composite parent, IProgressMonitor monitor) throws CoreException 
93
	public boolean playback(final Display display, final Shell parent, IProgressMonitor monitor) throws CoreException {
85
	{
94
		Event[] events = constructSWTEvents();
86
		Event[] events = constructSWTEvents ();
87
		boolean success = true;
95
		boolean success = true;
88
		
96
89
		for (int i = 0; i < events.length; i++)
97
		for (int i = 0; i < events.length; i++) {
90
		{			
91
			success = success && display.post(events[i]);
98
			success = success && display.post(events[i]);
92
		}
99
		}
93
						
100
		
94
		MacroUtil.processDisplayEvents(display);
101
		MacroUtil.processDisplayEvents(display);
95
		return success;
102
		return success;
96
	}
103
	}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/FocusCommand.java (-32 / +23 lines)
Lines 12-83 Link Here
12
12
13
import org.eclipse.core.runtime.CoreException;
13
import org.eclipse.core.runtime.CoreException;
14
import org.eclipse.core.runtime.IProgressMonitor;
14
import org.eclipse.core.runtime.IProgressMonitor;
15
import org.eclipse.swt.widgets.Composite;
16
import org.eclipse.swt.widgets.Display;
15
import org.eclipse.swt.widgets.Display;
17
import org.eclipse.swt.widgets.Event;
16
import org.eclipse.swt.widgets.Event;
18
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
17
import org.eclipse.swt.widgets.Shell;
19
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroObjectLocator;
18
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
20
19
21
public class FocusCommand extends AbstractMacroCommand
20
public class FocusCommand extends ObjectBasedCommand {
22
{
21
23
	public static final String TYPE = "focus";
22
	public static final String TYPE = IMacroCommand.FOCUS;
24
23
25
	public FocusCommand(MacroCommandShell parent, WidgetIdentifier wid)
24
	public FocusCommand(MacroCommandShell parent) {
26
	{
25
		super(parent);
27
		super(parent, wid);
28
	}
26
	}
29
27
30
	/**
28
	/**
31
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand#mergeEvent(org.eclipse.swt.widgets.Event)
29
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand#mergeEvent(org.eclipse.swt.widgets.Event)
32
	 */
30
	 */
33
	public boolean mergeEvent(Event e)
31
	public boolean mergeEvent(Event e) throws Exception {
34
	{
35
		/* we can directly merge repeated focus requests on the same widget */
32
		/* we can directly merge repeated focus requests on the same widget */
36
		return true;
33
		return true;
37
	}
34
	}
38
35
39
	
36
	/**
40
	/** 
41
	 * @see org.eclipse.ui.macro.MacroCommand#getType()
37
	 * @see org.eclipse.ui.macro.MacroCommand#getType()
42
	 */
38
	 */
43
	public String getType()
39
	public String getType() {
44
	{
45
		return TYPE;
40
		return TYPE;
46
	}
41
	}
47
42
48
	
43
	/**
49
	/** 
50
	 * @see org.eclipse.ui.macro.MacroCommand#processEvent(org.eclipse.swt.widgets.Event)
44
	 * @see org.eclipse.ui.macro.MacroCommand#processEvent(org.eclipse.swt.widgets.Event)
51
	 */
45
	 */
52
	public void processEvent(Event e)
46
	public void doProcessEvent(Event e) {
53
	{
54
		findDescriptiveField(e.widget);
47
		findDescriptiveField(e.widget);
55
	}
48
	}
56
49
57
	
50
	/**
58
	/** 
51
	 * @see org.eclipse.ui.macro.IPersistable#write(java.lang.String,
59
	 * @see org.eclipse.ui.macro.IWritable#write(java.lang.String, java.io.PrintWriter)
52
	 *      java.io.PrintWriter)
60
	 */
53
	 */
61
	public void write(int indent, StringBuffer sb)
54
	public void write(int indent, StringBuffer sb) {
62
	{
63
		/* Don't bother with the focus command if the id is invalid */
55
		/* Don't bother with the focus command if the id is invalid */
64
		if (getWidgetId() == null)
56
		if (getMacroObjectIdentifier() == null)
65
			return;
57
			return;
66
58
67
		super.write(indent, sb, true, true);
59
		super.write(indent, sb, true, true);
68
	}
60
	}
69
61
70
	
71
	/**
62
	/**
72
	 * @see org.eclipse.ui.macro.IPlayable#playback(org.eclipse.swt.widgets.Composite)
63
	 * @see org.eclipse.ui.macro.IPlayable#playback(org.eclipse.swt.widgets.Composite)
73
	 */
64
	 */
74
	public boolean playback(Display display, Composite parent, IProgressMonitor monitor) throws CoreException
65
	public boolean doPlayback(Display display, Shell parent,
75
	{
66
			IProgressMonitor monitor) throws CoreException {
76
		if (parent.isDisposed())
67
		if (parent.isDisposed())
77
			return false;
68
			return false;
78
		CommandTarget[] targets = MacroObjectLocator.locateCommandTarget(parent,getWidgetId(), getStartLine());
69
		if (macroObject != null)
79
		if (targets !=null && targets.length > 0)
70
			setFocus(macroObject);
80
			targets[0].setFocus();
81
		return true;
71
		return true;
82
	}
72
	}
73
83
}
74
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/BooleanSelectionCommand.java (-387 / +384 lines)
Lines 23-127 Link Here
23
import org.eclipse.swt.SWT;
23
import org.eclipse.swt.SWT;
24
import org.eclipse.swt.graphics.Point;
24
import org.eclipse.swt.graphics.Point;
25
import org.eclipse.swt.widgets.Button;
25
import org.eclipse.swt.widgets.Button;
26
import org.eclipse.swt.widgets.Composite;
27
import org.eclipse.swt.widgets.Display;
26
import org.eclipse.swt.widgets.Display;
28
import org.eclipse.swt.widgets.Event;
27
import org.eclipse.swt.widgets.Event;
29
import org.eclipse.swt.widgets.Listener;
28
import org.eclipse.swt.widgets.Listener;
30
import org.eclipse.swt.widgets.Menu;
29
import org.eclipse.swt.widgets.Menu;
31
import org.eclipse.swt.widgets.MenuItem;
30
import org.eclipse.swt.widgets.MenuItem;
31
import org.eclipse.swt.widgets.Shell;
32
import org.eclipse.swt.widgets.ToolItem;
32
import org.eclipse.swt.widgets.ToolItem;
33
import org.eclipse.swt.widgets.Widget;
33
import org.eclipse.swt.widgets.Widget;
34
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
34
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
35
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
35
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
36
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
36
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
37
import org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine;
37
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
38
import org.eclipse.tptp.test.auto.gui.internal.core.IUIObject;
39
import org.eclipse.tptp.test.auto.gui.internal.core.IWidgetId;
40
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
41
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
38
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
42
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
39
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
43
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroObjectLocator;
44
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
40
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
45
import org.eclipse.tptp.test.auto.gui.internal.macro.UIObject;
41
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObject;
46
import org.eclipse.tptp.test.auto.gui.internal.resolvers.PrimitiveWidgetId;
42
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptor;
43
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine;
44
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
45
import org.eclipse.tptp.test.auto.gui.internal.uiobject.PrimitiveUIObjectIdentifier;
46
import org.eclipse.tptp.test.auto.gui.internal.uiobject.UIObject;
47
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.UIObjectResolver;
48
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.deresolvingsupport.UIObjectDeprecatedDeresolvingSupport;
47
import org.w3c.dom.Node;
49
import org.w3c.dom.Node;
48
import org.w3c.dom.NodeList;
50
import org.w3c.dom.NodeList;
49
51
50
51
/**
52
/**
52
 * Represents the select command (e.g. button, check box, radio button, and 
53
 * Represents the select command (e.g. button, check box, radio button, and
53
 * etc... selections)
54
 * etc... selections)
54
 * 
55
 * 
55
 * @author Ali Mehregani
56
 * @author Ali Mehregani
57
 * @author Alexander Nyssen
56
 */
58
 */
57
public class BooleanSelectionCommand extends AbstractMacroCommand
59
public class BooleanSelectionCommand extends SingleSelectionCommand {
58
{
59
	public static final String TYPE = "select";
60
60
61
	private Boolean selection;
61
	public static final String TYPE = IMacroCommand.SELECT;
62
62
63
	private ArrayList path;
63
	private Boolean selection;
64
64
65
	/* Indicates the cursor location relative to the tool bar item (the value is non-zero
65
	/*
66
	 * if the toolbar item is dropped down */
66
	 * Indicates the cursor location relative to the tool bar item (the value is
67
	 * non-zero if the toolbar item is dropped down
68
	 */
67
	private Point toolBarLocation;
69
	private Point toolBarLocation;
68
70
69
	/* The detail of the event as described in the SWT class */
71
	/* The detail of the event as described in the SWT class */
70
	private int detail;
72
	private int detail;
71
	
72
	/* If an item is selected from a drop down menu, then this points to the id of the item */
73
	private IWidgetId itemSelectedId;
74
73
75
	/* The refrence id of the selected item that points to an object in an object mine */
74
	/*
75
	 * If an item is selected from a drop down menu, then this points to the id
76
	 * of the item
77
	 */
78
	private IUIObjectIdentifier itemSelectedIdentifier;
79
80
	/*
81
	 * The refrence id of the selected item that points to an object in an
82
	 * object mine
83
	 */
76
	private String itemSelectedRefId;
84
	private String itemSelectedRefId;
77
	
85
78
	/* This listener is used to get a reference to a drop-down menu */
86
	/* This listener is used to get a reference to a drop-down menu */
79
	private DropDownMenuListener dropDownMenuListener;
87
	private DropDownMenuListener dropDownMenuListener;
80
	
88
81
	/* Reference to a drop-down menu */
89
	/* Reference to a drop-down menu */
82
	private Menu dropDownMenu;
90
	private Menu dropDownMenu;
83
91
84
	/* Indicates whether we're waiting for a drop down menu item */
92
	/* Indicates whether we're waiting for a drop down menu item */
85
	private boolean menuIsNeeded;
93
	private boolean menuIsNeeded;
86
	
87
	/**
88
	 * The toolBarLocation argument is needed when the toolbar item is a drop down.
89
	 * 
90
	 * @param wid The widget identifier.
91
	 * @param toolBarLocation The cursor location
92
	 * @param detail The detail of the event as described by the SWT class
93
	 */
94
	public BooleanSelectionCommand(MacroCommandShell parent, WidgetIdentifier wid, Point toolBarLocation, int detail)
95
	{
96
		super(parent, wid);
97
		this.toolBarLocation = toolBarLocation;
98
		this.detail = detail;			
99
	}
100
94
101
	public BooleanSelectionCommand(MacroCommandShell parent, WidgetIdentifier wid)
95
	public BooleanSelectionCommand(MacroCommandShell parent) {
102
	{
96
		super(parent);
103
		super(parent, wid);
104
		this.detail = -10;		
105
	}
97
	}
106
98
107
	public String getType()
99
	public String getType() {
108
	{
109
		return TYPE;
100
		return TYPE;
110
	}
101
	}
111
102
112
	public void processEvent(Event e)
103
	public void doProcessEvent(Event event) {
113
	{
104
		if (event.x != 0 || event.y != 0 || event.detail != 0) {
114
		selection = getSelection(e.widget);
105
			this.toolBarLocation = new Point(event.x, event.y);
115
		if (e.widget instanceof MenuItem)
106
			this.detail = event.detail;
116
		{
107
		} else {
117
			path = getPath((MenuItem) e.widget);
108
			this.detail = -10;
118
		}
109
		}
119
		
110
120
		findDescriptiveField(e.widget);
111
		selection = getSelection(event.widget);
112
113
		findDescriptiveField(event.widget);
121
	}
114
	}
122
115
123
	private Boolean getSelection(Widget widget)
116
	private Boolean getSelection(Widget widget) {
124
	{
125
		if ((widget.getStyle() & (SWT.CHECK | SWT.RADIO)) == 0)
117
		if ((widget.getStyle() & (SWT.CHECK | SWT.RADIO)) == 0)
126
			return null;
118
			return null;
127
		if (widget instanceof Button)
119
		if (widget instanceof Button)
Lines 133-600 Link Here
133
		return null;
125
		return null;
134
	}
126
	}
135
127
136
	private ArrayList getPath(MenuItem item)
128
	public void load(Node node, Hashtable lineTable) throws CoreException {
137
	{
138
		ArrayList segments = new ArrayList();
139
		Object data = item.getData();
140
141
		if (data instanceof ContributionItem)
142
		{
143
			ContributionItem aitem = (ContributionItem) data;
144
			MenuManager manager = (MenuManager) aitem.getParent();
145
			while (manager != null)
146
			{
147
				String id = manager.getId();
148
				if (id == null)
149
					break;
150
				segments.add(0, id);
151
				manager = (MenuManager) manager.getParent();
152
			}
153
		}
154
		return segments.size() > 0 ? segments : null;
155
	}
156
157
	public void load(Node node, Hashtable lineTable) throws CoreException
158
	{
159
		super.load(node, lineTable);
129
		super.load(node, lineTable);
160
		String sel = MacroUtil.getAttribute(node, MacroConstants.SELECTION_ATTRIBUTE);
130
		String sel = MacroUtil.getAttribute(node,
161
		String xCoordStr = MacroUtil.getAttribute(node, MacroConstants.X_COORD_ATTRIBUTE);
131
				MacroConstants.SELECTION_ATTRIBUTE);
162
		String yCoordStr = MacroUtil.getAttribute(node, MacroConstants.Y_COORD_ATTRIBUTE);
132
		String xCoordStr = MacroUtil.getAttribute(node,
163
		String detailStr = MacroUtil.getAttribute(node, MacroConstants.DETAIL_ATTRIBUTE);
133
				MacroConstants.X_COORD_ATTRIBUTE);
134
		String yCoordStr = MacroUtil.getAttribute(node,
135
				MacroConstants.Y_COORD_ATTRIBUTE);
136
		String detailStr = MacroUtil.getAttribute(node,
137
				MacroConstants.DETAIL_ATTRIBUTE);
164
138
165
		if (xCoordStr != null && yCoordStr != null)
139
		if (xCoordStr != null && yCoordStr != null)
166
			toolBarLocation = new Point(Integer.parseInt(xCoordStr), Integer.parseInt(yCoordStr));
140
			toolBarLocation = new Point(Integer.parseInt(xCoordStr), Integer
141
					.parseInt(yCoordStr));
167
		if (detailStr != null)
142
		if (detailStr != null)
168
			detail = Integer.parseInt(detailStr);			
143
			detail = Integer.parseInt(detailStr);
169
		
170
144
171
		if (sel != null)
145
		if (sel != null) {
172
		{
146
			selection = sel.equals(MacroConstants.TRUE_VALUE) ? Boolean.TRUE
173
			selection = sel.equals(MacroConstants.TRUE_VALUE) ? Boolean.TRUE : Boolean.FALSE;
147
					: Boolean.FALSE;
174
		}
148
		}
175
		NodeList children = node.getChildNodes();
149
		NodeList children = node.getChildNodes();
176
		for (int i = 0; i < children.getLength(); i++)
150
		for (int i = 0; i < children.getLength(); i++) {
177
		{
178
			Node child = children.item(i);
151
			Node child = children.item(i);
179
			if (!(child.getNodeType() == Node.ELEMENT_NODE))
152
			if (!(child.getNodeType() == Node.ELEMENT_NODE))
180
				continue;
153
				continue;
181
			
154
182
			if (child.getNodeName().equals(MacroConstants.PARENT_ELEMENT))
155
			if (child.getNodeName().equals(MacroConstants.SELECT_ITEM_ELEMENT)) {
183
			{
156
				String pathOfItem = MacroUtil.getAttribute(child,
184
				if (path == null)
157
						MacroConstants.WIDGET_ID_ATTRIBUTE);
185
					path = new ArrayList();
158
				if (pathOfItem == null) {
186
				path.add(MacroUtil.getAttribute(child, MacroConstants.WIDGET_ID_ATTRIBUTE));
159
					String refId = MacroUtil.getAttribute(child,
187
			}
160
							MacroConstants.REFERENCE_ID_ATTRIBUTE);
188
			else if (child.getNodeName().equals(MacroConstants.SELECT_ITEM_ELEMENT))
161
					if (refId == null) {
189
			{
162
						itemSelectedIdentifier = null;
190
				String pathOfItem = MacroUtil.getAttribute(child, MacroConstants.PATH_ATTRIBUTE);
163
					} else {
191
				if (pathOfItem == null)
164
						MacroObjectDescriptor uiObject = MacroManager
192
				{
165
								.getInstance()
193
					String refId = MacroUtil.getAttribute(child, MacroConstants.REFERENCE_ID_ATTRIBUTE);
166
								.getObjectMine()
194
					if (refId == null)
167
								.lookupMacroObjectDescriptor(
195
					{
168
										getCorrespondingMacroObjectDescriptor(),
196
						itemSelectedId = null;
169
										refId);
197
					}
170
						if (uiObject != null) {
198
					else
171
							itemSelectedIdentifier = new PrimitiveUIObjectIdentifier(
199
					{
172
									uiObject.getWidgetId(), uiObject
200
						IUIObject uiObject = MacroManager.getInstance().getObjectMine().lookupUIObject(getCorrespondingObject(), refId);
173
											.getResolverId());
201
						if (uiObject != null)
202
						{
203
							itemSelectedId = new PrimitiveWidgetId(uiObject.getObjectId().toString());
204
							itemSelectedId.setResolverId(uiObject.getResolverId());
205
						}
174
						}
206
					}
175
					}
207
						
176
208
				}
177
				} else {
209
				else
178
					itemSelectedIdentifier = new PrimitiveUIObjectIdentifier(
210
				{
179
							pathOfItem);
211
					itemSelectedId = new PrimitiveWidgetId(pathOfItem);
212
				}
180
				}
213
				
181
214
				dropDownMenuListener = new DropDownMenuListener();
182
				dropDownMenuListener = new DropDownMenuListener();
215
			}
183
			}
216
		}
184
		}
217
	}
185
	}
218
186
219
	public void write(int indent, StringBuffer sb)
187
	public void write(int indent, StringBuffer sb) {
220
	{
221
		super.write(indent, sb);
188
		super.write(indent, sb);
222
		boolean childElementPresent = itemSelectedId != null;
189
		boolean childElementPresent = itemSelectedIdentifier != null;
223
		MacroUtil.addAttribute(sb, 
190
		MacroUtil
224
				new String[]{MacroConstants.X_COORD_ATTRIBUTE,
191
				.addAttribute(
225
							 MacroConstants.Y_COORD_ATTRIBUTE,
192
						sb,
226
							 MacroConstants.DETAIL_ATTRIBUTE,
193
						new String[] { MacroConstants.X_COORD_ATTRIBUTE,
227
							 MacroConstants.SELECTION_ATTRIBUTE
194
								MacroConstants.Y_COORD_ATTRIBUTE,
228
							},
195
								MacroConstants.DETAIL_ATTRIBUTE,
229
				
196
								MacroConstants.SELECTION_ATTRIBUTE },
230
				new String[]{toolBarLocation == null ? null : String.valueOf(toolBarLocation.x),
197
231
							 toolBarLocation == null ? null : String.valueOf(toolBarLocation.y),
198
						new String[] {
232
							 detail == -10 ? null : String.valueOf(detail),
199
								toolBarLocation == null ? null : String
233
							 selection == null ? null : selection.equals(Boolean.TRUE) ? MacroConstants.TRUE_VALUE : MacroConstants.FALSE_VALUE
200
										.valueOf(toolBarLocation.x),
234
							}, 
201
								toolBarLocation == null ? null : String
235
							!childElementPresent, true);
202
										.valueOf(toolBarLocation.y),
236
				
203
								detail == -10 ? null : String.valueOf(detail),
237
		
204
								selection == null ? null
205
										: selection.equals(Boolean.TRUE) ? MacroConstants.TRUE_VALUE
206
												: MacroConstants.FALSE_VALUE },
207
						!childElementPresent, true);
208
238
		int pindent = childElementPresent ? indent + 1 : 0;
209
		int pindent = childElementPresent ? indent + 1 : 0;
239
				
210
240
		if (itemSelectedId != null)
211
		if (itemSelectedIdentifier != null) {
241
		{	
212
			boolean useObjectMine = useObjectMine()
242
			boolean useObjectMine = MacroManager.getInstance().isObjectMineOn() && itemSelectedRefId != null;
213
					&& itemSelectedRefId != null;
243
			MacroUtil.addElement(sb, pindent, MacroConstants.SELECT_ITEM_ELEMENT, false, false);			
214
			MacroUtil.addElement(sb, pindent,
244
			MacroUtil.addAttribute(sb, new String[]
215
					MacroConstants.SELECT_ITEM_ELEMENT, false, false);
245
			          {
216
			MacroUtil
246
						useObjectMine ? MacroConstants.REFERENCE_ID_ATTRIBUTE : MacroConstants.PATH_ATTRIBUTE
217
					.addAttribute(
247
			          }, 
218
							sb,
248
			          new String[]
219
							new String[] { useObjectMine ? MacroConstants.REFERENCE_ID_ATTRIBUTE
249
			          {
220
									: MacroConstants.WIDGET_ID_ATTRIBUTE },
250
						useObjectMine ? itemSelectedRefId : itemSelectedId.toString()
221
							new String[] { useObjectMine ? itemSelectedRefId
251
			          }, true, true);
222
									: itemSelectedIdentifier.getWidgetId() },
252
			MacroUtil.addElement(sb, indent, MacroConstants.COMMAND_ELEMENT, true, true);
223
							true, true);
224
			MacroUtil.addElement(sb, indent, MacroConstants.COMMAND_ELEMENT,
225
					true, true);
253
		}
226
		}
254
	}
227
	}
255
228
256
	public boolean playback(Display display, Composite parent, IProgressMonitor monitor) throws CoreException
229
	public boolean doPlayback(Display display, Shell parent,
257
	{
230
			IProgressMonitor monitor) throws CoreException {
258
		CommandTarget[] targets = MacroObjectLocator.locateCommandTarget(parent, getWidgetId(), path, getStartLine());
231
259
		if (targets == null)
232
		if (macroObject == null)
260
			return false;
233
			return false;
261
		
234
262
		boolean executeForFirstMatch = false;
235
		// boolean executeForFirstMatch = false;
263
		for (int i = 0; i < targets.length && !executeForFirstMatch; i++)
236
		// for (int i = 0; i < targets.length && !executeForFirstMatch; i++) {
264
		{
237
		setFocus(macroObject);
265
			targets[i].setFocus();
238
		Widget widget = macroObject.getUIObject().getWidget();
266
			Widget widget = targets[i].getWidget();
239
267
			
240
		// executeForFirstMatch = widget instanceof Button;
268
			executeForFirstMatch = widget instanceof Button;
241
		Display currentDisplay = GuiPlugin.getDefault().getWorkbench()
269
			Display currentDisplay = GuiPlugin.getDefault().getWorkbench().getDisplay();
242
				.getDisplay();
270
			ActionContributionItem contributionItem = null;
243
		ActionContributionItem contributionItem = null;
271
			if ((widget.getStyle() & (SWT.CHECK | SWT.RADIO)) == 0)
244
		if ((widget.getStyle() & (SWT.CHECK | SWT.RADIO)) == 0) {
245
			/*
246
			 * If in case we're dealing with a toolbar item that is a drop-down,
247
			 * then register appropriate listeners that will be used for getting
248
			 * a reference to the menu. We only need to do this if a menu
249
			 * creator is not provided
250
			 */
251
			if (widget instanceof ToolItem && /* Are we a tool item? */
252
			(widget.getStyle() & SWT.DROP_DOWN) != 0 && /* Are we a drop down? */
253
			itemSelectedIdentifier != null && /*
254
												 * Do we have a selected item
255
												 * from our menu (i.e. is the
256
												 * menu even needed)?
257
												 */
258
			widget.getData() instanceof ActionContributionItem)/*
259
																 * Are we
260
																 * dealing with
261
																 * a
262
																 * contribution
263
																 * item?
264
																 */
272
			{
265
			{
273
				/* If in case we're dealing with a toolbar item that is a drop-down, then register 
266
274
				 * appropriate listeners that will be used for getting a reference to the menu.  We only need
267
				contributionItem = (ActionContributionItem) widget.getData();
275
				 * to do this if a menu creator is not provided */
268
276
				if ( widget instanceof ToolItem &&						/* Are we a tool item? */ 
269
				/* We don't have a menu creator. Register the listeners */
277
					 (widget.getStyle() & SWT.DROP_DOWN) != 0 && 		/* Are we a drop down? */
270
				if (contributionItem.getAction().getMenuCreator() == null) {
278
					 itemSelectedId != null &&							/* Do we have a selected item from our menu (i.e. is the menu even needed)? */ 		
271
					currentDisplay.addFilter(SWT.Show, dropDownMenuListener);
279
					 widget.getData() instanceof ActionContributionItem)/* Are we dealing with a contribution item? */
272
280
				{
281
							
282
					contributionItem = (ActionContributionItem)widget.getData();
283
					
284
					/* We don't have a menu creator.  Register the listeners */
285
					if (contributionItem.getAction().getMenuCreator() == null)
286
					{
287
						currentDisplay.addFilter(SWT.Show, dropDownMenuListener);			
288
						
289
					}
290
				}
273
				}
291
				
292
				if (itemSelectedId == null ||
293
				   (itemSelectedId != null && contributionItem != null && contributionItem.getAction().getMenuCreator() == null))
294
					doClick(display, widget, false);
295
			}
274
			}
296
			
297
275
298
			else if (selection != null)
276
			if (itemSelectedIdentifier == null
299
			{
277
					|| (itemSelectedIdentifier != null
300
				doSelect(display, widget);
278
							&& contributionItem != null && contributionItem
279
							.getAction().getMenuCreator() == null))
280
				doClick(display, widget, false);
281
		}
282
283
		else if (selection != null) {
284
			doSelect(display, widget);
285
		}
286
287
		/* Select the item from the drop-down menu, if there is one set */
288
		if (itemSelectedIdentifier != null) {
289
			if (contributionItem == null) {
290
				currentDisplay.removeFilter(SWT.Show, dropDownMenuListener);
291
				return false; // continue; /* we weren't able to select the
292
				// item */
301
			}
293
			}
302
						
294
303
			/* Select the item from the drop-down menu, if there is one set */
295
			Menu menu = null;
304
			if (itemSelectedId != null)
296
			IMenuCreator menuCreator = contributionItem.getAction()
305
			{
297
					.getMenuCreator();
306
				if (contributionItem == null)
298
307
				{
299
			/* Attempt to create the menu */
308
					currentDisplay.removeFilter(SWT.Show, dropDownMenuListener);			
300
			if (menuCreator != null)
309
					continue;					/* we weren't able to select the item */
301
				menu = menuCreator.getMenu(parent);
310
				}
302
			/* Otherwise we wait until the menu is handed out to us */
311
			
303
			else {
312
				Menu menu = null;
304
				try {
313
				IMenuCreator menuCreator = contributionItem.getAction().getMenuCreator(); 
305
					menuIsNeeded = true;
314
				
306
					/*
315
				/* Attempt to create the menu */
307
					 * Wait a maximum of INCREMENTS * COUNT in increments of
316
				if (menuCreator != null)
308
					 * INCREMENT
317
					menu = menuCreator.getMenu(parent);
309
					 */
318
				/* Otherwise we wait until the menu is handed out to us */
310
					final int INCREMENT = 200;
319
				else
311
					final int COUNT = 15;
320
				{				
312
					synchronized (this) {
321
					try 
313
						int count = 0;
322
					{
314
						while (dropDownMenu == null && count < COUNT) {
323
						menuIsNeeded = true;
315
							wait(INCREMENT);
324
						/* Wait a maximum of INCREMENTS * COUNT in increments of INCREMENT */
316
							count++;
325
						final int INCREMENT = 200;
326
						final int COUNT = 15;
327
						synchronized (this)
328
						{
329
							int count = 0;
330
							while (dropDownMenu == null && count < COUNT)
331
							{
332
								wait (INCREMENT);
333
								count++;
334
							}
335
						}
317
						}
336
					} 
337
					catch (InterruptedException e) 
338
					{					
339
						/* doesn't need to be handled */
340
					}
318
					}
341
					if (dropDownMenu != null)
319
				} catch (InterruptedException e) {
342
						menu = dropDownMenu;
320
					/* doesn't need to be handled */
343
				}
321
				}
344
				/* Bail out if we couldn't get the menu */
322
				if (dropDownMenu != null)
345
				if (menu == null)
323
					menu = dropDownMenu;
346
				{
324
			}
347
					currentDisplay.removeFilter(SWT.Show, dropDownMenuListener);							
325
			/* Bail out if we couldn't get the menu */
348
					continue;					/* we weren't able to select the item */
326
			if (menu == null) {
349
				}
350
				
351
				/* Unregister the listener */
352
				currentDisplay.removeFilter(SWT.Show, dropDownMenuListener);
327
				currentDisplay.removeFilter(SWT.Show, dropDownMenuListener);
353
				
328
				return false; // continue; /* we weren't able to select the
354
				/* Find the menu item corresponding to the drop down menu */
329
				// item */
355
				MenuItem[] menuItems = menu.getItems();
330
			}
356
				MenuItem foundItem = null;
331
357
				for (int j = 0; j < menuItems.length; j++)
332
			/* Unregister the listener */
358
				{				
333
			currentDisplay.removeFilter(SWT.Show, dropDownMenuListener);
359
					if (foundMenuItem(menuItems[j]))
334
360
					{
335
			/* Find the menu item corresponding to the drop down menu */
361
						foundItem = menuItems[j];
336
			MenuItem[] menuItems = menu.getItems();
362
						break;
337
			MenuItem foundItem = null;
363
					}
338
			for (int j = 0; j < menuItems.length; j++) {
339
				if (foundMenuItem(menuItems[j])) {
340
					foundItem = menuItems[j];
341
					break;
364
				}
342
				}
365
				
343
			}
366
				if (foundItem == null)
344
367
					continue;
345
			if (foundItem == null)
368
				
346
				return false;// /continue;
369
				doClick(display, foundItem, true);
347
370
				
348
			doClick(display, foundItem, true);
371
			}			
349
372
		}
350
		}
373
		
351
352
		// }
353
374
		return true;
354
		return true;
375
	}
355
	}
376
	
356
377
	private boolean foundMenuItem (MenuItem menuItem)
357
	private boolean foundMenuItem(MenuItem menuItem) {
378
	{
379
		/* Try the widget resolvers first */
358
		/* Try the widget resolvers first */
380
		if (MacroObjectLocator.foundItem(menuItem, itemSelectedId.getResolverId(), itemSelectedId.toString()))
359
		if (UIObjectDeprecatedDeresolvingSupport.foundItem(menuItem,
360
				itemSelectedIdentifier))
381
			return true;
361
			return true;
382
	
362
383
		/* Give the old policy a try */
363
		/* Give the old policy a try */
384
		Object menuItemIdObj = getDropDownItemTraditionalId(menuItem);
364
		Object menuItemIdObj = getDropDownItemTraditionalId(menuItem);
385
		if (menuItemIdObj.equals(itemSelectedId.toString()))
365
		if (menuItemIdObj.equals(itemSelectedIdentifier.getWidgetId()))
386
			return true;
366
			return true;
387
		
367
388
		return false;
368
		return false;
389
	}
369
	}
390
370
391
	
371
	private Object getDropDownItemTraditionalId(MenuItem menuItem) {
392
	private Object getDropDownItemTraditionalId (MenuItem menuItem)
393
	{
394
		Object data = menuItem.getData();
372
		Object data = menuItem.getData();
395
		if (data instanceof ActionContributionItem)
373
		if (data instanceof ActionContributionItem) {
396
		{
374
			return ((ActionContributionItem) data).getAction().getClass()
397
			return ((ActionContributionItem)data).getAction().getClass().getName();
375
					.getName();
398
		}
376
		} else if (data != null)
399
		else if (data!=null)
400
			return data.getClass().getName();
377
			return data.getClass().getName();
401
		
378
402
		/* As a last resort, index the menu item */		
379
		/* As a last resort, index the menu item */
403
		return findMenuItemInx (menuItem, "");
380
		return findMenuItemInx(menuItem, "");
404
	}
381
	}
405
	
382
406
	private String findMenuItemInx(MenuItem menuItem, String index) 
383
	private String findMenuItemInx(MenuItem menuItem, String index) {
407
	{
408
		if (index != null && index.length() > 0)
384
		if (index != null && index.length() > 0)
409
			index = index + "|";
385
			index = index + "|";
410
		
386
411
		Menu parentMenu = menuItem.getMenu();
387
		Menu parentMenu = menuItem.getMenu();
412
		
388
413
		if (parentMenu == null)
389
		if (parentMenu == null)
414
			parentMenu = menuItem.getParent();
390
			parentMenu = menuItem.getParent();
415
		
391
416
		if (parentMenu != null)
392
		if (parentMenu != null) {
417
		{
418
			int currentInx = parentMenu.indexOf(menuItem);
393
			int currentInx = parentMenu.indexOf(menuItem);
419
			MenuItem parentItem = parentMenu.getParentItem();
394
			MenuItem parentItem = parentMenu.getParentItem();
420
			
395
421
			index = index + currentInx;
396
			index = index + currentInx;
422
			if (parentItem != null)
397
			if (parentItem != null)
423
				return index + findMenuItemInx(parentItem, index);
398
				return index + findMenuItemInx(parentItem, index);
424
		}
399
		}
425
			
400
426
		return index;
401
		return index;
427
	}
402
	}
428
	
403
429
	private void doClick(Display display, Widget widget, boolean isItemSelected) throws CoreException
404
	private void doClick(Display display, Widget widget, boolean isItemSelected)
430
	{		
405
			throws CoreException {
406
431
		checkEnableStatus(widget);
407
		checkEnableStatus(widget);
432
		Event e = new Event();
408
		Event e = new Event();
433
		e.type = SWT.Selection;
409
		e.type = SWT.Selection;
434
		e.widget = widget;
410
		e.widget = widget;
435
		e.display = display;
411
		e.display = display;
436
		
412
437
		boolean positionSet = false;
413
		boolean positionSet = false;
438
		boolean detailSet = false;		
414
		boolean detailSet = false;
439
		if (!isItemSelected)
415
		if (!isItemSelected) {
440
		{
416
			if (toolBarLocation != null) {
441
			if (toolBarLocation != null)
442
			{
443
				e.x = toolBarLocation.x;
417
				e.x = toolBarLocation.x;
444
				e.y = toolBarLocation.y;
418
				e.y = toolBarLocation.y;
445
				positionSet = true;
419
				positionSet = true;
446
			}
420
			}
447
	
421
448
			if (detail != -10)			
422
			if (detail != -10) {
449
			{
450
				e.detail = detail;
423
				e.detail = detail;
451
				detailSet = true;
424
				detailSet = true;
452
			}					
425
			}
453
		}
426
		}
454
		
427
455
		boolean isWidgetNotified = false;
428
		boolean isWidgetNotified = false;
456
		
429
457
		/* We need to do an immediate notify if we're a drop down menu */
430
		/* We need to do an immediate notify if we're a drop down menu */
458
		if ((positionSet && detailSet) || menuIsNeeded)
431
		if ((positionSet && detailSet) || menuIsNeeded) {
459
		{
460
			isWidgetNotified = true;
432
			isWidgetNotified = true;
461
			widget.notifyListeners(e.type, e);
433
			widget.notifyListeners(e.type, e);
462
		}
434
		}
463
			
464
435
465
		/* If we're dealing with a drop down menu, then we have to send out this
436
		/*
466
		 * mouse down event.  Otherwise the readAndDispatch will wait indefinitely.
437
		 * If we're dealing with a drop down menu, then we have to send out this
467
		 * This is safe because we're only sending a mouse down event without a successive
438
		 * mouse down event. Otherwise the readAndDispatch will wait
468
		 * mouse up event. */
439
		 * indefinitely. This is safe because we're only sending a mouse down
469
		if (positionSet && detailSet)
440
		 * event without a successive mouse up event.
470
		{
441
		 */
442
		if (positionSet && detailSet) {
471
			/* Move the cursor to a safe position */
443
			/* Move the cursor to a safe position */
472
			Event mouseMoveEvent = new Event();
444
			Event mouseMoveEvent = new Event();
473
			mouseMoveEvent.type = SWT.MouseMove;
445
			mouseMoveEvent.type = SWT.MouseMove;
474
			mouseMoveEvent.x = 10;
446
			mouseMoveEvent.x = 10;
475
			mouseMoveEvent.y = widget.getDisplay().getClientArea().height / 2;
447
			mouseMoveEvent.y = widget.getDisplay().getClientArea().height / 2;
476
			widget.getDisplay().post(mouseMoveEvent);
448
			widget.getDisplay().post(mouseMoveEvent);
477
			
449
478
			Event mouseDownEvent = new Event();
450
			Event mouseDownEvent = new Event();
479
			mouseDownEvent.type = SWT.MouseDown;
451
			mouseDownEvent.type = SWT.MouseDown;
480
			mouseDownEvent.button = 1;
452
			mouseDownEvent.button = 1;
481
			widget.getDisplay().post(mouseDownEvent);	
453
			widget.getDisplay().post(mouseDownEvent);
482
		}
454
		}
483
455
484
		
485
		/* Run the events */
456
		/* Run the events */
486
		MacroUtil.processDisplayEvents(display);
457
		MacroUtil.processDisplayEvents(display);
487
		
458
488
		/* Now notify the listeners of the widget if they haven't already been notified */	
459
		/*
489
		if (!isWidgetNotified)
460
		 * Now notify the listeners of the widget if they haven't already been
461
		 * notified
462
		 */
463
		if (!isWidgetNotified) {
490
			widget.notifyListeners(e.type, e);
464
			widget.notifyListeners(e.type, e);
491
						
465
		}		
492
	}
466
	}
493
467
494
	private void doSelect(Display display, Widget widget) throws CoreException
468
	private void doSelect(Display display, Widget widget) throws CoreException {
495
	{
496
		checkEnableStatus(widget);
469
		checkEnableStatus(widget);
497
		boolean shouldClick = false;
470
		boolean shouldClick = false;
498
		if (widget instanceof Button)
471
		if (widget instanceof Button) {
499
		{
500
			((Button) widget).setSelection(selection.booleanValue());
472
			((Button) widget).setSelection(selection.booleanValue());
501
			shouldClick = true;
473
			shouldClick = true;
502
		}
474
		} else if (widget instanceof ToolItem) {
503
		else if (widget instanceof ToolItem)
504
		{
505
			((ToolItem) widget).setSelection(selection.booleanValue());
475
			((ToolItem) widget).setSelection(selection.booleanValue());
506
			shouldClick = true;						
476
			shouldClick = true;
507
		}
477
		} else if (widget instanceof MenuItem) {
508
		else if (widget instanceof MenuItem)
509
		{
510
			((MenuItem) widget).setSelection(selection.booleanValue());
478
			((MenuItem) widget).setSelection(selection.booleanValue());
511
			shouldClick = true;
479
			shouldClick = true;
512
		}
480
		}
513
		
481
514
		/* Ali M.: We need to also send out a selection event */
482
		/* Ali M.: We need to also send out a selection event */
515
		if (shouldClick)
483
		if (shouldClick)
516
			doClick(display, widget, selection.booleanValue());								
484
			doClick(display, widget, selection.booleanValue());
517
	}
485
	}
518
486
519
	
520
	/**
487
	/**
521
	 * Checks the enable status of the widget.  If in case the widget happens to be
488
	 * Checks the enable status of the widget. If in case the widget happens to
522
	 * disabled, then throw a core exception.
489
	 * be disabled, then throw a core exception.
523
	 * 
490
	 * 
524
	 * @param widget The widget whose status is being checked.
491
	 * @param widget
525
	 * @throws CoreException If widget is disabled
492
	 *            The widget whose status is being checked.
493
	 * @throws CoreException
494
	 *             If widget is disabled
526
	 */
495
	 */
527
	public void checkEnableStatus(Widget widget) throws CoreException
496
	public void checkEnableStatus(Widget widget) throws CoreException {
528
	{
529
		Button button = null;
497
		Button button = null;
530
		if (widget instanceof Button && !(button = ((Button)widget)).isEnabled())
498
		if (widget instanceof Button
531
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_DISABLE, button.getText()), getStartLine());
499
				&& !(button = ((Button) widget)).isEnabled())
500
			AutoGUIUtil.throwCoreException(NLS.bind(
501
					AutoGUIMessages.AUTO_GUI_ERROR_MACRO_DISABLE, button
502
							.getText()), getStartLine());
532
	}
503
	}
533
	
504
534
	
505
	public int getDetail() {
535
	public int getDetail()
536
	{
537
		return detail;
506
		return detail;
538
	}
507
	}
539
508
540
	public void setItemSelected(Event event)
509
	public void setItemSelected(Event event) {
541
	{
542
		if (!(event.widget instanceof MenuItem))
510
		if (!(event.widget instanceof MenuItem))
543
			return;
511
			return;
544
		
512
545
		itemSelectedId = MacroUtil.determineItemId((MenuItem)event.widget);
513
		// ANy: The formerly called determineItemId has moved into the
546
		
514
		// NonTrivialUIObjectResolverDelegate, which is the only contributor to
515
		// resolve/deresolve items,
516
		// so defect# 112668 is still handled properly here
517
		try {
518
			itemSelectedIdentifier = UIObjectResolver.resolve(new MacroObject(
519
					new UIObject(event.widget)).getContext(), new UIObject(
520
					(MenuItem) event.widget));
521
		} catch (Exception e) {
522
			e.printStackTrace();
523
		}
524
547
		/* Register the selected item with the object mine */
525
		/* Register the selected item with the object mine */
548
		MacroManager macroManager = MacroManager.getInstance();
526
		MacroManager macroManager = MacroManager.getInstance();
549
		if (macroManager.isObjectMineOn())
527
		if (macroManager.isObjectMineOn()) {
550
		{
528
			MacroObjectDescriptorMine objectMine = macroManager.getObjectMine();
551
			IObjectMine objectMine = macroManager.getObjectMine();
529
552
			IUIObject parent = objectMine.lookupUIObject(objectMine.getActiveObject(), getWidgetId().getReferenceId());
530
			MacroObjectDescriptor parent = objectMine
553
			IUIObject uiObject = objectMine.lookupUIObject(parent, null, itemSelectedId.toString());
531
					.lookupMacroObjectDescriptor(objectMine.getActiveObject(),
554
			if (uiObject == null)
532
							getCorrespondingMacroObjectDescriptor()
555
			{				
533
									.getReferenceId());
556
				uiObject = new UIObject(parent);
534
			MacroObjectDescriptor macroObjectDescriptor = objectMine
557
				uiObject.setObjectId(itemSelectedId.toString());
535
					.lookupMacroObjectDescriptor(parent, null,
558
				uiObject.setReferenceId(objectMine.getUniqueReferenceId());
536
							itemSelectedIdentifier.getWidgetId(), itemSelectedIdentifier.getObjectId());
559
				uiObject.setResolver(itemSelectedId.getResolverId());			
537
560
				uiObject.setDescriptive(getObjectClassName (event.widget));
538
			if (macroObjectDescriptor == null) {
561
				try
539
				macroObjectDescriptor = new MacroObjectDescriptor(parent);
562
				{
540
				((MacroObjectDescriptor) macroObjectDescriptor)
563
					uiObject = objectMine.registerObject(uiObject);
541
						.setWidgetId(itemSelectedIdentifier.getWidgetId());
564
				} 
542
				((MacroObjectDescriptor) macroObjectDescriptor)
565
				catch (Exception e)
543
				.setObjectId(itemSelectedIdentifier.getObjectId());				
566
				{
544
				((MacroObjectDescriptor) macroObjectDescriptor)
545
						.setResolver(itemSelectedIdentifier.getResolverId());
546
				((MacroObjectDescriptor) macroObjectDescriptor)
547
						.setDescriptive(getObjectClassName(event.widget));
548
				try {
549
					macroObjectDescriptor = objectMine
550
							.registerObject((MacroObjectDescriptor) macroObjectDescriptor);
551
				} catch (Exception e) {
567
					itemSelectedRefId = null;
552
					itemSelectedRefId = null;
568
				} 
553
				}
569
			}
554
			}
570
			
555
571
			if (uiObject != null)
556
			if (macroObjectDescriptor != null) {
572
			{
557
				itemSelectedRefId = macroObjectDescriptor.getReferenceId();
573
				itemSelectedRefId = uiObject.getReferenceId();
574
			}
558
			}
575
		}
559
		}
576
	}
560
	}
577
561
578
	public boolean isRepeatRedundant()
562
	public boolean isRepeatRedundant() {
579
	{
580
		return false;
563
		return false;
581
	}
564
	}
582
	
565
583
	
566
	public class DropDownMenuListener implements Listener {
584
	public class DropDownMenuListener implements Listener
567
585
	{
568
		public void handleEvent(Event event) {
586
569
			if (event.widget instanceof Menu) {
587
		public void handleEvent(Event event) 
570
				dropDownMenu = (Menu) event.widget;
588
		{
571
				synchronized (BooleanSelectionCommand.this) {
589
			if (event.widget instanceof Menu)
572
					BooleanSelectionCommand.this.notify();
590
			{				
573
				}
591
				dropDownMenu = (Menu)event.widget;				
592
				synchronized (BooleanSelectionCommand.this)
593
				{
594
					BooleanSelectionCommand.this.notify();	
595
				}				
596
			}
574
			}
597
		}
575
		}
598
		
576
599
	}
577
	}
578
579
	private static ArrayList getPath(MenuItem item) {
580
		ArrayList segments = new ArrayList();
581
		Object data = item.getData();
582
583
		if (data instanceof ContributionItem) {
584
			ContributionItem aitem = (ContributionItem) data;
585
			MenuManager manager = (MenuManager) aitem.getParent();
586
			while (manager != null) {
587
				String id = manager.getId();
588
				if (id == null)
589
					break;
590
				segments.add(0, id);
591
				manager = (MenuManager) manager.getParent();
592
			}
593
		}
594
		return segments.size() > 0 ? segments : null;
595
	}
596
600
}
597
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/StructuredSelectionCommand.java (-87 / +53 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2008 IBM Corporation and others.
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 10-16 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.commands;
11
package org.eclipse.tptp.test.auto.gui.internal.commands;
12
12
13
14
import java.util.ArrayList;
13
import java.util.ArrayList;
15
import java.util.Iterator;
14
import java.util.Iterator;
16
import java.util.Map;
15
import java.util.Map;
Lines 23-163 Link Here
23
import org.eclipse.swt.widgets.Tree;
22
import org.eclipse.swt.widgets.Tree;
24
import org.eclipse.swt.widgets.TreeItem;
23
import org.eclipse.swt.widgets.TreeItem;
25
import org.eclipse.swt.widgets.Widget;
24
import org.eclipse.swt.widgets.Widget;
26
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
25
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
27
import org.eclipse.tptp.test.auto.gui.internal.resolvers.PrimitiveWidgetId;
26
27
public class StructuredSelectionCommand extends AbstractStructuredCommand {
28
28
29
public class StructuredSelectionCommand extends AbstractStructuredCommand 
30
{
31
	private String type;
29
	private String type;
32
	public static final String DEFAULT_SELECT="default-select";
33
	public static final String ITEM_SELECT="item-select";
34
	
30
	
35
	public StructuredSelectionCommand(MacroCommandShell parent, WidgetIdentifier wid, String type) {
31
	public StructuredSelectionCommand(MacroCommandShell parent, String type) {
36
		super(parent, wid);
32
		super(parent);
37
		items = new ArrayList();
33
		items = new ArrayList();
38
		this.type = type;
34
		this.type = type;
39
	}
35
	}
40
36
41
	public boolean mergeEvent(Event e) 
37
	public boolean mergeEvent(Event e) throws Exception {
42
	{
43
		if (e.detail == SWT.CHECK)
38
		if (e.detail == SWT.CHECK)
44
			return false;
39
			return false;
45
		
40
46
		if (e.type==SWT.DefaultSelection) 
41
		if (e.type == SWT.DefaultSelection) {
47
		{
48
			this.type = DEFAULT_SELECT;
42
			this.type = DEFAULT_SELECT;
49
		}
43
		}
50
		
51
		// If the selected item number is 1, and the old and new item are the same, then merge.
52
		// Otherwise, do not merge, so that different command of selecting different items
53
		// can be generated.
54
		Object[] eventItems = getItemsForEvent(e);
55
		if (eventItems.length == 1)
56
		{
57
			ArrayList newItems = new ArrayList();
58
			Map attributeValuePairs = null;
59
			
60
			if (eventItems[0] instanceof Widget)
61
				attributeValuePairs = getItemAttributes((Widget)eventItems[0]);
62
			else
63
				attributeValuePairs = getItemAttributes(null, new PrimitiveWidgetId((String)eventItems[0]));
64
			
65
			if (attributeValuePairs != null)
66
				newItems.add(attributeValuePairs);
67
			
68
			if (!isSameList(items, newItems))
69
				return false;
70
		}
71
		
72
		return super.mergeEvent(e);
44
		return super.mergeEvent(e);
73
	}
45
	}
74
	
46
75
	public String getType() {
47
	public String getType() {
76
		return type;
48
		return type;
77
	}
49
	}
78
50
79
	protected Object[] getItemsForEvent(Event event) 
51
	public Object[] getItemsForEvent(Event event) {
80
	{
52
		if (event.widget instanceof Tree) {
81
		if (event.widget instanceof Tree) 
53
			return ((Tree) event.widget).getSelection();
82
		{
83
			return ((Tree)event.widget).getSelection();
84
		}
54
		}
85
		else if (event.widget instanceof Table) 
55
		else if (event.widget instanceof Table) {
86
		{
56
			return ((Table) event.widget).getSelection();
87
			return ((Table)event.widget).getSelection();
88
		}
57
		}
89
		else if (event.widget instanceof List)
58
		else if (event.widget instanceof List) {
90
		{
59
			return ((List) event.widget).getSelection();
91
			return ((List)event.widget).getSelection();
92
		}
60
		}
93
		return super.getItemsForEvent(event);
61
		return super.getItemsForEvent(event);
94
	}
62
	}
95
63
96
	protected void playStructuredCommand(Widget widget, Object[] matches) 
64
	protected void playStructuredCommand(Widget widget, Object[] matches) {
97
	{
65
98
		
99
		if (widget instanceof Tree)
66
		if (widget instanceof Tree)
100
			((Tree)widget).setSelection((TreeItem[])matches);
67
			((Tree) widget).setSelection((TreeItem[]) matches);
101
		else if (widget instanceof Table)
68
		else if (widget instanceof Table)
102
			((Table)widget).setSelection((TableItem[])matches);
69
			((Table) widget).setSelection((TableItem[]) matches);
103
		else if (widget instanceof List)
70
		else if (widget instanceof List)
104
			((List)widget).setSelection((String[])matches);
71
			((List) widget).setSelection((String[]) matches);
105
		
72
106
		fireEvent(widget, matches);
73
		fireEvent(widget,
74
			matches);
107
	}
75
	}
108
	
76
109
	private void fireEvent(Widget widget, Object[] items)
77
	private void fireEvent(Widget widget, Object[] items) {
110
	{
111
		Event e = new Event();
78
		Event e = new Event();
112
		e.widget = widget;
79
		e.widget = widget;
113
		e.type = type.equals(ITEM_SELECT)?SWT.Selection:SWT.DefaultSelection;
80
		e.type = type.equals(ITEM_SELECT)
114
		e.item = (items.length>0 && items instanceof Widget[] ? (Widget)items[0] : null);		
81
			? SWT.Selection
115
		widget.notifyListeners(e.type, e);
82
			: SWT.DefaultSelection;
83
		e.item = (items.length > 0 && items instanceof Widget[]
84
			? (Widget) items[0]
85
			: null);
86
		widget.notifyListeners(e.type,
87
			e);
116
	}
88
	}
117
	
89
118
	/**
90
	/**
119
	 * Overwrite this method in order to indicate that two item selection commands that have
91
	 * Overwrite this method in order to indicate that two item selection commands that have different items are not the same
120
	 * different items are not the same
121
	 */
92
	 */
122
	public boolean equals (Object obj)
93
	public boolean equals(Object obj) {
123
	{
124
		if (!(obj instanceof ChoiceSelectionCommand) || !super.equals(obj))
94
		if (!(obj instanceof ChoiceSelectionCommand) || !super.equals(obj))
125
			return false;
95
			return false;
126
		
96
127
		StructuredSelectionCommand compareWithObj = (StructuredSelectionCommand)obj;
97
		StructuredSelectionCommand compareWithObj = (StructuredSelectionCommand) obj;
128
		if (compareWithObj.items.size() == this.items.size() && isSameList(compareWithObj.items, this.items))
98
		if (compareWithObj.items.size() == this.items.size() && isSameList(compareWithObj.items,
99
			this.items))
129
			return true;
100
			return true;
130
		
101
131
		return false;
102
		return false;
132
	}
103
	}
133
104
134
	private boolean isSameList(ArrayList listA, ArrayList listB) 
105
	private boolean isSameList(ArrayList listA, ArrayList listB) {
135
	{
136
		if (listA.size() != listB.size())
106
		if (listA.size() != listB.size())
137
			return false;
107
			return false;
138
		
108
139
		for (int i = 0, listSize = listA.size(); i < listSize; i++)
109
		for (int i = 0, listSize = listA.size(); i < listSize; i++) {
140
		{
110
			Map itemDataA = (Map) listA.get(i);
141
			Map itemDataA = (Map)listA.get(i);
111
			Map itemDataB = (Map) listB.get(i);
142
			Map itemDataB = (Map)listB.get(i);
112
143
			
144
			
145
			if (itemDataA.size() != itemDataB.size())
113
			if (itemDataA.size() != itemDataB.size())
146
				return false;
114
				return false;
147
			
115
148
			for(Iterator keys = itemDataA.keySet().iterator(); keys.hasNext();)
116
			for (Iterator keys = itemDataA.keySet().iterator(); keys.hasNext();) {
149
			{
150
				Object currentKey = keys.next();
117
				Object currentKey = keys.next();
151
				if (!itemDataA.get(currentKey).equals(itemDataB.get(currentKey)))
118
				if (!itemDataA.get(currentKey).equals(itemDataB.get(currentKey)))
152
					return false;
119
					return false;
153
			}
120
			}
154
		}
121
		}
155
		
122
156
		return true;
123
		return true;
157
	}
124
	}
158
125
159
	protected void playStructuredCommandForFoundMatch(Widget widget, Object match) 
126
	protected void playStructuredCommandForFoundMatch(Widget widget, Object match) {
160
	{
161
		/* Doesn't need to be implemented */
127
		/* Doesn't need to be implemented */
162
	}
128
	}
163
}
129
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/AbstractMacroCommand.java (-165 / +172 lines)
Lines 14-182 Link Here
14
import java.util.Hashtable;
14
import java.util.Hashtable;
15
15
16
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.core.runtime.Path;
18
import org.eclipse.hyades.test.common.util.XMLUtil;
17
import org.eclipse.hyades.test.common.util.XMLUtil;
18
import org.eclipse.jface.window.Window;
19
import org.eclipse.swt.widgets.Control;
20
import org.eclipse.swt.widgets.Display;
19
import org.eclipse.swt.widgets.Event;
21
import org.eclipse.swt.widgets.Event;
20
import org.eclipse.swt.widgets.Widget;
22
import org.eclipse.swt.widgets.Widget;
21
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
22
import org.eclipse.tptp.test.auto.gui.internal.macro.AbstractMacroInstruction;
23
import org.eclipse.tptp.test.auto.gui.internal.macro.AbstractMacroInstruction;
24
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
23
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
25
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
24
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
25
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
26
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
27
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObject;
28
import org.eclipse.ui.IEditorPart;
29
import org.eclipse.ui.IViewPart;
30
import org.eclipse.ui.IWorkbenchPage;
26
import org.w3c.dom.Node;
31
import org.w3c.dom.Node;
27
32
28
/**
33
/**
29
 * An abstract implementation of {@link IMacroCommand}.  Contributors can subclass this 
34
 * An abstract implementation of {@link IMacroCommand}. Contributors can subclass this class or provide a direct implementation of
30
 * class or provide a direct implementation of {@link IMacroCommand}.
35
 * {@link IMacroCommand}.
31
 * 
36
 * 
32
 * @author Ali Mehregani
37
 * @author Ali Mehregani
38
 * @author Alexander Nyssen
33
 */
39
 */
34
public abstract class AbstractMacroCommand extends AbstractMacroInstruction implements IMacroCommand
40
public abstract class AbstractMacroCommand extends AbstractMacroInstruction implements IMacroCommand {
35
{
41
36
	/** The bound for the value of descriptive fields */
37
	protected static final int DESCRIPTIVE_FIELD_BOUND = 50;
38
	
39
	/** The parent command shell */
42
	/** The parent command shell */
40
	private MacroCommandShell parent;
43
	private MacroCommandShell parent;
41
	
44
42
	/** The descriptive field of this command */
45
	/** The descriptive field of this command */
43
	private String descriptiveField;	
46
	private String descriptiveField;
44
47
45
	/** Time difference between this command and the previous command (applicable when artificial wait time is enabled) */
48
	/** Time difference between this command and the previous command (applicable when artificial wait time is enabled) */
46
	private long timeDifference;	
49
	private long timeDifference;
47
	
50
48
	
49
	/**
51
	/**
50
	 * Constructor
52
	 * Constructor
51
	 * 
53
	 * 
52
	 * @param parent The parent command shell
54
	 * @param parent
53
	 * @param widgetId The associated widget id
55
	 *            The parent command shell
56
	 * @param widgetId
57
	 *            The associated widget id
54
	 */
58
	 */
55
	public AbstractMacroCommand(MacroCommandShell parent, WidgetIdentifier widgetId)
59
	public AbstractMacroCommand(MacroCommandShell parent) {
56
	{
57
		setWidgetId(widgetId);
58
		this.parent = parent;
60
		this.parent = parent;
59
	}
61
	}
60
62
	
61
63
	public boolean mergeEvent(Event e) throws Exception {
62
	public void load(Node node, Hashtable lineTable) throws CoreException
63
	{
64
		super.load(node, lineTable);
65
		String cid = MacroUtil.getAttribute(node, MacroConstants.CONTEXT_ID_ATTRIBUTE);
66
		String wid = MacroUtil.getAttribute(node, MacroConstants.WIDGET_ID_ATTRIBUTE);		
67
		String rid = MacroUtil.getAttribute(node, MacroConstants.RESOLVER_ATTRIBUTE);		
68
		
69
		if (cid != null && wid != null)
70
		{
71
			setWidgetId(new WidgetIdentifier(
72
					cid == null ? new Path(MacroConstants.EMPTY_STRING) : new Path(cid), 
73
					wid == null ? new Path(MacroConstants.EMPTY_STRING) : new Path(wid),
74
					rid));			
75
		}
76
	}
77
78
79
	public boolean mergeEvent(Event e)
80
	{
81
		return false;
64
		return false;
82
	}
65
	}
66
83
	
67
	
84
	
68
85
	/**
69
	/**
86
	 * Returns the descriptive field of this command.
70
	 * Returns the descriptive field of this command.
87
	 * 
71
	 * 
88
	 * @return The descriptive field of this command.
72
	 * @return The descriptive field of this command.
89
	 */
73
	 */
90
	public String getDescriptiveField()
74
	public String getDescriptiveField() {
91
	{
92
		return descriptiveField;
75
		return descriptiveField;
93
	}
76
	}
94
	
77
95
	
96
	/**
78
	/**
97
	 * Set the descriptive field of this command.  The descriptive field is used
79
	 * Set the descriptive field of this command. The descriptive field is used to more easily identify the semantics of a command.
98
	 * to more easily identify the semantics of a command. 
80
	 * 
99
	 *  
81
	 * @param descriptiveField
100
	 * @param descriptiveField The descriptive field (can be a button's text, a tree
82
	 *            The descriptive field (can be a button's text, a tree item label, or etc...)
101
	 * item label, or etc...)
83
	 */
102
	 */
84
	public void setDescriptiveField(String descriptiveField) {
103
	public void setDescriptiveField(String descriptiveField)
85
		this.descriptiveField = XMLUtil.useXMLSymbols(MacroUtil.normalizeDescriptiveField(MacroUtil.boundSize(descriptiveField,
104
	{
86
			DESCRIPTIVE_FIELD_BOUND)));
105
		this.descriptiveField = XMLUtil.useXMLSymbols(MacroUtil.normalizeDescriptiveField(MacroUtil.boundSize(descriptiveField, DESCRIPTIVE_FIELD_BOUND)));
106
	}
87
	}
107
88
108
	
109
	/**
89
	/**
110
	 * Initializes the descriptive field of this command based on the
90
	 * Initializes the descriptive field of this command based on the value returned by the getText() method of the widget (if it has one)
111
	 * value returned by the getText() method of the widget (if it has one)
112
	 * 
91
	 * 
113
	 * @param widget The widget
92
	 * @param widget
93
	 *            The widget
114
	 */
94
	 */
115
	protected void findDescriptiveField(Widget widget)
95
	protected void findDescriptiveField(Widget widget) {
116
	{
96
		setDescriptiveField(getText(widget));
117
		setDescriptiveField(getText(widget));	
118
	}
97
	}
119
	
98
120
	
121
	/**
99
	/**
122
	 * Similar to initializeDescriptiveField(Widget), but the descriptive field
100
	 * Similar to initializeDescriptiveField(Widget), but the descriptive field is a comma-separated string of all the descriptive fields that
123
	 * is a comma-separated string of all the descriptive fields that corresponds
101
	 * corresponds to the objects passed in.
124
	 * to the objects passed in.
125
	 * 
102
	 * 
126
	 * @param objects The objects
103
	 * @param objects
104
	 *            The objects
127
	 */
105
	 */
128
	protected void findDescriptiveField(Object[] objects) 
106
	protected void findDescriptiveField(Object[] objects) {
129
	{
130
		String descriptive = "";
107
		String descriptive = "";
131
		for (int i = 0; i < objects.length; i++) 
108
		for (int i = 0; i < objects.length; i++) {
132
		{
133
			if (descriptive.length() > 0)
109
			if (descriptive.length() > 0)
134
				descriptive += ", ";
110
				descriptive += ", ";
135
			String textValue = getText(objects[i]);
111
			String textValue = getText(objects[i]);
136
			if (textValue != null && textValue.length() > 0)
112
			if (textValue != null && textValue.length() > 0)
137
				descriptive += textValue; 			
113
				descriptive += textValue;
138
		}
114
		}
139
		
115
140
		if (descriptive.length() > 0)
116
		if (descriptive.length() > 0)
141
			setDescriptiveField(descriptive);
117
			setDescriptiveField(descriptive);
142
	}
118
	}
143
	
119
144
	
120
	protected String getText(Object obj) {
145
	protected String getText(Object obj)
146
	{
147
		if (obj == null)
121
		if (obj == null)
148
			return null;
122
			return null;
149
		
123
150
		try 
124
		try {
151
		{
125
			Method getText = obj.getClass().getMethod("getText",
152
			Method getText = obj.getClass().getMethod("getText", null);
126
				null);
153
			String textValue = (String)getText.invoke(obj, null);
127
			String textValue = (String) getText.invoke(obj,
128
				null);
154
			if (textValue != null && textValue.length() > 0)
129
			if (textValue != null && textValue.length() > 0)
155
				return textValue;				
130
				return textValue;
156
		} 
131
		}
157
		catch (Exception e)
132
		catch (Exception e) {
158
		{
159
			/* Doesn't need to be handled */
133
			/* Doesn't need to be handled */
160
		}
134
		}
161
		
135
162
		return null;
136
		return null;
163
	}
137
	}
164
138
165
139
	public String toString() {
166
	public String toString()
167
	{
168
		return "MacroCommand [" + getType() + ", line " + getStartLine() + "]";
140
		return "MacroCommand [" + getType() + ", line " + getStartLine() + "]";
169
	}
141
	}
170
	
142
171
	public boolean equals (Object obj)
143
	public boolean equals(Object obj) {
172
	{
173
		if (!(obj instanceof IMacroCommand))
144
		if (!(obj instanceof IMacroCommand))
174
			return false;
145
			return false;
175
		
146
176
		IMacroCommand compareWithObj = (IMacroCommand)obj;
147
		IMacroCommand compareWithObj = (IMacroCommand) obj;
177
		if (compareWithObj.getType() == this.getType() && compareWithObj.getWidgetId() != null && compareWithObj.getWidgetId().equals(getWidgetId()))
148
		if (compareWithObj.getType() == this.getType())
178
			return true;
149
			return true;
179
		
150
180
		return false;
151
		return false;
181
	}
152
	}
182
153
Lines 187-291 Link Here
187
	public void setParent(MacroCommandShell parent) {
158
	public void setParent(MacroCommandShell parent) {
188
		this.parent = parent;
159
		this.parent = parent;
189
	}
160
	}
190
	
161
191
	/**
162
	/**
192
	 * Should return false if executing this command just after it 
163
	 * Should return false if executing this command just after it has already been executed will have a different output. (e.g. If two focus commands
193
	 * has already been executed will have a different output.  
164
	 * that are identical are redundant but two button selections are not)
194
	 * (e.g. If two focus commands that are identical are redundant but 
165
	 */
195
	 * two button selections are not)
166
	public boolean isRepeatRedundant() {
196
	 */ 
197
	public boolean isRepeatRedundant()
198
	{
199
		return true;
167
		return true;
200
	}
168
	}
201
	
169
202
	/**
170
	/**
203
	 * This is our chance to write any artificial wait commands if the 
171
	 * This is our chance to write any artificial wait commands if the option is enabled.
204
	 * option is enabled.
205
	 * 
172
	 * 
206
	 * @param indent The current indent that the command should be at
173
	 * @param indent
207
	 * @param writer The writer used to write the macro
174
	 *            The current indent that the command should be at
175
	 * @param writer
176
	 *            The writer used to write the macro
208
	 */
177
	 */
209
	public void writeStart(int indent, StringBuffer writer)
178
	public void writeStart(int indent, StringBuffer writer) {
210
	{
211
		if (timeDifference <= 0)
179
		if (timeDifference <= 0)
212
			return;
180
			return;
213
		
181
214
		WaitCommand waitCommand = new WaitCommand(parent);
182
		WaitCommand waitCommand = new WaitCommand(parent);
215
		waitCommand.setWaitTime(timeDifference);			
183
		waitCommand.setWaitTime(timeDifference);
216
		waitCommand.write(indent, writer);
184
		waitCommand.write(indent,
185
			writer);
217
	}
186
	}
218
219
	
187
	
220
	/**
188
	/**
189
	 * {@inheritDoc}
190
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.AbstractMacroInstruction#load(org.w3c.dom.Node, java.util.Hashtable)
191
	 */
192
	public void load(Node node, Hashtable lineTable) throws CoreException {
193
		super.load(node,
194
			lineTable);
195
		// load the descriptive field
196
		descriptiveField = MacroUtil.getAttribute(node, MacroConstants.DESCRIPTIVE_ATTRIBUTE);
197
		
198
	}
199
200
	/**
221
	 * Equivalent to write(indent, writer, false, false)
201
	 * Equivalent to write(indent, writer, false, false)
222
	 */
202
	 */
223
	public void write(int indent, StringBuffer sb)
203
	public void write(int indent, StringBuffer sb) {
224
	{
204
		write(indent,
225
		write(indent, sb, false, false);
205
			sb,
206
			false,
207
			false);
226
	}
208
	}
227
	
209
228
	
229
	/**
210
	/**
230
	 * Writes the common fiels of this command
211
	 * Writes the common fiels of this command
231
	 * 
212
	 * 
232
	 * @param indent The current indent that the command should be at
213
	 * @param indent
233
	 * @param writer The writer used to write the macro
214
	 *            The current indent that the command should be at
234
	 * @param close A flag that indicates whether the command fragment should be closed (i.e.adding "/" to the end). 
215
	 * @param writer
235
	 * @param end A flag that indicates whether the command fragment should end (i.e.adding "/" to the end).
216
	 *            The writer used to write the macro
236
	 */
217
	 * @param close
237
	public void write(int indent, StringBuffer sb, boolean close, boolean end)
218
	 *            A flag that indicates whether the command fragment should be closed (i.e.adding "/" to the end).
238
	{
219
	 * @param end
239
		MacroUtil.addElement(sb, indent, MacroConstants.COMMAND_ELEMENT, false, false);		
220
	 *            A flag that indicates whether the command fragment should end (i.e.adding "/" to the end).
240
		boolean noWidgetId = getWidgetId() == null;
221
	 */
241
		boolean objectMineInUse = MacroManager.getInstance().isObjectMineOn() && getWidgetId().getReferenceId() != null;
222
	public void write(int indent, StringBuffer sb, boolean close, boolean end) {
242
		MacroUtil.addAttribute(sb, 
223
		MacroUtil.addElement(sb,
243
			new String[] {			
224
			indent,
244
				MacroConstants.DESCRIPTIVE_ATTRIBUTE,
225
			MacroConstants.COMMAND_ELEMENT,
245
				MacroConstants.TYPE_ATTRIBUTE, 
226
			false,
246
				MacroConstants.RESOLVER_ATTRIBUTE, 
227
			false);
247
				MacroConstants.CONTEXT_ID_ATTRIBUTE,
228
		MacroUtil.addAttribute(sb,
248
				MacroConstants.WIDGET_ID_ATTRIBUTE,
249
				MacroConstants.REFERENCE_ID_ATTRIBUTE}, 
250
			new String[] {
229
			new String[] {
251
				getDescriptiveField(),
230
				MacroConstants.DESCRIPTIVE_ATTRIBUTE,
252
				getType(),
231
				MacroConstants.TYPE_ATTRIBUTE},
253
				objectMineInUse || noWidgetId ? null : getWidgetId().getResolverId(),
232
			new String[] {getDescriptiveField(), getType()},
254
				objectMineInUse || noWidgetId ? null : getWidgetId().getContextId().toString(),
233
			close,
255
				objectMineInUse || noWidgetId ? null : getWidgetId().getObjectId().toString(),
234
			end);
256
				objectMineInUse && !noWidgetId ? getWidgetId().getReferenceId() : null
257
		}, close, end);
258
		
259
	}
235
	}
260
	
236
261
	
237
	public void writeFinish(int indent, StringBuffer writer) {
262
	public void writeFinish(int indent, StringBuffer writer)
238
263
	{
264
		
265
	}
239
	}
266
240
267
	public long getTimeDifference() 
241
	public long getTimeDifference() {
268
	{
269
		return timeDifference;
242
		return timeDifference;
270
	}
243
	}
271
244
272
	public void setTimeDifference(long timeDifference) 
245
	public void setTimeDifference(long timeDifference) {
273
	{
274
		this.timeDifference = timeDifference;
246
		this.timeDifference = timeDifference;
275
	}
247
	}
276
248
277
	
278
	
279
	/**
249
	/**
280
	 * Returns the class name of the object passed in (excluding the package name)
250
	 * Added by ANy
281
	 * This is useful for adding a descriptive field to the command
251
	 * 
252
	 * @param macroObject
253
	 */
254
	protected void setFocus(IMacroObject macroObject) {
255
		ensureVisible(macroObject);
256
		Widget widget = macroObject.getUIObject().getWidget();
257
		Display display = widget.getDisplay();
258
		if (widget instanceof Control) {
259
			Control c = (Control) widget;
260
			if (!c.equals(display.getFocusControl()))
261
				c.setFocus();
262
		}		
263
	}
264
265
	/*
266
	 * Added by ANy
267
	 */
268
	private void ensureVisible(IMacroObject macroObject) {
269
		if (macroObject.getContext() instanceof Window) {
270
			Window window = (Window) macroObject.getContext();
271
			window.getShell().setActive();
272
		}
273
		else if (macroObject.getContext() instanceof IEditorPart) {
274
			IEditorPart editor = (IEditorPart) macroObject.getContext();
275
			IWorkbenchPage page = editor.getEditorSite().getPage();
276
			page.activate(editor);
277
		}
278
		else if (macroObject.getContext() instanceof IViewPart) {
279
			IViewPart view = (IViewPart) macroObject.getContext();
280
			IWorkbenchPage page = view.getViewSite().getPage();
281
			page.activate(view);
282
		}
283
	}
284
285
	/**
286
	 * Returns the class name of the object passed in (excluding the package name) This is useful for adding a descriptive field to the command
282
	 * 
287
	 * 
283
	 * @param object The object
288
	 * @param object
289
	 *            The object
284
	 * @return The object class name
290
	 * @return The object class name
285
	 */
291
	 */
286
	protected String getObjectClassName (Object object)
292
	public String getObjectClassName(Object object) {
287
	{
293
		String className = object == null
288
		String className = object == null ? "" : object.getClass().getName();
294
			? ""
295
			: object.getClass().getName();
289
		int lastDotInx = className.lastIndexOf('.');
296
		int lastDotInx = className.lastIndexOf('.');
290
		if (lastDotInx != -1 && lastDotInx + 1 < className.length())
297
		if (lastDotInx != -1 && lastDotInx + 1 < className.length())
291
			return className.substring(lastDotInx + 1);
298
			return className.substring(lastDotInx + 1);
(-)src/org/eclipse/tptp/test/auto/gui/internal/resolvers/NonTrivialWidgetResolver.java (-538 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * $Id: NonTrivialWidgetResolver.java,v 1.7 2008/04/18 13:45:30 dmorris Exp $
8
 * 
9
 * Contributors:
10
 *     IBM Corporation - initial API and implementation
11
 *******************************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.resolvers;
13
14
import org.eclipse.hyades.models.hierarchy.TRCAgentProxy;
15
import org.eclipse.swt.custom.CTabItem;
16
import org.eclipse.swt.graphics.Point;
17
import org.eclipse.swt.widgets.Button;
18
import org.eclipse.swt.widgets.Composite;
19
import org.eclipse.swt.widgets.Control;
20
import org.eclipse.swt.widgets.Group;
21
import org.eclipse.swt.widgets.Item;
22
import org.eclipse.swt.widgets.Label;
23
import org.eclipse.swt.widgets.Menu;
24
import org.eclipse.swt.widgets.MenuItem;
25
import org.eclipse.swt.widgets.TabItem;
26
import org.eclipse.swt.widgets.Text;
27
import org.eclipse.swt.widgets.ToolBar;
28
import org.eclipse.swt.widgets.ToolItem;
29
import org.eclipse.swt.widgets.Tree;
30
import org.eclipse.swt.widgets.TreeItem;
31
import org.eclipse.swt.widgets.Widget;
32
import org.eclipse.tptp.test.auto.gui.internal.core.IWidgetId;
33
import org.eclipse.tptp.test.auto.gui.internal.core.IWidgetResolver;
34
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
35
import org.eclipse.tptp.trace.ui.internal.launcher.core.AnalysisType;
36
import org.eclipse.tptp.trace.ui.internal.launcher.core.DataCollectorTreeContentProvider.ParentChildNode;
37
import org.eclipse.ui.dialogs.FileSystemElement;
38
import org.eclipse.ui.model.IWorkbenchAdapter;
39
import org.eclipse.ui.views.IViewCategory;
40
41
/**
42
 * <p>
43
 * The purpose of this class is to resolve widgets that cannot be resolved using the 
44
 * AdaptiveWidgetResolver.  These widgets will likely require nested calls in order to
45
 * be determined.
46
 * </p>
47
 * <p>
48
 * Some of the properties used to resolve a widget are locale dependent (e.g. the name
49
 * of a button or the closest label to a text box)
50
 * </p>
51
 * 
52
 * @since 4.1
53
 * @author Ali Mehregani
54
 */
55
public class NonTrivialWidgetResolver implements IWidgetResolver
56
{
57
	/** 
58
	 * The id of this resolver -- must be in sync with the id registered with 
59
	 * the widgetResolver extension.
60
	 */
61
	private static final String ID = "org.eclipse.tptp.test.auto.gui.nontrivial";
62
63
	public IWidgetId getUniqueId(Widget parent, Object object)
64
	{
65
		if (!(object instanceof Widget))
66
			return null;
67
		
68
		Widget widget = (Widget) object;
69
		Object data = widget.getData();
70
		
71
		IWidgetId widgetId = null;
72
		
73
			
74
		/* Resolve the object based on the data type of the widget */
75
		/* An agent */
76
		if (data instanceof TRCAgentProxy)
77
		{
78
			widgetId = resolveAgentProxy (widget);
79
		}
80
		/* A file system element */
81
		else if (data instanceof FileSystemElement)
82
		{
83
			widgetId = resolveFileSystemElement (widget);
84
		}
85
		/* A view catgory */
86
		else if (data instanceof IViewCategory)
87
		{
88
			String id = ((IViewCategory)data).getId();
89
			if (id != null && id.length() > 0)
90
			{
91
				widgetId = new PrimitiveWidgetId();
92
				((PrimitiveWidgetId)widgetId).setId(id);
93
			}
94
		}
95
		/* Analysis type */
96
		else if (data instanceof ParentChildNode)
97
		{
98
			Object child = ((ParentChildNode)data).child;
99
			if (child instanceof AnalysisType)
100
			{
101
				widgetId = resolveAnalysisType((AnalysisType)child); 
102
			}
103
		}
104
105
		/* Resolve the object based on its widget type */
106
		/* A menu item or a tree item*/
107
		else if (widget instanceof MenuItem || widget instanceof TreeItem)
108
		{
109
			widgetId = resolveItem ((Item)widget);
110
		}
111
		/* A button */
112
		else if (widget instanceof Button)
113
		{
114
			widgetId = resolveButton (parent, (Button)widget, null);
115
		}
116
		/* A text box */
117
		else if (widget instanceof Text)
118
		{
119
			widgetId = resolveText ((Text)widget);
120
		}
121
		/* A CTab item */
122
		else if (widget instanceof CTabItem)
123
		{
124
			widgetId = validateText(((CTabItem)widget).getText());
125
		}		
126
		/* A tab item */
127
		else if (widget instanceof TabItem)
128
		{
129
			widgetId = validateText(((TabItem)widget).getText());
130
		}
131
		/* A toolbar */
132
		else if (widget instanceof ToolBar)
133
		{
134
			widgetId = resolveToolBar ((ToolBar)widget);
135
		}
136
		/* A tool item */
137
		else if (widget instanceof ToolItem)
138
		{
139
			widgetId = resolveToolbarItem ((ToolItem)widget);			
140
		}		
141
		
142
143
		if (widgetId != null)
144
		{
145
			widgetId.setResolverId(ID);
146
		}
147
		
148
		return widgetId;
149
	}
150
151
152
153
	private IWidgetId resolveAnalysisType(AnalysisType analysisType)
154
	{
155
		Object[] properties = 
156
		{
157
			new Object[] {analysisType.getId(), "1.0"},
158
		};
159
	
160
		return WeightedPropertyWidgetId.constructId (properties, (float)1.0);
161
	}
162
163
164
165
	private IWidgetId resolveToolBar(ToolBar toolbar)
166
	{
167
		int itemCount = toolbar.getItemCount();
168
		String 	firstItem = itemCount > 1 ? limitText(toolbar.getItem(0).getToolTipText()) : null, 
169
				lastItem = itemCount > 2 ? limitText(toolbar.getItem(itemCount - 1).getToolTipText()) : null;
170
		int style = toolbar.getStyle();
171
		
172
		if (firstItem == null && lastItem == null)
173
			return null;
174
		
175
		Object[] properties = 
176
		{
177
			new Object[] {convertText(firstItem), "0.5"},
178
			new Object[] {convertText(lastItem), "0.5"},
179
			new Object[] {String.valueOf(itemCount), "0.3"},
180
			new Object[] {String.valueOf(style), "0.2"}
181
		};
182
	
183
		return WeightedPropertyWidgetId.constructId (properties, (float)1.0);
184
	}
185
186
187
188
	private IWidgetId resolveToolbarItem(ToolItem item)
189
	{
190
		String text = convertText(limitText(item.getToolTipText()));
191
		String actionId = MacroUtil.getActionId(item).toString();
192
		String style = String.valueOf(item.getStyle());
193
		
194
		Object[] properties = 
195
		{
196
			new Object[] {text, "0.7"},
197
			new Object[] {actionId, "0.7"},
198
			new Object[] {style, "0.3"}
199
		};
200
	
201
		return WeightedPropertyWidgetId.constructId (properties, (float)1.0);
202
	}
203
204
205
206
	private String limitText(String str)
207
	{
208
		final int MAX_HOVER_TEXT_SIZE = 20;
209
		if (str != null && str.length() > MAX_HOVER_TEXT_SIZE)
210
		{	
211
			return str.substring(0,MAX_HOVER_TEXT_SIZE) + "...";			
212
		}
213
		return str;
214
	}
215
216
217
218
	private IWidgetId resolveButton(Widget parent, Button button, Object id)
219
	{	
220
		String text = null, hoverText = null, size = null, location = null;
221
		if ((text = button.getText()) != null)
222
		{
223
			text = convertText(text.replaceAll("\\&", ""));
224
		}
225
		/* First 20 characters of the hover text */
226
		hoverText = convertText(limitText(button.getToolTipText()));
227
		Point sizePt = button.getSize();
228
		Point locationPt = button.getLocation();
229
		size = "(" + sizePt.x + "," + sizePt.y + ")";		
230
		location = "("  + locationPt.x + "," + locationPt.y + ")";		
231
		
232
		if (id != null && WeightedPropertyWidgetId.countTokens(id.toString())  == 3)
233
		{
234
			
235
			Object[] properties = 
236
				{
237
					new Object[] {text, "0.5"},
238
					new Object[] {hoverText, "0.5"},
239
					new Object[] {size, "0.5"}
240
				};
241
			
242
			return WeightedPropertyWidgetId.constructId (properties, (float)1.0);
243
		}
244
		else
245
		{			
246
			if (parent instanceof Composite)
247
			{
248
				Control[] children = ((Composite)parent).getChildren();
249
				int buttonInx = 0;
250
				// if there are multiple buttons with the same text label
251
				int sameTextButtons = 0;
252
				String indexWeight = "0.2";
253
				String lengthWeight = "0.3";
254
				
255
				/* Find the index of the button */
256
				for (int i = 0; i < children.length; i++)
257
				{
258
					if (text != null && children[i] instanceof Button){
259
						String label = ((Button)children[i]).getText();
260
						if (label != null){
261
							label = convertText(label.replaceAll("\\&", ""));
262
							if (label.compareTo(text)  == 0)
263
								sameTextButtons++;
264
						}
265
					}
266
					if (button == children[i])
267
					{
268
						buttonInx = i;
269
						break;
270
					}
271
				}
272
				if (sameTextButtons > 0){
273
					// two or more buttons with the same label in the 
274
					// same child list under a composite parent
275
					// so shift the weighting to favor the button index
276
					// to get the right weighting
277
					indexWeight = "0.4";
278
					lengthWeight = "0.1";
279
				}
280
				
281
				Object[] properties = 
282
				{
283
						new Object[] {text, "0.3"},
284
						new Object[] {hoverText, "0.3"},
285
						new Object[] {String.valueOf(children.length), lengthWeight},
286
						new Object[] {size, "0.1"},
287
						new Object[] {location, "0.1"},
288
						new Object[] {String.valueOf(buttonInx), indexWeight},
289
				
290
				};
291
				
292
				float threshold = 0.7f;
293
				threshold += text != null ? 0.3 : 0;
294
				threshold += hoverText != null ? 0.3 : 0;
295
				
296
				if (threshold >= 1.0)
297
					return WeightedPropertyWidgetId.constructId (properties, (float)1.0);
298
			}
299
		}
300
		
301
		return null;
302
	}
303
304
305
	/**
306
	 * Replace "#", "\n" and "\r" with space to avoid having "#" generated in the
307
	 * object id. The "#" is taken as the separator between widget Class name and
308
	 * rest of object id (see MacroObjectLocator.locateVisibleChild).
309
	 * 
310
	 * @param label
311
	 * @return
312
	 */
313
	private String convertText(String label) {
314
		return label == null ? null : label.replaceAll("#", " ").replaceAll("\n", " ").replaceAll("\r", " ");
315
	}
316
317
318
	/**
319
	 * The text of the closest label to a text box is used as a unique
320
	 * identifier of the text box.  The label must be in a limited
321
	 * vicinity of the text box for its text to be considered as an identifier.
322
	 * If the text box is owned by a group and the group only owns one text box, 
323
	 * then the group text is used to identify the widget.
324
	 * 
325
	 * @param text The text box
326
	 * @return The widget id for text
327
	 */
328
	private IWidgetId resolveText(Text text)
329
	{
330
		Composite parent = text.getParent();
331
		Control[] children = parent.getChildren();
332
		
333
		String groupText = null;
334
		if (parent instanceof Group && (groupText = ((Group)parent).getText()) != null && (groupText = groupText.replaceAll("\\&", "")).length() > 0)
335
		{
336
			int textBoxNum = 0;
337
			for (int i = 0; i < children.length && textBoxNum <= 1; i++)
338
			{
339
				if (children[i] instanceof Text)
340
					textBoxNum++;
341
			}
342
			
343
			if (textBoxNum <= 1)
344
				return new PrimitiveWidgetId(convertText(groupText));
345
		}
346
		
347
		Label closestLabel = null;
348
		Point textLocation = text.getLocation();
349
		Point currentDistance = new Point(0,0);
350
		Point tempDistance = new Point(0,0);
351
		for (int i = 0; i < children.length; i++)
352
		{
353
			Point childLocation = children[i].getLocation();
354
			if 	(children[i] instanceof Label && 
355
				(closestLabel == null || (tempDistance = isLabelCloser(childLocation, currentDistance, textLocation)) != null))
356
			{
357
				boolean firstLabel = closestLabel == null;
358
				closestLabel = (Label)children[i];;
359
				if (firstLabel)
360
				{
361
					currentDistance = new Point (Math.abs(childLocation.x - textLocation.x), Math.abs(childLocation.y - textLocation.y));
362
				}
363
				else
364
				{
365
					currentDistance = tempDistance;
366
				}
367
			}
368
		}
369
		
370
		String closestLabelText = null;
371
		if (closestLabel != null && currentDistance.x + currentDistance.y <= 100 &&  
372
			closestLabel.getText() != null && (closestLabelText = closestLabel.getText().replaceAll("\\&", "")).length() > 0)
373
			return new PrimitiveWidgetId(convertText(closestLabelText));
374
		return null;
375
	}
376
377
378
	private Point isLabelCloser(Point newlblLocation, Point currentDistance, Point textLocation)
379
	{
380
		Point tempLocation = new Point (Math.abs(newlblLocation.x - textLocation.x), Math.abs(newlblLocation.y - textLocation.y));
381
		if (tempLocation.x + tempLocation.y < currentDistance.x + currentDistance.y)
382
			return tempLocation;
383
		return null;
384
	}
385
386
387
	private IWidgetId validateText(String text)
388
	{
389
		if (text != null && (text = text.replaceAll("\\&", "")).length() > 0)
390
			return new PrimitiveWidgetId(convertText(text));		
391
		return null;
392
	}
393
394
395
	/**
396
	 * Computes the item id based on the following properties
397
	 * and weights.  The threshold is set to 1.0:
398
	 * 
399
	 * <ul>
400
	 * 	<li> (Descriptive name of the item, 1.0) </li>
401
	 * </ul>
402
	 * @param item The item
403
	 * @return The weighted id
404
	 */
405
	private IWidgetId resolveItem(Item item) 
406
	{		
407
		StringBuffer descriptiveText = new StringBuffer();
408
		findItemText(item, descriptiveText);			
409
		
410
		/* Remove the ampersands */
411
		String itemText = convertText(descriptiveText.toString().replaceAll("\\&", ""));
412
		
413
		Object[] properties = 
414
			{
415
				new Object[] {itemText, "1.0"},
416
			};
417
		
418
		return WeightedPropertyWidgetId.constructId (properties, (float)1.0);
419
	}
420
421
	
422
	/**
423
	 * Walk through the item and return a descriptive text that corresponds
424
	 * to all item selections leading to the item. (e.g. File-New-Project)
425
	 * 
426
	 * @param item The item
427
	 * @param descriptiveText In the end, this buffer will contain a
428
	 * descriptive text of all items leading to the item that
429
	 * is passed in as argument
430
	 */
431
	private void findItemText(Item item, StringBuffer descriptiveText) 
432
	{
433
		if (item == null)
434
			return;
435
		
436
		String descriptiveTextStr = item.getText();
437
		if (descriptiveText.length() > 0)
438
			descriptiveTextStr += "-";
439
		
440
		descriptiveText.insert(0, descriptiveTextStr);
441
		
442
		Item parentItem = null;
443
		if (item instanceof MenuItem)
444
		{
445
			Menu menu = ((MenuItem)item).getParent();
446
			parentItem = (menu == null ? null : menu.getParentItem());
447
		}
448
		else if (item instanceof TreeItem)
449
		{
450
			parentItem = ((TreeItem)item).getParentItem();			
451
		}
452
				
453
		if (parentItem != null)
454
			findItemText(parentItem, descriptiveText);
455
	}
456
457
458
	private IWidgetId resolveFileSystemElement(Widget widget)
459
	{
460
			
461
		FileSystemElement fileSystemElement = (FileSystemElement) widget.getData();
462
		if (fileSystemElement.isDirectory())
463
			return null;
464
		
465
		Object[] properties = 
466
			{
467
				new Object[] {((IWorkbenchAdapter)fileSystemElement.getAdapter(IWorkbenchAdapter.class)).getLabel(null), "1.0"}
468
			};
469
		
470
		return WeightedPropertyWidgetId.constructId (properties, (float)1.0);
471
	}
472
473
	private WeightedPropertyWidgetId resolveAgentProxy(Widget widget)
474
	{	
475
		StringBuffer treeIndex = new StringBuffer();
476
		if (widget instanceof TreeItem)
477
			findTreeItemIndex((TreeItem)widget, treeIndex);
478
		else
479
			return null;
480
		
481
		TRCAgentProxy proxy = (TRCAgentProxy) widget.getData();
482
		Object[] properties = 
483
			{
484
				new Object[] {treeIndex.toString(), "0.4"},
485
				new Object[] {proxy.getProcessProxy().getName(), "0.2"},
486
				new Object[] {proxy.getProcessProxy().getVmArguments(), "0.1"},
487
				new Object[] {proxy.getProcessProxy().getClasspath(), "0.1"},
488
				new Object[] {proxy.getProcessProxy().getLocation(), "0.1"},
489
				new Object[] {proxy.getProcessProxy().getParameters(), "0.1"},
490
				new Object[] {proxy.getProfileFile(), "0.1"},
491
				new Object[] {proxy.getName(), "0.1"},
492
				new Object[] {String.valueOf(proxy.isAttached()), "0.1"},
493
				new Object[] {String.valueOf(proxy.isMonitored()), "0.1"},
494
				new Object[] {String.valueOf(proxy.isToProfileFile()), "0.1"},
495
			};
496
		
497
		return WeightedPropertyWidgetId.constructId (properties, (float)0.7);
498
	}
499
500
			
501
502
503
	private void findTreeItemIndex(TreeItem treeItem, StringBuffer sb)
504
	{
505
		TreeItem parentItem = treeItem.getParentItem();
506
		if (parentItem != null)
507
		{
508
			int index = parentItem.indexOf(treeItem);
509
			if (index != -1)
510
				sb.append("|" + String.valueOf(index + 1));
511
						
512
			findTreeItemIndex (parentItem, sb);			
513
		}
514
		Tree tree = treeItem.getParent();
515
		int index = tree.indexOf(treeItem);
516
		if (index != -1)
517
			sb.append("|" + String.valueOf(index));
518
		
519
	}
520
521
522
523
	public boolean foundWidget(Object object, Object id)
524
	{
525
		Object objectId = null;
526
		if (object instanceof Button)
527
		{
528
			Button button = (Button) object;
529
			objectId = resolveButton(button.getParent(), button, id);
530
		}
531
		
532
		if (objectId == null)
533
			objectId = getUniqueId(object instanceof Control ? ((Control)object).getParent() : null, object);
534
		return id == null ? false : objectId == null ? false : objectId.equals(id);		
535
	}
536
537
538
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/resolvers/PrimitiveWidgetId.java (-80 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.resolvers;
12
13
import org.eclipse.tptp.test.auto.gui.internal.core.IWidgetId;
14
15
16
/**
17
 * A primitive string widget id.  The string object must be an exact match
18
 * for the two given ids to equal.  Contributors can extend this class or 
19
 * provide a direct implementation of {@link IWidgetId}
20
 * 
21
 * @author Ali Mehregani
22
 */
23
public class PrimitiveWidgetId implements IWidgetId
24
{
25
	/** The resolver id */
26
	private String resolverId;
27
	
28
	/** The string id of the widget */
29
	private String id;
30
	
31
	
32
	public PrimitiveWidgetId()
33
	{
34
		
35
	}
36
	
37
	public PrimitiveWidgetId(String id)
38
	{
39
		this.id = id;
40
	}
41
	
42
	public String getResolverId()
43
	{
44
		return resolverId;
45
	}
46
47
	public void setResolverId(String resolverId)
48
	{
49
		this.resolverId = resolverId;
50
	}
51
52
	/**
53
	 * @return the id
54
	 */
55
	public String getId()
56
	{
57
		return id;
58
	}
59
60
	/**
61
	 * @param id the id to set
62
	 */
63
	public void setId(String id)
64
	{
65
		this.id = id;
66
	}
67
	
68
	public boolean equals(Object o)
69
	{
70
		if (id == null)
71
			return o == null;
72
		return id.equals(o);
73
	}
74
	
75
	public String toString()
76
	{
77
		return id;
78
	}
79
80
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/resolvers/WeightedPropertyWidgetId.java (-230 lines)
Removed Link Here
1
/********************************************************************** 
2
 * Copyright (c) 2005, 2006 IBM Corporation and others. 
3
 * All rights reserved.   This program and the accompanying materials 
4
 * are made available under the terms of the Eclipse Public License v1.0 
5
 * which accompanies this distribution, and is available at 
6
 * http://www.eclipse.org/legal/epl-v10.html         
7
 * $Id: WeightedPropertyWidgetId.java,v 1.3 2006/12/04 02:55:08 amehregani Exp $ 
8
 * 
9
 * Contributors: 
10
 * IBM - Initial API and implementation 
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.resolvers;
13
14
import java.util.regex.Matcher;
15
import java.util.regex.Pattern;
16
17
import org.eclipse.hyades.test.common.util.XMLUtil;
18
19
/**
20
 * Defines a widget Id by a set of properties that the widget must have.  Each
21
 * property is assigned a weight and if the total weight exceeds the threshold, then
22
 * the widget is identified as a match
23
 * 
24
 * @author Ali Mehregani
25
 */
26
public class WeightedPropertyWidgetId extends PrimitiveWidgetId
27
{
28
	/* Stored elements are of type Object[2], where the first element is the value returned by the
29
	 * method corresponding to the property and the second value is the weight associated with that
30
	 * property. */
31
	private Object[] propertyWeightPair;
32
	private float threshold;
33
	
34
	private final static Pattern pairPattern  = Pattern.compile(".*?\\{\\{([^\\}]+)\\}\\}-\\{\\{([^\\}]+)\\}\\}.*");
35
	
36
	public boolean equals(Object obj) 
37
	{
38
		String stringToCompare = null;
39
		boolean compare = false;
40
		
41
		/* The object is of our own kind */
42
		if (obj instanceof WeightedPropertyWidgetId)
43
		{
44
			WeightedPropertyWidgetId idToCompareWith = (WeightedPropertyWidgetId)obj;
45
			
46
			if (this == idToCompareWith)
47
				return true;
48
			
49
			compare = true;
50
			stringToCompare = idToCompareWith.toString();
51
		}
52
			
53
		/* The object is a string (most likely coming from a macro) */
54
		else if (obj instanceof String)
55
		{
56
			compare = true;
57
			stringToCompare = (String)obj;
58
		}
59
		
60
		if (!compare)
61
			return false;
62
		
63
		/* Use regular expression to distinguish the returned value of each method
64
		 * from the weight */	
65
		float accumMatchRate = 0;
66
		int loopIterationNo = -1;
67
		
68
		while (stringToCompare.length() > 0 && (loopIterationNo + 1) < propertyWeightPair.length)
69
		{
70
			loopIterationNo++;
71
			Matcher pairTokenMatcher = pairPattern.matcher(stringToCompare);
72
			
73
			/* Discontinue if there is no match */
74
			if (!pairTokenMatcher.matches() || pairTokenMatcher.groupCount() != 2)
75
				break;
76
			
77
			/* Otherwise walk through each token */
78
			String originalProperty = pairTokenMatcher.group(1);
79
			String prop = originalProperty;
80
			if (prop.length() > 0)
81
				prop = XMLUtil.removeXMLSymbols(prop);
82
			float weight = Float.parseFloat(pairTokenMatcher.group(2));
83
		
84
			/* The ordering of the tokens for the IDs being compared must be the same. */
85
			Object[] propertyWeightPair = (Object[])this.propertyWeightPair[loopIterationNo];
86
			if (!prop.equals("null") && 
87
				(prop.length() > 0 ? prop.charAt(0) == ((String)propertyWeightPair[0]).charAt(0) || prop.charAt(0) == '&' : true) &&  
88
				(prop.equals(propertyWeightPair[0]) || prop.replaceAll("\\&", "").equals(propertyWeightPair[0]) || prop.replace('/', '\\').equals(propertyWeightPair[0])))
89
				accumMatchRate += Float.parseFloat((String)propertyWeightPair[1]);
90
			
91
			String currentToken = "{{" + originalProperty + "}}-{{" + weight + "}}";
92
			if (currentToken.equals(stringToCompare))
93
				break;
94
			
95
			int inx = stringToCompare.indexOf(currentToken);
96
			if (inx != -1)
97
				stringToCompare = stringToCompare.substring(inx + currentToken.length(), stringToCompare.length());
98
			
99
			else
100
				break;				/* The control flow should never reach this block */
101
			
102
		}
103
		
104
		if (accumMatchRate >= threshold)
105
			return true;
106
		return false;
107
	}
108
	
109
	
110
	/**
111
	 * Return a string representation of this identifier.  The property, weight information
112
	 * is organized in this format:  {{property-value1}}-{{weight1}}{{property-value2}}:{{weight2}}
113
	 */
114
	public String toString() 
115
	{
116
		String retValue = "";
117
		for (int i = 0; i < this.propertyWeightPair.length; i++)
118
			retValue += "{{" + ((Object[])this.propertyWeightPair[i])[0] + "}}-{{" + ((Object[])this.propertyWeightPair[i])[1] + "}}";
119
		
120
		return XMLUtil.useXMLSymbols(retValue);
121
	}
122
123
124
	public float getThreshold()
125
	{
126
		return threshold;
127
	}
128
129
130
	public void setThreshold(float threshold)
131
	{
132
		this.threshold = threshold;
133
	}
134
135
136
	public Object[] getPropertyWeightPair()
137
	{
138
		return propertyWeightPair;
139
	}
140
141
142
	public void setPropertyWeightPair(Object[] propertyWeightPair)
143
	{
144
		this.propertyWeightPair = propertyWeightPair;
145
	}
146
147
	/**
148
	 * Walk through the properties and return true for as long as one of them is not null.
149
	 * 
150
	 * @return true if at least one property is not null; false otherwise
151
	 */
152
	public boolean noValidProperties()
153
	{
154
		if (propertyWeightPair == null)
155
			return true;
156
		
157
		for (int i = 0; i < propertyWeightPair.length; i++)
158
		{
159
			String property = (String)((Object[])propertyWeightPair[i])[0];
160
			if (property != null && !property.equals("null"))
161
				return false;
162
		}
163
		return true;
164
	}
165
	
166
	
167
	/**
168
	 * Convenient method available for clients to use in order to construct a 
169
	 * weighted property id
170
	 * 
171
	 * @param properties The (properties, weight) pairs of the item (weights should be a value between (0, 1])
172
	 * @param threshold The threshold that this property should meet (should be a value between (0-1])
173
	 * @return Returns an instance of this class with the appropriate fields set.  
174
	 */
175
	protected static WeightedPropertyWidgetId constructId(Object[] properties, float threshold)
176
	{
177
		/* Step through the properties and replace null values with the literal string null */
178
		for (int i = 0; i < properties.length; i++)
179
		{
180
			String property = (String)((Object[])properties[i])[0];
181
			if (property == null || property.length() <= 0)
182
				((Object[])properties[i])[0] = "null";
183
			
184
		}
185
		
186
		WeightedPropertyWidgetId widgetId = new WeightedPropertyWidgetId ();
187
		widgetId.setPropertyWeightPair(properties);
188
		widgetId.setThreshold(threshold);
189
		
190
		if (widgetId.noValidProperties())
191
			return null;
192
		return widgetId;
193
	}
194
	
195
	
196
	/**
197
	 * Given a string representation of the id, this method will return the number of tokens
198
	 * that it contains.  A token is a name, value pair in the format.
199
	 * 
200
	 * @param id The string representation of the id
201
	 * @return The number of tokens of the id
202
	 */
203
	protected static int countTokens(String id)
204
	{
205
		if (id == null)
206
			return 0;
207
		
208
		char[] characters = id.toCharArray();
209
		boolean braceInxHit = false;
210
		int tokenCount = 0;
211
		for (int i = 0; i < characters.length; i++)
212
		{
213
			if (characters[i] == '{')
214
			{
215
				if (braceInxHit)
216
				{
217
					tokenCount++;
218
				}
219
				else
220
				{
221
					braceInxHit = true;
222
					continue;
223
				}
224
			}
225
			braceInxHit = false;			
226
		}
227
		
228
		return tokenCount / 2;
229
	}
230
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/resolvers/AdaptiveWidgetResolver.java (-613 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * $Id: AdaptiveWidgetResolver.java,v 1.6 2007/04/26 20:03:22 paules Exp $
8
 * 
9
 * Contributors:
10
 *     IBM Corporation - initial API and implementation
11
 *******************************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.resolvers;
13
14
import java.io.IOException;
15
import java.io.InputStream;
16
import java.lang.reflect.Method;
17
import java.net.URL;
18
import java.util.Hashtable;
19
import java.util.Vector;
20
21
import org.eclipse.hyades.test.common.util.XMLUtil;
22
import org.eclipse.jface.dialogs.MessageDialog;
23
import org.eclipse.swt.widgets.Control;
24
import org.eclipse.swt.widgets.Widget;
25
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
26
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
27
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
28
import org.eclipse.tptp.test.auto.gui.internal.core.IWidgetId;
29
import org.eclipse.tptp.test.auto.gui.internal.core.IWidgetResolver;
30
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
31
import org.osgi.framework.Bundle;
32
import org.w3c.dom.Element;
33
import org.w3c.dom.NodeList;
34
35
/**
36
 * The following widget resolver attempts to resolve widgets using a static
37
 * XML file stored under the auto-gui folder under this plugin.
38
 * 
39
 * @since 4.1
40
 * @author Ali Mehregani
41
 */
42
public class AdaptiveWidgetResolver implements IWidgetResolver 
43
{
44
	/** 
45
	 * The id of this resolver -- must be in sync with the id registered with 
46
	 * the widgetResolver extension.
47
	 */
48
	private static final String ID = "org.eclipse.tptp.test.auto.gui.adaptive";
49
	
50
	/** The assumed file name relative to this plugin */
51
	public final static String WIDGET_REG_FILE = "auto-gui/widgetReg.xml";
52
	
53
	/** The widget registerations */
54
	private IWidgetRegistration widgetReg;
55
		
56
57
	public AdaptiveWidgetResolver()
58
	{		
59
		widgetReg = new WidgetRegistration (this, WIDGET_REG_FILE); 	
60
	}
61
	
62
	
63
	public IWidgetId getUniqueId(Widget parent, Object object)
64
	{
65
		if (!(object instanceof Widget))
66
			return null;
67
		
68
		widgetReg.load();
69
		IWidgetId widgetId = widgetReg.getWidgetId((Widget)object);
70
		if (widgetId != null)
71
			widgetId.setResolverId(ID);
72
		return widgetId;
73
	}
74
75
	/**
76
	 * Clients have the option of overwriting this in order to be able to locate
77
	 * the widget them self in the registeration entries that exist. 
78
	 */
79
	public WidgetRegValue findWidget (Hashtable registerations, Widget widget)
80
	{
81
		return null;
82
	}
83
	
84
	
85
	public class WidgetRegistration implements IWidgetRegistration
86
	{
87
		/* The file name */
88
		private String fileName;
89
		
90
		/* The last size of the file when it was properly read */
91
		private long lastModifiedDate;
92
		
93
		/* The file size (stored in case there was an error last time reading the file */
94
		private long lastModifiedDateDetected;
95
		
96
		/* Indicates if there was an error in parsing the file */
97
		private boolean errorOccurred;
98
		
99
		/* The data structures holding the registered widgets.
100
		 * Key = class name; Value =  WidgetRegValue */ 
101
		private Hashtable regWidgets;
102
			
103
		/* The global match threshold */
104
		private float globalMatchThreshold;
105
		
106
		/* The class name used for the default entry */
107
		public static final String DEFAULT_ENTYR = "0_DEFAULT_ENTRY";
108
		
109
		/* The adaptive widget resolver used as the driver for resolving widgets */
110
		private AdaptiveWidgetResolver adaptiveWidgetResolver; 
111
		
112
		public WidgetRegistration (AdaptiveWidgetResolver adaptiveWidgetResolver, String fileName)
113
		{
114
			this.fileName = fileName;
115
			this.lastModifiedDate = 0;
116
			this.lastModifiedDateDetected = 0;
117
			this.errorOccurred = false;
118
			this.regWidgets = new Hashtable();
119
			this.adaptiveWidgetResolver = adaptiveWidgetResolver;
120
		}
121
		
122
		
123
		public void load()
124
		{				
125
			InputStream regXMLInputStream = null;
126
			try
127
			{
128
				
129
			    
130
				Bundle guiBundle = GuiPlugin.getDefault().getBundle();
131
				long currentModifiedDate = guiBundle.getLastModified();// added for defect 169733 Liz Dancy
132
				
133
				/* Checking the file size doesn't guarantee to us that the file hasn't changed.  This is 
134
				 * the best we can do.  Replace this with last modified date if API is available. */
135
				if (currentModifiedDate > 0 && (currentModifiedDate == lastModifiedDate || (errorOccurred && lastModifiedDateDetected == currentModifiedDate)))
136
					return;
137
				
138
				URL regFileURL = GuiPlugin.getDefault().getBundle().getEntry(fileName);	
139
				lastModifiedDateDetected = currentModifiedDate;
140
				
141
				/* Parse the XML file */
142
				regXMLInputStream = regFileURL.openStream();
143
				Element rootElement = XMLUtil.loadDom(regXMLInputStream, "widgetResolverRule");
144
				if (rootElement == null)
145
				{
146
					lastModifiedDate = 0;
147
					errorOccurred = true;
148
					
149
					/* Display an error message if we are recording */
150
					if (MacroManager.getInstance().getGlobalState() == MacroManager.RECORDING_MODE)
151
					{
152
						AutoGUIUtil.showMessage(AutoGUIMessages.AUTO_GUI_ERROR_WID_RESOLVER_T, 
153
								AutoGUIMessages.AUTO_GUI_ERROR_WID_RESOLVER, MessageDialog.WARNING);
154
					}
155
					return;
156
				}
157
				this.regWidgets.clear();
158
				parseRegFile(rootElement);
159
				lastModifiedDate = currentModifiedDate;
160
			}
161
			catch (Throwable t)
162
			{
163
				/* Set the file size to zero to invalidate this widget resolver */
164
				lastModifiedDate = 0;
165
				errorOccurred = true;
166
				
167
				/* Display an error message if we are recording */
168
				if (MacroManager.getInstance().getGlobalState() == MacroManager.RECORDING_MODE)
169
				{
170
					AutoGUIUtil.showMessage(AutoGUIMessages.AUTO_GUI_ERROR_WID_RESOLVER_T, 
171
							AutoGUIMessages.AUTO_GUI_ERROR_WID_RESOLVER, MessageDialog.WARNING);
172
				}
173
			}
174
			finally
175
			{
176
				if (regXMLInputStream != null)
177
				{
178
					try
179
					{
180
						regXMLInputStream.close();
181
					} catch (IOException e)
182
					{
183
						/* Ignore the error */
184
					}
185
				}
186
			}
187
			
188
		}
189
190
		public float getGlobalThreshold()
191
		{
192
			return globalMatchThreshold;
193
		}
194
		
195
		/**
196
		 * parse the registation file that has already been loaded 
197
		 */
198
		private void parseRegFile(Element rootElement)
199
		{
200
			if (rootElement == null)
201
				return;
202
						
203
			NodeList classList = XMLUtil.getChildrenByName(rootElement, "class");
204
			parseClassElements (classList);
205
			globalMatchThreshold = Float.parseFloat(XMLUtil.getValue (rootElement, "globalMatchThreshold"));
206
			NodeList defaultList = XMLUtil.getChildrenByName(rootElement, "default");
207
			parseDefaultElements (defaultList);
208
		}
209
210
211
		private void parseDefaultElements(NodeList defaultList)
212
		{
213
			if (defaultList == null || defaultList.getLength() < 1)
214
				return;
215
			
216
			/* We only expect one default element */
217
			if(defaultList.item(0) instanceof Element)
218
			{
219
				Element defaultElement = (Element)defaultList.item(0);
220
				NodeList methodList = XMLUtil.getChildrenByName(defaultElement, "method");
221
				WidgetRegValue widgetReg = new WidgetRegValue();
222
					
223
				parseMethod (methodList, widgetReg);
224
				if (widgetReg != null)
225
					regWidgets.put(DEFAULT_ENTYR, widgetReg);
226
				
227
			}
228
		}
229
230
231
		/**
232
		 * Parse the class elements
233
		 */
234
		private void parseClassElements(NodeList classList)
235
		{
236
			if (classList == null || classList.getLength() <= 0)
237
				return;
238
			
239
			for(int i = 0; i < classList.getLength(); i++)
240
			{
241
				if(classList.item(i) instanceof Element)
242
				{
243
					
244
					Element classElement = (Element)classList.item(i);
245
					String className = XMLUtil.getValue(classElement, "name");
246
					NodeList methodList = XMLUtil.getChildrenByName(classElement, "method");
247
					WidgetRegValue widgetReg = new WidgetRegValue();
248
					String matchThreshold = XMLUtil.getValue(classElement, "matchThreshold");
249
					if (matchThreshold != null)
250
						widgetReg.setClassMatchThreshold(Float.parseFloat (matchThreshold));
251
					
252
					parseMethod (methodList, widgetReg);					
253
					if (widgetReg != null)
254
						regWidgets.put(className, widgetReg);
255
					
256
						
257
				}
258
			}
259
		}
260
261
262
		/**
263
		 * Parse the method element and return a widget registration entry
264
		 * 
265
		 * @param methodList The method list
266
		 * @param widgetReg the widget registration entry that will be augmented
267
		 * @return A widget registeration entry
268
		 */
269
		private void parseMethod(NodeList methodList, WidgetRegValue widgetReg)
270
		{
271
			if (methodList == null || methodList.getLength() <= 0)
272
				return;
273
			
274
			for(int i = 0; i < methodList.getLength(); i++)
275
			{
276
				if(methodList.item(i) instanceof Element)
277
				{
278
					Element methodElement = (Element)methodList.item(i);
279
					String methodName = XMLUtil.getValue(methodElement, "name");
280
					float weight = Float.parseFloat(XMLUtil.getValue(methodElement, "weight"));
281
					PropertyValue propertyVal = new PropertyValue();
282
					propertyVal.setWeight(weight);
283
					
284
					NodeList argumentList = XMLUtil.getChildrenByName(methodElement, "argument");
285
					if (argumentList != null)
286
						parseArguments(argumentList, propertyVal);
287
					
288
					widgetReg.addProperty(methodName, propertyVal);					
289
				}
290
			}			
291
		}
292
293
294
		/**
295
		 * Parse the arguments
296
		 * 
297
		 * @param argumentList The arugment list
298
		 * @param propertyVal The property value entry that will be augmented to.
299
		 */
300
		private void parseArguments(NodeList argumentList, PropertyValue propertyVal)
301
		{
302
			if (argumentList == null || argumentList.getLength() <= 0)
303
				return;
304
			
305
			Vector arguments = new Vector();
306
			for(int i = 0; i < argumentList.getLength(); i++)
307
			{
308
				if(argumentList.item(i) instanceof Element)
309
				{
310
					Element argumentElement = (Element)argumentList.item(i);
311
					String argumentValue = XMLUtil.getValue(argumentElement, "value");
312
					arguments.add(argumentValue);				
313
				}
314
			}	
315
			
316
			propertyVal.setArguments(arguments);			
317
		}
318
319
320
		public IWidgetId getWidgetId(Widget widget)
321
		{
322
			/* Use this resolver if we were able to successfully resolve parse the XML file */
323
			if (lastModifiedDate > 0)
324
			{
325
				/* First attempt the widget itself.  If that fails, then try its data attribute */
326
				Object data = widget;
327
328
				WidgetRegValue widgetValue = (WidgetRegValue)regWidgets.get(data.getClass().getName());
329
				if (widgetValue == null && widget.getData() != null)
330
				{
331
					data = widget.getData();
332
					widgetValue = (WidgetRegValue)regWidgets.get(data.getClass().getName());
333
					
334
					/* If that fails, then walk throught the class heirarchy (the interafaces and superclasses */
335
					if (widgetValue == null)
336
					{
337
						widgetValue = walkThroughClassHeirarchy (data.getClass());
338
339
					}					
340
				}
341
				
342
				/* As a final resolution, try and call the driver class to resolve the widget */
343
				if (widgetValue == null)
344
					widgetValue = adaptiveWidgetResolver.findWidget(regWidgets, widget);
345
				
346
				
347
				Vector propertyWeightPair = new Vector (5);
348
				WeightedPropertyWidgetId adaptiveWidgetId = new WeightedPropertyWidgetId();
349
				boolean specificValidEntry = false;
350
				boolean defaultValidEntry = false;
351
				
352
				if (widgetValue != null)
353
				{
354
					float threshold = widgetValue.getClassMatchThreshold();
355
					if (threshold == 0)
356
						threshold = globalMatchThreshold;
357
					adaptiveWidgetId.setThreshold(threshold);
358
					
359
					/* Specific properties associated with this type */
360
					specificValidEntry = appendProperties (data, propertyWeightPair, widgetValue);
361
				}
362
				
363
				/* Default properties */
364
				Vector defaultEntries = new Vector();
365
				defaultValidEntry = appendProperties (widget, defaultEntries, (WidgetRegValue)regWidgets.get(DEFAULT_ENTYR), true);
366
				if (defaultValidEntry)
367
					propertyWeightPair.addAll(propertyWeightPair);
368
				
369
				
370
				/* Return null if we weren't able to get any of the widgets properties */
371
				if (propertyWeightPair.size() <= 0)
372
					return null;
373
				
374
				adaptiveWidgetId.setPropertyWeightPair(propertyWeightPair.toArray());
375
				if (specificValidEntry || defaultValidEntry)
376
					return adaptiveWidgetId;
377
				return null;
378
			}
379
			
380
			return null;
381
		}
382
383
		
384
		private WidgetRegValue walkThroughClassHeirarchy(Class widgetClass) 
385
		{
386
			WidgetRegValue widgetValue = null;	
387
			
388
			widgetValue = (WidgetRegValue)regWidgets.get(widgetClass.getName());
389
			if (widgetValue != null)
390
				return widgetValue;
391
			
392
			Class[] interfaces = widgetClass.getInterfaces();
393
			
394
			/* Try the interfaces first */
395
			for (int i = 0; i < interfaces.length; i++)
396
			{
397
				widgetValue = (WidgetRegValue)regWidgets.get(interfaces[i].getName());
398
				widgetValue = (widgetValue == null ? walkThroughClassHeirarchy(interfaces[i]) : widgetValue);
399
				if (widgetValue != null)
400
					return widgetValue;
401
			}
402
			
403
			/* We failed with the interfaces, now try the super class */
404
			Class extendedClass = widgetClass.getSuperclass();
405
			if (extendedClass != null)
406
				widgetValue = walkThroughClassHeirarchy(extendedClass);
407
			
408
			return widgetValue;
409
		}
410
		
411
		
412
		private boolean appendProperties(Object data, Vector propertyWeightPair, WidgetRegValue widgetValue) 
413
		{
414
			return appendProperties(data, propertyWeightPair, widgetValue, false); 
415
		}
416
		
417
		private boolean appendProperties(Object data, Vector propertyWeightPair, WidgetRegValue widgetValue, boolean isDefault) 
418
		{
419
			boolean validEntry = false;
420
			if (widgetValue == null)
421
				return false;
422
			
423
			Vector properties = widgetValue.getProperties();
424
			for (int i = 0, propertySize = properties.size(); i < propertySize; i++)
425
			{
426
				String property = (String) properties.get(i);
427
				PropertyValue propertyValue = widgetValue.getPropertyValue(property);
428
				String retValue = invokeProperty (data, property, propertyValue);
429
				
430
				if ((retValue == null || retValue.length() <= 0) && isDefault)
431
					retValue = invokeProperty (((Widget)data).getData(), property, propertyValue);
432
				
433
				/* Don't add it if the return value is null or of zero length */
434
				if (retValue == null || retValue.length() <= 0)
435
					retValue = "null";				/* Set the value to the literal string 'null' */
436
				else
437
					validEntry = true;
438
				
439
				
440
				propertyWeightPair.add(new Object[] {retValue, String.valueOf(propertyValue.getWeight())});
441
			}
442
			return validEntry;
443
		}
444
445
446
		/**
447
		 * Invoke the appropriate method to get the property value
448
		 * 
449
		 * @param data The data corresponding to the widget or the data attribute of the widget
450
		 * @param theMethod The method corresponding to the property value 
451
		 * @param propertyValue The property information container
452
		 * 
453
		 * @return The returned value of the method corresponding to the argument
454
		 */
455
		private String invokeProperty(Object data, String theMethod, PropertyValue propertyValue)
456
		{
457
			try
458
			{
459
				Class theClass = data.getClass();
460
				int paramCount = 0;
461
				Vector args = propertyValue.getArguments(); 
462
				if (args != null && args.size() > 0)
463
					paramCount = args.size();
464
				
465
				/* We only support method with string parameters */
466
				Class[] params = new Class[paramCount];
467
				for (int i = 0; i < params.length; i++)
468
					params[i] = String.class;
469
				
470
				Method method = theClass.getMethod(theMethod, params);
471
				
472
				Object[] methodArgs = null;
473
				if (paramCount > 0)
474
					methodArgs = propertyValue.getArguments().toArray();
475
				
476
				Object retValue = method.invoke(data, methodArgs);
477
				return retValue.toString();
478
			}
479
			catch (Throwable t)
480
			{
481
				/* Return null if in case we can retrieve the property value */
482
				return null;	
483
			}
484
			
485
		}
486
487
488
		public WidgetRegValue getDefaultWidgetReg()
489
		{
490
			if (regWidgets == null)
491
				return null;
492
			return (WidgetRegValue)regWidgets.get(DEFAULT_ENTYR);
493
		}
494
		
495
	}
496
	
497
	
498
	/**
499
	 * Can be used to provide any alternative implementation of how the widget registration file 
500
	 * is loaded and queried.
501
	 * 
502
	 * @author Ali Mehregani
503
	 */
504
	public interface IWidgetRegistration
505
	{
506
		/**
507
		 * Used to load the necessary file and store the data in a datastructure that
508
		 * will later be used to query the registrations.
509
		 */
510
		public void load();
511
		
512
		/**
513
		 * Retrieve the widget id from the registrations
514
		 * 
515
		 * @param widget The widget in question
516
		 * @return The persistent identifier for the widget
517
		 */
518
		public IWidgetId getWidgetId (Widget widget);
519
	}
520
	
521
	
522
	/**
523
	 * A container class for the registeration value of a widget
524
	 * 
525
	 * @author Ali Mehregani
526
	 */
527
	private class WidgetRegValue
528
	{
529
		/* Key = method names, value = propertyValue */
530
		private Hashtable properties;
531
		
532
		/* Class match treshold */
533
		private float classMatchThreshold;
534
		
535
		/* This vector is used to preserve the ordering of the properties inserted in the hashtable */
536
		private Vector hashKeys;
537
		
538
		public WidgetRegValue()
539
		{
540
			properties = new Hashtable();
541
			classMatchThreshold = 0;
542
			hashKeys = new Vector();
543
		}
544
		
545
		public Vector getProperties()
546
		{
547
			return hashKeys;
548
		}
549
		
550
		public PropertyValue getPropertyValue (String propertyValue)
551
		{
552
			return (PropertyValue) properties.get(propertyValue);
553
		}
554
		
555
		public PropertyValue getPropertyValue (int inx)
556
		{
557
			if (inx >= hashKeys.size())
558
				return null;
559
			return (PropertyValue) properties.get(hashKeys.get(inx));
560
		}
561
		
562
		public void addProperty (String methodName, PropertyValue propertyValue)
563
		{
564
			hashKeys.add(methodName);
565
			properties.put (methodName, propertyValue);
566
		}
567
568
		public float getClassMatchThreshold()
569
		{
570
			return classMatchThreshold;
571
		}
572
573
		public void setClassMatchThreshold(float classMatchThreshold)
574
		{
575
			this.classMatchThreshold = classMatchThreshold;
576
		}
577
			
578
	}
579
	
580
	/**
581
	 * Container class for property values
582
	 * 
583
	 * @author Ali Mehregani
584
	 */
585
	private class PropertyValue
586
	{
587
		private Vector arguments;
588
		private float weight;
589
		
590
		public Vector getArguments()
591
		{
592
			return arguments;
593
		}
594
		public void setArguments(Vector arguments)
595
		{
596
			this.arguments = arguments;
597
		}
598
		public float getWeight()
599
		{
600
			return weight;
601
		}
602
		public void setWeight(float weight)
603
		{
604
			this.weight = weight;
605
		}			
606
	}
607
608
	public boolean foundWidget(Object object, Object id)
609
	{
610
		Object objectId = getUniqueId(object instanceof Control ? ((Control)object).getParent() : null, object);
611
		return id == null ? false : objectId == null ? false : objectId.equals(id);	
612
	}
613
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/IWidgetId.java (+1 lines)
Lines 18-23 Link Here
18
 * and {@link java.lang.Object#toString()}.
18
 * and {@link java.lang.Object#toString()}.
19
 * 
19
 * 
20
 * @since 4.3
20
 * @since 4.3
21
 * @deprecated 
21
 * @author Ali Mehregani
22
 * @author Ali Mehregani
22
 */
23
 */
23
public interface IWidgetId
24
public interface IWidgetId
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/IWidgetResolver.java (-19 / +28 lines)
Lines 13-49 Link Here
13
import org.eclipse.swt.widgets.Widget;
13
import org.eclipse.swt.widgets.Widget;
14
14
15
/**
15
/**
16
 * This interface is registered using extension point <code>org.eclipse.tptp.test.auto.gui.widgetResolver</code> 
16
 * This interface is registered using extension point
17
 * which is expected to return a unique identifier from a provided widget. The identifier must be reproducable 
17
 * <code>org.eclipse.tptp.test.auto.gui.widgetResolver</code> which is expected
18
 * between sessions so that it can be used to locate the widget on playback.
18
 * to return a unique identifier from a provided widget. The identifier must be
19
 * reproducable between sessions so that it can be used to locate the widget on
20
 * playback.
19
 * 
21
 * 
20
 * @since 3.1
22
 * @since 3.1
23
 * @deprecated
21
 */
24
 */
22
public interface IWidgetResolver
25
public interface IWidgetResolver {
23
{
24
	/**
26
	/**
25
	 * Returns a unique identifier for the provided widget.
27
	 * Returns a unique identifier for the provided widget.
26
	 * 
28
	 * 
27
	 * @param widget The parent object.  The value of this parameter can be null if the parent
29
	 * @param widget
28
	 * of object cannot be resolved.
30
	 *            The parent object. The value of this parameter can be null if
29
	 * @param object The object whose id is suppose to be resolved.  The type of this object is 
31
	 *            the parent of object cannot be resolved.
30
	 * <b>usually</b> a widget, but it can also be a <code>java.lang.String</code> or any other
32
	 * @param object
31
	 * arbitrary type depending on the implementation of the widget.  For example, when attempting
33
	 *            The object whose id is suppose to be resolved. The type of
32
	 * to resolve a combo box item, parent will point to the combo box and object will point to 
34
	 *            this object is <b>usually</b> a widget, but it can also be a
33
	 * a <code>java.lang.String</code> item representing the item selected.
35
	 *            <code>java.lang.String</code> or any other arbitrary type
34
	 *   
36
	 *            depending on the implementation of the widget. For example,
37
	 *            when attempting to resolve a combo box item, parent will point
38
	 *            to the combo box and object will point to a
39
	 *            <code>java.lang.String</code> item representing the item
40
	 *            selected.
41
	 * 
35
	 * @return unique identifier that can be used to locate the widget or
42
	 * @return unique identifier that can be used to locate the widget or
36
	 *         <code>null</code> if none can be found.
43
	 *         <code>null</code> if none can be found.
37
	 */
44
	 */
38
	public IWidgetId getUniqueId(Widget parent, Object object);
45
	public IWidgetId getUniqueId(Widget parent, Object object);
39
46
40
	
41
	/**
47
	/**
42
	 * Given an object and an id, this method should return true if and only if the id
48
	 * Given an object and an id, this method should return true if and only if
43
	 * of object as determined by this resolver equals the 'id' passed in.
49
	 * the id of object as determined by this resolver equals the 'id' passed
44
	 *  
50
	 * in.
45
	 * @param object An object 
51
	 * 
46
	 * @param id The being searched for
52
	 * @param object
53
	 *            An object
54
	 * @param id
55
	 *            The being searched for
47
	 * @return true iff object's id is equalled to 'id'
56
	 * @return true iff object's id is equalled to 'id'
48
	 */
57
	 */
49
	public boolean foundWidget(Object object, Object id);
58
	public boolean foundWidget(Object object, Object id);
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/IMacroInstruction.java (-88 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.core;
12
13
import java.util.Hashtable;
14
15
import org.eclipse.core.runtime.CoreException;
16
import org.w3c.dom.Node;
17
18
19
/**
20
 * Represents a macro instruction.  The instruction is expected to  
21
 * both be writable and playable.  
22
 * 
23
 * @author Ali Mehregani
24
 */
25
public interface IMacroInstruction extends IWritable, IPlayable
26
{
27
	/**
28
	 * Invoked to load the macro instruction based on its corresponding
29
	 * XML node.
30
	 * 
31
	 * @param node The XML node representing this macro instruction
32
	 * @param lineTable Contains line level information
33
	 * 
34
	 * @throws CoreException In case of an unexpected error
35
	 */
36
	public void load(Node node, Hashtable lineTable) throws CoreException;
37
	
38
	
39
	/**
40
	 * Returns the corresponding widget id of this instruction
41
	 *  
42
	 * @return The widget id
43
	 */
44
	public WidgetIdentifier getWidgetId();
45
		
46
	
47
	/**
48
	 * Sets the widget identifier for this macro instruction
49
	 *  
50
	 * @return widgetIdentifier The widget identifier
51
	 */
52
	public void setWidgetId(WidgetIdentifier widgetIdentifier);
53
	
54
	
55
	/**
56
	 * Returns the corresponding IUIObject of this macro instruction.
57
	 * If an object is not supported then null will be returned.
58
	 * 
59
	 * @return The corresponding object of this instruction
60
	 */
61
	public IUIObject getCorrespondingObject();
62
	
63
	
64
	/**
65
	 * Sets the UI object for this macro instruction.
66
	 * 
67
	 * @param uiObject The corresponding object
68
	 */
69
	public void setCorrespondingObject(IUIObject uiObject);
70
	
71
	
72
	/**
73
	 * Returns the starting line number of this macro instruction in the
74
	 * macro script that it belongs to.
75
	 * 
76
	 * @return The starting line
77
	 */
78
	public int getStartLine();
79
	
80
		
81
	/**
82
	 * Returns the last line number of this macro instruction in the
83
	 * macro script that it belongs to.
84
	 * 
85
	 * @return The last line
86
	 */
87
	public int getStopLine();
88
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/WidgetResolverLoader.java (-37 / +119 lines)
Lines 10-80 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.core;
11
package org.eclipse.tptp.test.auto.gui.internal.core;
12
12
13
import java.util.Hashtable;
14
import java.util.Vector;
15
13
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.core.runtime.CoreException;
14
import org.eclipse.core.runtime.IConfigurationElement;
17
import org.eclipse.core.runtime.IConfigurationElement;
18
import org.eclipse.core.runtime.Platform;
15
19
16
/**
20
/**
17
 * Represents each widgetResolver element that appears under a 
21
 * Represents each widgetResolver element that appears under a widgetResolver
18
 * widgetResolver extension
22
 * extension
19
 * 
23
 * 
20
 * @author Ali Mehregani
24
 * @author Ali Mehregani
25
 * @deprecated
21
 */
26
 */
22
public class WidgetResolverLoader 
27
public class WidgetResolverLoader {
23
{
28
	private static final String EXTENSION_POINT = "widgetResolver";
29
24
	/** The id of the widget resolver */
30
	/** The id of the widget resolver */
25
	private String id;
31
	private String id;
26
	
32
27
	/** The widget resolver class */
33
	/** The widget resolver class */
28
	private IWidgetResolver widgetResolver;
34
	private IWidgetResolver widgetResolver;
29
	
35
30
	/** The priority of this widget resolver registeration */
36
	/** The priority of this widget resolver registeration */
31
	private int priority;
37
	private int priority;
32
	
38
33
	
39
	/* Keeps an ordered list of the resolver ids */
40
	private static String[] resolverIds;
41
42
	/*
43
	 * The widget resolver: KEY = resolver id VALUE = A class of type
44
	 * WidgetResolverLoader
45
	 */
46
	private static Hashtable widgetResolvers = new Hashtable();
47
34
	/**
48
	/**
35
	 * Limit the visibility of the constructor
49
	 * Limit the visibility of the constructor
36
	 */
50
	 */
37
	private WidgetResolverLoader(String id, IWidgetResolver resolver, int priority)
51
	private WidgetResolverLoader(String id, IWidgetResolver resolver,
38
	{
52
			int priority) {
39
		this.id = id;
53
		this.id = id;
40
		this.widgetResolver = resolver;
54
		this.widgetResolver = resolver;
41
		this.priority = priority;
55
		this.priority = priority;
42
	}
56
	}
43
	
57
44
	
45
	/**
58
	/**
46
	 * Constructs an instance of this class based on the configuration
59
	 * Constructs an instance of this class based on the configuration element
47
	 * element passed in
60
	 * passed in
48
	 * 
61
	 * 
49
	 * @param confiugrationElement The configuration element to be loaded
62
	 * @param confiugrationElement
50
	 * @return An instance of this class based on the configuration element passed in.
63
	 *            The configuration element to be loaded
51
	 * null will be returned if there is an error loading the configuration element.
64
	 * @return An instance of this class based on the configuration element
52
	 */
65
	 *         passed in. null will be returned if there is an error loading the
53
	public static WidgetResolverLoader constructInstance(IConfigurationElement configuraitonElement)
66
	 *         configuration element.
54
	{
67
	 */
55
		if (!"widgetResolver".equals(configuraitonElement.getName()))
68
	public static WidgetResolverLoader constructInstance(
69
			IConfigurationElement configuraitonElement) {
70
		if (!EXTENSION_POINT.equals(configuraitonElement.getName()))
56
			return null;
71
			return null;
57
		
72
58
		try
73
		try {
59
		{
60
			String id = configuraitonElement.getAttribute("id");
74
			String id = configuraitonElement.getAttribute("id");
61
			IWidgetResolver widgetResolver = (IWidgetResolver) configuraitonElement.createExecutableExtension("class");
75
			IWidgetResolver widgetResolver = (IWidgetResolver) configuraitonElement
62
			int priority = Integer.parseInt(configuraitonElement.getAttribute("priority"));
76
					.createExecutableExtension("class");
63
			
77
			int priority = Integer.parseInt(configuraitonElement
78
					.getAttribute("priority"));
79
64
			if (id == null || widgetResolver == null)
80
			if (id == null || widgetResolver == null)
65
				return null;
81
				return null;
66
			
67
			return new WidgetResolverLoader (id, widgetResolver, priority);
68
82
83
			return new WidgetResolverLoader(id, widgetResolver, priority);
84
85
		} catch (CoreException e) {
69
		}
86
		}
70
		catch (CoreException e)
87
71
		{			
72
		}
73
				
74
		return null;
88
		return null;
75
	}
89
	}
76
90
77
78
	/**
91
	/**
79
	 * @return the id
92
	 * @return the id
80
	 */
93
	 */
Lines 82-88 Link Here
82
		return id;
95
		return id;
83
	}
96
	}
84
97
85
86
	/**
98
	/**
87
	 * @return the priority
99
	 * @return the priority
88
	 */
100
	 */
Lines 90-102 Link Here
90
		return priority;
102
		return priority;
91
	}
103
	}
92
104
93
94
	/**
105
	/**
95
	 * @return the widgetResolver
106
	 * @return the widgetResolver
96
	 */
107
	 */
97
	public IWidgetResolver getWidgetResolver() {
108
	public IWidgetResolver getWidgetResolver() {
98
		return widgetResolver;
109
		return widgetResolver;
99
	}
110
	}
100
	
101
111
112
	public static WidgetResolverLoader[] getWidgetResolverLoaders() {
113
		if (resolverIds == null) {
114
			loadWidgetResolvers();
115
		}
116
117
		WidgetResolverLoader[] resolvers = new WidgetResolverLoader[resolverIds.length];
118
		for (int i = 0; i < resolverIds.length; i++) {
119
			resolvers[i] = ((WidgetResolverLoader) widgetResolvers
120
					.get(resolverIds[i]));
121
		}
122
		return resolvers;
123
	}
124
125
	private static void loadWidgetResolvers() {
126
		IConfigurationElement[] elements = Platform.getExtensionRegistry()
127
				.getConfigurationElementsFor(
128
						"org.eclipse.tptp.test.auto.gui.widgetResolver");
129
		Vector tempContainer = new Vector(elements.length);
130
131
		for (int i = 0; i < elements.length; i++) {
132
			WidgetResolverLoader widgetResolverLoader = WidgetResolverLoader
133
					.constructInstance(elements[i]);
134
			if (widgetResolverLoader != null) {
135
				tempContainer.add(findIndex(widgetResolverLoader.getPriority(),
136
						tempContainer), widgetResolverLoader);
137
				widgetResolvers.put(widgetResolverLoader.getId(),
138
						widgetResolverLoader);
139
			}
140
		}
141
142
		resolverIds = new String[tempContainer.size()];
143
		for (int i = 0; i < resolverIds.length; i++) {
144
			resolverIds[i] = ((WidgetResolverLoader) tempContainer.get(i))
145
					.getId();
146
		}
147
	}
148
149
	private static int findIndex(int desiredPriority, Vector container,
150
			int startIntervalInx, int endIntervalInx, int length) {
151
		if (startIntervalInx == endIntervalInx
152
				|| startIntervalInx == endIntervalInx - 1) {
153
			if (length > 0) {
154
				WidgetResolverLoader widgetResolverReg = (WidgetResolverLoader) container
155
						.get(startIntervalInx);
156
				int priority = widgetResolverReg.getPriority();
157
				if (desiredPriority < priority)
158
					return startIntervalInx;
159
			}
160
			return endIntervalInx;
161
		}
162
163
		/* What's in the middle? */
164
		int middleInx = startIntervalInx
165
				+ (int) Math.ceil((endIntervalInx - startIntervalInx) / 2);
166
		WidgetResolverLoader widgetResolverReg = (WidgetResolverLoader) container
167
				.get(middleInx);
168
		int middleElementPriority = widgetResolverReg.getPriority();
169
170
		if (middleElementPriority > desiredPriority)
171
			endIntervalInx = middleInx;
172
		else if (middleElementPriority < desiredPriority)
173
			startIntervalInx = middleInx;
174
		else
175
			return middleInx;
176
		return findIndex(desiredPriority, container, startIntervalInx,
177
				endIntervalInx, length);
178
	}
179
180
	private static int findIndex(int priority, Vector container) {
181
		int length = container.size();
182
		return findIndex(priority, container, 0, length, length);
183
	}
102
}
184
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/VerifHookClassLoader.java (-104 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * $Id: VerifHookClassLoader.java,v 1.2 2006/07/14 23:17:02 amehregani Exp $
8
 * 
9
 * Contributors:
10
 *     IBM Corporation - initial API and implementation
11
 *******************************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.core;
13
14
import java.net.URL;
15
import java.net.URLClassLoader;
16
import java.util.Vector;
17
18
import org.eclipse.core.runtime.Platform;
19
import org.eclipse.osgi.util.NLS;
20
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
21
22
/**
23
 * A custom class loader that is used to resolve a class that the verificaiton hook is in along
24
 * with any other classes that are imported by the verification class.
25
 * 
26
 * @author Ali Mehregani
27
 */
28
public class VerifHookClassLoader extends URLClassLoader
29
{
30
	/* The plugins that the verification plugin requires */
31
	private Vector reqPluginNames;
32
	
33
	public VerifHookClassLoader (URL[] urls, ClassLoader parent, Vector requiredPluginNames)
34
	{
35
		super (urls, parent);		
36
		reqPluginNames = requiredPluginNames;
37
	}
38
	
39
   
40
	/**
41
	 * Invoked when a class can't be resolved by the upper level class loaders associated with
42
	 * this class.
43
	 */
44
	protected Class findClass(final String name) 
45
	 throws ClassNotFoundException 			 
46
    {  	
47
		
48
    	/* Try and walk through the required plugins of the plugin
49
    	 * containing the test suite */
50
    	try
51
    	{			
52
    		Class classFile = loadFromReqPlugins(name, 0);
53
    		if (classFile != null)
54
    			return classFile;
55
    	}
56
    	catch (Throwable t)
57
    	{
58
    		/* Doesn't need to be handled */
59
    	}
60
    	
61
		
62
		try
63
		{
64
			Class classFile = super.findClass(name);
65
			if (classFile != null)
66
				return classFile;
67
		}
68
		catch (Throwable t)
69
		{
70
			/* Doesn't need to be handled */
71
		}
72
		
73
	    		    	
74
    	
75
    	throw new ClassNotFoundException (NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_VER_CLASS_NOT_FS, name));
76
    }
77
78
79
	/**
80
	 * Attempt to load the class from the required plugins.
81
	 * 
82
	 * @param name
83
	 * @param inx
84
	 * @return
85
	 */
86
	private Class loadFromReqPlugins(String name, int inx)
87
	{
88
		try
89
		{
90
			if (reqPluginNames == null || inx >= reqPluginNames.size())
91
				return null;
92
			
93
			Class classFile = Platform.getBundle(((String)reqPluginNames.get(inx))).loadClass(name);				
94
			if (classFile != null)
95
				return classFile;
96
		}
97
		catch (Throwable t)
98
		{
99
			/* Handled by next statement */
100
		}
101
		
102
		return loadFromReqPlugins(name, inx + 1);
103
	}
104
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/IPlayable.java (-20 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.core;
12
13
import org.eclipse.core.runtime.*;
14
import org.eclipse.core.runtime.CoreException;
15
import org.eclipse.swt.widgets.*;
16
import org.eclipse.swt.widgets.Composite;
17
18
public interface IPlayable {
19
	boolean playback(Display display, Composite parent, IProgressMonitor monitor) throws CoreException;
20
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/WidgetIdentifier.java (-177 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.core;
12
13
import org.eclipse.core.runtime.IPath;
14
import org.eclipse.core.runtime.Path;
15
16
17
/**
18
 * Used as an identifier for widgets.  At a minimum, a context id and a widget id
19
 * is required as part of a widget identifier.
20
 * 
21
 * @author Ali Mehregani
22
 */
23
public class WidgetIdentifier
24
{
25
	/** A null identifier */
26
	public static final WidgetIdentifier NULL_IDENTIFIER = new WidgetIdentifier(new Path(""), new Path(""), null);
27
	
28
	/** The context id */
29
	private IPath contextId;
30
31
	/** The widget id */
32
	private IPath objectId;
33
34
	/** The id that is used to reference this widget in the object mine */
35
	private String referenceId;
36
	
37
	/** The resolver id that resovled this widget */
38
	private String resolverId;
39
	
40
	
41
	/**
42
	 * Constructor 
43
	 * 
44
	 * @param contextId The context id
45
	 * @param widgetId The widget id
46
	 */
47
	public WidgetIdentifier(IPath contextId, IPath widgetId, String resolverId)
48
	{
49
		this.contextId = contextId;
50
		this.objectId = widgetId;
51
		this.resolverId = resolverId;
52
	}
53
54
	
55
	/**
56
	 * Returns the fully qualified path of this widget id.  The fully qualified
57
	 * path is the context id/path appended with the widget path/id.
58
	 *  
59
	 * @return The fully qualified path of this identifier.
60
	 */
61
	public IPath getFullyQualifiedPath()
62
	{
63
		return contextId.append(objectId);
64
	}
65
66
	
67
	/**
68
	 * Equivalent to getFullyQualifiedPath().toString().
69
	 * 
70
	 * @return The fully qualified id
71
	 */
72
	public String getFullyQualifiedId()
73
	{
74
		return getFullyQualifiedPath().toString();
75
	}
76
77
	
78
	/**
79
	 * An object in question is equalled to this object iff the object is of the same type and
80
	 * the context and the widget ids are the same.
81
	 * 
82
	 * @param object The object in question
83
	 * 
84
	 * @return A boolean indicating whether object is equalled to this object or not.
85
	 */
86
	public boolean equals(Object object)
87
	{
88
		if (object == null)
89
			return false;
90
		if (object == this)
91
			return true;
92
		if (object instanceof WidgetIdentifier)
93
		{
94
			WidgetIdentifier wid = (WidgetIdentifier) object;
95
			return wid.contextId.equals(contextId) && wid.objectId.equals(objectId);
96
		}
97
		return false;
98
	}
99
100
101
	/**
102
	 * Returns the context id of this identifier
103
	 * 
104
	 * @return The context id
105
	 */
106
	public IPath getContextId()
107
	{
108
		return contextId;
109
	}
110
	
111
	
112
113
	/**
114
	 * @param contextId the contextId to set
115
	 */
116
	public void setContextId(IPath contextId)
117
	{
118
		this.contextId = contextId;
119
	}
120
121
122
	/**
123
	 * Returns the widget id of this identifier
124
	 * 
125
	 * @return The widget id
126
	 */
127
	public IPath getObjectId()
128
	{
129
		return objectId;
130
	}
131
	
132
	
133
	/**
134
	 * @param objectId the objectId to set
135
	 */
136
	public void setObjectId(IPath objectId)
137
	{
138
		this.objectId = objectId;
139
	}
140
141
142
	/**
143
	 * @return the referenceId
144
	 */
145
	public String getReferenceId()
146
	{
147
		return referenceId;
148
	}
149
150
151
	/**
152
	 * @param referenceId the referenceId to set
153
	 */
154
	public void setReferenceId(String referenceId)
155
	{
156
		this.referenceId = referenceId;
157
	}
158
159
160
	/**
161
	 * @return the resolverId
162
	 */
163
	public String getResolverId()
164
	{
165
		return resolverId;
166
	}
167
168
169
	/**
170
	 * @param resolverId the resolverId to set
171
	 */
172
	public void setResolverId(String resolverId)
173
	{
174
		this.resolverId = resolverId;
175
	}
176
	
177
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/IObjectMine.java (-244 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.core;
12
13
import java.util.List;
14
15
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.hyades.models.common.facades.behavioral.ITestSuite;
17
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMine.IDCollisionException;
18
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMine.UIObjectNotFound;
19
import org.w3c.dom.Node;
20
21
22
/**
23
 * Represents an object mine that belongs to a particular test suite.  The mine
24
 * keeps track of the objects that the test cases depends on.  Object mines
25
 * can be shared among multiple test suites, allowing users to centralize the objects
26
 * identified by test cases spanning multiple test suites.  The output source of an object 
27
 * mine can be different from the test suite that owns the mine.  
28
 * 
29
 * <p>
30
 * The inclusion and output source options introduce some ambiguities in registering a new 
31
 * object with an object mine.  The general contract when registering a new object is outlined below.
32
 * </p>
33
 * 
34
 * <p>
35
 * 	Assume object mine om1 includes om2 and outputs to om3:
36
 * </p>
37
 *    
38
 * <ul>
39
 * 	<li> If object o is infant, then it is registered with om3 </li>
40
 *  <li> If object o has a parent that belongs to om1, then it is registered with om1 </li>
41
 * 	<li> If object o has a parent that belongs to om2, then it is registered with om2 </li>
42
 *  <li> If object o has a parent that belongs to om3, then it is registered with om3 </li>
43
 * </ul>
44
 * 
45
 * Changing the output source of an object mine to an alternative test suite does not guarantee
46
 * that new objects will be written to the set test suite's object mine.
47
 * 
48
 * @author Ali Mehregani
49
 */
50
public interface IObjectMine 
51
{
52
53
	/**
54
	 * The test suite that owns this object mine.  The owner and the output source
55
	 * can be different.
56
	 * 
57
	 * @return The owner
58
	 */
59
	public ITestSuite getOwner();
60
	
61
	
62
	/**
63
	 * Sets the owner of this test suite.  The owner and the output source
64
	 * can be different.
65
	 * 
66
	 * @param testSuite The owner
67
	 */
68
	public void setOwner(ITestSuite testSuite);
69
	
70
	
71
	/**
72
	 * Set the output source to the object mine that is passed in.  If
73
	 * the user uses the test suite that is the owner of this mine to
74
	 * record a test case that results in finding a new object, then the
75
	 * object will be contributed to the object mine of the output source, not
76
	 * the owner of this object mine (some exceptions apply - see class comment).
77
	 * 
78
	 * @param objectMine The object mine that will act as the output source
79
	 * for this mine 
80
	 */
81
	public void setOutputSource(IObjectMine objectMine);
82
83
	
84
	/**
85
	 * Returns the output of this object mine
86
	 * 
87
	 * @return The output source
88
	 */
89
	public IObjectMine getOutputSource();
90
	
91
	
92
	/**
93
	 * Includes another object mine as part of this mine.  The lookup method for
94
	 * an object is required to walk through the registered objects of this object
95
	 * mine and the registered objects of included object mines.
96
	 * 
97
	 * @param objectMine The object mine to include
98
	 */
99
	public void addInclude(IObjectMine objectMine);
100
101
	
102
	/**
103
	 * Returns the external object mines that have been added to this 
104
	 * object mine
105
	 * 
106
	 * @return The added external object mines
107
	 */
108
	public List getIncludes();
109
	
110
	
111
	/**
112
	 * Looks up the UI object with the reference id passed in.  null should be 
113
	 * returned if the objct can't be found.  Time complexity = T(h) = h (where h is the height of the 
114
	 * object mine tree)
115
	 * 
116
	 * @param parent The parent of the object
117
	 * @param referenceId The reference id of the object
118
	 * 
119
	 * @return The object with the reference id passed in; or null if none is found.
120
	 * 
121
	 * @throws UIObjectNotFound If the parent object is not found
122
	 */
123
	public IUIObject lookupUIObject(IUIObject parent, String referenceId);
124
	
125
	
126
	/**
127
	 * Looks up the UI object based on the context id and the object id that is passed in.  This
128
	 * lookup operation is more expensive than lookup(parent, referenceId).  The latter should be
129
	 * used where possible.  Time complexity = T(h, n) = h + n (where h is the height of the 
130
	 * object mine tree and n is the number of nodes owned by the parent node)
131
	 * 
132
	 * @param parent The parent of the object
133
	 * @param contextId The context id of the object
134
	 * @param objectId The object id of the object
135
	 * 
136
	 * @return The object with the matching context and object id; or null if none is found.
137
	 * 
138
	 * @throws UIObjectNotFound If the parent object is not found
139
	 */
140
	public IUIObject lookupUIObject(IUIObject parent, String contextId, String objectId);
141
	
142
	
143
	/**
144
	 * Returns the direct children of the root object that this object mine points to
145
	 * 
146
	 * @return The children of the root object 
147
	 */
148
	public IUIObject[] getChildren();
149
150
	
151
	/**
152
	 * Register the object embedded in the node passed in.  The parent of the
153
	 * registered object should be set to the parent argument.  If the object is already
154
	 * registered, then this method will not have any effects.
155
	 * 
156
	 * @param parent The parent of the object to be registered
157
	 * @param node The node containing the object information to be registered
158
	 * 
159
	 * @return The object that gets registered.
160
	 * 
161
	 * @throws IDCollisionException If there is a reference id collision
162
	 * @throws UIObjectNotFound If the parent object is not found
163
	 * @throws CoreException Wraps any unexpected error 
164
	 */
165
	public IUIObject registerObject(IUIObject parent, Node currentNode) throws IDCollisionException, UIObjectNotFound, CoreException;
166
167
168
	/**
169
	 * Registers uiObject under the parent object passed in.  If the object is already
170
	 * registered, then this method will not have any effects.
171
	 * 
172
	 * @param uiObject The object to be registered
173
	 * @return The object that gets registered (i.e. uiObject).
174
	 * 
175
	 * @throws IDCollisionException If there is a reference id collision
176
	 * @throws UIObjectNotFound If the parent object of uiObject is not found
177
	 * @throws CoreException Wraps any unexpected error 
178
	 */
179
	public IUIObject registerObject(IUIObject uiObject) throws IDCollisionException, UIObjectNotFound, CoreException;
180
	
181
	
182
	/**
183
	 * Serializes this object mine to a string representation that can be stored
184
	 * and retrieved for later use.  This is often the result of <code>serializeHeaderToString()</code>
185
	 * appended to the result of <code>serializeObjetsToString()</code>.
186
	 * 
187
	 * @return The string representation of this object mine
188
	 */
189
	public String serializeToString();
190
	
191
	
192
	/**
193
	 * Serializes only the header of this object mine to a string representation that
194
	 * can be stored and retrieved for later use.
195
	 * 
196
	 * @return The string representation of the header of this object mine
197
	 */
198
	public String serializeHeaderToString();
199
	
200
	
201
	/**
202
	 * Serializes only the objects of this object mine to a string representation that
203
	 * can be stored and retrieved for later use.
204
	 * 
205
	 * @return The string representation of the object directly owned by this object mine
206
	 */
207
	public String serializeObjetsToString();
208
	
209
	
210
	/**
211
	 * Sets the active object of this object mine.  This is commonly used to determine the active
212
	 * object corresponding to the active shell.
213
	 * 
214
	 * @param activeObject The active object.
215
	 */
216
	public void setActiveObject(IUIObject activeObject);
217
	
218
	
219
	/**
220
	 * Returns the active object of this object mine.  This is commonly used to determine the active
221
	 * object corresponding to the active shell.
222
	 * 
223
	 * @return The active object.
224
	 */	
225
	public IUIObject getActiveObject();
226
227
228
	/**
229
	 * Returns the next available unique reference id that can be used.  The id's returned will be an
230
	 * integer even though the type is set to String.
231
	 * 
232
	 * @return The next available reference id.
233
	 */
234
	public String getUniqueReferenceId();
235
	
236
	
237
	/**
238
	 * Returns the roo object
239
	 * 
240
	 * @return The root object
241
	 */
242
	public IUIObject getRoot();
243
244
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/IUIObject.java (-226 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.core;
12
13
import java.util.LinkedList;
14
import java.util.Map;
15
16
import org.eclipse.core.runtime.CoreException;
17
18
19
/**
20
 * Represents a UI object such as a widget.
21
 * 
22
 * @author Ali Mehregani
23
 */
24
public interface IUIObject
25
{
26
	/**
27
	 * Returns the hierarchical relationshipt of this object relative to its parents.
28
	 * A linked list is returned whose first element is the child of the root UI object node and
29
	 * its last node is this UI object.  An object directly above a node is the parent of that
30
	 * node.
31
	 *  
32
	 * @return A linked list indicating the hierarchical relationship between this node and
33
	 * its parents.
34
	 */
35
	public LinkedList getHierarchicalRelation();
36
37
	
38
	/**
39
	 * Set the reference id of this object.
40
	 * 
41
	 * @param referenceId The reference id
42
	 */
43
	public void setReferenceId(String referenceId);
44
	
45
	
46
	/**
47
	 * Return the reference id of this object
48
	 * 
49
	 * @return reference id
50
	 */
51
	public String getReferenceId();
52
53
	
54
	/**
55
	 * Sets the context id of this object
56
	 * 
57
	 * @param contextId The context id of this object
58
	 */
59
	public void setContextId(String contextId);
60
	
61
	
62
	/**
63
	 * Returns the context id of this object
64
	 * 
65
	 * @return The context id
66
	 */
67
	public String getContextId();
68
69
	
70
	/**
71
	 * Sets the id of this object.  This is the id used by the playback operations to
72
	 * identify the UI object.
73
	 * 
74
	 * @param id The id of this UI object
75
	 */
76
	public void setObjectId(String objectId);
77
	
78
	
79
	/**
80
	 * Returns the id of this object.  This is the id used by the playback operations to
81
	 * identify the UI object.
82
	 * 
83
	 * @return object id
84
	 */
85
	public String getObjectId();
86
87
	
88
	/**
89
	 * Returns the descriptive field of this object.  The descriptive field is human readable
90
	 * label that is used to easily recognize the object.
91
	 * 
92
	 * @param descriptive field
93
	 */
94
	public void setDescriptive(String descriptive);
95
96
	
97
	/**
98
	 * Returns the descriptive field of this object.  The descriptive field is human readable
99
	 * label that is used to easily recognize the object.
100
	 * 
101
	 * @return descriptive field
102
	 */
103
	public String getDescriptive();
104
	
105
	
106
	/**
107
	 * Add a property to this UI object.
108
	 * 
109
	 * @param name The name of the property 
110
	 * @param value The value of the property
111
	 */
112
	public void addProperty (String name, String value);
113
114
	
115
	/**
116
	 * Returns the property of this object
117
	 * 
118
	 * @param name The name of the property.
119
	 * @return The value of the property with the name passed in.  null is returned if the
120
	 * property can't be found.
121
	 */
122
	public String getProperty (String name);
123
	
124
	
125
	/**
126
	 * Returns the properties of this UI object.
127
	 * 
128
	 * @return The properties of this UI object
129
	 */
130
	public Map getProperties ();
131
	
132
	
133
	/**
134
	 * Set the parent of this UI object 
135
	 * 
136
	 * @param parent The parent
137
	 */
138
	public void setParent(IUIObject parent);
139
	
140
	
141
	/**
142
	 * Returns the parent of this UI object
143
	 * 
144
	 * @return The parent
145
	 */
146
	public IUIObject getParent();
147
148
149
	/**
150
	 * Sets the resolver id for this object.
151
	 * 
152
	 * @param resolverId The resolver id.
153
	 */
154
	public void setResolver(String resolverId);
155
	
156
	
157
	/**
158
	 * Returns the resolver id that has resolved this object 
159
	 * 
160
	 * @return A resolver id
161
	 */
162
	public String getResolverId();
163
	
164
	
165
	/**
166
	 * Returns the number of children that this UI object has
167
	 * 
168
	 * @return the number of children of this object
169
	 */
170
	public int childCount();
171
	
172
	
173
	/**
174
	 * Returns the children of this UI object
175
	 * 
176
	 * @return The children of this UI object
177
	 */
178
	public IUIObject[] getChildren();
179
	
180
	
181
	/**
182
	 * Adds a child to this object.  Has no effects if child is already
183
	 * part of this object's children
184
	 * 
185
	 * @param child The child to add
186
	 * @throws CoreException In case of any unexpected error
187
	 */
188
	public void addChild(IUIObject child) throws CoreException;
189
	
190
	
191
	/**
192
	 * Removes a  child from this object
193
	 * 
194
	 * @param child The child to remove
195
	 * @return The child removed
196
	 */
197
	public IUIObject removeChild(IUIObject child);
198
	
199
	
200
	/**
201
	 * Returns the data associated with this object.
202
	 * 
203
	 * @return The associated data
204
	 */
205
	public Object getData();
206
	
207
	
208
	/**
209
	 * Can be used to associate a general data object with this object.
210
	 * 
211
	 * @param data The data
212
	 */
213
	public void setData(Object data);
214
	
215
	
216
	/**
217
	 * Returns the child with a matching reference id passed in; null if none is found
218
	 * 
219
	 * @param referenceId The reference id of the child
220
	 * @return A IUIObject with a matching referenceId or null if none is found.
221
	 */
222
	public IUIObject findChild(String referenceId);
223
	
224
}
225
226
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/VerificationMetaData.java (-103 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * $Id: VerificationMetaData.java,v 1.2 2006/10/27 14:39:10 amehregani Exp $
8
 * 
9
 * Contributors:
10
 *     IBM Corporation - initial API and implementation
11
 *******************************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.core;
13
14
15
/**
16
 * A container class for the data that the verificaiton command will need 
17
 * 
18
 * @author Ali Mehregani
19
 */
20
public class VerificationMetaData
21
{
22
	/* The possible types */
23
	public static final byte EDITOR 	= 0x01;
24
	public static final byte VIEW 		= 0x02;
25
	public static final byte SHELL		= 0x03;
26
	
27
	
28
	/* The context id is the id of the editor, viewer, etc... that will be used to retrieve it */
29
	private String contextId;
30
	
31
	/* The location is the plugin that contains the hook source code */
32
	private String location;
33
	
34
	/* The resource is the class name containing the hook */
35
	private String resource;
36
	
37
	/* The hook is the method name representing the verification point */
38
	private String hook;
39
	
40
	/* The focus type indicates whether the type of context being retrieved */ 
41
	private byte focusType;
42
43
	public VerificationMetaData()
44
	{
45
		focusType = -1;
46
	}
47
			
48
	public String getContextId()
49
	{
50
		return contextId;
51
	}
52
53
	public void setContextId(String contextId)
54
	{
55
		this.contextId = contextId;
56
	}
57
58
	public byte getFocusType()
59
	{
60
		return focusType;
61
	}
62
63
	public void setFocusType(byte focusType)
64
	{
65
		this.focusType = focusType;
66
	}
67
68
	public String getHook()
69
	{
70
		return hook;
71
	}
72
73
	public void setHook(String hook)
74
	{
75
		this.hook = hook;
76
	}
77
78
	public String getLocation()
79
	{
80
		return location;
81
	}
82
83
	public void setLocation(String location)
84
	{
85
		this.location = location;
86
	}
87
88
	public String getResource()
89
	{
90
		return resource;
91
	}
92
93
	public void setResource(String resource)
94
	{
95
		this.resource = resource;
96
	}
97
	
98
	public boolean isComplete()
99
	{
100
		return contextId != null && location != null &&  resource != null && hook != null && focusType != -1; 
101
	}
102
	
103
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/IRecorderListener.java (-26 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.core;
12
13
public interface IRecorderListener {
14
	int STOP = 1;
15
	int INDEX = 2;
16
	void recordingStarted();
17
	void recordingStopped();
18
/**
19
 * Called when the user pressed Ctrl+Shift+F10 (index)
20
 * or Ctrl+Shift+F11 (stop) to interrupt
21
 * the recording process. Clients may use this event
22
 * to insert named indexes, stop the recording etc.
23
 * @param type <code>STOP</code> or <code>INDEX</code>
24
 */
25
	void recordingInterrupted(int type);
26
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/IWritable.java (-53 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.core;
12
13
14
/**
15
 * A writable object is capable of serializing itself to string and writing the string
16
 * version to a PrintWriter that is passed to parameters to the methods that are described
17
 * below.
18
 * <br/>
19
 * The ideal order of the method invocations are:
20
 * <ul>
21
 * 	<li> writeStart(String indent, gPrintWriter writer) </li>
22
 * 	<li> write(String indent, PrintWriter writer) </li>
23
 * 	<li> writeFinish(String indent, PrintWriter writer) </li>
24
 * </ul>
25
 */
26
public interface IWritable 
27
{
28
	/**
29
	 * Invoked at start of the write of a writable object
30
	 * 
31
	 * @param indent The indents
32
	 * @param sb The buffer that the string serialization should be written to
33
	 */
34
	public void writeStart(int indent, StringBuffer sb);
35
	
36
	
37
	/**
38
	 * Invoked after writeStart
39
	 * 
40
	 * @param indent The indents
41
	 * @param sb The buffer that the string serialization should be written to
42
	 */
43
	public void write(int indent, StringBuffer sb);
44
	
45
	
46
	/**
47
	 * Invoked in the end of the write of a writable object
48
	 * 
49
	 * @param indent The indents
50
	 * @param sb The buffer that the string serialization should be written to
51
	 */
52
	public void writeFinish(int indent, StringBuffer sb);
53
}
(-)plugin.properties (-1 / +3 lines)
Lines 27-30 Link Here
27
TST_SUITE_AUTO_GUI_DESC 		= Use this suite to create Automated GUI test cases in the Eclipse platform
27
TST_SUITE_AUTO_GUI_DESC 		= Use this suite to create Automated GUI test cases in the Eclipse platform
28
TST_CASE_AUTO_GUI_NAME			= TPTP Automated GUI Test Case
28
TST_CASE_AUTO_GUI_NAME			= TPTP Automated GUI Test Case
29
TST_CASE_AUTO_GUI_DESC			= Test Case which can store events recorded on the UI and be used to play them back
29
TST_CASE_AUTO_GUI_DESC			= Test Case which can store events recorded on the UI and be used to play them back
30
widgetResolver = Widget Resolver Extension
30
widgetResolver = Widget Resolver Extension (Deprecated)
31
uiObjectResolverDelegate = UI Object Resolver Delegate Extension
32
macroCommandFactory = MacroCommandFactory Replacement Extension
(-)plugin.xml (-9 / +20 lines)
Lines 14-19 Link Here
14
 -->
14
 -->
15
<?eclipse version="3.0"?>
15
<?eclipse version="3.0"?>
16
<plugin>
16
<plugin>
17
   <extension-point id="uiObjectResolverDelegate" name="%uiObjectResolverDelegate" schema="schema/uiObjectResolverDelegate.exsd"/>
18
   <extension-point id="macroCommandFactory" name="%macroCommandFactory" schema="schema/macroCommandFactory.exsd"/>
17
   <extension-point id="widgetResolver" name="%widgetResolver" schema="schema/widgetResolver.exsd"/>
19
   <extension-point id="widgetResolver" name="%widgetResolver" schema="schema/widgetResolver.exsd"/>
18
   <extension
20
   <extension
19
         point="org.eclipse.hyades.ui.typeDescriptions">
21
         point="org.eclipse.hyades.ui.typeDescriptions">
Lines 93-118 Link Here
93
  </extension>
95
  </extension>
94
 	
96
 	
95
 
97
 
96
  <!-- The widget resolvers -->
98
   <!-- ANy: Migrated extension point to new UI object resolver delegate interface -->
99
  <!-- The UI object resolvers -->
97
  <extension
100
  <extension
98
		point="org.eclipse.tptp.test.auto.gui.widgetResolver">
101
		point="org.eclipse.tptp.test.auto.gui.uiObjectResolverDelegate">-->
99
102
100
		<!-- The adaptive widget resolver -->	
103
		<!-- The adaptive widget resolver -->	
101
	    <widgetResolver 
104
	   <uiObjectResolverDelegate 
102
	    	id = "org.eclipse.tptp.test.auto.gui.adaptive"	
105
	    	id = "org.eclipse.tptp.test.auto.gui.adaptive"	
103
	    	class="org.eclipse.tptp.test.auto.gui.internal.resolvers.AdaptiveWidgetResolver"
106
	    	class="org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.AdaptiveUIObjectResolverDelegate"
104
	    	priority="10"
107
	    	priority="10"
105
	    />
108
	    />
106
		
109
		
107
		<!-- Non trivial widget resolver.  Use this if adaptive widget resolver can't be used -->
110
		<!-- Non trivial widget resolver.  Use this if adaptive widget resolver can't be used -->
108
		<!-- (e.g. Nested calls are required)  												-->		    
111
		<!-- (e.g. Nested calls are required)  												-->		    
109
	   	<widgetResolver 
112
	   	<uiObjectResolverDelegate 
110
			id = "org.eclipse.tptp.test.auto.gui.nontrivial"	    	
113
			id = "org.eclipse.tptp.test.auto.gui.nontrivial"	    	
111
	    	class="org.eclipse.tptp.test.auto.gui.internal.resolvers.NonTrivialWidgetResolver"
114
	    	class="org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.NonTrivialUIObjectResolverDelegate"
112
	    	priority="11"
115
	    	priority="11"
113
	    />
116
	    />	    
114
	    
117
  </extension>
115
  </extension>  
116
  
118
  
117
  
119
  
118
  <!-- Make the test type launchable -->
120
  <!-- Make the test type launchable -->
Lines 256-259 Link Here
256
      </verdictProvider>
258
      </verdictProvider>
257
   </extension>
259
   </extension>
258
   
260
   
261
   <extension
262
         point="org.eclipse.tptp.test.auto.gui.macroCommandFactory">
263
      <macroCommandFactory
264
            id="org.eclipse.tptp.test.auto.gui.macroCommandFactory"
265
            class="org.eclipse.tptp.test.auto.gui.internal.commands.factory.MacroCommandFactory"
266
            priority="10">
267
      </macroCommandFactory>
268
   </extension>
269
   
259
</plugin>
270
</plugin>
(-).project (-1 / +1 lines)
Lines 1-6 Link Here
1
<?xml version="1.0" encoding="UTF-8"?>
1
<?xml version="1.0" encoding="UTF-8"?>
2
<projectDescription>
2
<projectDescription>
3
	<name>org.eclipse.tptp.test.auto.gui</name>
3
	<name>Copy of org.eclipse.tptp.test.auto.gui</name>
4
	<comment></comment>
4
	<comment></comment>
5
	<projects>
5
	<projects>
6
	</projects>
6
	</projects>
(-)src/org/eclipse/tptp/test/auto/gui/internal/actions/AutoGUIRecordAction.java (-277 / +273 lines)
Lines 31-37 Link Here
31
import org.eclipse.tptp.test.auto.gui.internal.codegen.AutoGUIGenerator;
31
import org.eclipse.tptp.test.auto.gui.internal.codegen.AutoGUIGenerator;
32
import org.eclipse.tptp.test.auto.gui.internal.codegen.CodeGeneratorHelper;
32
import org.eclipse.tptp.test.auto.gui.internal.codegen.CodeGeneratorHelper;
33
import org.eclipse.tptp.test.auto.gui.internal.commands.VerificationCommand;
33
import org.eclipse.tptp.test.auto.gui.internal.commands.VerificationCommand;
34
import org.eclipse.tptp.test.auto.gui.internal.core.VerificationMetaData;
35
import org.eclipse.tptp.test.auto.gui.internal.dialogs.AutoGUIInputCollectorDialog;
34
import org.eclipse.tptp.test.auto.gui.internal.dialogs.AutoGUIInputCollectorDialog;
36
import org.eclipse.tptp.test.auto.gui.internal.dialogs.AutoGUITestControllerDialog;
35
import org.eclipse.tptp.test.auto.gui.internal.dialogs.AutoGUITestControllerDialog;
37
import org.eclipse.tptp.test.auto.gui.internal.dialogs.AutoGUITestControllerDialog.AutoGUIControllerListener;
36
import org.eclipse.tptp.test.auto.gui.internal.dialogs.AutoGUITestControllerDialog.AutoGUIControllerListener;
Lines 39-49 Link Here
39
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCasesForm.GUITestCaseProperties;
38
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCasesForm.GUITestCaseProperties;
40
import org.eclipse.tptp.test.auto.gui.internal.macro.Macro;
39
import org.eclipse.tptp.test.auto.gui.internal.macro.Macro;
41
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
40
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
42
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMineManager;
41
import org.eclipse.tptp.test.auto.gui.internal.macro.ModeConstants;
43
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager.GlobalStateListener;
42
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager.GlobalStateListener;
44
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager.VerificationHookListener;
43
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager.VerificationHookListener;
45
import org.eclipse.ui.IEditorPart;
44
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMineManager;
46
import org.eclipse.ui.IViewPart;
47
import org.eclipse.ui.IWorkbench;
45
import org.eclipse.ui.IWorkbench;
48
import org.eclipse.ui.IWorkbenchWindow;
46
import org.eclipse.ui.IWorkbenchWindow;
49
import org.eclipse.ui.WorkbenchException;
47
import org.eclipse.ui.WorkbenchException;
Lines 54-520 Link Here
54
 * 
52
 * 
55
 * @author      Ali Mehregani
53
 * @author      Ali Mehregani
56
 * @author      Paul E. Slauenwhite
54
 * @author      Paul E. Slauenwhite
55
 * @author      Alexander Nyssen
57
 * @version     March 5, 2008
56
 * @version     March 5, 2008
58
 * @since       March 17, 2006
57
 * @since       March 17, 2006
59
 */
58
 */
60
public class AutoGUIRecordAction extends AddTestCase implements AutoGUIControllerListener
59
public class AutoGUIRecordAction extends AddTestCase implements AutoGUIControllerListener {
61
{
60
62
	
63
	/* The test suite provider */
61
	/* The test suite provider */
64
	private IITestSuiteProvider suiteProvider;
62
	private IITestSuiteProvider suiteProvider;
65
	
63
66
	/* The perspective the user was in before adding a test case */
64
	/* The perspective the user was in before adding a test case */
67
	private String perspectiveId;
65
	private String perspectiveId;
68
		
66
69
	/* Control center dialog */
67
	/* Control center dialog */
70
	private AutoGUITestControllerDialog controllerDialog;
68
	private AutoGUITestControllerDialog controllerDialog;
71
	
69
72
	/* A global state listener */
70
	/* A global state listener */
73
	private CustomGlobalStateListener globalStateListener;
71
	private CustomGlobalStateListener globalStateListener;
74
	
72
75
	/* Start record dialog */
73
	/* Start record dialog */
76
	private AutoGUIInputCollectorDialog inputCollectorDialog;
74
	private AutoGUIInputCollectorDialog inputCollectorDialog;
77
	
75
78
	/* Stores the user input collected from the input dialog */
76
	/* Stores the user input collected from the input dialog */
79
	private AutoGUIInputCollectorDialog.AutoGUIInputContainer userInput;
77
	private AutoGUIInputCollectorDialog.AutoGUIInputContainer userInput;
80
78
81
	/* The test suite provider */
79
	/* The test suite provider */
82
	private IITestSuiteProvider testSuiteProvider;
80
	private IITestSuiteProvider testSuiteProvider;
83
		
81
84
	/**
82
	/**
85
	 * The constructor
83
	 * The constructor
86
	 * 
84
	 * 
87
	 * @param testSuiteProvider The test suite provider used to get the test suite associated with this action
85
	 * @param testSuiteProvider
88
	 * @param baseName The base name of the test case
86
	 *            The test suite provider used to get the test suite associated with this action
87
	 * @param baseName
88
	 *            The base name of the test case
89
	 */
89
	 */
90
	public AutoGUIRecordAction(IITestSuiteProvider testSuiteProvider, String baseName) 
90
	public AutoGUIRecordAction(IITestSuiteProvider testSuiteProvider, String baseName) {
91
	{
91
		super(testSuiteProvider,
92
		super(testSuiteProvider, GuiPlugin.getTestSuiteType(), baseName);		
92
			GuiPlugin.getTestSuiteType(),
93
			baseName);
93
		this.suiteProvider = testSuiteProvider;
94
		this.suiteProvider = testSuiteProvider;
94
		this.testSuiteProvider = testSuiteProvider;
95
		this.testSuiteProvider = testSuiteProvider;
95
		setToolTipText(AutoGUIMessages.TST_SUITE_AUTO_MACRO_RECORD);
96
		setToolTipText(AutoGUIMessages.TST_SUITE_AUTO_MACRO_RECORD);
96
		setImageDescriptor(AutoGUIImages.getInstance().getImageDescriptor("e", AutoGUIImages.RECORD));
97
		setImageDescriptor(AutoGUIImages.getInstance().getImageDescriptor("e",
97
		
98
			AutoGUIImages.RECORD));
99
98
		IWorkbench workbench = GuiPlugin.getDefault().getWorkbench();
100
		IWorkbench workbench = GuiPlugin.getDefault().getWorkbench();
99
		IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow();
101
		IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow();
100
		Shell activeShell = activeWorkbenchWindow.getShell();
102
		Shell activeShell = activeWorkbenchWindow.getShell();
101
		inputCollectorDialog = new AutoGUIInputCollectorDialog (activeShell);
103
		inputCollectorDialog = new AutoGUIInputCollectorDialog(activeShell);
102
	}
104
	}
103
	
105
104
	
105
	/**
106
	/**
106
	 * Invoked when this action is create
107
	 * Invoked when this action is create
107
	 */
108
	 */
108
	public void run()
109
	public void run() {
109
	{ 
110
		setActionPerformed(false);
110
		setActionPerformed(false);		
111
		IWorkbench workbench = GuiPlugin.getDefault().getWorkbench();
111
		IWorkbench workbench = GuiPlugin.getDefault().getWorkbench();
112
		IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow();
112
		IWorkbenchWindow activeWorkbenchWindow = workbench.getActiveWorkbenchWindow();
113
		Shell activeShell = activeWorkbenchWindow.getShell();
113
		Shell activeShell = activeWorkbenchWindow.getShell();
114
		userInput = inputCollectorDialog.openDialog();
114
		userInput = inputCollectorDialog.openDialog();
115
		
115
116
		
117
		/* We don't need to do anything if cancel is pressed */
116
		/* We don't need to do anything if cancel is pressed */
118
		if (userInput == null || !userInput.isOkPressed())
117
		if (userInput == null || !userInput.isOkPressed()) {
119
		{
118
			setActionPerformed(true);
120
			setActionPerformed (true);
121
			return;
119
			return;
122
		}
120
		}
123
		
121
124
		/* Otherwise, we'll need to add the test case.  Here are the phases:
122
		/*
125
		 * 	- Switch to the perspective that corresponds to the starting point of the test case
123
		 * Otherwise, we'll need to add the test case. Here are the phases: - Switch to the perspective that corresponds to the starting point of the
126
		 *  - Display the control center dialog box
124
		 * test case - Display the control center dialog box - Begin recording user actions
127
		 *  - Begin recording user actions */
125
		 */
128
		userInput.setDescription(userInput.getDescription() == null ? "" : userInput.getDescription());
126
		userInput.setDescription(userInput.getDescription() == null
129
		
127
			? ""
130
		/* Switch the perspecitve */			
128
			: userInput.getDescription());
131
		try
129
132
		{
130
		/* Switch the perspecitve */
131
		try {
133
			/* Store the perspective that we're in before switching it */
132
			/* Store the perspective that we're in before switching it */
134
			perspectiveId = activeWorkbenchWindow.getActivePage().getPerspective().getId();
133
			perspectiveId = activeWorkbenchWindow.getActivePage().getPerspective().getId();
135
			workbench.showPerspective(userInput.getStartingPoint(), activeWorkbenchWindow);
134
			workbench.showPerspective(userInput.getStartingPoint(),
136
		} catch (WorkbenchException e)
135
				activeWorkbenchWindow);
137
		{
136
		}
138
			/* Something wrong happened while chaning the perspective.  Show an error */
137
		catch (WorkbenchException e) {
138
			/* Something wrong happened while chaning the perspective. Show an error */
139
			String[] errorArgs = {userInput.getStartingPoint(), e.getMessage()};
139
			String[] errorArgs = {userInput.getStartingPoint(), e.getMessage()};
140
			AutoGUIUtil.openErrorWithDetail(
140
			AutoGUIUtil.openErrorWithDetail(AutoGUIMessages.AUTO_GUI_ERROR_PERS_SWITCH_TITLE,
141
					AutoGUIMessages.AUTO_GUI_ERROR_PERS_SWITCH_TITLE,
141
				NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_PERS_SWITCH,
142
					NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_PERS_SWITCH, errorArgs),
142
					errorArgs),
143
					e);			
143
				e);
144
		}
144
		}
145
		
145
146
		/* Display the control center dialog box asynchronously */
146
		/* Display the control center dialog box asynchronously */
147
		controllerDialog = new AutoGUITestControllerDialog(activeShell);
147
		controllerDialog = new AutoGUITestControllerDialog(activeShell);
148
		controllerDialog.registerListener(this);
148
		controllerDialog.registerListener(this);
149
		controllerDialog.openDialog();		
149
		controllerDialog.openDialog();
150
		
150
151
		MacroManager macroManagerInstance = MacroManager.getInstance();
151
		MacroManager macroManagerInstance = MacroManager.getInstance();
152
		globalStateListener = new CustomGlobalStateListener(false);
152
		globalStateListener = new CustomGlobalStateListener(false);
153
		macroManagerInstance.registerGlobalStateListener(globalStateListener);
153
		macroManagerInstance.registerGlobalStateListener(globalStateListener);
154
		macroManagerInstance.setGlobalState(MacroManager.RECORDING_MODE);
154
		macroManagerInstance.setGlobalState(ModeConstants.RECORDING_MODE);
155
		controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_REC);
155
		controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_REC);
156
156
157
		startRecording(userInput.isObjectMineOn());
157
		startRecording(userInput.isObjectMineOn());
158
		setActionPerformed(true);
158
		setActionPerformed(true);
159
	}
159
	}
160
	
160
161
	
161
	private void startRecording(boolean isObjectMineOn) {
162
	private void startRecording(boolean isObjectMineOn)
162
		/* The control center is now open. Start recording the user's actions */
163
	{
163
		try {
164
		/* The control center is now open.  Start recording the user's actions */
164
			MacroManager.getInstance().startRecording(suiteProvider.getTestSuite(),
165
		try
165
				isObjectMineOn);
166
		{
166
		}
167
			MacroManager.getInstance().startRecording(suiteProvider.getTestSuite(), isObjectMineOn);
167
		catch (Exception e) {
168
		} 
168
			MacroManager.getInstance().setObjectMine(null);
169
		catch (Exception e)
169
			;
170
		{			
170
			if (controllerDialog != null) {
171
			MacroManager.getInstance().setObjectMine(null);;			
172
			if (controllerDialog != null)
173
			{
174
				controllerDialog.terminate();
171
				controllerDialog.terminate();
175
			}
172
			}
176
			
173
177
			AutoGUIUtil.openErrorWithDetail(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_REC_TITLE, AutoGUIMessages.AUTO_GUI_ERROR_MACRO_REC, e);
174
			AutoGUIUtil.openErrorWithDetail(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_REC_TITLE,
178
		} 
175
				AutoGUIMessages.AUTO_GUI_ERROR_MACRO_REC,
179
	}
176
				e);
180
	
177
		}
181
	
182
	protected void adjusTestCase(ITestCase testCase)
183
	{
184
	}
178
	}
185
179
180
	protected void adjusTestCase(ITestCase testCase) {
181
	}
186
182
187
	public void handleEvent(byte event, Object value)
183
	public void handleEvent(byte event, Object value) {
188
	{
189
		MacroManager macroManager = MacroManager.getInstance();
184
		MacroManager macroManager = MacroManager.getInstance();
190
		
185
191
		switch (event)
186
		switch (event) {
192
		{
187
			/*
193
			/* When user terminates, we have to take the macro and transfer it to the test suite.
188
			 * When user terminates, we have to take the macro and transfer it to the test suite. We'll also need to reset the perspective back to
194
			 * We'll also need to reset the perspective back to what it was */
189
			 * what it was
195
			case AutoGUITestControllerDialog.TERMINATE:				
190
			 */
196
				try
191
			case AutoGUITestControllerDialog.TERMINATE:
197
				{
192
				try {
198
					/* Stop the macro */
193
					/* Stop the macro */
199
					Macro macro = macroManager.stopRecording(false);
194
					Macro macro = macroManager.stopRecording(false);
200
					
195
201
					/* Something went wrong in the macro manager */
196
					/* Something went wrong in the macro manager */
202
					if (macro == null)
197
					if (macro == null) {
203
					{
204
						/* Display error message and switch to the original perspective of the user */
198
						/* Display error message and switch to the original perspective of the user */
205
						IWorkbench workbench = GuiPlugin.getDefault().getWorkbench();												
199
						IWorkbench workbench = GuiPlugin.getDefault().getWorkbench();
206
						MessageDialog.openError(workbench.getActiveWorkbenchWindow().getShell(),
200
						MessageDialog.openError(workbench.getActiveWorkbenchWindow().getShell(),
207
								AutoGUIMessages.AUTO_GUI_ERROR_MACRO_GENERATE_T,
201
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_GENERATE_T,
208
								AutoGUIMessages.AUTO_GUI_ERROR_MACRO_GENERATE);						
202
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_GENERATE);
209
					
203
210
						try
204
						try {
211
						{
205
							workbench.showPerspective(perspectiveId,
212
							workbench.showPerspective (perspectiveId, workbench.getActiveWorkbenchWindow());
206
								workbench.getActiveWorkbenchWindow());
213
						} 
207
						}
214
						catch (WorkbenchException e)
208
						catch (WorkbenchException e) {
215
						{
209
							/* Not a huge deal if we can't restore the perspective */
216
							/* Not a huge deal if we can't restore the perspective */					
217
						}
210
						}
218
														
211
219
						return;					
212
						return;
220
					}
213
					}
221
					
214
222
					
223
					StringWriter swriter = null;
215
					StringWriter swriter = null;
224
					try 
216
					try {
225
					{
226
						swriter = new StringWriter();
217
						swriter = new StringWriter();
227
						PrintWriter pwriter = new PrintWriter(swriter);
218
						PrintWriter pwriter = new PrintWriter(swriter);
228
						macro.write(0, pwriter);
219
						macro.write(0,
220
							pwriter);
229
						pwriter.close();
221
						pwriter.close();
230
						swriter.close();
222
						swriter.close();
231
					}
223
					}
232
					catch (Exception e) 
224
					catch (Exception e) {
233
					{
234
						String messageWithOrigin = AutoGUIUtil.getOriginOfException(e);
225
						String messageWithOrigin = AutoGUIUtil.getOriginOfException(e);
235
						String cause = messageWithOrigin + "\n" + AutoGUIUtil.getExceptionStackTrace(e);
226
						String cause = messageWithOrigin + "\n" + AutoGUIUtil.getExceptionStackTrace(e);
236
						AutoGUIUtil.openErrorWithDetail(
227
						AutoGUIUtil.openErrorWithDetail(GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(),
237
								GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(), 
228
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_STOP_TITLE,
238
								AutoGUIMessages.AUTO_GUI_ERROR_MACRO_STOP_TITLE, 
229
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_STOP,
239
								AutoGUIMessages.AUTO_GUI_ERROR_MACRO_STOP, 
230
							cause);
240
								cause);												
231
241
						
242
						return;
232
						return;
243
					}
233
					}
244
					
234
245
					/* Create the test case and add the required properties */
235
					/* Create the test case and add the required properties */
246
					ITestSuite testSuite = getTestSuite();
236
					ITestSuite testSuite = getTestSuite();
247
					boolean isExternalBehavior = testSuite.getImplementor().isExternalImplementor();
237
					boolean isExternalBehavior = testSuite.getImplementor().isExternalImplementor();
248
					ITestCase testcase = TestCommonUtil.createTestCase(testSuite, getType(), isExternalBehavior, userInput.getName());		
238
					ITestCase testcase = TestCommonUtil.createTestCase(testSuite,
239
						getType(),
240
						isExternalBehavior,
241
						userInput.getName());
249
					testcase.setDescription(userInput.getDescription());
242
					testcase.setDescription(userInput.getDescription());
250
					
243
251
					/* Add the starting point */
244
					/* Add the starting point */
252
					((AutoGUITestCasesForm)suiteProvider).addProperty(testcase, GUITestCaseProperties.STARTING_PT, userInput.getStartingPoint());
245
					((AutoGUITestCasesForm) suiteProvider).addProperty(testcase,
253
					
246
						GUITestCaseProperties.STARTING_PT,
247
						userInput.getStartingPoint());
248
254
					/* Add the macro */
249
					/* Add the macro */
255
					String contents = swriter.toString();
250
					String contents = swriter.toString();
256
					
251
257
					/* Get rid of the last line break */
252
					/* Get rid of the last line break */
258
					int lastLineBreak = contents.lastIndexOf(GlobalConstants.LINE_SEPARATOR);
253
					int lastLineBreak = contents.lastIndexOf(GlobalConstants.LINE_SEPARATOR);
259
					if (lastLineBreak != -1 && contents.substring(lastLineBreak).trim().length() <= 0)
254
					if (lastLineBreak != -1 && contents.substring(lastLineBreak).trim().length() <= 0)
260
						contents = contents.substring(0, lastLineBreak);
255
						contents = contents.substring(0,
261
					
256
							lastLineBreak);
262
					((AutoGUITestCasesForm)suiteProvider).addProperty(testcase, GUITestCaseProperties.MACRO_FRAGMENT, contents);					
257
263
				
258
					((AutoGUITestCasesForm) suiteProvider).addProperty(testcase,
259
						GUITestCaseProperties.MACRO_FRAGMENT,
260
						contents);
261
264
					/* Switch the perspective to where we were before */
262
					/* Switch the perspective to where we were before */
265
					try
263
					try {
266
					{
267
						IWorkbench workbench = GuiPlugin.getDefault().getWorkbench();
264
						IWorkbench workbench = GuiPlugin.getDefault().getWorkbench();
268
						workbench.showPerspective (perspectiveId, workbench.getActiveWorkbenchWindow());
265
						workbench.showPerspective(perspectiveId,
269
					} 
266
							workbench.getActiveWorkbenchWindow());
270
					catch (WorkbenchException e)
271
					{
272
						/* Not a huge deal if we can't restore the perspective */					
273
					}
267
					}
274
					
268
					catch (WorkbenchException e) {
269
						/* Not a huge deal if we can't restore the perspective */
270
					}
271
275
					adjusTestCase(testcase);
272
					adjusTestCase(testcase);
276
					
273
277
					/* Cause a selection event */
274
					/* Cause a selection event */
278
					if (testSuiteProvider instanceof AutoGUITestCasesForm)
275
					if (testSuiteProvider instanceof AutoGUITestCasesForm) {
279
					{
276
						AutoGUITestCasesForm testCaseForm = (AutoGUITestCasesForm) testSuiteProvider;
280
						AutoGUITestCasesForm testCaseForm = (AutoGUITestCasesForm)testSuiteProvider;
281
						testCaseForm.getLogicalRepresentationListener().selectionChanged(null);
277
						testCaseForm.getLogicalRepresentationListener().selectionChanged(null);
282
						testCaseForm.getLogicalTreeRepresentaion().selectionChanged(null);
278
						testCaseForm.getLogicalTreeRepresentaion().selectionChanged(null);
283
						testCaseForm.getObjectMineTreeStruct().refresh();
279
						testCaseForm.getObjectMineTreeStruct().refresh();
284
					}
280
					}
285
				}
281
				}
286
				catch (Throwable t)
282
				catch (Throwable t) {
287
				{
288
					t.printStackTrace();
283
					t.printStackTrace();
289
				}
284
				}
290
				
285
291
				break;
286
				break;
292
				
287
293
			/* A verificaiton point is inserted */
288
			/* A verificaiton point is inserted */
294
			case AutoGUITestControllerDialog.VERIFICATION_HOOK_INSERT:		
289
			case AutoGUITestControllerDialog.VERIFICATION_HOOK_INSERT:
295
				
290
296
				/* Make sure the verification hook name conforms to the standard defined */
291
				/* Make sure the verification hook name conforms to the standard defined */
297
				String hookName = (String) value;
292
				String hookName = (String) value;
298
				boolean validName = hookName != null && !hookName.equals("") && hookName.length() < 100 && !containSpecialChars (hookName);
293
				boolean validName = hookName != null && !hookName.equals("") && hookName.length() < 100 && !containSpecialChars(hookName);
299
				if (!validName)
294
				if (!validName) {
300
				{
301
					/* display an error */
295
					/* display an error */
302
					macroManager.setGlobalState(MacroManager.SUSPEND_MODE);
296
					macroManager.setGlobalState(ModeConstants.SUSPEND_MODE);
303
					
297
304
					AutoGUIUtil.openErrorWithDetail(
298
					AutoGUIUtil.openErrorWithDetail(GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(),
305
							GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(), 
299
						AutoGUIMessages.AUTO_GUI_ERROR_VER_INVALID_NM_T,
306
							AutoGUIMessages.AUTO_GUI_ERROR_VER_INVALID_NM_T, 
300
						AutoGUIMessages.AUTO_GUI_ERROR_VER_INVALID_NM,
307
							AutoGUIMessages.AUTO_GUI_ERROR_VER_INVALID_NM, 
301
						(String) null);
308
							(String)null
302
309
							);
303
					macroManager.setGlobalState(ModeConstants.RECORDING_MODE);
310
					
311
					macroManager.setGlobalState(MacroManager.RECORDING_MODE);
312
					return;
304
					return;
313
				}
305
				}
314
				
315
306
316
				macroManager.setGlobalState(MacroManager.SUSPEND_MODE);
307
				macroManager.setGlobalState(ModeConstants.SUSPEND_MODE);
317
				controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_GEN);
308
				controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_GEN);
318
				
309
319
				AutoGUIGenerator generator = new AutoGUIGenerator (((AutoGUITestCasesForm)suiteProvider).getTestSuite(), CodeGeneratorHelper.AUTO_GUI_VERIFICATION_HOOK_CLASS);
310
				AutoGUIGenerator generator =
320
				try
311
					new AutoGUIGenerator(((AutoGUITestCasesForm) suiteProvider).getTestSuite(), CodeGeneratorHelper.AUTO_GUI_VERIFICATION_HOOK_CLASS);
321
				{
312
				try {
322
					generator.createChange(new NullProgressMonitor()).perform(new NullProgressMonitor());
313
					generator.createChange(new NullProgressMonitor()).perform(new NullProgressMonitor());
323
				} 
314
				}
324
				catch (Exception e)
315
				catch (Exception e) {
325
				{
326
					/* There was an error in generating the source code */
316
					/* There was an error in generating the source code */
327
					AutoGUIUtil.openErrorWithDetail(
317
					AutoGUIUtil.openErrorWithDetail(AutoGUIMessages.AUTO_GUI_ERROR_VER_GEN_SRC_T,
328
							AutoGUIMessages.AUTO_GUI_ERROR_VER_GEN_SRC_T, 
318
						AutoGUIMessages.AUTO_GUI_ERROR_VER_GEN_SRC,
329
							AutoGUIMessages.AUTO_GUI_ERROR_VER_GEN_SRC, 
319
						e);
330
							e);
331
320
332
					return;
321
					return;
333
				}
322
				}
334
				
323
335
				macroManager.setGlobalState(MacroManager.RECORDING_MODE);
324
				macroManager.setGlobalState(ModeConstants.RECORDING_MODE);
336
				controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_REC);
325
				controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_REC);
337
326
338
				
339
				/* Allow the user to select an editor or a view */
327
				/* Allow the user to select an editor or a view */
340
				controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_VER);
328
				controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_VER);
341
				macroManager.setVerListener(new CustomVerHookListener(generator, hookName));
329
				macroManager.setVerListener(new CustomVerHookListener(generator, hookName, controllerDialog.isVerficationScopeExtended()));
342
				macroManager.setGlobalState(MacroManager.VERIFICATION_MODE);
330
				macroManager.setGlobalState(ModeConstants.VERIFICATION_MODE);
343
				
331
344
				if (globalStateListener != null)
332
				if (globalStateListener != null)
345
					globalStateListener.turnOn(true);
333
					globalStateListener.turnOn(true);
346
				
334
347
				break;
335
				break;
348
				
336
349
			/* The restart button is pressed */
337
			/* The restart button is pressed */
350
			case AutoGUITestControllerDialog.RESTART:	
338
			case AutoGUITestControllerDialog.RESTART:
351
				/* Restart recording */
339
				/* Restart recording */
352
				macroManager.stopRecording(true);
340
				macroManager.stopRecording(true);
353
				ObjectMineManager.getInstance().clearCache();
341
				MacroObjectDescriptorMineManager.getInstance().clearCache();
354
				AutoGUIUtil.showMessage(AutoGUIMessages.AUTO_GUI_CONTROL_RESTART_MSG_T, 
342
				AutoGUIUtil.showMessage(AutoGUIMessages.AUTO_GUI_CONTROL_RESTART_MSG_T,
355
						AutoGUIMessages.AUTO_GUI_CONTROL_RESTART_MSG,
343
					AutoGUIMessages.AUTO_GUI_CONTROL_RESTART_MSG,
356
						MessageDialog.INFORMATION);
344
					MessageDialog.INFORMATION);
357
				startRecording(MacroManager.getInstance().isObjectMineOn());
345
				startRecording(MacroManager.getInstance().isObjectMineOn());
358
				
346
359
				if (!controllerDialog.isPositionBasedOn())
347
				if (!controllerDialog.isPositionBasedOn())
360
					break;
348
					break;
361
			
349
362
			/* The position based recording option is turned on/off */
350
				/* The position based recording option is turned on/off */
363
			case AutoGUITestControllerDialog.POSITION_BASED:
351
			case AutoGUITestControllerDialog.POSITION_BASED:
364
				boolean success = MacroManager.getInstance().togglePositionBasedRec(controllerDialog.isPositionBasedOn());
352
				boolean success = MacroManager.getInstance().togglePositionBasedRec(controllerDialog.isPositionBasedOn());
365
353
366
				if (success)
354
				if (success) {
367
				{
368
					if (controllerDialog.isPositionBasedOn())
355
					if (controllerDialog.isPositionBasedOn())
369
						controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_POS);
356
						controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_POS);
370
					else
357
					else
371
						controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_REC);
358
						controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_REC);
372
				}
359
				}
373
				
360
374
				break;
361
				break;
375
			
362
376
			/* Wait time recording is turned on/off */
363
			/* Wait time recording is turned on/off */
377
			case AutoGUITestControllerDialog.WAIT_TIME:
364
			case AutoGUITestControllerDialog.WAIT_TIME:
378
				MacroManager.getInstance().setArtificialWaitOn(controllerDialog.isWaitTimeOn()); 
365
				MacroManager.getInstance().setArtificialWaitOn(controllerDialog.isWaitTimeOn());
379
			
366
380
		}
367
		}
381
		
368
382
	}
369
	}
383
	
370
384
	
371
	private boolean containSpecialChars(String hookName) {
385
	private boolean containSpecialChars(String hookName)
386
	{
387
		boolean condition = false;
372
		boolean condition = false;
388
		
373
389
		char currentChar = hookName.charAt(0);
374
		char currentChar = hookName.charAt(0);
390
		condition = (currentChar < 65 || currentChar > 90) && (currentChar < 97 || currentChar > 122);
375
		condition = (currentChar < 65 || currentChar > 90) && (currentChar < 97 || currentChar > 122);
391
		
376
392
		if (condition)
377
		if (condition)
393
			return condition;
378
			return condition;
394
		
379
395
		for (int i = 1; i < hookName.length(); i++)
380
		for (int i = 1; i < hookName.length(); i++) {
396
		{
397
			currentChar = hookName.charAt(i);
381
			currentChar = hookName.charAt(i);
398
			condition = (currentChar < 65 || currentChar > 90) && (currentChar < 97 || currentChar > 122) &&
382
			condition =
399
						(currentChar < 48 || currentChar > 57) && currentChar != 36 && currentChar != 95;
383
				(currentChar < 65 || currentChar > 90)
384
					&& (currentChar < 97 || currentChar > 122)
385
					&& (currentChar < 48 || currentChar > 57)
386
					&& currentChar != 36
387
					&& currentChar != 95;
400
			if (condition)
388
			if (condition)
401
				return condition;
389
				return condition;
402
		}
390
		}
403
		return false;
391
		return false;
404
	}
392
	}
405
393
394
	public class CustomVerHookListener implements VerificationHookListener {
406
395
407
	public class CustomVerHookListener implements VerificationHookListener
408
	{
409
		private String verHook;
396
		private String verHook;
410
		private AutoGUIGenerator generator; 
397
		private boolean extendedScope;
398
		private AutoGUIGenerator generator;
411
		private boolean instanceReady;
399
		private boolean instanceReady;
412
		
400
413
		public CustomVerHookListener(AutoGUIGenerator generator, String verificationHook)
401
		public CustomVerHookListener(AutoGUIGenerator generator, String verificationHook, boolean extendedScope) {
414
		{
415
			this.verHook = verificationHook;
402
			this.verHook = verificationHook;
403
			this.extendedScope = extendedScope;
416
			this.generator = generator;
404
			this.generator = generator;
417
			this.instanceReady = false;
405
			this.instanceReady = false;
418
		}
406
		}
419
		
407
420
		
408
		public synchronized void error(String error) {
421
		public synchronized void error(String error)
422
		{
423
			if (!instanceReady)
409
			if (!instanceReady)
424
				controllerDialog.setStatus(error);		
410
				controllerDialog.setStatus(error);
425
			else
411
			else
426
				controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_REC);
412
				controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_REC);
427
		}
413
		}
428
414
429
		public synchronized void instanceReady(VerificationCommand verificationCommand)
415
		public synchronized void instanceReady(VerificationCommand verificationCommand) {
430
		{
431
			instanceReady = true;
416
			instanceReady = true;
432
			/* We no longer need this class after being notified of the instance construciton */
417
			/* We no longer need this class after being notified of the instance construciton */
433
			MacroManager.getInstance().removeVerListener();
418
			MacroManager.getInstance().removeVerListener();
434
			
419
435
			controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_INS);
420
			controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_INS);
436
			
421
437
			/* We got the instance that we were looking for.  Time to generate the method in the source code that
438
			 * is associated with this test suite */					
439
			String argument = "Q";
440
			byte verificationContextType = verificationCommand.getMetaData().getFocusType();
441
			switch (verificationContextType)
442
			{
443
				case VerificationMetaData.EDITOR:
444
					argument += IEditorPart.class.getName();
445
					break;
446
				case VerificationMetaData.VIEW:
447
					argument += IViewPart.class.getName();
448
					break;
449
				case VerificationMetaData.SHELL:
450
					argument += Shell.class.getName();
451
					break;
452
			}
453
			argument = argument + ";";
454
			
455
			/* Insert a method in the source file corresponding to the name of the verification hook */
422
			/* Insert a method in the source file corresponding to the name of the verification hook */
456
			try
423
			try {
457
			{
424
				/*
425
				 * We got the instance that we were looking for. Time to generate the method in the source code that is associated with this test
426
				 * suite
427
				 */
428
				String contextArgument = "Q";
429
				contextArgument += verificationCommand.getContextClass().getName();
430
				contextArgument += ";";
431
432
				String[] args;
433
				if (!extendedScope) {
434
					args = new String[] {contextArgument};
435
				}
436
				else {
437
					// construct a second argument for the UI object being selected
438
					String widgetArgument = "Q";
439
					widgetArgument += verificationCommand.getWidgetClass().getName();
440
					widgetArgument += ";";
441
					
442
					String objectArgument = null;
443
					if(verificationCommand.getObjectClass() != null){
444
						objectArgument = "Q";
445
						objectArgument += verificationCommand.getObjectClass().getName();
446
						objectArgument += ";";						
447
					}
448
449
					args = objectArgument == null ? new String[2] : new String[3];
450
					args[0] = contextArgument;
451
					args[1] = widgetArgument;
452
					if(objectArgument != null){
453
						args[2] = objectArgument;
454
					}
455
				}
456
458
				/* This should never happen */
457
				/* This should never happen */
459
				if (argument.length() <= 2)
458
				if (contextArgument.length() <= 2)
460
					throw new Exception (AutoGUIMessages.AUTO_GUI_ERROR_VER_NOT_SUPP_CON);
459
					throw new Exception(AutoGUIMessages.AUTO_GUI_ERROR_VER_NOT_SUPP_CON);
461
					
460
462
				/* Complete the verification command's meta data */
461
				/* Complete the verification command's meta data */
463
				ITestSuite testSuite = ((AutoGUITestCasesForm)suiteProvider).getTestSuite();
462
				ITestSuite testSuite = ((AutoGUITestCasesForm) suiteProvider).getTestSuite();
464
				VerificationMetaData metaData = verificationCommand.getMetaData();
463
				verificationCommand.setLocation(testSuite.getImplementor().getLocation());
465
				metaData.setLocation(testSuite.getImplementor().getLocation());
464
				verificationCommand.setResource(testSuite.getImplementor().getResource());
466
				metaData.setResource(testSuite.getImplementor().getResource());
465
				verificationCommand.setHook(verHook + ":" + (args.length > 1 ? (args.length > 2 ? args[0] + args[1] + args[2] : args[0] + args[1]) : args[0]));
467
				metaData.setHook(verHook + ":" + argument);
466
				verificationCommand.setExtendedScope(extendedScope);
468
				
467
469
				generator.setInput(userInput.getName(), userInput.getDescription());
468
				generator.setInput(userInput.getName(),
470
				generator.createMethod (verHook, argument);
469
					userInput.getDescription());
471
			} catch (Exception e)
470
				generator.createMethod(verHook,
472
			{
471
					args);
472
			}
473
			catch (Exception e) {
473
				MessageDialog.openWarning(GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(),
474
				MessageDialog.openWarning(GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(),
474
										AutoGUIMessages.AUTO_GUI_ERROR_VER_GEN_METHOD_T,
475
					AutoGUIMessages.AUTO_GUI_ERROR_VER_GEN_METHOD_T,
475
										NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_VER_GEN_METHOD, e.getLocalizedMessage()));				
476
					NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_VER_GEN_METHOD,
477
						e.getLocalizedMessage()));
476
			}
478
			}
477
			
479
478
			/* Change the state of the macro manager to recording */
480
			/* Change the state of the macro manager to recording */
479
			if (globalStateListener != null)
481
			if (globalStateListener != null)
480
				globalStateListener.turnOn(false);
482
				globalStateListener.turnOn(false);
481
			MacroManager.getInstance().setGlobalState(MacroManager.RECORDING_MODE);
483
			MacroManager.getInstance().setGlobalState(ModeConstants.RECORDING_MODE);
482
			controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_REC);	
484
			controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_REC);
483
		
485
484
		}
486
		}
485
	
487
486
	}
488
	}
487
489
488
	
490
	public class CustomGlobalStateListener implements GlobalStateListener {
489
	public class CustomGlobalStateListener implements GlobalStateListener
490
	{
491
491
492
		private boolean isOn;
492
		private boolean isOn;
493
		
493
494
		public CustomGlobalStateListener(boolean isOn)
494
		public CustomGlobalStateListener(boolean isOn) {
495
		{
496
			this.isOn = isOn;
495
			this.isOn = isOn;
497
		}
496
		}
498
		
497
499
		public void turnOn (boolean isOn)
498
		public void turnOn(boolean isOn) {
500
		{
501
			this.isOn = isOn;
499
			this.isOn = isOn;
502
		}
500
		}
503
		
501
504
		public boolean isListenerOn()
502
		public boolean isListenerOn() {
505
		{
506
			return isOn;
503
			return isOn;
507
		}
504
		}
508
505
509
		public void globalStateChange(byte oldState, byte newState)
506
		public void globalStateChange(byte oldState, byte newState) {
510
		{
507
			/*
511
			/* We're only interested when we're in verification mode and we 
508
			 * We're only interested when we're in verification mode and we get interrupted
512
			 * get interrupted */
509
			 */
513
			if (oldState == MacroManager.VERIFICATION_MODE && newState == MacroManager.SUSPEND_MODE)
510
			if (oldState == ModeConstants.VERIFICATION_MODE && newState == ModeConstants.SUSPEND_MODE) {
514
			{
511
				controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_REC);
515
				controllerDialog.setStatus(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_REC);	
516
			}
512
			}
517
		}
513
		}
518
		
514
519
	}
515
	}
520
}
516
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/actions/AutoGUIUpdateTestCaseAction.java (-167 / +357 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2006, 2007 IBM Corporation and others.
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 15-310 Link Here
15
import java.util.Hashtable;
15
import java.util.Hashtable;
16
import java.util.Map;
16
import java.util.Map;
17
17
18
import org.eclipse.core.runtime.IPath;
19
import org.eclipse.core.runtime.Path;
18
import org.eclipse.jface.dialogs.MessageDialog;
20
import org.eclipse.jface.dialogs.MessageDialog;
19
import org.eclipse.jface.resource.ImageDescriptor;
21
import org.eclipse.jface.resource.ImageDescriptor;
20
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
22
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
21
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
23
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
22
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
24
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
23
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
25
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
24
import org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine;
25
import org.eclipse.tptp.test.auto.gui.internal.core.IUIObject;
26
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCasesForm;
26
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCasesForm;
27
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCasesForm.GUITestCaseProperties;
27
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCasesForm.GUITestCaseProperties;
28
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
28
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
29
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
29
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
30
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
30
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
31
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMineManager;
31
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptor;
32
import org.eclipse.tptp.test.auto.gui.internal.macro.UIObject;
32
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine;
33
import org.eclipse.tptp.test.auto.gui.internal.macro.XMLDefaultHandler;
33
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMineManager;
34
import org.eclipse.tptp.test.auto.gui.internal.util.XMLDefaultHandler;
34
import org.w3c.dom.NamedNodeMap;
35
import org.w3c.dom.NamedNodeMap;
35
import org.w3c.dom.Node;
36
import org.w3c.dom.Node;
36
import org.w3c.dom.NodeList;
37
import org.w3c.dom.NodeList;
37
38
38
/**
39
/**
39
 * This action will update the macro of the selected test cases to use the 
40
 * This action will update the macro of the selected test cases to use the
40
 * latest syntax of the macro.
41
 * latest syntax of the macro.
41
 * 
42
 * 
42
 * @author Ali Mehregani
43
 * @author Ali Mehregani
44
 * @author Alexander Nyssen
43
 */
45
 */
44
public class AutoGUIUpdateTestCaseAction extends AutoGUITestCaseAction
46
public class AutoGUIUpdateTestCaseAction extends AutoGUITestCaseAction
45
{
47
{
46
	/** Versions */
48
	/** Versions */
47
	private static final String VERSION_1_0 = "1.0";
49
	private static final String VERSION_1_0 = "1.0";
48
	
50
	private static final String VERSION_1_1 = "1.1";
49
	/** The updater table contains the method name that can update a particular version of a macro 
51
50
	 * KEY = The macro version that can be updated
52
	/**
51
	 * VALUE = The method name that will do the update
53
	 * The updater table contains the method name that can update a particular
54
	 * version of a macro KEY = The macro version that can be updated VALUE =
55
	 * The method name that will do the update
52
	 */
56
	 */
53
	private Map updaterTable;
57
	private Map updaterTable;
54
	
58
55
	/** The object mine that belongs to the test suite of this action */
59
	/** The object mine that belongs to the test suite of this action */
56
	private IObjectMine objectMine;
60
	private MacroObjectDescriptorMine objectMine;
57
	
61
58
	
62
	public AutoGUIUpdateTestCaseAction(AutoGUITestCasesForm testCaseForm,
59
	public AutoGUIUpdateTestCaseAction(AutoGUITestCasesForm testCaseForm, String text, ImageDescriptor imageDescriptor)
63
			String text, ImageDescriptor imageDescriptor) {
60
	{
61
		super(testCaseForm, text, imageDescriptor);
64
		super(testCaseForm, text, imageDescriptor);
62
		setEnabled(false);
65
		setEnabled(false);
63
		
66
64
		/* Initialize the updater table */
67
		/* Initialize the updater table */
65
		updaterTable = new Hashtable();					
68
		updaterTable = new Hashtable();
66
		final String VERSION_01 = "0.1";
69
		final String VERSION_0_1 = "0.1";
67
		final String UPDATER_01 = "updater01";
70
		final String UPDATER__0_1__1_0 = "Update_0_1_to_1_0";
68
		
71
		final String UPDATER__1_0__1_1 = "Update_1_0_to_1_1";
69
		updaterTable.put(VERSION_01, UPDATER_01);		
72
		updaterTable.put(VERSION_0_1, UPDATER__0_1__1_0);
73
		updaterTable.put(VERSION_1_0, UPDATER__1_0__1_1);
70
	}
74
	}
71
	
75
72
	
73
	/**
76
	/**
74
	 * Invoked when the action is executed.  Walk through each of the selected test cases 
77
	 * Invoked when the action is executed. Walk through each of the selected
75
	 * and update their corresponding macro.  
78
	 * test cases and update their corresponding macro.
76
	 */
79
	 */
77
	public void run() 
80
	public void run() {
78
	{		
81
		if (!MessageDialog.openQuestion(GuiPlugin.getDefault().getWorkbench()
79
		if (!MessageDialog.openQuestion(
82
				.getActiveWorkbenchWindow().getShell(),
80
				GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(), 
83
				AutoGUIMessages.AUTO_GUI_TST_CASE_UPDATE_TITLE,
81
				AutoGUIMessages.AUTO_GUI_TST_CASE_UPDATE_TITLE, 
84
				AutoGUIMessages.AUTO_GUI_TST_CASE_UPDATE)) {
82
				AutoGUIMessages.AUTO_GUI_TST_CASE_UPDATE))
83
		{
84
			return;
85
			return;
85
		}
86
		}
86
		
87
87
		try
88
		try {
88
		{
89
			objectMine = MacroObjectDescriptorMineManager.getInstance()
89
			objectMine = ObjectMineManager.getInstance().loadObjectMine(testCaseForm.getTestSuite());
90
					.loadObjectMine(testCaseForm.getTestSuite());
90
		} 
91
		} catch (Exception e) {
91
		catch (Exception e)
92
		{
93
			AutoGUIUtil.openErrorWithDetail(
92
			AutoGUIUtil.openErrorWithDetail(
94
					AutoGUIMessages.AUTO_GUI_COMMON_ERROR, 
93
					AutoGUIMessages.AUTO_GUI_COMMON_ERROR,
95
					AutoGUIMessages.AUTO_GUI_ERROR_MACRO_REC, 
94
					AutoGUIMessages.AUTO_GUI_ERROR_MACRO_REC, e);
96
					e);
97
			return;
95
			return;
98
		}
96
		}
99
		
97
100
		/* For each selected test case */
98
		/* For each selected test case */
101
		boolean updated = false;
99
		boolean updated = false;
102
		for (int i = 0; i < selectedTestCases.length; i++)
100
		for (int i = 0; i < selectedTestCases.length; i++) {
103
		{
104
			/* Parse the macro of the selected test case */
101
			/* Parse the macro of the selected test case */
105
			String testCaseMacro = testCaseForm.getProperty(selectedTestCases[i], GUITestCaseProperties.MACRO_FRAGMENT);
102
			String testCaseMacro = testCaseForm.getProperty(
103
					selectedTestCases[i], GUITestCaseProperties.MACRO_FRAGMENT);
106
			if (testCaseMacro == null || testCaseMacro.length() <= 0)
104
			if (testCaseMacro == null || testCaseMacro.length() <= 0)
107
				continue;
105
				continue;
108
			
106
109
			XMLDefaultHandler handler = null;
107
			XMLDefaultHandler handler = null;
110
			Node rootElement = null;
108
			Node rootElement = null;
111
			try
109
			try {
112
			{
110
				handler = MacroManager.getInstance().createMacroDocument(
113
				handler = MacroManager.getInstance().createMacroDocument(new ByteArrayInputStream(testCaseMacro.getBytes("UTF-8")));
111
						new ByteArrayInputStream(testCaseMacro
112
								.getBytes("UTF-8")));
114
				rootElement = handler.getDocumentElement();
113
				rootElement = handler.getDocumentElement();
115
			}
114
			} catch (Exception e) {
116
			catch (Exception e)
117
			{
118
				/* Handled by the next line */
115
				/* Handled by the next line */
119
			}
116
			}
120
			
117
121
			if (rootElement != null && !MacroConstants.MACRO_ELEMENT.equals(rootElement.getNodeName()))
118
			if (rootElement == null
119
					&& !MacroConstants.MACRO_ELEMENT.equals(rootElement
120
							.getNodeName()))
122
				continue;
121
				continue;
123
			
122
124
			
123
			/*
125
			/* Look up the current version of the macro and call its corresponding update method */
124
			 * Look up the current version of the macro and call its
126
			Node macroVersion = rootElement.getAttributes().getNamedItem(MacroConstants.VERSION_ATTRIBUTE);					
125
			 * corresponding update method
126
			 */
127
			Node macroVersion = rootElement.getAttributes().getNamedItem(
128
					MacroConstants.VERSION_ATTRIBUTE);
127
			String currentVersion;
129
			String currentVersion;
128
			if (macroVersion == null || (currentVersion = macroVersion.getNodeValue()) == null)
130
			if (macroVersion == null
131
					|| (currentVersion = macroVersion.getNodeValue()) == null)
129
				continue;
132
				continue;
130
									
133
131
			/* For every sequential update required */
134
			/* For every sequential update required */
132
			String updater = null;
135
			String updater = null;
133
			boolean updateTestCaseMacro = false;
136
			boolean updateTestCaseMacro = false;
134
			while ((updater = (String)updaterTable.get(currentVersion)) != null)
137
			while ((updater = (String) updaterTable.get(currentVersion)) != null) {
135
			{
138
				try {
136
				try
139
					Method method = this.getClass().getMethod(
137
				{
140
							updater,
138
					Method method = this.getClass().getMethod(updater, new Class[] {XMLDefaultHandler.class, IUIObject.class, Node.class});
141
							new Class[] { XMLDefaultHandler.class,
139
					if (method != null)
142
									MacroObjectDescriptor.class, Node.class });
140
					{
143
					if (method != null) {
141
						currentVersion = (String)(method.invoke(this, new Object[]{handler, null, rootElement}));
144
						currentVersion = (String) (method.invoke(this,
145
								new Object[] { handler, null, rootElement }));
142
						updateTestCaseMacro = true;
146
						updateTestCaseMacro = true;
143
					}
147
					} else {
144
					else
145
					{
146
						break;
148
						break;
147
					}												
149
					}
148
				} 
150
				} catch (Exception e) {
149
				catch (Exception e)
150
				{
151
					/* Should not happen */
151
					/* Should not happen */
152
					e.printStackTrace();
152
					e.printStackTrace();
153
					break;
153
					break;
154
				}
154
				}
155
			}
155
			}
156
			
156
157
			/* Update the test case macro and the object mine */
157
			/* Update the test case macro and the object mine */
158
			if (updateTestCaseMacro)
158
			if (updateTestCaseMacro) {
159
			{
160
				updated = true;
159
				updated = true;
161
				StringBuffer buffer = new StringBuffer();
160
				StringBuffer buffer = new StringBuffer();
162
				serializeXMLToString(buffer, rootElement, 0);
161
				serializeXMLToString(buffer, rootElement, 0);
163
				testCaseForm.updateTestProperty (null, buffer.toString(), false);		
162
				testCaseForm.updateTestProperty(null, buffer.toString(), false);
164
				
163
165
				ObjectMineManager.getInstance().writeObjectMine(objectMine);
164
				MacroObjectDescriptorMineManager.getInstance().writeObjectMine(
165
						objectMine);
166
				testCaseForm.refresh();
166
				testCaseForm.refresh();
167
			}			
167
			}
168
		}	
168
		}
169
		
169
170
		if (!updated)
170
		if (!updated) {
171
		{
171
			MessageDialog.openInformation(GuiPlugin.getDefault().getWorkbench()
172
			MessageDialog.openInformation(
172
					.getActiveWorkbenchWindow().getShell(),
173
					GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(), 
173
					AutoGUIMessages.AUTO_GUI_COMMON_INFORMATION,
174
					AutoGUIMessages.AUTO_GUI_COMMON_INFORMATION, 
175
					AutoGUIMessages.AUTO_GUI_TST_CASE_NO_UPDATE);
174
					AutoGUIMessages.AUTO_GUI_TST_CASE_NO_UPDATE);
176
		}
175
		}
177
	}
176
	}
178
	
177
179
	private void serializeXMLToString(StringBuffer buffer, Node node, int indent)
178
	private void serializeXMLToString(StringBuffer buffer, Node node, int indent) {
180
	{		
181
		/* Write the current element */
179
		/* Write the current element */
182
		boolean hasChildren = node.hasChildNodes();
180
		boolean hasChildren = node.hasChildNodes();
183
		boolean hasAttributes = node.hasAttributes();
181
		boolean hasAttributes = node.hasAttributes();
184
		String nodeName = node.getNodeName();
182
		String nodeName = node.getNodeName();
185
		final String TEXT_NODE_NAME = "#text";
183
		final String TEXT_NODE_NAME = "#text";
186
		
184
187
		if (TEXT_NODE_NAME.equals(nodeName))
185
		if (TEXT_NODE_NAME.equals(nodeName)) {
188
		{
189
			String textContent = node.getNodeValue().trim();
186
			String textContent = node.getNodeValue().trim();
190
			boolean isContentEmpty = textContent == null || MacroConstants.EMPTY_STRING.equals(textContent);; 
187
			boolean isContentEmpty = textContent == null
191
			if (!isContentEmpty)
188
					|| MacroConstants.EMPTY_STRING.equals(textContent);
192
			{
189
			;
190
			if (!isContentEmpty) {
193
				MacroUtil.addIndent(buffer, indent);
191
				MacroUtil.addIndent(buffer, indent);
194
				buffer.append(textContent);
192
				buffer.append(textContent);
195
				buffer.append(GlobalConstants.LINE_SEPARATOR);
193
				buffer.append(GlobalConstants.LINE_SEPARATOR);
196
			}
194
			}
197
			
195
198
			return;
196
			return;
199
		}
197
		}
200
			
198
201
		
199
		MacroUtil.addElement(buffer, indent, nodeName, !hasChildren
202
		MacroUtil.addElement(buffer, indent, nodeName, !hasChildren && !hasAttributes, !hasAttributes);
200
				&& !hasAttributes, !hasAttributes);
203
		
201
204
		/* Get the attributes */
202
		/* Get the attributes */
205
		if (hasAttributes)
203
		if (hasAttributes) {
206
		{
207
			NamedNodeMap attributes = node.getAttributes();
204
			NamedNodeMap attributes = node.getAttributes();
208
			int attCount = attributes.getLength();
205
			int attCount = attributes.getLength();
209
			String[] attributeNames = new String[attCount];
206
			String[] attributeNames = new String[attCount];
210
			String[] attributeValues = new String[attCount];
207
			String[] attributeValues = new String[attCount];
211
			for (int i = 0; i < attCount; i++)
208
			for (int i = 0; i < attCount; i++) {
212
			{
213
				Node currentAttribute = attributes.item(i);
209
				Node currentAttribute = attributes.item(i);
214
				attributeNames[i] = currentAttribute.getNodeName();
210
				attributeNames[i] = currentAttribute.getNodeName();
215
				attributeValues[i] = currentAttribute.getNodeValue();			
211
				attributeValues[i] = currentAttribute.getNodeValue();
216
			}
212
			}
217
			MacroUtil.addAttribute(buffer, attributeNames, attributeValues, !hasChildren, true);
213
			MacroUtil.addAttribute(buffer, attributeNames, attributeValues,
214
					!hasChildren, true);
218
		}
215
		}
219
		
216
220
		/* For each child */
217
		/* For each child */
221
		NodeList nodeList = node.getChildNodes();
218
		NodeList nodeList = node.getChildNodes();
222
		for (int i = 0, nodeListCount = nodeList.getLength(); i < nodeListCount; i++)
219
		for (int i = 0, nodeListCount = nodeList.getLength(); i < nodeListCount; i++) {
223
		{			
220
			serializeXMLToString(buffer, nodeList.item(i), indent + 1);
224
			serializeXMLToString (buffer, nodeList.item(i), indent + 1);
225
		}
221
		}
226
		
222
227
		/* Close the XML node */
223
		/* Close the XML node */
228
		if (hasChildren)
224
		if (hasChildren) {
229
		{
230
			MacroUtil.addElement(buffer, indent, nodeName, true, true);
225
			MacroUtil.addElement(buffer, indent, nodeName, true, true);
231
		}
226
		}
232
		
227
233
	}
228
	}
234
229
230
	/**
231
	 * Converts a prior 1.1 context id to the new 1.1. format (using separators
232
	 * instead of PATH.SEPARATOR)
233
	 * 
234
	 * @param oldContextId
235
	 * @return
236
	 */
237
	private String convertSerializedContextId(String oldContextId) {
238
		if (oldContextId != null
239
				&& (oldContextId.startsWith(MacroConstants.LOCAL_TOOLBAR_VALUE)
240
						|| oldContextId.startsWith(MacroConstants.POPUP_VALUE) || oldContextId
241
						.startsWith(MacroConstants.TAB_VALUE))
242
				&& oldContextId
243
						.indexOf(MacroConstants.WIDGET_ID_SUFFIX_SEPARATOR) < 0) {
244
			// may be old format (or the context id does not use a
245
			// nested serealized macro object id), have to convert
246
			IPath wpath = new Path(oldContextId);
247
			String widgetId = wpath.lastSegment();
248
			wpath = wpath.removeLastSegments(1);
249
			while (widgetId.startsWith("}}")) {
250
				widgetId = wpath.lastSegment() + IPath.SEPARATOR + widgetId;
251
				wpath = wpath.removeLastSegments(1);
252
			}
253
			String contextId = wpath.toString()
254
					+ MacroConstants.WIDGET_ID_SUFFIX_SEPARATOR + widgetId;
255
			return contextId;
256
		}
257
		return oldContextId;
258
	}
259
260
	/*
261
	 * Convert widget id where the object id was stored as suffix into distinct
262
	 * widget and object ids
263
	 */
264
	private String[] convertConcatWidgetId(String oldWidgetId) {
265
		if (oldWidgetId != null
266
				&& oldWidgetId
267
						.indexOf(MacroConstants.OBJECT_ID_SUFFIX_SEPARATOR) >= 0) {
268
			String[] uiObjectId = new String[2];
269
			uiObjectId[0] = oldWidgetId.substring(0, oldWidgetId
270
					.indexOf(MacroConstants.OBJECT_ID_SUFFIX_SEPARATOR));
271
			uiObjectId[1] = oldWidgetId.substring(oldWidgetId
272
					.indexOf(MacroConstants.OBJECT_ID_SUFFIX_SEPARATOR) + 3);
273
			return uiObjectId;
274
		}
275
		return new String[] { oldWidgetId };
276
	}
235
277
236
	public String updater01 (XMLDefaultHandler handler, IUIObject parent, Node rootNode)
278
	public String Update_1_0_to_1_1(XMLDefaultHandler handler,
237
	{
279
			MacroObjectDescriptor parent, Node rootNode) {
238
		NodeList nodeList = rootNode.getChildNodes();
280
		NodeList nodeList = rootNode.getChildNodes();
239
		Node currentNode;
281
		Node currentNode;
282
283
		/* Update the version of the macro */
284
		if (MacroConstants.MACRO_ELEMENT.equals(rootNode.getNodeName())) {
285
			NamedNodeMap rootAttributes = rootNode.getAttributes();
286
			Node versionAttribute = null;
287
			if (rootAttributes != null
288
					&& (versionAttribute = rootAttributes
289
							.getNamedItem(MacroConstants.VERSION_ATTRIBUTE)) != null) {
290
				versionAttribute.setNodeValue(VERSION_1_1);
291
			}
292
		}
293
294
		/* For each child */
295
		for (int i = 0, nodeListCount = nodeList.getLength(); i < nodeListCount; i++) {
296
			currentNode = nodeList.item(i);
297
			NamedNodeMap attributes = currentNode.getAttributes();
298
			if (attributes == null)
299
				continue;
300
301
			// Fix old context identifiers (serialized widget identifiers)
302
			if (attributes.getNamedItem(MacroConstants.CONTEXT_ID_ATTRIBUTE) != null) {
303
				Node contextIdAttributeNode = attributes
304
						.getNamedItem(MacroConstants.CONTEXT_ID_ATTRIBUTE);
305
				String oldContextId = contextIdAttributeNode.getNodeValue();
306
				String newContextId = convertSerializedContextId(oldContextId);
307
				if (!oldContextId.equals(newContextId)) {
308
					contextIdAttributeNode.setNodeValue(newContextId);
309
				}
310
			}
311
312
			// Replace old ID attribute of shell with WIDGET_ID (now used
313
			// globally)
314
			if (attributes.getNamedItem(MacroConstants.ID_ATTRIBUTE) != null) {
315
				Node idAttributeNode = attributes
316
						.getNamedItem(MacroConstants.ID_ATTRIBUTE);
317
				String widgetId = idAttributeNode.getNodeValue();
318
				attributes.removeNamedItem(MacroConstants.ID_ATTRIBUTE);
319
				Node widgetIdAttribute = handler.getDocument().createAttribute(
320
						MacroConstants.WIDGET_ID_ATTRIBUTE);
321
				widgetIdAttribute.setNodeValue(widgetId);
322
				attributes.setNamedItem(widgetIdAttribute);
323
			}
324
325
			// Fix old widget identifiers (that have the object id as suffix)
326
			if (attributes.getNamedItem(MacroConstants.WIDGET_ID_ATTRIBUTE) != null) {
327
				Node widgetIdAttributeNode = attributes
328
						.getNamedItem(MacroConstants.WIDGET_ID_ATTRIBUTE);
329
				String oldWidgetId = widgetIdAttributeNode.getNodeValue();
330
				String[] uiObjectId = convertConcatWidgetId(oldWidgetId);
331
				if (!oldWidgetId.equals(uiObjectId[0])) {
332
					widgetIdAttributeNode.setNodeValue(uiObjectId[0]);
333
					// we have an object id, add an object id
334
					if (uiObjectId.length > 1) {
335
						Node objectIdAttribute = handler.getDocument()
336
								.createAttribute(
337
										MacroConstants.OBJECT_ID_ATTRIBUTE);
338
						objectIdAttribute.setNodeValue(uiObjectId[1]);
339
						attributes.setNamedItem(objectIdAttribute);
340
					}
341
				}
342
			}
343
344
			// Replace old PATH attribute of item -> now also WIDGET_ID
345
			boolean isItem = MacroConstants.ITEM_ELEMENT.equals(currentNode
346
					.getNodeName())
347
					|| MacroConstants.SELECT_ITEM_ELEMENT.equals(currentNode
348
							.getNodeName());
349
			if (isItem
350
					&& attributes.getNamedItem(MacroConstants.PATH_ATTRIBUTE) != null) {
351
				Node idAttributeNode = attributes
352
						.getNamedItem(MacroConstants.PATH_ATTRIBUTE);
353
				String widgetId = idAttributeNode.getNodeValue();
354
				attributes.removeNamedItem(MacroConstants.PATH_ATTRIBUTE);
355
				Node widgetIdAttribute = handler.getDocument().createAttribute(
356
						MacroConstants.WIDGET_ID_ATTRIBUTE);
357
				widgetIdAttribute.setNodeValue(widgetId);
358
				attributes.setNamedItem(widgetIdAttribute);
359
			}
360
361
			// // replace the old CHOICE_ID attribute -> now the more general
362
			// OBJECT_ID can be used
363
			// if (attributes.getNamedItem(MacroConstants.CHOICE_ID_ATTRIBUTE)
364
			// != null) {
365
			// Node idAttributeNode = attributes
366
			// .getNamedItem(MacroConstants.CHOICE_ID_ATTRIBUTE);
367
			// String objectId = idAttributeNode.getNodeValue();
368
			// attributes.removeNamedItem(MacroConstants.CHOICE_ID_ATTRIBUTE);
369
			// Node objectIdAttribute = handler.getDocument().createAttribute(
370
			// MacroConstants.OBJECT_ID_ATTRIBUTE);
371
			// objectIdAttribute.setNodeValue(objectId);
372
			// attributes.setNamedItem(objectIdAttribute);
373
			// }
374
375
			// if the object is stored in the object mine, make sure the old
376
			// context id is converted
377
			Node refIdNode = attributes
378
					.getNamedItem(MacroConstants.REFERENCE_ID_ATTRIBUTE);
379
			String refId = refIdNode == null ? null : refIdNode.getNodeValue();
380
			boolean isShell = MacroConstants.SHELL_ELEMENT.equals(currentNode
381
					.getNodeName());
382
383
			MacroObjectDescriptor descriptor = null;
384
			if (refId != null) {
385
				descriptor = objectMine.lookupMacroObjectDescriptor(
386
						isShell ? null : parent, refId);
387
				// fix the context id
388
				if (descriptor != null) {
389
					descriptor
390
							.setContextId(convertSerializedContextId(descriptor
391
									.getContextId()));
392
				}
393
394
				// NOTE: the object id was not stored as suffix of the widget id up to now (due to a bug),
395
				// so we do not have to convert it here.
240
				
396
				
397
				// the ID -> WIDGET_ID conversion is done implicitly for the
398
				// stored descriptors when saving the object mine
399
			}
400
401
			if (currentNode.hasChildNodes())
402
				Update_1_0_to_1_1(handler, descriptor == null ? parent
403
						: descriptor, currentNode);
404
405
		}
406
		return VERSION_1_1;
407
	}
408
409
	public String Update_0_1_to_1_0(XMLDefaultHandler handler,
410
			MacroObjectDescriptor parent, Node rootNode) {
411
		NodeList nodeList = rootNode.getChildNodes();
412
		Node currentNode;
413
241
		/* Update the version of the macro */
414
		/* Update the version of the macro */
242
		if (MacroConstants.MACRO_ELEMENT.equals(rootNode.getNodeName()))
415
		if (MacroConstants.MACRO_ELEMENT.equals(rootNode.getNodeName())) {
243
		{
244
			NamedNodeMap rootAttributes = rootNode.getAttributes();
416
			NamedNodeMap rootAttributes = rootNode.getAttributes();
245
			Node versionAttribute = null;
417
			Node versionAttribute = null;
246
			if (rootAttributes != null && (versionAttribute = rootAttributes.getNamedItem(MacroConstants.VERSION_ATTRIBUTE)) != null)
418
			if (rootAttributes != null
247
			{
419
					&& (versionAttribute = rootAttributes
420
							.getNamedItem(MacroConstants.VERSION_ATTRIBUTE)) != null) {
248
				versionAttribute.setNodeValue(VERSION_1_0);
421
				versionAttribute.setNodeValue(VERSION_1_0);
249
			}
422
			}
250
		}
423
		}
251
		
424
252
		/* For each child */
425
		/* For each child */
253
		for (int i = 0, nodeListCount = nodeList.getLength(); i < nodeListCount; i++)
426
		for (int i = 0, nodeListCount = nodeList.getLength(); i < nodeListCount; i++) {
254
		{			
255
			currentNode = nodeList.item(i);
427
			currentNode = nodeList.item(i);
256
			NamedNodeMap attributes = currentNode.getAttributes();
428
			NamedNodeMap attributes = currentNode.getAttributes();
257
			if (attributes == null)
429
			if (attributes == null)
258
				continue;
430
				continue;
259
			
431
260
			Node contextIdNode = attributes.getNamedItem(MacroConstants.CONTEXT_ID_ATTRIBUTE);
432
			Node contextIdNode = attributes
261
			boolean isShell = MacroConstants.SHELL_ELEMENT.equals(currentNode.getNodeName());
433
					.getNamedItem(MacroConstants.CONTEXT_ID_ATTRIBUTE);
262
			boolean isItem = MacroConstants.ITEM_ELEMENT.equals(currentNode.getNodeName()) || MacroConstants.SELECT_ITEM_ELEMENT.equals(currentNode.getNodeName());
434
			boolean isShell = MacroConstants.SHELL_ELEMENT.equals(currentNode
263
			String idAttributeName =  isShell ? MacroConstants.ID_ATTRIBUTE : isItem ? MacroConstants.PATH_ATTRIBUTE : MacroConstants.WIDGET_ID_ATTRIBUTE;
435
					.getNodeName());
264
			Node objectIdNode = attributes.getNamedItem(idAttributeName);
436
			boolean isItem = MacroConstants.ITEM_ELEMENT.equals(currentNode
265
					
437
					.getNodeName())
266
			String contextId = contextIdNode == null ? null : contextIdNode.getNodeValue();
438
					|| MacroConstants.SELECT_ITEM_ELEMENT.equals(currentNode
267
			String objectId = objectIdNode == null ? null : objectIdNode.getNodeValue();
439
							.getNodeName());
268
			
440
			String idAttributeName = isShell ? MacroConstants.ID_ATTRIBUTE
269
			IUIObject uiObject = null;
441
					: isItem ? MacroConstants.PATH_ATTRIBUTE
270
			if (objectId != null)		
442
							: MacroConstants.WIDGET_ID_ATTRIBUTE;
271
			{
443
			Node widgetIdNode = attributes.getNamedItem(idAttributeName);
272
				uiObject = objectMine.lookupUIObject(isShell ? null : parent, contextId, objectId);
444
273
				if (uiObject == null)
445
			String contextId = contextIdNode == null ? null : contextIdNode
274
				{
446
					.getNodeValue();
275
					try
447
			String widgetId = widgetIdNode == null ? null : widgetIdNode
276
					{
448
					.getNodeValue();
277
						uiObject = new UIObject(parent);
449
278
						uiObject.setContextId(contextId);
450
			MacroObjectDescriptor uiObject = null;
279
						uiObject.setDescriptive(attributes.getNamedItem(MacroConstants.DESCRIPTIVE_ATTRIBUTE) == null ? MacroConstants.OBJECT_ELEMENT : attributes.getNamedItem(MacroConstants.DESCRIPTIVE_ATTRIBUTE).getNodeValue());
451
			if (widgetId != null) {
280
						uiObject.setObjectId(objectId);
452
				uiObject = objectMine.lookupMacroObjectDescriptor(
281
						uiObject.setParent(isShell ? null : parent);
453
						isShell ? null : parent, contextId, widgetId, null);
282
						uiObject.setReferenceId(objectMine.getUniqueReferenceId());
454
				if (uiObject == null) {
283
						
455
					try {
284
						objectMine.registerObject(uiObject);
456
						uiObject = new MacroObjectDescriptor(parent);
285
					} 
457
						((MacroObjectDescriptor) uiObject)
286
					catch (Exception e)
458
								.setContextId(contextId);
287
					{
459
						((MacroObjectDescriptor) uiObject)
460
								.setDescriptive(attributes
461
										.getNamedItem(MacroConstants.DESCRIPTIVE_ATTRIBUTE) == null ? MacroConstants.OBJECT_ELEMENT
462
										: attributes
463
												.getNamedItem(
464
														MacroConstants.DESCRIPTIVE_ATTRIBUTE)
465
												.getNodeValue());
466
						((MacroObjectDescriptor) uiObject)
467
								.setWidgetId(widgetId);
468
						((MacroObjectDescriptor) uiObject).setObjectId(null);
469
						((MacroObjectDescriptor) uiObject)
470
								.setParent(isShell ? null : parent);
471
						objectMine
472
								.registerObject((MacroObjectDescriptor) uiObject);
473
					} catch (Exception e) {
288
						/* Shouldn't happen */
474
						/* Shouldn't happen */
289
						e.printStackTrace();
475
						e.printStackTrace();
290
					}
476
					}
291
				}
477
				}
292
				
478
293
				if (uiObject != null)
479
				if (uiObject != null) {
294
				{
295
					if (contextId != null)
480
					if (contextId != null)
296
						attributes.removeNamedItem(MacroConstants.CONTEXT_ID_ATTRIBUTE);
481
						attributes
482
								.removeNamedItem(MacroConstants.CONTEXT_ID_ATTRIBUTE);
297
					attributes.removeNamedItem(idAttributeName);
483
					attributes.removeNamedItem(idAttributeName);
298
					Node refIdAttribute = handler.getDocument().createAttribute(MacroConstants.REFERENCE_ID_ATTRIBUTE);
484
					Node refIdAttribute = handler.getDocument()
299
					refIdAttribute.setNodeValue(uiObject.getReferenceId());					
485
							.createAttribute(
486
									MacroConstants.REFERENCE_ID_ATTRIBUTE);
487
					refIdAttribute.setNodeValue(uiObject.getReferenceId());
300
					attributes.setNamedItem(refIdAttribute);
488
					attributes.setNamedItem(refIdAttribute);
301
				}
489
				}
302
			}
490
			}
303
			
491
304
			if (currentNode.hasChildNodes())
492
			if (currentNode.hasChildNodes())
305
				updater01(handler, uiObject == null ? parent : uiObject, currentNode);
493
				Update_0_1_to_1_0(handler,
494
						uiObject == null ? parent : uiObject, currentNode);
306
		}
495
		}
307
		
496
308
		return VERSION_1_0;
497
		return VERSION_1_0;
309
	}
498
	}
499
310
}
500
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/actions/AutoGUIPlayAction.java (-2 / +4 lines)
Lines 17-22 Link Here
17
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCasesForm;
17
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCasesForm;
18
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCasesForm.GUITestCaseProperties;
18
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCasesForm.GUITestCaseProperties;
19
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
19
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
20
import org.eclipse.tptp.test.auto.gui.internal.macro.ModeConstants;
20
import org.eclipse.tptp.test.auto.gui.internal.runner.AutoGUIRunner;
21
import org.eclipse.tptp.test.auto.gui.internal.runner.AutoGUIRunner;
21
import org.eclipse.tptp.test.auto.gui.internal.runner.ExtendedScriptParser;
22
import org.eclipse.tptp.test.auto.gui.internal.runner.ExtendedScriptParser;
22
import org.eclipse.tptp.test.auto.gui.internal.runner.AutoGUIRunner.ITestRunnerDelegator;
23
import org.eclipse.tptp.test.auto.gui.internal.runner.AutoGUIRunner.ITestRunnerDelegator;
Lines 31-36 Link Here
31
 * 
32
 * 
32
 * @author      Ali Mehregani
33
 * @author      Ali Mehregani
33
 * @author      Paul E. Slauenwhite
34
 * @author      Paul E. Slauenwhite
35
 * @author      Alexander Nyssen
34
 * @version     March 5, 2008
36
 * @version     March 5, 2008
35
 * @since       March 17, 2006
37
 * @since       March 17, 2006
36
 */
38
 */
Lines 56-62 Link Here
56
	public void run()
58
	public void run()
57
	{	
59
	{	
58
		/* Change the state of the macro manager */
60
		/* Change the state of the macro manager */
59
		MacroManager.getInstance().setGlobalState(MacroManager.QUICK_RUN_MODE);
61
		MacroManager.getInstance().setGlobalState(ModeConstants.QUICK_RUN_MODE);
60
		
62
		
61
		/* This handler attempts to closely simulate the environment set before the 
63
		/* This handler attempts to closely simulate the environment set before the 
62
		 * auto gui runner is executed.  This is important in order to make the quick
64
		 * auto gui runner is executed.  This is important in order to make the quick
Lines 98-104 Link Here
98
			public void run() 
100
			public void run() 
99
			{			
101
			{			
100
				/* Change the state back to idle */
102
				/* Change the state back to idle */
101
				MacroManager.getInstance().setGlobalState(MacroManager.IDLE_MODE);
103
				MacroManager.getInstance().setGlobalState(ModeConstants.IDLE_MODE);
102
				
104
				
103
				/* Re-store perspective */
105
				/* Re-store perspective */
104
				try
106
				try
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/UIObject.java (-260 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macro;
12
13
import java.util.ArrayList;
14
import java.util.Hashtable;
15
import java.util.LinkedList;
16
import java.util.Map;
17
18
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.osgi.util.NLS;
20
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
21
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
22
import org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand;
23
import org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine;
24
import org.eclipse.tptp.test.auto.gui.internal.core.IUIObject;
25
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
26
27
public class UIObject implements IUIObject
28
{
29
	/** The context id */
30
	private String contextId;
31
	
32
	/** The id of the object being resolved */
33
	private String objectId;
34
	
35
	/** The reference id of this UI object */
36
	private String referenceId;
37
	
38
	/** The descriptive attribute (a human readable identification) of this UI object */
39
	private String descriptive;
40
	
41
	/** Keeps track of the hierarchical relationship */
42
	private LinkedList hierarchicalRelation;
43
	
44
	/** The parent of this UI object */
45
	private IUIObject parent;
46
	
47
	/** The properties of this UI Object */
48
	private Hashtable properties;
49
50
	/** The id of the resolver that has resolved this object */
51
	private String resolverId;
52
	
53
	/** The children of this object */
54
	private ArrayList children;
55
56
	/** The associated data of this object */
57
	private Object data;
58
	
59
	/** Children indexed based on their reference id
60
	 * KEY = Reference id
61
	 * VALUE = IUIObject that is a child of this object
62
	 */
63
	private Hashtable idIndexedChildren;
64
	
65
	public UIObject(IUIObject parent)
66
	{
67
		this.parent = parent;
68
		properties = new Hashtable();
69
		children = new ArrayList();
70
		idIndexedChildren = new Hashtable();
71
	}
72
	
73
	
74
	/**
75
	 * Creates an instace of this class based on a command passed in.
76
	 * 
77
	 * @param objectMine The object mine that this object will be registered with
78
	 * @param command The command that this object will be based on
79
	 * @param parent The parent of this object
80
	 * 
81
	 * @return An instance of this class based on widgetIdentifier 
82
	 */
83
	public static IUIObject createInstance(IObjectMine objectMine, AbstractMacroCommand command, IUIObject parent)
84
	{
85
		WidgetIdentifier widgetIdentifier = command.getWidgetId();
86
		IUIObject uiObject = new UIObject (parent);
87
		uiObject.setContextId(widgetIdentifier.getContextId() != null ? widgetIdentifier.getContextId().toString() : MacroConstants.EMPTY_STRING);
88
		uiObject.setObjectId(widgetIdentifier.getObjectId().toString());
89
		uiObject.setReferenceId(objectMine.getUniqueReferenceId());
90
		uiObject.setDescriptive(command.getDescriptiveField());
91
		uiObject.setResolver(widgetIdentifier.getResolverId());
92
				
93
		return uiObject;
94
	}
95
	
96
	
97
	public String getContextId()
98
	{
99
		return contextId;
100
	}
101
102
	public String getDescriptive()
103
	{
104
		return descriptive;
105
	}
106
107
	public LinkedList getHierarchicalRelation()
108
	{
109
		if (hierarchicalRelation != null)
110
			return hierarchicalRelation;
111
		
112
		hierarchicalRelation = new LinkedList();
113
		findHierarchicalRelation(this);
114
		
115
		return hierarchicalRelation;
116
	}
117
	
118
	private void findHierarchicalRelation(IUIObject currentObject)
119
	{
120
		if (currentObject == null)
121
			return;
122
		hierarchicalRelation.addFirst(currentObject);
123
		findHierarchicalRelation(currentObject.getParent());
124
	}
125
126
	public String getObjectId()
127
	{
128
		return objectId;
129
	}
130
131
	public Map getProperties()
132
	{
133
		return properties;
134
	}
135
136
	public String getProperty(String name)
137
	{
138
		return (String)properties.get(name);
139
	}
140
141
	public String getReferenceId()
142
	{
143
		return referenceId;
144
	}
145
146
	public void setContextId(String contextId)
147
	{
148
		this.contextId = contextId;
149
	}
150
151
	public void setDescriptive(String descriptive)
152
	{
153
		this.descriptive = descriptive;
154
	}
155
156
	public void setObjectId(String id)
157
	{
158
		this.objectId = id;
159
	}
160
161
	public void addProperty(String name, String value)
162
	{
163
		properties.put(name, value);
164
	}
165
166
	public void setReferenceId(String referenceId)
167
	{
168
		this.referenceId = referenceId;
169
	}
170
	
171
	public IUIObject getParent()
172
	{
173
		return parent;
174
	}
175
176
	public void setParent(IUIObject parent)
177
	{
178
		this.parent = parent;
179
	}
180
181
182
	public String getResolverId()
183
	{		
184
		return resolverId;
185
	}
186
187
188
	public void setResolver(String resolverId)
189
	{
190
		this.resolverId = resolverId;
191
	}
192
193
194
	public void addChild(IUIObject child) throws CoreException
195
	{
196
		if (!children.contains(child))
197
		{
198
			try
199
			{
200
				/* If there is a collision, then try to resolve it */
201
				int referenceId = Integer.parseInt(child.getReferenceId());
202
				while (idIndexedChildren.get(child.getReferenceId()) != null)
203
				{
204
					referenceId++; 
205
				}
206
				child.setReferenceId(String.valueOf(referenceId));
207
			}
208
			catch (NumberFormatException nfe)
209
			{
210
				/* Ignore the error */
211
			}
212
			
213
			/* If there is still a collision, then throw an exception */
214
			if (idIndexedChildren.get(child.getReferenceId()) != null)
215
				AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE_ID, child.getReferenceId()));
216
			
217
			idIndexedChildren.put(child.getReferenceId(), child);
218
			children.add(child);
219
		}
220
	}
221
222
223
	public int childCount()
224
	{
225
		return children.size();
226
	}
227
228
229
	public IUIObject[] getChildren()
230
	{
231
		IUIObject[] objects = new IUIObject[children.size()];
232
		children.toArray(objects);
233
		return objects;
234
	}
235
236
237
	public IUIObject removeChild(IUIObject child)
238
	{
239
		children.remove(child);
240
		return child;
241
	}
242
243
244
	public Object getData()
245
	{
246
		return data;
247
	}
248
249
250
	public void setData(Object data)
251
	{
252
		this.data = data;
253
	}
254
255
256
	public IUIObject findChild(String referenceId)
257
	{
258
		return (IUIObject) idIndexedChildren.get(referenceId);
259
	}
260
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/ObjectMineManager.java (-395 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006, 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macro;
12
13
import java.io.ByteArrayInputStream;
14
import java.io.IOException;
15
import java.util.Hashtable;
16
import java.util.List;
17
18
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.core.runtime.IPath;
20
import org.eclipse.core.runtime.Path;
21
import org.eclipse.emf.common.util.URI;
22
import org.eclipse.emf.ecore.EObject;
23
import org.eclipse.emf.ecore.resource.Resource;
24
import org.eclipse.hyades.models.common.facades.behavioral.ITestSuite;
25
import org.eclipse.hyades.models.common.facades.behavioral.impl.HyadesUtil;
26
import org.eclipse.hyades.test.core.util.EMFUtil;
27
import org.eclipse.osgi.util.NLS;
28
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
29
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
30
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
31
import org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine;
32
import org.eclipse.tptp.test.auto.gui.internal.core.IUIObject;
33
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMine.IDCollisionException;
34
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMine.UIObjectNotFound;
35
import org.w3c.dom.NamedNodeMap;
36
import org.w3c.dom.Node;
37
import org.w3c.dom.NodeList;
38
import org.xml.sax.SAXException;
39
40
41
/**
42
 * In addition to the macro of each test case, a test suite also contains an object
43
 * mine keeps a reference of all resolved objects.  The purpose of the object mine
44
 * is to resolve a widget once and use it many times. 
45
 * <p/>
46
 * This is a singleton class that can be accessed via <code>getInstance()</code>
47
 * <p/>
48
 * 
49
 * 
50
 * @author  Ali Mehregani
51
 * @author  Paul E. Slauenwhite
52
 * @version March 7, 2008
53
 * @since   July 10, 2006
54
 */
55
public class ObjectMineManager 
56
{	
57
	/** The instance of this class */
58
	private static ObjectMineManager instance = new ObjectMineManager();
59
		
60
	
61
	/** Cached object mines 
62
	 * KEY = Test suite id
63
	 * VALUE = An object of type IObjectMine that represents the object mine of the test suite */	
64
	private Hashtable cachedObjectMines;
65
	
66
	
67
	/** Indicates whether a test suite's object mine is dirty or not
68
	 * KEY = test suite id
69
	 * VALUE = Boolean.TRUE if object mine is dirty; Boolean.FALSE otherwise  
70
	 */
71
	private Hashtable dirtyStateTable;
72
	
73
	
74
	/**
75
	 * Restrict the visibility of the constructor
76
	 */
77
	private ObjectMineManager()
78
	{
79
		cachedObjectMines = new Hashtable();
80
		dirtyStateTable = new Hashtable();
81
	}
82
	
83
	
84
	/**
85
	 * Return the instance of this singleton class
86
	 * 
87
	 * @return The instance of this class
88
	 */
89
	public static ObjectMineManager getInstance()
90
	{
91
		return instance;
92
	}
93
	
94
	
95
	/**
96
	 * Load the object mine of the passed in test suite
97
	 * 
98
	 * @param testSuite The test suite whose object mine is requested
99
	 * @param useCache Uses the cached value if this is set to true; otherwise the
100
	 * object mine is reloaded and returned.
101
	 * 
102
	 * @return the object mine of the test suite that is passed in.
103
	 * 
104
	 * @throws UIObjectNotFound In case an expected object is not found
105
	 * @throws IDCollisionException  In case there is a collision id
106
	 * @throws CoreException In case of any unexpected error
107
	 */
108
	public IObjectMine loadObjectMine (ITestSuite testSuite, boolean useCache) throws UIObjectNotFound, IDCollisionException, CoreException
109
	{
110
		/* Is the object mine in cache? */
111
		String testSuiteId = testSuite.getId();
112
		IObjectMine objectMine = null;
113
		if (useCache && (objectMine = (IObjectMine)cachedObjectMines.get(testSuiteId)) != null)
114
		{
115
			objectMine.setOwner(testSuite);
116
			return objectMine;
117
		}
118
			
119
		
120
		/* Otherwise, it needs to be loaded.  We need:
121
		 * - Get the object mine XML fragment
122
		 * - Parse it and load it */
123
		String objectMineXML = HyadesUtil.getTestSuiteVariable(testSuite, GlobalConstants.TEST_SUITE_PROPERTY_OBJECT_MINE);
124
		if (objectMineXML == null || objectMineXML.length() <= 0)
125
		{
126
			/* Return a fresh object mine */
127
			objectMine = new ObjectMine(testSuite, null);			
128
		}
129
			
130
		if (objectMine == null)
131
		{
132
			objectMine = loadObjectMine (testSuite, objectMineXML);
133
		}
134
		
135
		if (objectMine != null)
136
		{
137
			cachedObjectMines.put(testSuiteId, objectMine);
138
		}
139
		
140
		return objectMine;
141
	}
142
143
	private IObjectMine loadObjectMine (ITestSuite testSuite, String objectMineXML) throws UIObjectNotFound, IDCollisionException, CoreException
144
	{
145
		if (objectMineXML == null || objectMineXML.length() <= 0)
146
			return new ObjectMine(testSuite, null);
147
		
148
		XMLDefaultHandler handler = null;
149
150
		try
151
		{
152
			handler = MacroUtil.createXMLDocument(new ByteArrayInputStream(objectMineXML.getBytes("UTF-8")));
153
		}
154
		catch (SAXException e)
155
		{
156
			AutoGUIUtil.throwCoreException(AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE, 0, e);
157
		}
158
		catch (IOException e)
159
		{
160
			AutoGUIUtil.throwCoreException(AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE, 0, e);
161
		}
162
			
163
		/* Walk through the elemets and parse the document */
164
		Node rootElement = handler.getDocumentElement();
165
		NodeList children = rootElement.getChildNodes();
166
		
167
		IObjectMine objectMine = new ObjectMine(testSuite, handler);
168
		for (int i = 0, childCount = children.getLength(); i < childCount; i++)
169
		{
170
			Node currentChild = children.item(i);
171
			String nodeName = currentChild.getNodeName();
172
			if (MacroConstants.HEADER_ELEMENT.equals(nodeName))
173
			{
174
				loadHeader(objectMine, currentChild);
175
			}
176
			else if (MacroConstants.OBJECTS_ELEMENT.equals(nodeName))
177
			{
178
				loadObjects (objectMine, currentChild);
179
			}
180
		}
181
		
182
		
183
		return objectMine;
184
	}
185
	
186
	
187
	/**
188
	 * This method should be used if the object mine will be loaded for reading purposes.
189
	 * Contributors will not be able to use this returned object mine to write any objects.
190
	 * 
191
	 * @param objectMineXML The XML string representing the object mine 
192
	 * 
193
	 * @return the object mine of the test suite that is passed in.
194
	 * 
195
	 * @throws UIObjectNotFound In case an expected object is not found
196
	 * @throws IDCollisionException  In case there is a collision id
197
	 * @throws CoreException In case of any unexpected error
198
	 */
199
	public IObjectMine loadObjectMine (String objectMineXML) throws UIObjectNotFound, IDCollisionException, CoreException
200
	{
201
		return loadObjectMine(null, objectMineXML);
202
	}
203
	
204
	
205
	private void loadHeader(IObjectMine objectMine, Node headerNode) throws CoreException, UIObjectNotFound, IDCollisionException
206
	{
207
		/* Let's first read in the contribute attribute */
208
		NamedNodeMap attributes = headerNode.getAttributes();
209
		Node contributeAtt = attributes.getNamedItem(MacroConstants.OUTPUT_ATTRIBUTE);
210
		if (contributeAtt != null)
211
		{
212
			ITestSuite testSuite = loadTestSuite(contributeAtt.getNodeValue());
213
			if (testSuite == null)
214
			{
215
				AutoGUIUtil.openErrorWithDetail(
216
						AutoGUIMessages.AUTO_GUI_COMMON_ERROR, 
217
						AutoGUIMessages.AUTO_GUI_ERROR_OBJ_MINE_OUT_NF, 
218
						null);
219
				
220
			}
221
			else
222
			{
223
				try
224
				{
225
					IObjectMine outputObjectMine = ObjectMineManager.getInstance().loadObjectMine(testSuite);
226
					objectMine.setOutputSource(outputObjectMine);
227
				} 
228
				catch (Exception e)
229
				{					
230
					objectMine.setOutputSource(null);
231
					AutoGUIUtil.openErrorWithDetail(
232
							AutoGUIMessages.AUTO_GUI_COMMON_ERROR, 
233
							NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_OBJ_MINE_OUTPUT, testSuite.getName()), 
234
							e);
235
				} 
236
			}			
237
		}
238
		
239
		/* Now load in all includes */
240
		NodeList children = headerNode.getChildNodes();
241
		for (int i = 0, childCount = children.getLength(); i < childCount; i++)
242
		{
243
			Node currentChild = children.item(i);
244
			String nodeName = currentChild.getNodeName();
245
			if (MacroConstants.INCLUDE_ELEMENT.equals(nodeName))
246
			{
247
				Node pathAttribute = currentChild.getAttributes().getNamedItem(MacroConstants.PATH_ATTRIBUTE);
248
				if (pathAttribute != null)
249
				{
250
					ITestSuite testSuite = loadTestSuite(pathAttribute.getNodeValue());
251
					IObjectMine includedObjectMine = loadObjectMine(testSuite);
252
					objectMine.addInclude(includedObjectMine);
253
				}
254
			}
255
		}
256
	}
257
	
258
	
259
	private void loadObjects(IObjectMine objectMine, Node objectsNode) throws CoreException, UIObjectNotFound, IDCollisionException 
260
	{
261
		NodeList children = objectsNode.getChildNodes();		
262
		registerObjects(objectMine, null, children);
263
	}
264
	
265
	
266
	private void registerObjects(IObjectMine objectMine, IUIObject parent, NodeList children) throws CoreException, UIObjectNotFound, IDCollisionException
267
	{
268
		/* For every object */
269
		for (int i = 0, childCount = children.getLength(); i < childCount; i++)
270
		{
271
			Node currentNode = children.item(i);	
272
273
			NamedNodeMap attributes = currentNode.getAttributes();
274
			Node referenceIdNode = attributes.getNamedItem(MacroConstants.REFERENCE_ID_ATTRIBUTE);
275
			String referenceId = null;
276
			if (referenceIdNode == null || (referenceId = referenceIdNode.getNodeValue()) == null)
277
			{
278
				Node idAttribute = attributes.getNamedItem(MacroConstants.ID_ATTRIBUTE);
279
				String objectId = idAttribute == null ? AutoGUIMessages.AUTO_GUI_COMMON_UNKNOWN : idAttribute.getNodeValue(); 
280
				AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE_REF, objectId), 0);
281
			}
282
				
283
			IUIObject guiObject = objectMine.lookupUIObject(parent, referenceId);
284
				
285
			/* Register the object if it's not yet registered */
286
			if (guiObject == null)
287
			{
288
				guiObject = objectMine.registerObject(parent, currentNode);
289
			}
290
			/* Otherwise throw an exception if there is an id collision */
291
			else
292
			{
293
				Node contextIdNode = attributes.getNamedItem(MacroConstants.CONTEXT_ID_ATTRIBUTE);
294
				Node objectIdNode = attributes.getNamedItem(MacroConstants.ID_ATTRIBUTE);
295
				String contextId = contextIdNode == null ? null : contextIdNode.getNodeValue();
296
				String objectId = objectIdNode.getNodeValue();
297
				
298
				if (((contextId == null && guiObject.getContextId() != null) || 
299
					(contextId != null && !contextId.equals(guiObject.getContextId()))) ||
300
					!objectId.equals(guiObject.getObjectId()))
301
				{
302
					throw new IDCollisionException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE_ID, referenceId));
303
				}
304
			}
305
306
			/* Load the children of this object */
307
			if (currentNode.getChildNodes().getLength() > 0)
308
				registerObjects(objectMine, guiObject, currentNode.getChildNodes());				
309
		}			
310
	}
311
312
313
	private ITestSuite loadTestSuite(String testSuitePath) throws CoreException
314
	{
315
		if (testSuitePath == null || testSuitePath.length() <= 0)
316
			return null;
317
		
318
		IPath path = new Path(testSuitePath);
319
		URI uri = URI.createPlatformResourceURI(path.toString());
320
		EObject[] eObjects = EMFUtil.getEObjects(uri, true);
321
		return eObjects != null && eObjects.length > 0 && eObjects[0] instanceof ITestSuite ? (ITestSuite)eObjects[0] : null;
322
	}
323
	
324
	
325
	public void writeObjectMine(IObjectMine objectMine)
326
	{
327
		writeObjectMine (objectMine, false);
328
	}
329
	
330
	private void writeObjectMine(IObjectMine objectMine, boolean autoSave)
331
	{
332
		ITestSuite testSuite = objectMine.getOwner();
333
		Resource testSuiteResource = ((EObject)testSuite).eResource();
334
		autoSave = autoSave && (testSuiteResource != null && !testSuiteResource.isModified());
335
		
336
		String xmlSerialization = objectMine.serializeToString();
337
		HyadesUtil.setTestSuiteVariable(testSuite, GlobalConstants.TEST_SUITE_PROPERTY_OBJECT_MINE, xmlSerialization);		
338
		
339
		if (autoSave)
340
		{			
341
			try
342
			{
343
				EMFUtil.save(testSuiteResource);
344
			} catch (Exception e)
345
			{
346
				/* Shouldn't happen */
347
				e.printStackTrace();
348
			}
349
		}
350
		
351
		/* We also need to update all object mines included by the object mine passed in */
352
		List includes = objectMine.getIncludes();
353
		for (int i = 0, includeCount = includes.size(); i < includeCount; i++)
354
		{
355
			IObjectMine currentObjectMine = (IObjectMine)includes.get(i);
356
			writeObjectMine (currentObjectMine, true);
357
		}
358
		
359
		
360
		dirtyStateTable.put(testSuite.getId(), Boolean.TRUE);
361
	}
362
363
364
	public IObjectMine loadObjectMine(ITestSuite testSuite) throws UIObjectNotFound, IDCollisionException, CoreException
365
	{
366
		Boolean dirtyState = (Boolean)dirtyStateTable.get(testSuite.getId());
367
		boolean isObjectMineDirty = dirtyState == null ? false : dirtyState.booleanValue();
368
		dirtyStateTable.put(testSuite.getId(), Boolean.FALSE);
369
		return loadObjectMine(testSuite, !isObjectMineDirty);
370
	}
371
372
373
	/**
374
	 * Marks the object mine of the passed in test suite as dirty
375
	 * 
376
	 * @param testSuite The test suite
377
	 */
378
	public void markObjectMineDirty(ITestSuite testSuite)
379
	{
380
		if (testSuite == null)
381
			return;
382
		
383
		dirtyStateTable.put(testSuite.getId(), Boolean.TRUE);	
384
	}
385
	
386
	
387
	/**
388
	 * Removes all entries in cache.
389
	 * This should be carefully used.
390
	 */
391
	public void clearCache()
392
	{
393
		cachedObjectMines.clear();
394
	}
395
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/MacroUtil.java (-1027 / +507 lines)
Lines 13-19 Link Here
13
import java.io.IOException;
13
import java.io.IOException;
14
import java.io.InputStream;
14
import java.io.InputStream;
15
import java.util.Hashtable;
15
import java.util.Hashtable;
16
import java.util.Vector;
17
16
18
import javax.xml.parsers.ParserConfigurationException;
17
import javax.xml.parsers.ParserConfigurationException;
19
import javax.xml.parsers.SAXParser;
18
import javax.xml.parsers.SAXParser;
Lines 23-43 Link Here
23
import org.eclipse.core.runtime.IPath;
22
import org.eclipse.core.runtime.IPath;
24
import org.eclipse.core.runtime.Path;
23
import org.eclipse.core.runtime.Path;
25
import org.eclipse.hyades.test.common.util.XMLUtil;
24
import org.eclipse.hyades.test.common.util.XMLUtil;
26
import org.eclipse.jface.action.ActionContributionItem;
25
import org.eclipse.jface.action.ContributionManager;
27
import org.eclipse.jface.action.CoolBarManager;
26
import org.eclipse.jface.action.CoolBarManager;
28
import org.eclipse.jface.action.IAction;
29
import org.eclipse.jface.action.IContributionItem;
30
import org.eclipse.jface.action.IMenuManager;
27
import org.eclipse.jface.action.IMenuManager;
31
import org.eclipse.jface.action.IToolBarManager;
28
import org.eclipse.jface.action.IToolBarManager;
32
import org.eclipse.jface.action.MenuManager;
29
import org.eclipse.jface.action.MenuManager;
33
import org.eclipse.jface.action.ToolBarManager;
30
import org.eclipse.jface.action.ToolBarManager;
34
import org.eclipse.jface.window.ApplicationWindow;
31
import org.eclipse.jface.window.ApplicationWindow;
35
import org.eclipse.jface.window.Window;
36
import org.eclipse.jface.wizard.IWizardPage;
32
import org.eclipse.jface.wizard.IWizardPage;
37
import org.eclipse.jface.wizard.WizardDialog;
33
import org.eclipse.jface.wizard.WizardDialog;
38
import org.eclipse.osgi.util.NLS;
34
import org.eclipse.osgi.util.NLS;
39
import org.eclipse.swt.custom.CTabFolder;
35
import org.eclipse.swt.SWT;
40
import org.eclipse.swt.custom.CTabItem;
41
import org.eclipse.swt.graphics.Point;
36
import org.eclipse.swt.graphics.Point;
42
import org.eclipse.swt.graphics.Rectangle;
37
import org.eclipse.swt.graphics.Rectangle;
43
import org.eclipse.swt.widgets.Button;
38
import org.eclipse.swt.widgets.Button;
Lines 46-57 Link Here
46
import org.eclipse.swt.widgets.CoolBar;
41
import org.eclipse.swt.widgets.CoolBar;
47
import org.eclipse.swt.widgets.Display;
42
import org.eclipse.swt.widgets.Display;
48
import org.eclipse.swt.widgets.Event;
43
import org.eclipse.swt.widgets.Event;
49
import org.eclipse.swt.widgets.Item;
50
import org.eclipse.swt.widgets.Menu;
44
import org.eclipse.swt.widgets.Menu;
51
import org.eclipse.swt.widgets.MenuItem;
45
import org.eclipse.swt.widgets.MenuItem;
52
import org.eclipse.swt.widgets.Shell;
46
import org.eclipse.swt.widgets.Shell;
53
import org.eclipse.swt.widgets.TabFolder;
54
import org.eclipse.swt.widgets.TabItem;
55
import org.eclipse.swt.widgets.ToolBar;
47
import org.eclipse.swt.widgets.ToolBar;
56
import org.eclipse.swt.widgets.ToolItem;
48
import org.eclipse.swt.widgets.ToolItem;
57
import org.eclipse.swt.widgets.Widget;
49
import org.eclipse.swt.widgets.Widget;
Lines 59-839 Link Here
59
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
51
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
60
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
52
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
61
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
53
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
62
import org.eclipse.tptp.test.auto.gui.internal.core.IWidgetId;
54
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObjectIdentifier;
63
import org.eclipse.tptp.test.auto.gui.internal.core.VerificationMetaData;
55
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObjectIdentifier;
64
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
56
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
65
import org.eclipse.tptp.test.auto.gui.internal.resolvers.PrimitiveWidgetId;
57
import org.eclipse.tptp.test.auto.gui.internal.uiobject.PrimitiveUIObjectIdentifier;
58
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.NonTrivialUIObjectResolverDelegate;
59
import org.eclipse.tptp.test.auto.gui.internal.util.XMLDefaultHandler;
66
import org.eclipse.ui.IEditorPart;
60
import org.eclipse.ui.IEditorPart;
61
import org.eclipse.ui.IEditorReference;
67
import org.eclipse.ui.IPartListener;
62
import org.eclipse.ui.IPartListener;
68
import org.eclipse.ui.IPluginContribution;
69
import org.eclipse.ui.IViewPart;
63
import org.eclipse.ui.IViewPart;
70
import org.eclipse.ui.IViewReference;
64
import org.eclipse.ui.IViewReference;
71
import org.eclipse.ui.IWorkbench;
65
import org.eclipse.ui.IWorkbench;
72
import org.eclipse.ui.IWorkbenchPage;
66
import org.eclipse.ui.IWorkbenchPage;
73
import org.eclipse.ui.IWorkbenchPart;
67
import org.eclipse.ui.IWorkbenchPart;
74
import org.eclipse.ui.IWorkbenchPartSite;
75
import org.eclipse.ui.IWorkbenchWindow;
68
import org.eclipse.ui.IWorkbenchWindow;
69
import org.eclipse.ui.PartInitException;
76
import org.eclipse.ui.intro.IIntroManager;
70
import org.eclipse.ui.intro.IIntroManager;
77
import org.eclipse.ui.intro.IIntroPart;
71
import org.eclipse.ui.intro.IIntroPart;
72
import org.eclipse.ui.testing.IWorkbenchPartTestable;
78
import org.w3c.dom.Node;
73
import org.w3c.dom.Node;
79
import org.xml.sax.SAXException;
74
import org.xml.sax.SAXException;
80
75
81
/**
76
/**
82
 * A helper class that is used while recording a macro. <b>Important: </b> This
77
 * A helper class that is used while recording a macro. <b>Important: </b> This class uses internal classes.
83
 * class uses internal classes.
78
 * 
79
 * @author Alexander Nyssen (moved everything related to resolving/deresolving out of here
84
 */
80
 */
85
public class MacroUtil
81
public class MacroUtil {
86
{	
82
87
	private static Hashtable workbenchPartListeners;
88
	private static WorkbenchPartListener workbenchPartLisntener;
89
	
90
	/** The parser used to parse XML fragments */
83
	/** The parser used to parse XML fragments */
91
	private static SAXParser parser;
84
	private static SAXParser parser;
92
		
85
93
	static
86
	private static Hashtable workbenchPartListeners = new Hashtable();
94
	{
87
	private static IPartListener workbenchPartListener = new IPartListener() {
95
		workbenchPartListeners = new Hashtable();
88
96
	}
89
		public void partActivated(IWorkbenchPart part) {
97
	
90
			/* Doesn't need to be implemented */
98
	/**
91
		}
99
	 * Returns the path where counters of the given event are stored, or null if
92
100
	 * we are not keeping records of the given event.
93
		public void partBroughtToTop(IWorkbenchPart part) {
101
	 * 
94
			/* Doesn't need to be implemented */
102
	 * @param event
95
		}
103
	 * @return
96
104
	 */
97
		/**
105
	public static WidgetIdentifier getWidgetIdentifier(Widget widget)
98
		 * This method will generate a close workbench part command. We can't determine for sure through events reported by a display of when a
106
	{
99
		 * workbench part is closed. This part listener is a work around that allows us to capture close events on workbench parts.
107
		IWidgetId widgetId = null;
100
		 * 
108
		if (widget instanceof MenuItem)
101
		 * @param part
109
		{
102
		 *            The part is closed.
103
		 */
104
		public void partClosed(IWorkbenchPart part) {
105
			Macro currentMacro = MacroManager.getInstance().getCurrentMacro();
106
			Event event = new Event();
107
108
			event.type = EventConstants.EVENT_TYPE__WORKBENCH_PART_CLOSED;
109
			event.data = part;
110
			event.display = part.getSite().getShell().getDisplay();
111
			if (currentMacro != null) {
112
				try {
113
					currentMacro.addEvent(event);
114
				}
115
				catch (Exception e) {
116
					/* Ignore the error. It doesn't generate the command */
117
					e.printStackTrace();
118
				}
119
			}
120
		}
121
122
		public void partDeactivated(IWorkbenchPart part) {
123
			/* Doesn't need to be implemented */
124
		}
125
126
		public void partOpened(IWorkbenchPart part) {
127
			/* Doesn't need to be implemented */
128
		}
129
	};
130
131
	private static IWorkbenchWindow findHookTarget(Widget widget) {
132
		if (widget instanceof MenuItem) {
110
			MenuItem menuItem = (MenuItem) widget;
133
			MenuItem menuItem = (MenuItem) widget;
111
			widgetId = determineItemId (menuItem);
112
			IViewPart view = null;
134
			IViewPart view = null;
113
			if (onMenubar(menuItem))
135
			if ((view = onWorkbenchPartToolbar(menuItem)) != null) {
114
			{								
136
				// TODO: check if the toolbar manager has to be used to find the hook target...
115
				return new WidgetIdentifier(new Path(MacroConstants.MENUS_VALUE), new Path(widgetId.toString()), widgetId.getResolverId()); //$NON-NLS-1$
137
				/* The context id should be the workbench part toolbar */
116
			}			
117
			else if ((view = onWorkbenchPartToolbar(menuItem)) != null)
118
			{
119
				/* The context id should be the workbench part toolbar */			
120
				IToolBarManager toolbarManager = view.getViewSite().getActionBars().getToolBarManager();
138
				IToolBarManager toolbarManager = view.getViewSite().getActionBars().getToolBarManager();
121
				if (toolbarManager == null || !(toolbarManager instanceof ToolBarManager))
139
				if (toolbarManager == null || !(toolbarManager instanceof ToolBarManager))
122
					return null;
140
					return null;
123
								
141
124
				view.setFocus();
142
				// CHECK: setting the focus does not seem to be necessary to find a hook target
125
				WidgetIdentifier contextId = getControlIdentifier(((ToolBarManager)toolbarManager).getControl());
143
				// -> wihtout it, this method is side effect free
126
				return new WidgetIdentifier(new Path(MacroConstants.LOCAL_TOOLBAR_MENU_VALUE).append(contextId.getFullyQualifiedPath()), new Path(widgetId.toString()), widgetId.getResolverId()); //$NON-NLS-1$				
144
				// view.setFocus();
145
				return findHookTarget(((ToolBarManager) toolbarManager).getControl());
127
			}
146
			}
128
			Control c = widget.getDisplay().getFocusControl();
147
			Control c = widget.getDisplay().getFocusControl();
129
			WidgetIdentifier ci = getControlIdentifier(c);
148
			return findHookTarget(c);
130
			if (ci == null)
131
				return null;
132
			return new WidgetIdentifier(new Path(MacroConstants.POPUP_VALUE).append(ci.getFullyQualifiedPath()), new Path(widgetId.toString()), widgetId.getResolverId()); //$NON-NLS-1$
133
		}
149
		}
134
		else if (widget instanceof ToolItem)
150
		else if (widget instanceof ToolItem) {
135
		{
136
			ToolItem toolItem = (ToolItem) widget;
151
			ToolItem toolItem = (ToolItem) widget;
137
			widgetId = determineItemId (toolItem);
138
			
139
			/* Check to see if this toolbar belongs to the global toolbar of the workbench */
140
			if (onToolbar(toolItem))
141
				return new WidgetIdentifier(new Path(MacroConstants.TOOLBAR_VALUE), new Path(widgetId.toString()), widgetId.getResolverId()); //$NON-NLS-1$
142
152
143
			/* Local toolbar somewhere - locate the parent first */
153
			/* Local toolbar somewhere - locate the parent first */
144
			ToolBar toolBar = toolItem.getParent();
154
			ToolBar toolBar = toolItem.getParent();
145
			WidgetIdentifier controlId = getControlIdentifier(toolBar);
155
			return findHookTarget(toolBar);
146
			if (controlId != null)
147
			{
148
				IPath localPath = controlId.getFullyQualifiedPath();
149
				return new WidgetIdentifier(new Path(MacroConstants.LOCAL_TOOLBAR_VALUE).append(localPath), new Path(widgetId.toString()), widgetId.getResolverId());
150
			}
151
		}
152
		else if (widget instanceof Shell)
153
		{
154
			widgetId =  getShellId((Shell) widget, null);
155
			return new WidgetIdentifier(new Path(MacroConstants.SHELL_VALUE), new Path(widgetId.toString()), widgetId.getResolverId());
156
		}
157
		else if (widget instanceof Control)
158
		{
159
			return getControlIdentifier((Control) widget);
160
		}
161
		else if (widget instanceof Menu)
162
		{
163
			widgetId = getActionId((Menu) widget);
164
			return new WidgetIdentifier(new Path(MacroConstants.MENUS_VALUE), new Path(widgetId.toString()), widgetId.getResolverId());
165
		}
156
		}
166
		return null;
157
		else if (widget instanceof Control) {
167
	}
158
			Shell shell = ((Control) widget).getShell();
168
	
159
			Object data = shell.getData();
169
160
			if (data instanceof IWorkbenchWindow) {
170
	public static IWidgetId getShellId(Shell shell, String resolverId)
161
				IWorkbenchWindow window = (IWorkbenchWindow) data;
171
	{
162
				return window;
172
		IWidgetId widgetId = MacroManager.getInstance().resolveWidget(shell.getParent(), shell, resolverId, newCounter());
173
		if (widgetId != null)
174
			return widgetId;
175
		return getDefaultShellId(shell);
176
	}
177
178
	public static IWidgetId getDefaultShellId(Shell shell)
179
	{
180
		Object data = shell.getData();
181
		String id = "";
182
		if (data instanceof WizardDialog)
183
		{
184
			id = data.getClass().getName().toString();
185
		}
186
		else if (data instanceof Window)
187
		{
188
			id = data.getClass().getName().toString();
189
		}
190
		
191
		PrimitiveWidgetId widgetId = new PrimitiveWidgetId();
192
		widgetId.setId(id);
193
		return widgetId;
194
	}
195
	
196
	public static WidgetIdentifier getControlIdentifier(Control control)
197
	{
198
		Shell shell = control.getShell();
199
		Object data = shell.getData();
200
		if (data instanceof WizardDialog)
201
		{
202
			// in wizard
203
			WizardDialog wd = (WizardDialog) data;
204
			IWizardPage page = wd.getCurrentPage();
205
			if (page == null)
206
				return null;
207
			Control pageControl = page.getControl();
208
			IWidgetId relativePath = computeRelativePath((Composite) pageControl, null, control);
209
			if (relativePath != null)
210
			{
211
				IPath path = new Path(MacroConstants.WIZARD_PAGE_VALUE).append(page.getName());
212
				return new WidgetIdentifier(path, new Path(relativePath.toString()), relativePath.getResolverId());
213
			}
214
			// check for wizard buttons
215
			if (control instanceof Button)
216
			{
217
				relativePath = computeRelativePath(shell, (Composite) pageControl, control);
218
				return new WidgetIdentifier(new Path(MacroConstants.WIZARD_VALUE), new Path(relativePath.toString()), relativePath.getResolverId());
219
			}
163
			}
220
			return null;
164
			return null;
221
		}
165
		}
222
		else if (data instanceof IWorkbenchWindow)
166
		return null;
223
		{
167
	}
224
168
225
			IWorkbenchWindow window = (IWorkbenchWindow) data;
169
	protected static void hookWorkbenchPartListener(Widget widget) {
226
			IWorkbenchPage page = window.getActivePage();
170
		IWorkbenchWindow workbenchWindow = findHookTarget(widget);
171
		if (workbenchWindow != null) {
172
			IWorkbenchPage page = workbenchWindow.getActivePage();
227
173
228
			/**
174
			/**
229
			 * Ali M.: Under some situations, the part that is returned by the
175
			 * Ali M.: Under some situations, the part that is returned by the 'getActivePart' method is the old active part. Although the control
230
			 * 'getActivePart' method is the old active part. Although the
176
			 * object is coming from the newly active part, the part that is retrieved below will be from the old active part. This will cause
231
			 * control object is coming from the newly active part, the part
177
			 * MacroUtil.getControlIdentifier to return null when attempting to retrieve the widget id in the wrong context. One situation that this
232
			 * that is retrieved below will be from the old active part. This
178
			 * fails under is when: - Macro recorder start while the test suite editor is active - A hook is inserted - The package view is focused
233
			 * will cause MacroUtil.getControlIdentifier to return null when
179
			 * (not activated and focused but just focused)
234
			 * attempting to retrieve the widget id in the wrong context. One
235
			 * situation that this fails under is when: - Macro recorder start
236
			 * while the test suite editor is active - A hook is inserted - The
237
			 * package view is focused (not activated and focused but just
238
			 * focused)
239
			 * 
180
			 * 
240
			 * To resolve this issue, I have registered a part listener when the
181
			 * To resolve this issue, I have registered a part listener when the client starts recording. When there is a new active part detected, an
241
			 * client starts recording. When there is a new active part
182
			 * event is created and fired to the usual onEvent handler in MacroManager. See MacroManager.hookPartListener.
242
			 * detected, an event is created and fired to the usual onEvent
243
			 * handler in MacroManager. See MacroManager.hookPartListener.
244
			 */
183
			 */
245
			IWorkbenchPart part = page.getActivePart();
184
			IWorkbenchPart part = page.getActivePart();
246
			IWorkbenchPartSite site = part.getSite();
185
			/*
247
186
			 * Ali M.: Register a dispose listener with this workbench part if we have not already done so. This is so that close commands can be
248
			
187
			 * generated.
249
			/* Ali M.: Register a dispose listener with this workbench part if we have not
188
			 */
250
			 * already done so.  This is so that close commands can be generated. */
189
			if (workbenchPartListeners.get(page) == null) {
251
			if (workbenchPartListeners.get(page) == null)
190
				page.addPartListener(workbenchPartListener);
252
			{				
191
				workbenchPartListeners.put(page,
253
				if (workbenchPartLisntener == null)
192
					workbenchPartListener);
254
					workbenchPartLisntener = new WorkbenchPartListener();
193
			}
255
				
256
				page.addPartListener(workbenchPartLisntener);
257
				workbenchPartListeners.put(page, workbenchPartLisntener);
258
			}
259
			
260
			IPath path;
261
262
			if (part instanceof IViewPart)
263
			{
264
				path = new Path(MacroConstants.VIEW_VALUE).append(site.getId());
265
			}
266
			else if (part instanceof IEditorPart)
267
			{
268
				String inputName = ((IEditorPart) part).getEditorInput().getName();
269
				path = new Path(MacroConstants.EDITOR_VALUE).append(site.getId()).append(inputName);
270
			}
271
			else
272
			{
273
				return null;
274
			}
275
276
			Composite paneComposite = MacroObjectLocator.getWorkbenchPartControl(part);
277
278
			/* If the control we are looking for is a local tool bar, go up one level */
279
			if (part instanceof IViewPart && control instanceof ToolBar)
280
				paneComposite = paneComposite.getParent();
281
			IWidgetId relativePath = computeRelativePath(paneComposite, null, control);
282
283
			if (relativePath != null)
284
			{
285
				return new WidgetIdentifier(path, new Path(relativePath.toString()), relativePath.getResolverId());
286
			}
287
		}
288
		else
289
		{
290
			/* unknown shell - fetch controls starting from the shell */
291
			IWidgetId relativePath = computeRelativePath(shell, null, control);
292
			if (relativePath == null)
293
				return null;
294
			return new WidgetIdentifier(new Path(MacroConstants.SHELL_VALUE), new Path(relativePath.toString()), relativePath.getResolverId());
295
		}
194
		}
296
		return null;
297
	}
298
299
	private static IWidgetId computeRelativePath(Composite parent, Composite skip, Control control)
300
	{
301
		int[] counter = newCounter();
302
		Vector indices = new Vector();		
303
		boolean result = computeControlIndex(parent, skip, control, counter, indices);
304
		if (!result && skip == null)
305
			return null;
306
		
307
		int index = result ? ((Integer)indices.get(0)).intValue() : 0;
308
		IWidgetId widgetId = MacroManager.getInstance().resolveWidget(control, null, newCounter());
309
		if (widgetId != null)
310
			return widgetId;
311
		return computeDefaultControlId(control, index);
312
	}
195
	}
313
196
314
	
197
	public static int[] newCounter() {
315
	public static int[] newCounter()
316
	{
317
		int[] inx = new int[1];
198
		int[] inx = new int[1];
318
		inx[0] = 0;
199
		inx[0] = 0;
319
		return inx;
200
		return inx;
320
	}
201
	}
321
	
322
	
323
	/**
324
	 * Determines the index of the desiredControl relative to the parent control sent in.  The
325
	 * Index is stored in index[0].
326
	 * 
327
	 * @param parent The parent control
328
	 * @param skip Indicates whether a composite should be skipped
329
	 * @param desiredControl The desired control
330
	 * @param index The current index calculated thus far (stored in index[0].  The type of this
331
	 * parameter is an int array because its value needs to be preserved between recursive calls.
332
	 * 
333
	 * @return true if the index was found; false otherwise.
334
	 */
335
	private static boolean computeControlIndex(Composite parent, Composite skip, Control desiredControl, int[] index, Vector indices)
336
	{
337
		return recursiveSearch(parent, skip, desiredControl, null, null, index, new Vector(), indices) != null;
338
	}
339
202
340
	
203
	public static boolean isInputControl(Control control) {
341
	
342
	public static Control recursiveSearch(Composite parent, Composite skip, Control desiredControl, WidgetIdentifier id, String widgetClassName, int[] index, Vector matches, Vector indices)
343
	{
344
		boolean searchForControl = id == null;
345
		Control[] children = parent.getChildren();		
346
		boolean[] checkTypeAndEquality;
347
		Control searchResult;
348
		boolean isTabFolder, isCTabFolder;
349
		
350
		for (int i = 0; i < children.length; i++)
351
		{
352
			Control child = children[i];			
353
			
354
			if (!child.isVisible())
355
			{
356
				/* If the control is of the same type, then we'll need to increment the index */
357
				if ((widgetClassName != null && child.getClass().getName().equals(widgetClassName)) || (desiredControl != null && desiredControl.getClass().getName().equals(child.getClass().getName())))
358
					index[0]++;
359
				
360
				continue;
361
			}
362
363
			checkTypeAndEquality = searchForControl ? checkTypeAndEqual(desiredControl, child, index) : checkTypeAndId (child, id, widgetClassName, index);
364
			if (checkTypeAndEquality[0])
365
			{
366
				if (checkTypeAndEquality[1])
367
				{
368
					addMatch (matches, indices, child, index[0]);
369
				}
370
				
371
				/* Defect 111371 -- We need to step through the items of a tab */		
372
				isTabFolder = child instanceof TabFolder;
373
				isCTabFolder = child instanceof CTabFolder;
374
				if (isTabFolder || isCTabFolder)
375
				{
376
					Object[] tabItems = isTabFolder ? (Object[])((TabFolder)child).getItems() : ((CTabFolder)child).getItems();
377
					if (tabItems != null)
378
					{
379
						for (int j = 0; j < tabItems.length; j++)
380
						{
381
							Control tabItemControl = isTabFolder ? ((TabItem)tabItems[j]).getControl() : ((CTabItem)tabItems[j]).getControl();
382
							
383
							if (tabItemControl == null)
384
								continue;
385
							
386
							checkTypeAndEquality = searchForControl ? checkTypeAndEqual (tabItemControl, desiredControl, index) : checkTypeAndId (tabItemControl, id, widgetClassName, index);
387
							if (checkTypeAndEquality[0] && checkTypeAndEquality[1])
388
							{
389
								addMatch (matches, indices, tabItemControl, index[0]);
390
							}
391
							if ((searchResult = recursiveSearch(tabItemControl, skip, desiredControl, id, widgetClassName, index, matches, indices)) != null)
392
							{
393
								addMatch (matches, indices, searchResult, index[0]);								
394
							}				
395
						}
396
					}
397
				}
398
399
			}
400
			
401
			if ((searchResult = recursiveSearch (child, skip, desiredControl, id, widgetClassName, index, matches, indices)) != null)
402
			{
403
				addMatch (matches, indices, searchResult, index[0]);
404
			}
405
		}
406
		
407
		if (matches.size() > 0)
408
			return (Control)matches.get(0);
409
		
410
		return null;		
411
	}
412
	
413
	private static void addMatch (Vector container, Vector indices, Object item, int index)
414
	{
415
		if (!container.contains(item))
416
		{
417
			container.add(item);
418
			indices.add(new Integer(index));
419
		}
420
	}
421
	
422
	private static Control recursiveSearch(Control currentSearchPoint, Composite skip, Control desiredControl, WidgetIdentifier desiredId, String desiredWidgetClassName, int[] index, Vector matches, Vector indices) 
423
	{
424
		Control searchResult = null;
425
		if (currentSearchPoint instanceof Composite && !(skip != null && currentSearchPoint.equals(skip)) && currentSearchPoint.isVisible())
426
		{
427
			searchResult = recursiveSearch((Composite) currentSearchPoint, skip, desiredControl, desiredId, desiredWidgetClassName, index, matches, indices);
428
		}
429
				
430
		return searchResult;
431
	}
432
	
433
	
434
	/**
435
	 * A helper method used to indicate whether expected is of the same type as actual.  The 
436
	 * return value also indicates if expected == actual.
437
	 * 
438
	 * @param expected The expected control
439
	 * @param actual The actual control that 'expected' is checked against
440
	 * @param counter A counter that is used for indexing.
441
	 * 
442
	 * @return This method has the side affect of incrementing counter if the class types 
443
	 * of the two controls are the same.  The return value indicates type and whether expected == actual.
444
	 */
445
	private static boolean[] checkTypeAndEqual (Control expected, Control actual, int[] counter)
446
	{
447
		boolean[] typeAndEqualCheck = new boolean[2];
448
		if (expected.getClass().equals(actual.getClass()))
449
		{
450
			typeAndEqualCheck[0] = true;
451
			
452
			// same type - increment counter
453
			counter[0]++;
454
			if (expected.equals(actual))
455
			{
456
				// bingo
457
				typeAndEqualCheck[1] = true;
458
			}
459
		}
460
		
461
		return typeAndEqualCheck;
462
	}
463
	
464
	
465
	public static boolean[] checkTypeAndId (Control presentControl, WidgetIdentifier desiredId, String desiredWidgetClassName, int[] counter)
466
	{
467
		boolean[] checkTypeAndEqualId = new boolean[2];
468
		
469
		if (desiredWidgetClassName == null || presentControl.getClass().getName().equals(desiredWidgetClassName))
470
		{
471
			// same type - increment counter
472
			if (!presentControl.isVisible())
473
				return checkTypeAndEqualId;
474
			
475
			checkTypeAndEqualId[0] = true;
476
			counter[0]++;
477
			if (MacroObjectLocator.foundWidget(presentControl, desiredId.getResolverId(), desiredId.getObjectId().toString()) || computeDefaultControlId(presentControl, counter[0]).equals(desiredId.getObjectId().toString()))
478
			{
479
				checkTypeAndEqualId[1] = true;
480
			}			
481
		}
482
		
483
		return checkTypeAndEqualId;
484
	}
485
	
486
	
487
	private static IWidgetId computeDefaultControlId(Control control, int controlIndex)
488
	{
489
		PrimitiveWidgetId primitiveWidgetId = new PrimitiveWidgetId();
490
		primitiveWidgetId.setId(control.getClass().getName() + "#" + controlIndex);
491
		return primitiveWidgetId;
492
	}
493
494
495
	public static boolean isInputControl(Control control)
496
	{
497
		return true;
204
		return true;
498
	}
205
	}
499
206
500
	/**
501
	 * @param menuItem
502
	 * @return
503
	 */
504
	private static boolean onMenubar(MenuItem menuItem)
505
	{
506
		Menu parent = menuItem.getParent();
507
		MenuItem parentItem = parent.getParentItem();
508
509
		if (parentItem != null)
510
		{
511
			return onMenubar(parentItem);
512
		}
513
514
		Shell theShell = parent.getShell();
515
		return parent == theShell.getMenuBar();
516
	}
517
518
	private static boolean onToolbar(ToolItem toolItem)
519
	{
520
		ToolBar toolBar = toolItem.getParent();
521
		Shell shell = toolBar.getShell();
522
		Object data = shell.getData();
523
		if (data instanceof ApplicationWindow)
524
		{
525
			ApplicationWindow window = (ApplicationWindow) data;
526
			ToolBarManager mng = window.getToolBarManager();
527
			if (mng != null)
528
			{
529
				if (mng.getControl() != null && mng.getControl() == toolBar)
530
					return true;
531
			}
532
			CoolBarManager cmng = window.getCoolBarManager();
533
			if (cmng != null)
534
			{
535
				CoolBar cbar = cmng.getControl();
536
				Composite parent = toolBar.getParent();
537
				while (parent != null)
538
				{
539
					if (parent == cbar)
540
						return true;
541
					parent = parent.getParent();
542
				}
543
			}
544
		}
545
		return false;
546
	}
547
	
548
	private static IViewPart onWorkbenchPartToolbar(MenuItem menuItem)
549
	{
550
		IWorkbenchPage[] pages = GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getPages();
551
		
552
		/* For evey page */
553
		for (int i = 0; i < pages.length; i++)
554
		{
555
			IViewReference[] viewReferences = pages[i].getViewReferences();
556
			
557
			/* For evey opened view */
558
			for (int j = 0; j < viewReferences.length; j++)
559
			{
560
				IViewPart viewPart = viewReferences[j].getView(false);
561
				if (viewPart == null)
562
					continue;
563
				
564
				IMenuManager menuManager = viewPart.getViewSite().getActionBars().getMenuManager();
565
				if (menuManager != null && menuManager instanceof MenuManager && searchForMenuItem(((MenuManager)menuManager).getMenu(), menuItem))
566
					return viewPart;
567
			}
568
		}
569
		
570
		return null;
571
	}
572
573
	private static boolean searchForMenuItem(Menu menu, MenuItem menuItem)
574
	{
575
		if (menu == null)
576
			return false;
577
		
578
		MenuItem[] items = menu.getItems();
579
		for (int i = 0; i < items.length; i++)
580
		{
581
			if (items[i] == menuItem)
582
				return true;
583
			Menu cascadeMenu = items[i].getMenu();
584
			if (cascadeMenu != null && searchForMenuItem (cascadeMenu, menuItem))
585
				return true;
586
		}
587
		
588
		return false;
589
	}
590
591
592
	/**
593
	 * @param toolItem
594
	 * @return
595
	 */
596
	private static String getDisplayName(ToolItem toolItem)
597
	{
598
		String name = toolItem.getText();
599
600
		if (name != null && !name.equals(MacroConstants.EMPTY_STRING))
601
		{
602
			return name;
603
		}
604
605
		name = toolItem.getToolTipText();
606
607
		if (name != null)
608
		{
609
			return name;
610
		}
611
612
		return "unknown"; //$NON-NLS-1$
613
	}
614
615
	/**
616
	 * Returns an identifier for the given MenuItem, based on its user-readable
617
	 * strings
618
	 * 
619
	 * @param menuItem
620
	 * @return
621
	 */
622
	private static String getDisplayName(MenuItem menuItem)
623
	{
624
		if (menuItem.getParent() == null || menuItem.getParent().getParentItem() == null)
625
		{
626
			return removeChar(menuItem.getText(), '&');
627
		}
628
629
		return getDisplayName(menuItem.getParent()) + "/" //$NON-NLS-1$
630
				+ removeChar(menuItem.getText(), '&');
631
	}
632
633
	/**
634
	 * Returns an identifier for the given Menu, based on its user-readable
635
	 * strings
636
	 * 
637
	 * @param menu
638
	 * @return
639
	 */
640
	private static String getDisplayName(Menu menu)
641
	{
642
643
		MenuItem parentItem = menu.getParentItem();
644
645
		if (parentItem == null)
646
		{
647
			return MacroConstants.EMPTY_STRING;
648
		}
649
650
		return getDisplayName(parentItem);
651
	}
652
653
654
	/**
655
	 * Defect #: 112668 This method is invoked to retrieve the id of a menu item.  
656
	 * Here's the policy that it employs:
657
	 * <ol>
658
	 * 	<li> Use the contributed widget resolvers </li>
659
	 * 	<li> If failed, default to what was being used before </li>
660
	 * </ol>
661
	 * 
662
	 * @param item The menu item
663
	 * @return The id of the passed item.
664
	 */
665
	public static IWidgetId determineItemId (Item item)
666
	{
667
		IWidgetId menuItemIdObj = MacroManager.getInstance().resolveWidget(item, null, newCounter());
668
		
669
		/* Give a chance for contributors to resolve the menu item */
670
		if (menuItemIdObj != null)
671
			return menuItemIdObj;
672
		
673
		if (item instanceof ToolItem)
674
		{
675
			return getActionId((ToolItem)item);
676
		}
677
		else if (item instanceof MenuItem)
678
		{
679
			return getActionId((MenuItem)item);
680
		}
681
		else if (item instanceof IContributionItem)
682
		{
683
			return getActionId((IContributionItem)item);
684
		}
685
		return null;
686
	}
687
688
	
689
	/**
690
	 * Walks through all parent menus of the menuItem and returns an index of format
691
	 * &lt;num&gt;|&lt;num&gt;|&lt;num&gt;|...  For example assuming menuItem is
692
	 * placed as follows:
693
	 * 
694
	 * 		item 1
695
	 *       |_item 2
696
	 *       |    |_item 4
697
	 *       |_item 3
698
	 *            |_menuItem
699
	 *            
700
	 * then its respective index will be 1|2|1
701
	 * 
702
	 * @param menuItem The menu item whose index will be determined
703
	 * @return The index of the menu item as described above.
704
	 */
705
	public static String findMenuItemIndex(MenuItem menuItem, String menuInx)
706
	{
707
		if (menuItem == null)
708
			return menuInx;
709
		
710
		if (menuInx.length() > 0)
711
			menuInx = "|" + menuInx;
712
		menuInx = menuItem.getParent().indexOf(menuItem) + menuInx;
713
		return findMenuItemIndex(menuItem.getParent().getParentItem(), menuInx);
714
	}
715
716
717
	/*
207
	/*
718
	 * (non-Javadoc)
208
	 * (non-Javadoc)
719
	 * 
209
	 * 
720
	 * @see org.eclipse.instrumentation.IDataProvider#getDefaultValue(org.eclipse.core.runtime.IPath)
210
	 * @see org.eclipse.instrumentation.IDataProvider#getDefaultValue(org.eclipse.core.runtime.IPath)
721
	 */
211
	 */
722
	public Object getDefaultValue(IPath node)
212
	public Object getDefaultValue(IPath node) {
723
	{
724
		return null;
213
		return null;
725
	}
214
	}
726
215
727
	private MenuItem getMenuItem(Menu menu, IPath menuPath)
216
	private MenuItem getMenuItem(Menu menu, IPath menuPath) {
728
	{
217
		if (menuPath.isEmpty()) {
729
		if (menuPath.isEmpty())
730
		{
731
			return null;
218
			return null;
732
		}
219
		}
733
220
734
		String toFind = menuPath.segment(0);
221
		String toFind = menuPath.segment(0);
735
		MenuItem[] items = menu.getItems();
222
		MenuItem[] items = menu.getItems();
736
223
737
		for (int idx = 0; idx < items.length; idx++)
224
		for (int idx = 0; idx < items.length; idx++) {
738
		{
739
			MenuItem item = items[idx];
225
			MenuItem item = items[idx];
740
226
741
			String itemName = removeChar(item.getText(), '&');
227
			String itemName = removeChar(item.getText(),
228
				'&');
742
229
743
			if (itemName.equals(toFind))
230
			if (itemName.equals(toFind)) {
744
			{
231
				return getMenuItem(item,
745
				return getMenuItem(item, menuPath.removeFirstSegments(1));
232
					menuPath.removeFirstSegments(1));
746
			}
233
			}
747
		}
234
		}
748
235
749
		return null;
236
		return null;
750
	}
237
	}
751
238
752
	private MenuItem getMenuItem(MenuItem menu, IPath menuPath)
239
	private MenuItem getMenuItem(MenuItem menu, IPath menuPath) {
753
	{
240
		if (menuPath.isEmpty()) {
754
		if (menuPath.isEmpty())
755
		{
756
			return menu;
241
			return menu;
757
		}
242
		}
758
243
759
		Menu subMenu = menu.getMenu();
244
		Menu subMenu = menu.getMenu();
760
		if (subMenu == null)
245
		if (subMenu == null) {
761
		{
762
			return null;
246
			return null;
763
		}
247
		}
764
248
765
		return getMenuItem(subMenu, menuPath);
249
		return getMenuItem(subMenu,
250
			menuPath);
766
251
767
	}
252
	}
768
253
769
	public static String removeChar(String input, char toRemove)
254
	public static void forceMenuClosed(Menu menu) {
770
	{
255
		Event e = new Event();
771
		StringBuffer buf = new StringBuffer(input.length());
256
		e.type = SWT.Hide;
772
257
		e.widget = menu;
773
		int last = 0;
258
	
774
		for (int pos = input.indexOf(toRemove); pos != -1; pos = input.indexOf(toRemove, last))
259
		menu.notifyListeners(e.type, e);
775
		{
260
		processDisplayEvents(menu.getDisplay());
776
			buf.append(input.substring(last, pos));
261
	}
777
			last = pos + 1;
778
		}
779
780
		buf.append(input.substring(last, input.length()));
781
262
782
		return buf.toString();
263
	public static void forceMenuOpen(Menu menu) {
264
		Event e = new Event();
265
		e.type = SWT.Show;
266
		e.widget = menu;
267
	
268
		menu.notifyListeners(e.type, e);
269
		processDisplayEvents(menu.getDisplay());
783
	}
270
	}
784
271
785
	public static String getAttribute(Node node, String name)
272
	public static String getAttribute(Node node, String name) {
786
	{
787
		Node value = node.getAttributes().getNamedItem(name);
273
		Node value = node.getAttributes().getNamedItem(name);
788
		if (value != null)
274
		if (value != null)
789
			return value.getNodeValue();
275
			return value.getNodeValue();
790
		return null;
276
		return null;
791
	}
277
	}
792
278
793
		
794
	/**
279
	/**
795
	 * Adds an XML element to the string buffer passed in.
280
	 * Adds an XML element to the string buffer passed in.
796
	 * 
281
	 * 
797
	 * @param stringBuffer The string buffer that the element will be written to
282
	 * @param stringBuffer
798
	 * @param indent The number of indents that should be prefixed to the element written
283
	 *            The string buffer that the element will be written to
799
	 * @param elementName The element name
284
	 * @param indent
800
	 * @param close Indicates whether this element should be closed or not.  If set, 
285
	 *            The number of indents that should be prefixed to the element written
801
	 * a forward slash is added before theelement is ended.  
286
	 * @param elementName
802
	 * @param end Indicates if the element should be ended with a closed angle bracket.  
287
	 *            The element name
803
	 * For example elements requring attributes are not ended.
288
	 * @param close
804
	 */
289
	 *            Indicates whether this element should be closed or not. If set, a forward slash is added before theelement is ended.
805
	public static void addElement (StringBuffer stringBuffer, int indent, String elementName, boolean close, boolean end)
290
	 * @param end
806
	{
291
	 *            Indicates if the element should be ended with a closed angle bracket. For example elements requring attributes are not ended.
807
		addIndent(stringBuffer, indent);
292
	 */
293
	public static void addElement(StringBuffer stringBuffer, int indent, String elementName, boolean close, boolean end) {
294
		addIndent(stringBuffer,
295
			indent);
808
		stringBuffer.append(MacroConstants.OPEN_ANGLE_BRACKET);
296
		stringBuffer.append(MacroConstants.OPEN_ANGLE_BRACKET);
809
		stringBuffer.append(close ? MacroConstants.FORWARD_SLASH : MacroConstants.EMPTY_STRING);		
297
		stringBuffer.append(close
298
			? MacroConstants.FORWARD_SLASH
299
			: MacroConstants.EMPTY_STRING);
810
		stringBuffer.append(elementName);
300
		stringBuffer.append(elementName);
811
		stringBuffer.append(end ? MacroConstants.CLOSE_ANGLE_BRACKET + GlobalConstants.LINE_SEPARATOR: MacroConstants.EMPTY_STRING);		
301
		stringBuffer.append(end
302
			? MacroConstants.CLOSE_ANGLE_BRACKET + GlobalConstants.LINE_SEPARATOR
303
			: MacroConstants.EMPTY_STRING);
812
	}
304
	}
813
305
814
	
815
	/**
306
	/**
816
	 * Adds XML attributes to the string buffer passed in.  Attributes with a null value will
307
	 * Adds XML attributes to the string buffer passed in. Attributes with a null value will not be written.
817
	 * not be written.
818
	 * 
308
	 * 
819
	 * Pre-condition:
309
	 * Pre-condition:
820
	 * <ul>
310
	 * <ul>
821
	 * 	<li> attributes and attributeValues must be valid (i.e. non-null) </li>
311
	 * <li> attributes and attributeValues must be valid (i.e. non-null) </li>
822
	 * 	<li> attributes and attributeValues length must be the same </li>
312
	 * <li> attributes and attributeValues length must be the same </li>
823
	 * </ul>
313
	 * </ul>
824
	 *  
314
	 * 
825
	 * @param stringBuffer The string buffer that the attributes will be written to
315
	 * @param stringBuffer
826
	 * @param attributeNames The attribute names
316
	 *            The string buffer that the attributes will be written to
827
	 * @param attributeValues The attribute values
317
	 * @param attributeNames
828
	 * @param close If set, a forward slash is added after the attributes.  
318
	 *            The attribute names
829
	 * @param end If set, a closed angle bracket is added after the attributes
319
	 * @param attributeValues
830
	 */
320
	 *            The attribute values
831
	public static void addAttribute(StringBuffer stringBuffer, String[] attributeNames, String[] attributeValues, boolean close, boolean end)
321
	 * @param close
832
	{
322
	 *            If set, a forward slash is added after the attributes.
833
		for (int i = 0; i < attributeValues.length; i++)
323
	 * @param end
834
		{
324
	 *            If set, a closed angle bracket is added after the attributes
835
			if (attributeValues[i] == null)
325
	 */
836
			{
326
	public static void addAttribute(StringBuffer stringBuffer, String[] attributeNames, String[] attributeValues, boolean close, boolean end) {
327
		for (int i = 0; i < attributeValues.length; i++) {
328
			if (attributeValues[i] == null) {
837
				continue;
329
				continue;
838
			}
330
			}
839
			stringBuffer.append(MacroConstants.SINGLE_SPACE);
331
			stringBuffer.append(MacroConstants.SINGLE_SPACE);
Lines 843-868 Link Here
843
			stringBuffer.append(XMLUtil.useXMLSymbols(attributeValues[i]));
335
			stringBuffer.append(XMLUtil.useXMLSymbols(attributeValues[i]));
844
			stringBuffer.append(MacroConstants.DOUBLE_QUOTE);
336
			stringBuffer.append(MacroConstants.DOUBLE_QUOTE);
845
		}
337
		}
846
		
338
847
		stringBuffer.append(close ? MacroConstants.FORWARD_SLASH : MacroConstants.EMPTY_STRING);
339
		stringBuffer.append(close
848
		stringBuffer.append(end ? MacroConstants.CLOSE_ANGLE_BRACKET + GlobalConstants.LINE_SEPARATOR : MacroConstants.EMPTY_STRING);
340
			? MacroConstants.FORWARD_SLASH
341
			: MacroConstants.EMPTY_STRING);
342
		stringBuffer.append(end
343
			? MacroConstants.CLOSE_ANGLE_BRACKET + GlobalConstants.LINE_SEPARATOR
344
			: MacroConstants.EMPTY_STRING);
849
	}
345
	}
850
	
346
851
	
347
	public static void addIndent(StringBuffer stringBuffer, int indent) {
852
	public static void addIndent (StringBuffer stringBuffer, int indent)
348
		for (int i = 0; i < indent; i++) {
853
	{
854
		for (int i = 0; i < indent; i++)
855
		{
856
			stringBuffer.append("\t");
349
			stringBuffer.append("\t");
857
		}
350
		}
858
	}
351
	}
859
	
352
860
	
353
	public static boolean isIgnorableEvent(Event e) {
861
	public static boolean isIgnorableEvent(Event e)
862
	{
863
		Shell shell = e.display.getActiveShell();
354
		Shell shell = e.display.getActiveShell();
864
		if (shell != null)
355
		if (shell != null) {
865
		{
866
			Boolean ivalue = (Boolean) shell.getData(MacroManager.IGNORE);
356
			Boolean ivalue = (Boolean) shell.getData(MacroManager.IGNORE);
867
			if (ivalue != null && ivalue.equals(Boolean.TRUE))
357
			if (ivalue != null && ivalue.equals(Boolean.TRUE))
868
				return true;
358
				return true;
Lines 870-1313 Link Here
870
		return false;
360
		return false;
871
	}
361
	}
872
362
873
	public static Control getFirstChild(IWorkbenchPart part)
363
	public static Control getFirstChild(IWorkbenchPart part) {
874
	{
364
		Composite partControl = getWorkbenchPartControl(part);
875
		Composite partControl = MacroObjectLocator.getWorkbenchPartControl(part);
876
		return partControl.getChildren()[0];
365
		return partControl.getChildren()[0];
877
	}
366
	}
878
367
879
	/**
368
	/**
880
	 * Given a context id, return the focus type.
369
	 * We have to use internal APIs here to get the controls of a part
881
	 * 
882
	 * @param contextId
883
	 *            The id of the context
884
	 * @return The type of the context (i.e. focus type). -1 is returned if the
885
	 *         focus type is not recognized.
886
	 */
370
	 */
887
	public static byte findFocusType(String contextId)
371
	public static Composite getWorkbenchPartControl(IWorkbenchPart part) {
888
	{
372
		IWorkbenchPartTestable testable = (IWorkbenchPartTestable) part.getSite().getAdapter(IWorkbenchPartTestable.class);
889
		if (contextId.startsWith(MacroConstants.VIEW_VALUE + "/"))
373
		return testable.getControl().getParent();
890
			return VerificationMetaData.VIEW;
891
		else if (contextId.startsWith(MacroConstants.EDITOR_VALUE + "/"))
892
			return VerificationMetaData.EDITOR;
893
		else if (contextId.startsWith(MacroConstants.SHELL_VALUE + "/"))
894
			return VerificationMetaData.SHELL;
895
896
		return -1;
897
	}
898
899
	/**
900
	 * Return the class name containing the verification point that this meta
901
	 * data points to.
902
	 * 
903
	 * @param metaData
904
	 *            The verification point's meta data
905
	 * @return The class name. null is returned if it can't be determined
906
	 */
907
	public static String getClassName(VerificationMetaData metaData)
908
	{
909
		String className = metaData.getResource();
910
911
		if (className == null || className.length() <= 0)
912
			return null;
913
914
		int index = className.lastIndexOf('.');
915
		if (index != -1)
916
			return className.substring(index + 1, className.length());
917
		return className;
918
	}
374
	}
919
375
920
	/**
376
	/**
921
	 * Find the method name corresponding the verification hook
377
	 * If str.length() is greater than bound, then the first bound letters of str is returned followed by "..."; otherwise str is returned.
922
	 * 
378
	 * 
923
	 * @param metaData
379
	 * @param str
924
	 * @return
380
	 *            The string to bound
925
	 */
381
	 * @param bound
926
	public static String findMethodName(VerificationMetaData metaData)
382
	 *            The bound
927
	{
928
		String methodName = metaData.getHook();
929
930
		if (methodName == null || methodName.length() <= 0)
931
			return null;
932
933
		int index = methodName.indexOf(':');
934
		if (index != -1)
935
			return methodName.substring(0, index);
936
937
		return methodName;
938
	}
939
940
	/**
941
	 * Find the parameter types of the verificaiton hook
942
	 * 
943
	 * @param metaData
944
	 * @return
945
	 */
946
	public static Class[] findParameterType(VerificationMetaData metaData)
947
	{
948
		Class param = null;
949
		if (metaData.getFocusType() == VerificationMetaData.EDITOR)
950
			param = IEditorPart.class;
951
		else if (metaData.getFocusType() == VerificationMetaData.VIEW)
952
			param = IViewPart.class;
953
		else if (metaData.getFocusType() == VerificationMetaData.SHELL)
954
			param = Shell.class;
955
956
		if (param != null)
957
			return new Class[] { param };
958
959
		return null;
960
	}
961
962
	
963
	/**
964
	 * If str.length() is greater than bound, then the first bound letters
965
	 * of str is returned followed by "..."; otherwise str is returned.
966
	 * 
967
	 * @param str The string to bound
968
	 * @param bound The bound
969
	 * @return A bounded version of str
383
	 * @return A bounded version of str
970
	 */
384
	 */
971
	public static String boundSize(String str, int bound) 
385
	public static String boundSize(String str, int bound) {
972
	{					
973
		if (str == null || str.length() <= bound)
386
		if (str == null || str.length() <= bound)
974
			return str;
387
			return str;
975
		
388
976
		return str.substring(0, bound) + "...";
389
		return str.substring(0,
390
			bound) + "...";
977
	}
391
	}
978
	
979
392
980
	
981
	/**
393
	/**
982
	 * "Cleans" up the descriptive fields.  For example, it removes the '&' sign that is usually included
394
	 * "Cleans" up the descriptive fields. For example, it removes the '&' sign that is usually included as part of button labels.
983
	 * as part of button labels.
984
	 * 
395
	 * 
985
	 * @param descriptiveField The descriptive field
396
	 * @param descriptiveField
397
	 *            The descriptive field
986
	 * @return A "cleaned" up version of the descriptive field.
398
	 * @return A "cleaned" up version of the descriptive field.
987
	 */
399
	 */
988
	public static String normalizeDescriptiveField(String descriptiveField) 
400
	public static String normalizeDescriptiveField(String descriptiveField) {
989
	{
990
		if (descriptiveField == null || descriptiveField.length() <= 0)
401
		if (descriptiveField == null || descriptiveField.length() <= 0)
991
			return descriptiveField;
402
			return descriptiveField;
992
		
403
993
		/* This array holds character array that are of length two.  The first item is the unwanted character and the second
404
		/*
994
		 * item is the replacement character. */
405
		 * This array holds character array that are of length two. The first item is the unwanted character and the second item is the replacement
995
		final char[][] UNWANTED_CHARACTERS = new char[][] {new char[]{'&', 0}, new char[]{'\t', ' '}, new char[]{'\n', ' '}, new char[]{'\r', ' '}};
406
		 * character.
407
		 */
408
		final char[][] UNWANTED_CHARACTERS =
409
			new char[][] {new char[] {'&', 0}, new char[] {'\t', ' '}, new char[] {'\n', ' '}, new char[] {'\r', ' '}};
996
		String cleanDescription = "";
410
		String cleanDescription = "";
997
		char currentCharacter;
411
		char currentCharacter;
998
		boolean isUnwantedChar;
412
		boolean isUnwantedChar;
999
		for (int i = 0, descriptionLength = descriptiveField.length(); i < descriptionLength; i++)
413
		for (int i = 0, descriptionLength = descriptiveField.length(); i < descriptionLength; i++) {
1000
		{
1001
			currentCharacter = descriptiveField.charAt(i);
414
			currentCharacter = descriptiveField.charAt(i);
1002
			isUnwantedChar = false;
415
			isUnwantedChar = false;
1003
			
416
1004
			for (int j = 0; j < UNWANTED_CHARACTERS.length; j++)
417
			for (int j = 0; j < UNWANTED_CHARACTERS.length; j++) {
1005
			{
418
				if (currentCharacter == UNWANTED_CHARACTERS[j][0]) {
1006
				if (currentCharacter == UNWANTED_CHARACTERS[j][0])
1007
				{
1008
					if (UNWANTED_CHARACTERS[j][1] > 0)
419
					if (UNWANTED_CHARACTERS[j][1] > 0)
1009
						cleanDescription += UNWANTED_CHARACTERS[j][1];
420
						cleanDescription += UNWANTED_CHARACTERS[j][1];
1010
					
421
1011
					isUnwantedChar = true;
422
					isUnwantedChar = true;
1012
					break;
423
					break;
1013
				}
424
				}
1014
			}
425
			}
1015
			
426
1016
			if (!isUnwantedChar)
427
			if (!isUnwantedChar)
1017
				cleanDescription += currentCharacter;
428
				cleanDescription += currentCharacter;
1018
		}
429
		}
1019
				
430
1020
		return cleanDescription;
431
		return cleanDescription;
1021
	}
432
	}
1022
	
433
1023
	public static void closeWelcomePage()
434
	public static void closeWelcomePage() {
1024
	{		
1025
		IIntroManager introManager = GuiPlugin.getDefault().getWorkbench().getIntroManager();
435
		IIntroManager introManager = GuiPlugin.getDefault().getWorkbench().getIntroManager();
1026
		IIntroPart introPart = introManager.getIntro();
436
		IIntroPart introPart = introManager.getIntro();
1027
		if (introPart != null)
437
		if (introPart != null)
1028
			introManager.closeIntro(introPart);
438
			introManager.closeIntro(introPart);
1029
	}
439
	}
1030
440
1031
	
441
	public static void maximizeWorkbench() {
1032
	public static void maximizeWorkbench()
1033
	{
1034
		IWorkbench workbench = GuiPlugin.getDefault().getWorkbench();
442
		IWorkbench workbench = GuiPlugin.getDefault().getWorkbench();
1035
		Shell workbenchShell = workbench.getActiveWorkbenchWindow().getShell();
443
		Shell workbenchShell = workbench.getActiveWorkbenchWindow().getShell();
1036
		Rectangle clientArea = workbench.getDisplay().getClientArea();
444
		Rectangle clientArea = workbench.getDisplay().getClientArea();
1037
		workbenchShell.setLocation (0, 0);
445
		workbenchShell.setLocation(0,
446
			0);
1038
		workbenchShell.setSize(new Point(clientArea.width, clientArea.height));
447
		workbenchShell.setSize(new Point(clientArea.width, clientArea.height));
1039
		workbenchShell.redraw();
448
		workbenchShell.redraw();
1040
	}
449
	}
1041
	public static void clearWorkbenchPartListeners()
1042
	{
1043
		workbenchPartListeners.clear();
1044
	}
1045
	
1046
	
1047
	private static class WorkbenchPartListener implements IPartListener
1048
	{
1049
450
1050
		public void partActivated(IWorkbenchPart part) 
451
	public static void clearWorkbenchPartListeners() {
1051
		{
452
		workbenchPartListeners.clear();
1052
			/* Doesn't need to be implemented */
1053
		}
1054
1055
		public void partBroughtToTop(IWorkbenchPart part)
1056
		{
1057
			/* Doesn't need to be implemented */			
1058
		}
1059
1060
		/**
1061
		 * This method will generate a close workbench part command.  We can't determine for sure through
1062
		 * events reported by a display of when a workbench part is closed.  This part listener is
1063
		 * a work around that allows us to capture close events on workbench parts.
1064
		 * 
1065
		 * @param part The part is closed.
1066
		 */
1067
		public void partClosed(IWorkbenchPart part) 
1068
		{
1069
			Macro currentMacro = MacroManager.getInstance().getCurrentMacro(); 
1070
			Event event = new Event();
1071
			
1072
			event.type = Macro.WORKBENCH_PART_CLOSED;
1073
			event.data = part;
1074
			event.display = part.getSite().getShell().getDisplay();
1075
			if (currentMacro != null)
1076
			{
1077
				try 
1078
				{
1079
					currentMacro.addEvent(event);
1080
				} 
1081
				catch (Exception e) 
1082
				{
1083
					/* Ignore the error.  It doesn't generate the command */
1084
					e.printStackTrace();
1085
				}
1086
			}			
1087
		}
1088
1089
		public void partDeactivated(IWorkbenchPart part) 
1090
		{
1091
			/* Doesn't need to be implemented */
1092
		}
1093
1094
		public void partOpened(IWorkbenchPart part) 
1095
		{
1096
			/* Doesn't need to be implemented */			
1097
		}
1098
		
1099
	}
453
	}
1100
454
1101
	public static WidgetIdentifier getCustomEventIdentifier(Event event) 
455
	public static IMacroObjectIdentifier getCustomEventIdentifier(Event event) {
1102
	{
456
		if (event.type == EventConstants.EVENT_TYPE__WORKBENCH_PART_CLOSED) {
1103
		if (event.type == Macro.WORKBENCH_PART_CLOSED)
457
			IWorkbenchPart part = (IWorkbenchPart) event.data;
1104
		{
1105
			IWorkbenchPart part = (IWorkbenchPart)event.data;
1106
			String partId = part.getSite().getId();
458
			String partId = part.getSite().getId();
1107
							
459
1108
			/* The path to the context */
460
			/* The path to the context */
1109
			IPath contextId = null;
461
			IPath contextId = null;
1110
			IPath partIdPath = null;
462
			IPath partIdPath = null;
1111
			if (part instanceof IViewPart)
463
			if (part instanceof IViewPart) {
1112
			{
1113
				contextId = new Path(MacroConstants.VIEW_VALUE);
464
				contextId = new Path(MacroConstants.VIEW_VALUE);
1114
				partIdPath = new Path(partId);
465
				partIdPath = new Path(partId);
1115
			}
466
			}
1116
			else if (part instanceof IEditorPart)
467
			else if (part instanceof IEditorPart) {
1117
			{
1118
				contextId = new Path(MacroConstants.EDITOR_VALUE);
468
				contextId = new Path(MacroConstants.EDITOR_VALUE);
1119
				partIdPath = new Path(partId).append(((IEditorPart)part).getEditorInput().getName());
469
				partIdPath = new Path(partId).append(((IEditorPart) part).getEditorInput().getName());
470
			}
471
472
			if (contextId != null && partId != null) {
473
				return new MacroObjectIdentifier(contextId.toString(), new PrimitiveUIObjectIdentifier(partIdPath.toString(), null));
1120
			}
474
			}
1121
			
1122
			if (contextId != null && partId != null)
1123
				return new WidgetIdentifier (contextId, partIdPath, null);			
1124
		}
475
		}
1125
		return null;
476
		return null;
1126
	}
477
	}
1127
478
1128
	
1129
	/* Returns an identifier for the verification hook context */
1130
	public static WidgetIdentifier getVerificationContextIdentifier(Event event) 
1131
	{
1132
		/* See if the context is an editor or a view */
1133
		Control control = null;
1134
		if (event.widget instanceof Control)
1135
		{
1136
			control = (Control)event.widget;
1137
			WidgetIdentifier widgetId = getControlIdentifier(control);
1138
			if (widgetId != null)
1139
			{
1140
				String firstSegment = new Path(widgetId.getContextId().toString()).segment(0);
1141
				if (firstSegment.equals(MacroConstants.VIEW_VALUE) || firstSegment.equals(MacroConstants.EDITOR_VALUE))
1142
					return widgetId;
1143
			}
1144
		}
1145
		
1146
		/* It's not an editor or a view.  See if it's a shell */
1147
		Shell shellFound = null;
1148
		if (event.widget instanceof Shell)
1149
			shellFound = (Shell) event.widget;
1150
		else if (control != null)
1151
			shellFound = control.getShell();
1152
		
1153
		/* Make sure that the shell is not the workbench shell */
1154
		if (shellFound == null || GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell().equals(shellFound))
1155
			return null;
1156
		
1157
		IWidgetId shellPath = getShellId(shellFound, null);
1158
		if (shellPath.toString().length() <= 0)
1159
			return null;
1160
		
1161
		return new WidgetIdentifier (new Path(MacroConstants.SHELL_VALUE).append(shellPath.toString()), null, shellPath.getResolverId());
1162
	}
1163
	
1164
	
1165
	/**
479
	/**
1166
	 * This method is provided to close any nested shells that a test case may have
480
	 * This method is provided to close any nested shells that a test case may have activated.
1167
	 * activated. 
1168
	 */
481
	 */
1169
	public static void closeSecondaryShells(final Display display)
482
	public static void closeSecondaryShells(final Display display) {
1170
	{
483
		display.syncExec(new Runnable() {
1171
		display.syncExec(new Runnable(){
484
1172
			public void run() 
485
			public void run() {
1173
			{				
1174
				Shell[] shells = display.getShells();
486
				Shell[] shells = display.getShells();
1175
				for (int i = 0; i < shells.length; i++)
487
				for (int i = 0; i < shells.length; i++) {
1176
				{
1177
					if (!shells[i].isDisposed() && shells[i].getData(GlobalConstants.OPENED_SHELL_INDICATOR) == null)
488
					if (!shells[i].isDisposed() && shells[i].getData(GlobalConstants.OPENED_SHELL_INDICATOR) == null)
1178
						shells[i].close();
489
						shells[i].close();
1179
				}				
490
				}
1180
			}
491
			}
1181
		});
492
		});
1182
	}
493
	}
1183
	
494
1184
	public static void processDisplayEvents(Display display)
495
	public static void processDisplayEvents(Display display) {
1185
	{
496
		for (int i = 0;; i++) {
1186
		for (int i = 0;;i++)
1187
		{			
1188
			if (!display.readAndDispatch())
497
			if (!display.readAndDispatch())
1189
				break;
498
				break;
1190
		}
499
		}
1191
	}
500
	}
1192
	
501
1193
	
502
	public static XMLDefaultHandler createXMLDocument(InputStream is) throws CoreException, SAXException, IOException {
1194
	public static XMLDefaultHandler createXMLDocument (InputStream is) throws CoreException, SAXException, IOException
1195
	{
1196
		XMLDefaultHandler handler = null;
503
		XMLDefaultHandler handler = null;
1197
		try
504
		try {
1198
		{
1199
			SAXParser parser = getParser();
505
			SAXParser parser = getParser();
1200
			handler = new XMLDefaultHandler();
506
			handler = new XMLDefaultHandler();
1201
			parser.parse(is, handler);
507
			parser.parse(is,
508
				handler);
1202
		}
509
		}
1203
		finally
510
		finally {
1204
		{
511
			try {
1205
			try
1206
			{
1207
				is.close();
512
				is.close();
1208
			}
513
			}
1209
			catch (IOException e)
514
			catch (IOException e) {
1210
			{
1211
			}
515
			}
1212
		}
516
		}
1213
		
517
1214
		return handler;
518
		return handler;
1215
	}
519
	}
1216
	
520
1217
	private static SAXParser getParser() throws CoreException
521
	private static SAXParser getParser() throws CoreException {
1218
	{
522
		if (parser == null) {
1219
		if (parser == null)
523
			try {
1220
		{
1221
			try
1222
			{
1223
				return SAXParserFactory.newInstance().newSAXParser();
524
				return SAXParserFactory.newInstance().newSAXParser();
1224
			}
525
			}
1225
			catch (ParserConfigurationException e)
526
			catch (ParserConfigurationException e) {
1226
			{
527
				AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_PARSING,
1227
				AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_PARSING, e.getLocalizedMessage()), 0, e);
528
					e.getLocalizedMessage()),
1228
			}
529
					0,
1229
			catch (SAXException e)
530
					e);
1230
			{
531
			}
1231
				AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_PARSING, e.getLocalizedMessage()), 0, e);
532
			catch (SAXException e) {
533
				AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_PARSING,
534
					e.getLocalizedMessage()),
535
					0,
536
					e);
1232
			}
537
			}
1233
		}
538
		}
1234
		return parser;
539
		return parser;
1235
	}
540
	}
1236
541
1237
	
542
	public static String removeChar(String input, char toRemove) {
1238
	private static PrimitiveWidgetId getActionId(IContributionItem contrib)
543
		StringBuffer buf = new StringBuffer(input.length());
1239
	{
544
1240
		String id = null;
545
		int last = 0;
1241
		PrimitiveWidgetId widgetId = new PrimitiveWidgetId();
546
		for (int pos = input.indexOf(toRemove); pos != -1; pos = input.indexOf(toRemove,
1242
		
547
			last)) {
1243
		if (contrib instanceof IPluginContribution)
548
			buf.append(input.substring(last,
1244
		{
549
				pos));
1245
			id = ((IPluginContribution) contrib).getLocalId();
550
			last = pos + 1;
1246
		}
551
		}
1247
		id = id == null ? contrib.getId() : id;	
552
1248
		if (id != null)
553
		buf.append(input.substring(last,
1249
		{
554
			input.length()));
1250
			widgetId.setId("contribid/" + id); //$NON-NLS-1$
555
1251
		}
556
		return buf.toString();
1252
		else
557
	}
1253
		{
558
1254
			if (contrib instanceof ActionContributionItem)
559
	/**
1255
			{
560
	 * @param menuItem
1256
				ActionContributionItem actionItem = (ActionContributionItem) contrib;		
561
	 * @return
1257
				id = actionItem.getId();		
562
	 */
1258
				if (id != null)
563
	public static boolean onMenubar(MenuItem menuItem) {
1259
				{
564
		Menu parent = menuItem.getParent();
1260
					widgetId.setId("actionid/" + id); //$NON-NLS-1$
565
		MenuItem parentItem = parent.getParentItem();
1261
				}
566
1262
				else
567
		if (parentItem != null) {
1263
				{		
568
			return onMenubar(parentItem);
1264
					IAction action = actionItem.getAction();			
569
		}
1265
					id = action.getActionDefinitionId();			
570
1266
					if (id != null)
571
		Shell theShell = parent.getShell();
1267
					{
572
		return parent == theShell.getMenuBar();
1268
						widgetId.setId("defid/" + id); //$NON-NLS-1$
573
	}
1269
					}
574
1270
					else
575
	public static ContributionManager onToolbar(ToolItem toolItem) {
1271
					{
576
		ToolBar toolBar = toolItem.getParent();
1272
						widgetId.setId("actionclass/" + action.getClass().getName()); //$NON-NLS-1$
577
		Shell shell = toolBar.getShell();
1273
					}
578
		Object data = shell.getData();
579
		if (data instanceof ApplicationWindow) {
580
			ApplicationWindow window = (ApplicationWindow) data;
581
			ToolBarManager mng = window.getToolBarManager();
582
			if (mng != null) {
583
				if (mng.getControl() != null && mng.getControl() == toolBar)
584
					return mng;
585
			}
586
			CoolBarManager cmng = window.getCoolBarManager();
587
			if (cmng != null) {
588
				CoolBar cbar = cmng.getControl();
589
				Composite parent = toolBar.getParent();
590
				while (parent != null) {
591
					if (parent == cbar)
592
						return cmng;
593
					parent = parent.getParent();
1274
				}
594
				}
1275
			}
595
			}
1276
			else
596
		}
1277
			{
597
		return null;
1278
				widgetId.setId("contribclass/" + contrib.getClass().getName()); //$NON-NLS-1$				
598
	}
599
600
	public static IViewPart onWorkbenchPartToolbar(MenuItem menuItem) {
601
		IWorkbenchPage[] pages = GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getPages();
602
603
		/* For evey page */
604
		for (int i = 0; i < pages.length; i++) {
605
			IViewReference[] viewReferences = pages[i].getViewReferences();
606
607
			/* For evey opened view */
608
			for (int j = 0; j < viewReferences.length; j++) {
609
				IViewPart viewPart = viewReferences[j].getView(false);
610
				if (viewPart == null)
611
					continue;
612
613
				IMenuManager menuManager = viewPart.getViewSite().getActionBars().getMenuManager();
614
				if (menuManager != null && menuManager instanceof MenuManager && searchForMenuItem(((MenuManager) menuManager).getMenu(),
615
					menuItem))
616
					return viewPart;
1279
			}
617
			}
1280
		}
618
		}
1281
		
619
1282
		return widgetId;
620
		return null;
1283
	}
621
	}
1284
622
623
	private static boolean searchForMenuItem(Menu menu, MenuItem menuItem) {
624
		if (menu == null)
625
			return false;
626
627
		MenuItem[] items = menu.getItems();
628
		for (int i = 0; i < items.length; i++) {
629
			if (items[i] == menuItem)
630
				return true;
631
			Menu cascadeMenu = items[i].getMenu();
632
			if (cascadeMenu != null && searchForMenuItem(cascadeMenu,
633
				menuItem))
634
				return true;
635
		}
1285
636
637
		return false;
638
	}
639
	
1286
	/**
640
	/**
1287
	 * @param widget
641
	 * @param wd
642
	 * @param control
1288
	 * @return
643
	 * @return
1289
	 */
644
	 */
1290
	public static IWidgetId getActionId(Widget widget)
645
	public static boolean onWizardDialog(WizardDialog wd, Button control) {
1291
	{
646
		// see if we have a button on the wizard page or on the wizard dialog (i.e. wizard)
1292
		Object data = widget.getData();
647
		IWizardPage page = wd.getCurrentPage();
1293
		PrimitiveWidgetId widgetId = new PrimitiveWidgetId();
648
		Shell shell = control.getShell();
1294
		if (data != null && (data instanceof IContributionItem))
649
		Control pageControl = page.getControl();
1295
		{
650
		IUIObjectIdentifier relativePath = NonTrivialUIObjectResolverDelegate.computeRelativePath(
1296
			widgetId = getActionId((IContributionItem) data);
651
			(Composite) pageControl,
1297
			if (!widgetId.toString().equals(MacroConstants.EMPTY_STRING))
652
			null,
1298
			{
653
			control);
1299
				if (widget instanceof MenuItem)
654
		if (relativePath != null) {
1300
				{
655
			return false;
1301
					String menuInx = findMenuItemIndex((MenuItem)widget, "");
656
		}
1302
					widgetId.setId(widgetId.toString() + menuInx);
657
		// check for wizard buttons
658
		if (control instanceof Button) {
659
			relativePath = NonTrivialUIObjectResolverDelegate.computeRelativePath(
660
				shell,
661
				(Composite) pageControl,
662
				control);
663
			return true;
664
		}
665
		return false;
666
667
	}
668
	
669
	/**
670
	 * Used to located the editor part with the passed id.
671
	 * 
672
	 * @param shell
673
	 *            The current shell
674
	 * @param id
675
	 *            The id of the editor part
676
	 * @param line
677
	 *            The line number of the script (used to indicate the line number if we throw a core exception. Mark as -1 if a script is not being
678
	 *            used)
679
	 * @param input
680
	 *            If not null, then it attempts to match the input of the identified editor with the input that is passed it.
681
	 * 
682
	 * @return The editor part with the passed 'id'
683
	 * 
684
	 * @throws CoreException
685
	 *             If the editor part cannot be located.
686
	 */
687
	public static IEditorPart locateEditor(Shell shell, String id, String input) throws CoreException {
688
		Object data = shell.getData();
689
		IEditorPart editor = null;
690
691
		try {
692
			if (data instanceof IWorkbenchWindow) {
693
				IWorkbenchWindow window = (IWorkbenchWindow) data;
694
				IWorkbenchPage page = window.getActivePage();
695
696
				if (page != null) {
697
					IEditorReference[] erefs = page.getEditorReferences();
698
699
					for (int i = 0; i < erefs.length; i++) {
700
						IEditorReference eref = erefs[i];
701
						if (eref.getId().equals(id)) {
702
							// check the input
703
							IEditorPart part = eref.getEditor(true);
704
							if (input == null) {
705
								editor = part;
706
								break;
707
							}
708
							else if (part.getEditorInput().getName().equals(input)) {
709
								editor = part;
710
								break;
711
							}
712
						}
713
					}
714
				}
715
			}
716
		}
717
		catch (Throwable t) {
718
719
		}
720
		if (editor != null) {
721
			editor.getSite().getPage().activate(editor);
722
			return editor;
723
		}
724
725
		AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_EDITOR,
726
			id));
727
		return null;
728
	}
729
	
730
	/**
731
	 * Used to located the view part with the passed id.
732
	 * 
733
	 * @param shell
734
	 *            The current shell
735
	 * @param id
736
	 *            The id of the view part
737
	 * @param line
738
	 *            The line number of the script (used to indicate the line number if we throw a core exception. Mark as -1 if a script is not being
739
	 *            used)
740
	 * 
741
	 * @return The view part with the passed 'id'
742
	 * 
743
	 * @throws CoreException
744
	 *             If the view part cannot be located.
745
	 */
746
	public static IViewPart locateView(Shell shell, String id) throws CoreException {
747
		try {
748
			Object data = shell.getData();
749
750
			if (data instanceof IWorkbenchWindow) {
751
				IWorkbenchWindow window = (IWorkbenchWindow) data;
752
				IWorkbenchPage page = window.getActivePage();
753
				if (page != null) {
754
					IViewPart view = page.findView(id);
755
756
					if (view == null) {
757
						try {
758
							view = page.showView(id);
759
760
						}
761
						catch (PartInitException pie) {
762
							/* Do a thorough search */
763
							IWorkbenchWindow[] windows = GuiPlugin.getDefault().getWorkbench().getWorkbenchWindows();
764
765
							/* For every workbench window */
766
							for (int i = 0; i < windows.length && view == null; i++) {
767
								/* For every page of a workbench window */
768
								IWorkbenchPage[] pages = windows[i].getPages();
769
								for (int j = 0; j < pages.length && view == null; j++) {
770
									view = pages[j].findView(id);
771
772
								}
773
							}
774
							// need to mke sure that even if it is found in another page, we show it.
775
776
						}
777
					}
778
					// added for defcet 175320 in order to ensure the page is
779
					// given focus no matter where it is found
780
					page.showView(id);
781
					return view;
1303
				}
782
				}
1304
			}
783
			}
1305
		}
784
		}
1306
		else
785
		catch (Throwable t) {
1307
		{
786
			/* The next line will throw an exception */
1308
			widgetId.setId("readablename/" + ((widget instanceof MenuItem) ? getDisplayName((MenuItem)widget) : getDisplayName((ToolItem)widget)));			//$NON-NLS-1$
1309
		}
787
		}
1310
		
788
		AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_VIEW,
1311
		return widgetId; 
789
			id));
790
		return null;
1312
	}
791
	}
792
1313
}
793
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/MacroConstants.java (-3 / +13 lines)
Lines 40-59 Link Here
40
	public static final String OBJECT_ELEMENT = "object";	
40
	public static final String OBJECT_ELEMENT = "object";	
41
	public static final String ITEM_ELEMENT = "item";
41
	public static final String ITEM_ELEMENT = "item";
42
	public static final String SELECT_ITEM_ELEMENT = "selected-item";
42
	public static final String SELECT_ITEM_ELEMENT = "selected-item";
43
	public static final String PARENT_ELEMENT = "parent";
43
	//ANy: was never used: public static final String PARENT_ELEMENT = "parent";
44
44
45
	/** XML Attributes */
45
	/** XML Attributes */
46
	public static final String DESCRIPTIVE_ATTRIBUTE = "descriptive";
46
	public static final String DESCRIPTIVE_ATTRIBUTE = "descriptive";
47
	public static final String TYPE_ATTRIBUTE = "type";
47
	public static final String TYPE_ATTRIBUTE = "type";
48
	public static final String CONTEXT_ID_ATTRIBUTE = "contextId";
48
	public static final String CONTEXT_ID_ATTRIBUTE = "contextId";
49
	public static final String WIDGET_ID_ATTRIBUTE = "widgetId";	
49
	public static final String WIDGET_ID_ATTRIBUTE = "widgetId";
50
	public static final String OBJECT_ID_ATTRIBUTE = "objectId";
50
	public static final String ID_ATTRIBUTE = "id";
51
	public static final String ID_ATTRIBUTE = "id";
51
	public static final String RETURN_CODE_ATTRIBUTE = "return-code";
52
	public static final String RETURN_CODE_ATTRIBUTE = "return-code";
52
	public static final String TIME_TO_WAIT_ATTRIBUTE = "time-to-wait";
53
	public static final String TIME_TO_WAIT_ATTRIBUTE = "time-to-wait";
53
	public static final String OUTPUT_ATTRIBUTE = "output";
54
	public static final String OUTPUT_ATTRIBUTE = "output";
54
	public static final String PATH_ATTRIBUTE = "path";
55
	public static final String PATH_ATTRIBUTE = "path";
55
	public static final String REFERENCE_ID_ATTRIBUTE = "referenceId";
56
	public static final String REFERENCE_ID_ATTRIBUTE = "referenceId";
56
	public static final String RESOLVER_ATTRIBUTE = "resolverId";	
57
	public static final String RESOLVER_ID_ATTRIBUTE = "resolverId";	
57
	public static final String VERSION_ATTRIBUTE = "version";
58
	public static final String VERSION_ATTRIBUTE = "version";
58
	public static final String X_COORD_ATTRIBUTE = "x-coord";
59
	public static final String X_COORD_ATTRIBUTE = "x-coord";
59
	public static final String Y_COORD_ATTRIBUTE = "y-coord";
60
	public static final String Y_COORD_ATTRIBUTE = "y-coord";
Lines 75-81 Link Here
75
	public static final String LOCAL_TOOLBAR_MENU_VALUE = "local-toolbar-menu";
76
	public static final String LOCAL_TOOLBAR_MENU_VALUE = "local-toolbar-menu";
76
	public static final String TOOLBAR_VALUE = "toolbar";
77
	public static final String TOOLBAR_VALUE = "toolbar";
77
	public static final String LOCAL_TOOLBAR_VALUE = "local-toolbar";
78
	public static final String LOCAL_TOOLBAR_VALUE = "local-toolbar";
79
	public static final String TAB_VALUE = "tab"; // ANy: introduced for TabItems and CTabItems
78
	public static final String WIZARD_VALUE = "wizard";
80
	public static final String WIZARD_VALUE = "wizard";
79
	public static final String WIZARD_PAGE_VALUE = "wizard-page";
81
	public static final String WIZARD_PAGE_VALUE = "wizard-page";
80
	
82
	
83
	
84
	public static final String RESOLVER_ID_SUFFIX_SEPARATOR = "@@@";
85
	public static final String WIDGET_ID_SUFFIX_SEPARATOR = "%%%";
86
	public static final String OBJECT_ID_SUFFIX_SEPARATOR = "$$$";
87
	public static final String WIDGET_ID_UNIQUENESS_INDEX_SEPARATOR = "!!!";
88
	
89
	
90
	
81
}
91
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/ObjectMine.java (-569 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macro;
12
13
import java.util.ArrayList;
14
import java.util.Hashtable;
15
import java.util.LinkedList;
16
import java.util.List;
17
18
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.hyades.models.common.facades.behavioral.ITestSuite;
20
import org.eclipse.osgi.util.NLS;
21
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
22
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
23
import org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine;
24
import org.eclipse.tptp.test.auto.gui.internal.core.IUIObject;
25
import org.w3c.dom.NamedNodeMap;
26
import org.w3c.dom.Node;
27
28
29
/**
30
 * A concrete implementation of IObjectMine.
31
 * 
32
 * @author Ali Mehregani
33
 */
34
public class ObjectMine implements IObjectMine
35
{
36
	/** The root node of the tree structure that contains the objects */
37
	private IUIObject root;
38
	
39
	/** Included object mines */
40
	private ArrayList includes;
41
	
42
	/** The test suite that owns this object mine */
43
	private ITestSuite owner;
44
		
45
	/** The output object mine */
46
	private IObjectMine outputObjectMine;
47
	
48
	/** The active object */
49
	private IUIObject activeObject;
50
51
	/** Keeps track of the maximum reference id in use.  This is used to generate a unique
52
	 * reference id when requested */
53
	private int maximumRefId;
54
55
	/** The xml handler used to parse the object mine */
56
	private XMLDefaultHandler defaultXMLHandler;
57
	
58
	
59
	public ObjectMine (ITestSuite testSuite, XMLDefaultHandler defaultXMLHandler)
60
	{
61
		owner = testSuite;
62
		root = new UIObject(null);
63
		includes = new ArrayList();
64
		this.defaultXMLHandler = defaultXMLHandler;
65
	}
66
	
67
	public void addInclude(IObjectMine objectMine)
68
	{		
69
		includes.add(objectMine);		
70
		if (outputObjectMine != null)
71
		{
72
			IObjectMine foundObjectMine = findIncludedObjectMine(outputObjectMine);
73
			outputObjectMine = foundObjectMine == null ? outputObjectMine : foundObjectMine;
74
		}
75
	}
76
77
	public IUIObject lookupUIObject(IUIObject parent, String referenceId)
78
	{	
79
		IUIObject uiObject = lookupIncludes(parent, referenceId);
80
		if (uiObject != null)
81
			return uiObject;
82
				
83
		uiObject = lookupUIObject(parent);		
84
		if (uiObject == null)
85
			return null;
86
87
		uiObject = uiObject.findChild(referenceId);				
88
		return uiObject;
89
	}
90
	
91
	
92
	
93
	private IUIObject lookupUIObject(IUIObject object, boolean requiresPresence) throws UIObjectNotFound
94
	{
95
		if (object == null)
96
		{
97
			return root;
98
		}
99
		
100
		LinkedList relationship = object.getHierarchicalRelation();
101
		IUIObject currentNode = root;
102
		for (int i = 0, height=relationship.size(); currentNode != null && i < height; i++)
103
		{
104
			currentNode = currentNode.findChild(((IUIObject)relationship.get(i)).getReferenceId());
105
		}
106
		
107
		if (currentNode == null && requiresPresence)
108
			throw new UIObjectNotFound(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_OBJ_MINE_NF, object.getReferenceId()));
109
		
110
		return currentNode;
111
	}
112
	
113
	
114
	public IUIObject lookupUIObject(IUIObject parent, String contextId, String objectId)
115
	{
116
		IUIObject uiObject = lookupIncludes(parent, contextId, objectId);
117
		if (uiObject != null)
118
			return uiObject;
119
		
120
		IUIObject parentNode = lookupUIObject(parent);
121
		if (parentNode == null)
122
			return null;
123
		
124
		IUIObject[] children = parentNode.getChildren();
125
		for (int i = 0; i < children.length; i++)
126
		{
127
			if (((contextId == null && children[i].getContextId() == null) || (contextId != null && contextId.equals(children[i].getContextId()))) &&
128
				objectId.equals(children[i].getObjectId()))
129
			{
130
				return children[i];
131
			}
132
			
133
		}
134
		return null;
135
	}
136
	
137
	public IUIObject[] getChildren()
138
	{
139
		return root.getChildren();
140
	}
141
	
142
	
143
	
144
	private IUIObject lookupUIObject (IUIObject parent)
145
	{
146
		try
147
		{
148
			return lookupUIObject(parent, false);
149
		} 
150
		catch (UIObjectNotFound e)
151
		{
152
			return null;
153
		}
154
	}
155
156
	
157
	/**
158
	 * Looks up the included object mine to determine if they have a corresponding object
159
	 * with the reference id passed in.
160
	 * 
161
	 * @param parent The parent of the object
162
	 * @param referenceId The reference id of the object
163
	 * 
164
	 * @return The object with the reference id passed in; null if none is found. 
165
	 * @throws UIObjectNotFound In case the parent can't be found.
166
	 */
167
	private IUIObject lookupIncludes(IUIObject parent, String referenceId) 
168
	{
169
		IUIObject[] uiObject = lookupIncludes (parent, referenceId, null, null);
170
		return uiObject != null && uiObject.length > 0 ? uiObject[0] : null;
171
	}
172
173
	
174
	/**
175
	 * Looks up the included object mine to determine if they have a corresponding object
176
	 * with the contextId id and object id passed in.
177
	 * 
178
	 * @param parent The parent of the object
179
	 * @param contextId The context id of the object
180
	 * @param objectId The id of the object
181
	 * 
182
	 * @return The object with the matching context and object id passed in; null if none is found. 
183
	 * @throws UIObjectNotFound In case the parent can't be found.
184
	 */
185
	private IUIObject lookupIncludes(IUIObject parent, String contextId, String objectId) 
186
	{
187
		IUIObject[] uiObject = lookupIncludes (parent, null, contextId, objectId);
188
		return uiObject != null && uiObject.length > 0 ? uiObject[0] : null;
189
	}
190
	
191
	
192
	/**
193
	 * Looks up the included object mines to find an object that has been requested.
194
	 * If reference id happens to be null, then context/object id are used.
195
	 * 
196
	 * @param parent The parent of the object
197
	 * @param referenceId The reference id of the object. 
198
	 * @param contextId The context id of the object
199
	 * @param objectId The id of the object
200
	 *  
201
	 * @return The objects to look for
202
	 */
203
	private IUIObject[] lookupIncludes(IUIObject parent, String referenceId, String contextId, String objectId)
204
	{
205
		boolean useReferenceId = referenceId != null;
206
		boolean useObjectId = objectId != null;
207
		
208
		IUIObject objectRequested = null;
209
		IUIObject[] children = null; 
210
		for (int i = 0, includeCount = includes.size(); i < includeCount; i++)
211
		{
212
			IObjectMine objectMine = (IObjectMine)includes.get(i);
213
			if (useReferenceId)
214
			{
215
				objectRequested = objectMine.lookupUIObject(parent, referenceId);
216
			}
217
			else if (useObjectId)
218
			{
219
				objectRequested = objectMine.lookupUIObject(parent, contextId, objectId);
220
			}
221
		
222
			children = objectRequested == null ? children : new IUIObject[] {objectRequested};
223
			if (children != null)
224
			{
225
				return children;
226
			}
227
		}
228
		
229
		return null;
230
	}
231
	
232
	
233
	public IUIObject getRoot()
234
	{
235
		return root;
236
	}
237
238
	
239
	public IUIObject registerObject(IUIObject parent, Node objectNode) throws IDCollisionException, UIObjectNotFound, CoreException
240
	{
241
		NamedNodeMap attributes = objectNode.getAttributes();
242
		IUIObject uiObject = new UIObject(parent);
243
244
		IUIObject node = lookupUIObject(parent, true);		
245
		
246
		/* Set the attributes of the object */
247
		String referenceIdStr = getAttribute(attributes, MacroConstants.REFERENCE_ID_ATTRIBUTE);
248
		updateMaxReferenceId(referenceIdStr);
249
		
250
		Hashtable lineLevelDetail = null;
251
		if (defaultXMLHandler != null)
252
			lineLevelDetail = defaultXMLHandler.getLineTable();
253
		uiObject.setReferenceId(referenceIdStr);
254
		uiObject.setContextId(getAttribute(attributes, MacroConstants.CONTEXT_ID_ATTRIBUTE));
255
		uiObject.setObjectId(getAttribute(attributes, MacroConstants.ID_ATTRIBUTE));
256
		uiObject.setDescriptive(getAttribute(attributes, MacroConstants.DESCRIPTIVE_ATTRIBUTE));
257
		uiObject.setResolver(getAttribute(attributes, MacroConstants.RESOLVER_ATTRIBUTE));
258
		if (lineLevelDetail != null)
259
			uiObject.setData(((Integer[])lineLevelDetail.get(objectNode)));
260
		node.addChild(uiObject);
261
		
262
		return uiObject;
263
	}
264
	
265
	public IUIObject registerObject(IUIObject uiObject) throws IDCollisionException, UIObjectNotFound, CoreException
266
	{
267
		updateMaxReferenceId(uiObject.getReferenceId());
268
		
269
		IUIObject parentObject = uiObject.getParent();
270
		
271
		/* If the object that is about to be registered happens to be at the first level (i.e. 
272
		 * it is an infant), then it needs to be registered with the output destination of this object mine */
273
		if (parentObject == null && outputObjectMine != null)
274
		{
275
			outputObjectMine.registerObject(uiObject);
276
			includes.contains(outputObjectMine);
277
			return uiObject;
278
		}
279
		
280
		if (parentObject == null)
281
		{
282
			root.addChild(uiObject);
283
		}
284
		else
285
		{			
286
			parentObject.addChild(uiObject);	
287
		}
288
		
289
		
290
		return uiObject;
291
	}
292
293
	private void updateMaxReferenceId(String referenceIdStr)
294
	{
295
		try
296
		{
297
			int referenceId = Integer.parseInt(referenceIdStr);
298
			int maximumIncludedRefId = findMaximumIncludedRefId();
299
			maximumRefId = Math.max(Math.max(referenceId, maximumIncludedRefId), maximumRefId);
300
			
301
			if (referenceId == maximumRefId)
302
				maximumRefId++;
303
		}
304
		catch (NumberFormatException nfe)
305
		{
306
			/* Doesn't need to be handled */
307
		}
308
	}
309
	
310
	
311
	/**
312
	 * Walks through the included object mines of this object mine to determine the
313
	 * unique reference id.
314
	 * 
315
	 * @return A unique reference id that is global to all included object mines.
316
	 */
317
	private int findMaximumIncludedRefId()
318
	{
319
		int uniqueRefId = 0;
320
321
		for (int i = 0, includeCount = includes.size(); i < includeCount; i++)
322
		{
323
			IObjectMine currentObjectMine = (IObjectMine)includes.get(i);
324
			try
325
			{
326
				uniqueRefId = Math.max(Integer.parseInt(currentObjectMine.getUniqueReferenceId()), uniqueRefId);
327
			}
328
			catch (NumberFormatException nfe)
329
			{
330
				/* Ignore the exception */
331
			}
332
		}		
333
		return uniqueRefId;
334
	}
335
336
	private String getAttribute(NamedNodeMap attributes, String attributeName)
337
	{
338
		Node attr = attributes.getNamedItem(attributeName);
339
		return attr == null ? null : attr.getNodeValue();
340
	}
341
342
	public void setOutputSource(IObjectMine objectMine)
343
	{
344
		outputObjectMine = objectMine == null ? null : findIncludedObjectMine(objectMine);
345
		if (outputObjectMine == null)
346
			outputObjectMine = objectMine;		
347
	}
348
349
350
	public IObjectMine getOutputSource()
351
	{
352
		return outputObjectMine;
353
	}
354
355
	
356
	private IObjectMine findIncludedObjectMine(IObjectMine objectMine)
357
	{
358
		for (int i = 0, includeCount = includes.size(); i < includeCount; i++)
359
		{
360
			IObjectMine currentObjectMine = (IObjectMine)includes.get(i);
361
			if (currentObjectMine.equals(objectMine))
362
				return currentObjectMine;
363
		}
364
		
365
		return null;
366
	}
367
	
368
	public ITestSuite getOwner()
369
	{
370
		return owner;
371
	}
372
	
373
	
374
	public static class UIObjectNotFound extends Exception
375
	{
376
		static final long serialVersionUID = 4699726279267599112L;
377
		
378
		public UIObjectNotFound(String message)
379
		{
380
			super(message);
381
		}
382
	}
383
	
384
	
385
	public static class IDCollisionException extends Exception
386
	{
387
		static final long serialVersionUID = -6526030843455792891L;
388
		
389
		public IDCollisionException(String message)
390
		{
391
			super(message);
392
		}		
393
	}
394
395
396
	public String serializeToString()
397
	{
398
		StringBuffer objectMineSerialized = new StringBuffer();
399
		int indent = 0;
400
		
401
		/* <object-mine> */
402
		MacroUtil.addElement(objectMineSerialized, indent, MacroConstants.OBJECT_MINE_ELEMENT, false, true);
403
				
404
		serializeHeader(objectMineSerialized, indent + 1, true);
405
		serializeObjects(objectMineSerialized, indent + 1, true);
406
		
407
		/* </object-mine> */
408
		MacroUtil.addElement(objectMineSerialized, indent, MacroConstants.OBJECT_MINE_ELEMENT, true, true);
409
		
410
		return objectMineSerialized.toString();
411
	}
412
413
414
	private void serializeHeader(StringBuffer objectMineSerialized, int indent, boolean includeHeader)
415
	{
416
		/* Don't write anything if the header is empty */
417
		if (outputObjectMine == null && (includes == null || includes.size() <= 0))
418
			return;
419
		
420
		boolean outputElement = outputObjectMine != null;
421
		
422
		/* <header output="..."/>*/
423
		if (includeHeader)
424
		{
425
			MacroUtil.addElement(objectMineSerialized, indent, MacroConstants.HEADER_ELEMENT, false, !outputElement);
426
			if (outputElement)
427
				MacroUtil.addAttribute(objectMineSerialized, new String[] {MacroConstants.OUTPUT_ATTRIBUTE}, new String[] {AutoGUIUtil.resolveTestSuitePath(outputObjectMine.getOwner())}, false, true);
428
		}
429
430
		/* Add the <include .../> elements */
431
		for (int i = 0, includeCount = includes.size(); i < includeCount; i++)
432
		{
433
			IObjectMine currentInclude = (IObjectMine)includes.get(i);
434
			ITestSuite testSuite = currentInclude.getOwner();
435
			String path = AutoGUIUtil.resolveTestSuitePath(testSuite);
436
			
437
			if (path  != null)
438
			{
439
				MacroUtil.addElement(objectMineSerialized, indent + 1, MacroConstants.INCLUDE_ELEMENT, false, false);
440
				MacroUtil.addAttribute(objectMineSerialized, 
441
							new String[] {MacroConstants.PATH_ATTRIBUTE}, 
442
							new String[] {path}, 
443
							true, true);
444
			}
445
		}
446
		
447
		if (includeHeader)
448
		{
449
			MacroUtil.addElement(objectMineSerialized, indent, MacroConstants.HEADER_ELEMENT, true, true);
450
		}
451
	}
452
453
	
454
	private void serializeObjects(StringBuffer objectMineSerialized, int indent, boolean includeHeader)
455
	{	
456
		IUIObject[] rootChildren = root.getChildren();
457
		if (rootChildren == null || rootChildren.length <= 0)
458
			return;
459
		
460
		/* Add the objects */
461
		if (includeHeader)
462
		{
463
			MacroUtil.addElement(objectMineSerialized, indent, MacroConstants.OBJECTS_ELEMENT, false, true);
464
			addObject(objectMineSerialized, indent + 1, rootChildren);
465
			MacroUtil.addElement(objectMineSerialized, indent, MacroConstants.OBJECTS_ELEMENT, true, true);
466
			return;
467
		}
468
		
469
		addObject(objectMineSerialized, indent + 1, rootChildren);
470
	}
471
	
472
	/**
473
	 * @see org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine#serializeHeaderToString()
474
	 */
475
	public String serializeHeaderToString()
476
	{
477
		StringBuffer sb = new StringBuffer();
478
		serializeHeader(sb, 0, false);
479
		return sb.toString();
480
	}
481
482
	
483
	/**
484
	 * @see org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine#serializeObjetsToString()
485
	 */
486
	public String serializeObjetsToString()
487
	{
488
		StringBuffer sb = new StringBuffer();
489
		serializeObjects(sb, 0, false);
490
		return sb.toString();
491
	}
492
	
493
	private void addObject(StringBuffer objectMapSerialized, int indent, IUIObject[] rootChildren)
494
	{		
495
		if (rootChildren == null)
496
			return;
497
		
498
		for (int i = 0; i < rootChildren.length; i++)
499
		{
500
			IUIObject currentUIObject = rootChildren[i];			
501
			IUIObject[] children = rootChildren[i].getChildren();
502
			
503
			/* If the object is a shell without any children, then skip it */
504
			if (currentUIObject.getParent() == null && (children == null || children.length <= 0))
505
				continue;
506
			
507
			boolean hasChildren =  children!= null && children.length > 0;
508
			MacroUtil.addElement (objectMapSerialized, indent, MacroConstants.OBJECT_ELEMENT, false, false);
509
			MacroUtil.addAttribute(objectMapSerialized, 
510
					new String[] {MacroConstants.DESCRIPTIVE_ATTRIBUTE,
511
								  MacroConstants.REFERENCE_ID_ATTRIBUTE,
512
								  MacroConstants.CONTEXT_ID_ATTRIBUTE,
513
								  MacroConstants.RESOLVER_ATTRIBUTE,
514
								  MacroConstants.ID_ATTRIBUTE},
515
					new String[] {currentUIObject.getDescriptive(),
516
								  currentUIObject.getReferenceId(),
517
								  currentUIObject.getContextId(),
518
								  currentUIObject.getResolverId(),
519
								  currentUIObject.getObjectId()}
520
					, !hasChildren, true);
521
			if (hasChildren)
522
			{
523
				addObject(objectMapSerialized, indent + 1, rootChildren[i].getChildren());
524
				MacroUtil.addElement (objectMapSerialized, indent, MacroConstants.OBJECT_ELEMENT, true, true);
525
			}
526
		}
527
		
528
	}
529
530
531
	public IUIObject getActiveObject()
532
	{
533
		return activeObject;
534
	}
535
536
	public void setActiveObject(IUIObject activeObject)
537
	{
538
		this.activeObject = activeObject;
539
	}
540
541
	public String getUniqueReferenceId()
542
	{
543
		int maximumIncludedRefId = findMaximumIncludedRefId();
544
		maximumRefId = Math.max(maximumIncludedRefId, maximumRefId);
545
		
546
		/* Restart the reference id */
547
		if (maximumRefId >= Integer.MAX_VALUE - 10)
548
		{
549
			maximumRefId = 0;
550
		}
551
		return String.valueOf(maximumRefId);
552
	}
553
554
	public List getIncludes()
555
	{
556
		return includes;
557
	}
558
	
559
	public boolean equals(Object o)
560
	{
561
		return o instanceof IObjectMine ? getOwner().getId().equals(((IObjectMine)o).getOwner().getId()) : false;		
562
	}
563
564
	public void setOwner(ITestSuite testSuite)
565
	{
566
		this.owner = testSuite;		
567
	}
568
569
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/MacroManager.java (-595 / +375 lines)
Lines 13-23 Link Here
13
import java.io.IOException;
13
import java.io.IOException;
14
import java.io.InputStream;
14
import java.io.InputStream;
15
import java.lang.reflect.InvocationTargetException;
15
import java.lang.reflect.InvocationTargetException;
16
import java.util.Hashtable;
17
import java.util.Vector;
16
import java.util.Vector;
18
17
19
import org.eclipse.core.runtime.CoreException;
18
import org.eclipse.core.runtime.CoreException;
20
import org.eclipse.core.runtime.IConfigurationElement;
21
import org.eclipse.core.runtime.IProgressMonitor;
19
import org.eclipse.core.runtime.IProgressMonitor;
22
import org.eclipse.core.runtime.NullProgressMonitor;
20
import org.eclipse.core.runtime.NullProgressMonitor;
23
import org.eclipse.core.runtime.Platform;
21
import org.eclipse.core.runtime.Platform;
Lines 29-51 Link Here
29
import org.eclipse.jface.operation.IRunnableContext;
27
import org.eclipse.jface.operation.IRunnableContext;
30
import org.eclipse.osgi.util.NLS;
28
import org.eclipse.osgi.util.NLS;
31
import org.eclipse.swt.SWT;
29
import org.eclipse.swt.SWT;
32
import org.eclipse.swt.widgets.Control;
33
import org.eclipse.swt.widgets.Display;
30
import org.eclipse.swt.widgets.Display;
34
import org.eclipse.swt.widgets.Event;
31
import org.eclipse.swt.widgets.Event;
35
import org.eclipse.swt.widgets.Listener;
32
import org.eclipse.swt.widgets.Listener;
36
import org.eclipse.swt.widgets.Shell;
33
import org.eclipse.swt.widgets.Shell;
37
import org.eclipse.swt.widgets.Widget;
38
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
34
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
39
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
35
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
40
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
36
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
41
import org.eclipse.tptp.test.auto.gui.internal.commands.MacroCommandShell;
42
import org.eclipse.tptp.test.auto.gui.internal.commands.VerificationCommand;
37
import org.eclipse.tptp.test.auto.gui.internal.commands.VerificationCommand;
43
import org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine;
38
import org.eclipse.tptp.test.auto.gui.internal.commands.factory.IMacroCommandFactory;
44
import org.eclipse.tptp.test.auto.gui.internal.core.IWidgetId;
39
import org.eclipse.tptp.test.auto.gui.internal.commands.factory.MacroCommandFactoryLoader;
45
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetResolverLoader;
40
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine;
46
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMine.IDCollisionException;
41
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMineManager;
47
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMine.UIObjectNotFound;
42
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine.IDCollisionException;
43
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine.UIObjectNotFound;
48
import org.eclipse.tptp.test.auto.gui.internal.runner.AutoGUIRunner;
44
import org.eclipse.tptp.test.auto.gui.internal.runner.AutoGUIRunner;
45
import org.eclipse.tptp.test.auto.gui.internal.util.XMLDefaultHandler;
49
import org.eclipse.ui.IPartListener;
46
import org.eclipse.ui.IPartListener;
50
import org.eclipse.ui.IWorkbench;
47
import org.eclipse.ui.IWorkbench;
51
import org.eclipse.ui.IWorkbenchPage;
48
import org.eclipse.ui.IWorkbenchPage;
Lines 57-72 Link Here
57
import org.xml.sax.SAXException;
54
import org.xml.sax.SAXException;
58
55
59
/**
56
/**
60
 * A singleton class that manages the macro recording and playback.  Clients should always keep in
57
 * A singleton class that manages the macro recording and playback. Clients
61
 * mind that there is only one instance of a macro manager always running.  Proper synchronization
58
 * should always keep in mind that there is only one instance of a macro manager
62
 * and clean up is left to the client
59
 * always running. Proper synchronization and clean up is left to the client
63
 */
60
 */
64
public class MacroManager
61
public class MacroManager {
65
{
62
66
	public static final String IGNORE = "__macro_ignore__";
63
	public static final String IGNORE = "__macro_ignore__";
67
64
68
	/* The state of jobs.  This is used to listen for on going jobs and adding wait commands when
65
	/*
69
	 * there is a job running */
66
	 * The state of jobs. This is used to listen for on going jobs and adding
67
	 * wait commands when there is a job running
68
	 */
70
	public static final int IDLE = 0;
69
	public static final int IDLE = 0;
71
70
72
	public static final int RUNNING = 1;
71
	public static final int RUNNING = 1;
Lines 78-107 Link Here
78
	/* The instance that this singleton class holds */
77
	/* The instance that this singleton class holds */
79
	private static MacroManager macroManagerInstance;
78
	private static MacroManager macroManagerInstance;
80
79
81
	/* Keeps track of the global states that the macro manager is in.  See the
80
	/*
82
	 * global state events for the possible states that this macro manager can be in.  This
81
	 * Keeps track of the global states that the macro manager is in. See the
83
	 * variable must be locked when it is read/written from/to.  Use globalStateLock to lock
82
	 * global state events for the possible states that this macro manager can
84
	 * this field. */
83
	 * be in. This variable must be locked when it is read/written from/to. Use
84
	 * globalStateLock to lock this field.
85
	 */
85
	private byte globalState;
86
	private byte globalState;
86
87
87
	/* Global state lock */
88
	/* Global state lock */
88
	private Boolean globalStateLock;
89
	private Boolean globalStateLock;
89
90
90
	/* Global states */
91
	public static final byte RECORDING_MODE = 0x00; 			/* Recording mode */
92
	public static final byte VERIFICATION_MODE = 0x01; 			/* Verificaiton mode */
93
	public static final byte SUSPEND_MODE = 0x02; 				/* Suspend mode */
94
	public static final byte QUICK_RUN_MODE = 0x03; 			/* Quick run mode (when current workbench is used as the context) */
95
	public static final byte EXECUTION_RUN_MODE = 0x04; 		/* Execution run mode (when proper launch configuration is used) */
96
	public static final byte IDLE_MODE = 0x05; 					/* Idle mode */
97
	public static final byte POSITION_BASED_REC_MODE = 0x06;	/* Position based recording */
98
99
	/* Custom event details */
100
	public static final int POSITION_BASED_EVENT = Integer.MIN_VALUE;
101
	
102
	/* The verification command */
103
	private VerificationCommand verificationCommand;
104
105
	/* Verification hook listener */
91
	/* Verification hook listener */
106
	private VerificationHookListener verificationHooksListener;
92
	private VerificationHookListener verificationHooksListener;
107
93
Lines 111-118 Link Here
111
	/* The part listener */
97
	/* The part listener */
112
	private IPartListener partListener;
98
	private IPartListener partListener;
113
99
114
	/* Global state listeners that will be invoked when the global state 
100
	/*
115
	 * of this macro manager changes */
101
	 * Global state listeners that will be invoked when the global state of this
102
	 * macro manager changes
103
	 */
116
	private Vector globalStateListeners;
104
	private Vector globalStateListeners;
117
105
118
	/* Stores the dependecies of the current test suite that is being executed */
106
	/* Stores the dependecies of the current test suite that is being executed */
Lines 120-165 Link Here
120
108
121
	/* Stores the runner that is running the current test suite */
109
	/* Stores the runner that is running the current test suite */
122
	private AutoGUIRunner runner;
110
	private AutoGUIRunner runner;
123
	
111
124
	/* Indicates whether artificial wait time is on/off */
112
	/* Indicates whether artificial wait time is on/off */
125
	private boolean artificialWaitOn;
113
	private boolean artificialWaitOn;
126
	
114
127
	/* Stores the allowable time-out threshold time for individual command execution */
115
	/*
116
	 * Stores the allowable time-out threshold time for individual command
117
	 * execution
118
	 */
128
	private int commandTimeoutThreshold;
119
	private int commandTimeoutThreshold;
129
	
120
130
	/* Points to the object mine loaded for the operation (e.g. record/playback) that is in progress */
121
	/*
131
	private IObjectMine objectMine;
122
	 * Points to the object mine loaded for the operation (e.g. record/playback)
132
	
123
	 * that is in progress
124
	 */
125
	private MacroObjectDescriptorMine objectMine;
126
127
	private IMacroCommandFactory commandFactory;
128
133
	/* Points to the test suite that is being used to record a test case */
129
	/* Points to the test suite that is being used to record a test case */
134
	private ITestSuite testSuite;
130
	private ITestSuite testSuite;
135
	
131
136
	/* Indicates whether object mines should be used for a recording session or not */
132
	/*
137
	private boolean objectMineOn;
133
	 * Indicates whether object mines should be used for a recording session or
138
	
134
	 * not
139
	/* Keeps an ordered list of the resolver ids */
140
	private String[] resolverIds;
141
	
142
	/* The widget resolver:
143
	 * KEY = resolver id
144
	 * VALUE = A class of type WidgetResolverLoader
145
	 */
135
	 */
146
	private Hashtable widgetResolvers;
136
	private boolean objectMineOn;
147
	
137
148
	/* The display listeners */
138
	/* The display listeners */
149
	private DisplayListener listener;
139
	private DisplayListener listener;
150
140
151
	/* The job listeners */
141
	/* The job listeners */
152
	private JobListener jobListener;
142
	private JobListener jobListener;
153
143
154
	
144
	class DisplayListener implements Listener {
155
	class DisplayListener implements Listener
145
156
	{
146
		public void handleEvent(Event event) {
157
		public void handleEvent(Event event)
158
		{
159
			/* Bail out if we are in the suspend mode */
147
			/* Bail out if we are in the suspend mode */
160
			synchronized (globalStateLock)
148
			synchronized (globalStateLock) {
161
			{
149
				if (globalState == ModeConstants.SUSPEND_MODE)
162
				if (globalState == SUSPEND_MODE)
163
					return;
150
					return;
164
			}
151
			}
165
152
Lines 167-195 Link Here
167
		}
154
		}
168
	}
155
	}
169
156
170
	class JobListener extends JobChangeAdapter
157
	class JobListener extends JobChangeAdapter {
171
	{
158
172
		private int state = IDLE;
159
		private int state = IDLE;
173
160
174
		public void running(IJobChangeEvent event)
161
		public void running(IJobChangeEvent event) {
175
		{
176
			if (!event.getJob().isSystem() && state == IDLE)
162
			if (!event.getJob().isSystem() && state == IDLE)
177
				state = RUNNING;
163
				state = RUNNING;
178
		}
164
		}
179
165
180
		public void done(IJobChangeEvent event)
166
		public void done(IJobChangeEvent event) {
181
		{
182
			if (!event.getJob().isSystem() && state == RUNNING)
167
			if (!event.getJob().isSystem() && state == RUNNING)
183
				state = DONE;
168
				state = DONE;
184
		}
169
		}
185
170
186
		public void reset()
171
		public void reset() {
187
		{
188
			state = IDLE;
172
			state = IDLE;
189
		}
173
		}
190
174
191
		public int getState()
175
		public int getState() {
192
		{
193
			return state;
176
			return state;
194
		}
177
		}
195
	}
178
	}
Lines 197-209 Link Here
197
	/**
180
	/**
198
	 * Private constructor. Use getInstance()
181
	 * Private constructor. Use getInstance()
199
	 */
182
	 */
200
	private MacroManager()
183
	private MacroManager() {
201
	{
202
		listener = new DisplayListener();
184
		listener = new DisplayListener();
203
		jobListener = new JobListener();		
185
		jobListener = new JobListener();
204
		globalStateLock = new Boolean(false);
186
		globalStateLock = new Boolean(false);
205
		globalState = RECORDING_MODE; /* The initial global state is recording */
187
		globalState = ModeConstants.RECORDING_MODE; /*
206
		widgetResolvers = new Hashtable();
188
													 * The initial global state
189
													 * is recording
190
													 */
207
	}
191
	}
208
192
209
	/**
193
	/**
Lines 211-337 Link Here
211
	 * 
195
	 * 
212
	 * @return An instance of this class
196
	 * @return An instance of this class
213
	 */
197
	 */
214
	public static MacroManager getInstance()
198
	public static MacroManager getInstance() {
215
	{
216
		if (macroManagerInstance == null)
199
		if (macroManagerInstance == null)
217
			macroManagerInstance = new MacroManager();
200
			macroManagerInstance = new MacroManager();
218
201
219
		return macroManagerInstance;
202
		return macroManagerInstance;
220
	}
203
	}
221
204
222
	public boolean isRecording()
205
	public boolean isRecording() {
223
	{
224
		return currentMacro != null;
206
		return currentMacro != null;
225
	}
207
	}
226
208
227
	/**
209
	/**
228
	 * Invoked to start a recording session
210
	 * Invoked to start a recording session
229
	 * 
211
	 * 
230
	 * @param testSuite The test suite
212
	 * @param testSuite
231
	 * @param objectMineOn Indicates whether object mines should be used or not
213
	 *            The test suite
214
	 * @param objectMineOn
215
	 *            Indicates whether object mines should be used or not
232
	 * 
216
	 * 
233
	 * @throws CoreException In case of an unexpected error
217
	 * @throws CoreException
234
	 * @throws UIObjectNotFound If an expected UI object is not found
218
	 *             In case of an unexpected error
235
	 * @throws IDCollisionException If there is a ID collision between UI objects
219
	 * @throws UIObjectNotFound
220
	 *             If an expected UI object is not found
221
	 * @throws IDCollisionException
222
	 *             If there is a ID collision between UI objects
236
	 */
223
	 */
237
	public void startRecording(ITestSuite testSuite, boolean objectMineOn) throws CoreException, UIObjectNotFound, IDCollisionException
224
	public void startRecording(ITestSuite testSuite, boolean objectMineOn)
238
	{
225
			throws CoreException, UIObjectNotFound, IDCollisionException {
239
		this.objectMineOn = objectMineOn;
226
		this.objectMineOn = objectMineOn;
240
		Display display = PlatformUI.getWorkbench().getDisplay();
227
		Display display = PlatformUI.getWorkbench().getDisplay();
241
		hookListeners(display);
228
		hookListeners(display);
242
		MacroUtil.clearWorkbenchPartListeners();
229
		MacroUtil.clearWorkbenchPartListeners();
243
		currentMacro = new Macro();
230
		currentMacro = new Macro();
244
		currentMacro.initializeForRecording(display);
231
		currentMacro.initializeForRecording(display);
245
		
232
246
		this.testSuite = testSuite; 
233
		this.testSuite = testSuite;
247
		objectMine = ObjectMineManager.getInstance().loadObjectMine(testSuite);
234
		objectMine = MacroObjectDescriptorMineManager.getInstance()
248
		
235
				.loadObjectMine(testSuite);
249
		hookPartListener();		
236
237
		hookPartListener();
250
	}
238
	}
251
239
252
	
253
	/**
240
	/**
254
	 * Stops the current macro that this macro manager maintains.  The macro returned
241
	 * Stops the current macro that this macro manager maintains. The macro
255
	 * can be null, if a previous error has caused the current macro to be null
242
	 * returned can be null, if a previous error has caused the current macro to
243
	 * be null
256
	 * 
244
	 * 
257
	 * @param interrupted true if it is interrupted and false if it is normally stopped. 
245
	 * @param interrupted
258
	 * @return The macro to be stopped (null if a previous error has occurred in macro manager)
246
	 *            true if it is interrupted and false if it is normally stopped.
247
	 * @return The macro to be stopped (null if a previous error has occurred in
248
	 *         macro manager)
259
	 */
249
	 */
260
	public Macro stopRecording(boolean interrupted)
250
	public Macro stopRecording(boolean interrupted) {
261
	{
262
		removePartListener();
251
		removePartListener();
263
252
264
		/* Write the object mine to the test suite */
253
		/* Write the object mine to the test suite */
265
		if (testSuite != null && objectMine != null && objectMineOn)
254
		if (testSuite != null && objectMine != null && objectMineOn) {
266
		{
267
			if (!interrupted)
255
			if (!interrupted)
268
				ObjectMineManager.getInstance().writeObjectMine(objectMine);
256
				MacroObjectDescriptorMineManager.getInstance().writeObjectMine(
257
						objectMine);
269
			testSuite = null;
258
			testSuite = null;
270
			objectMine = null;
259
			objectMine = null;
271
		}
260
		}
272
		
261
273
		if (currentMacro != null)
262
		if (currentMacro != null)
274
			currentMacro.stopRecording();
263
			currentMacro.stopRecording();
275
264
276
		Macro newMacro = currentMacro;
265
		Macro newMacro = currentMacro;
277
		currentMacro = null;		
266
		currentMacro = null;
278
267
279
		shutdown();
268
		shutdown();
280
		return newMacro;
269
		return newMacro;
281
	}
270
	}
282
	
283
	
284
271
285
	/**
272
	/**
286
	 * Register a part listener
273
	 * Register a part listener
287
	 */
274
	 */
288
	private void hookPartListener()
275
	private void hookPartListener() {
289
	{
276
		activePage = GuiPlugin.getDefault().getWorkbench()
290
		activePage = GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getActivePage();
277
				.getActiveWorkbenchWindow().getActivePage();
291
		partListener = new IPartListener()
278
		partListener = new IPartListener() {
292
		{
279
293
			public void partActivated(IWorkbenchPart part)
280
			public void partActivated(IWorkbenchPart part) {
294
			{
295
				Event event = null;
281
				Event event = null;
296
282
297
				/* Simulate a focus in event */
283
				/* Simulate a focus in event */
298
				try
284
				try {
299
				{
300
					event = new Event();
285
					event = new Event();
301
					event.type = SWT.FocusIn;
286
					event.type = SWT.FocusIn;
302
					Shell shell = part.getSite().getPage().getWorkbenchWindow().getShell();
287
					Shell shell = part.getSite().getPage().getWorkbenchWindow()
288
							.getShell();
303
					event.display = shell.getDisplay();
289
					event.display = shell.getDisplay();
304
					event.widget = MacroUtil.getFirstChild(part);
290
					event.widget = MacroUtil.getFirstChild(part);
305
				}
291
				} catch (Exception e) {
306
				catch (Exception e)
307
				{
308
					/* Don't report an event if there is an error */
292
					/* Don't report an event if there is an error */
309
					System.err.println(e.getMessage());
293
					System.err.println(e.getMessage());
310
				}
294
				}
311
295
312
				if (event != null)
296
				if (event != null) {
313
				{
314
					listener.handleEvent(event);
297
					listener.handleEvent(event);
315
				}
298
				}
316
			}
299
			}
317
300
318
			public void partBroughtToTop(IWorkbenchPart part)
301
			public void partBroughtToTop(IWorkbenchPart part) {
319
			{
320
				/* Does not need to be implmented */
302
				/* Does not need to be implmented */
321
			}
303
			}
322
304
323
			public void partClosed(IWorkbenchPart part)
305
			public void partClosed(IWorkbenchPart part) {
324
			{
325
				/* Does not need to be implmented */
306
				/* Does not need to be implmented */
326
			}
307
			}
327
308
328
			public void partDeactivated(IWorkbenchPart part)
309
			public void partDeactivated(IWorkbenchPart part) {
329
			{
330
				/* Does not need to be implmented */
310
				/* Does not need to be implmented */
331
			}
311
			}
332
312
333
			public void partOpened(IWorkbenchPart part)
313
			public void partOpened(IWorkbenchPart part) {
334
			{
335
				/* Does not need to be implmented */
314
				/* Does not need to be implmented */
336
			}
315
			}
337
316
Lines 343-350 Link Here
343
	/**
322
	/**
344
	 * Remove the part listener
323
	 * Remove the part listener
345
	 */
324
	 */
346
	private void removePartListener()
325
	private void removePartListener() {
347
	{
348
		if (activePage == null)
326
		if (activePage == null)
349
			return;
327
			return;
350
328
Lines 352-367 Link Here
352
		activePage = null;
330
		activePage = null;
353
		partListener = null;
331
		partListener = null;
354
	}
332
	}
355
	
333
356
	public Macro getCurrentMacro()
334
	public Macro getCurrentMacro() {
357
	{
358
		return currentMacro;
335
		return currentMacro;
359
	}
336
	}
360
337
361
338
	public void hookListeners(Display display) {
362
363
	public void hookListeners(Display display)
364
	{
365
		display.addFilter(SWT.MouseUp, listener);
339
		display.addFilter(SWT.MouseUp, listener);
366
		display.addFilter(SWT.KeyUp, listener);
340
		display.addFilter(SWT.KeyUp, listener);
367
		display.addFilter(SWT.KeyDown, listener);
341
		display.addFilter(SWT.KeyDown, listener);
Lines 370-397 Link Here
370
		display.addFilter(SWT.Expand, listener);
344
		display.addFilter(SWT.Expand, listener);
371
		display.addFilter(SWT.Collapse, listener);
345
		display.addFilter(SWT.Collapse, listener);
372
		display.addFilter(SWT.Modify, listener);
346
		display.addFilter(SWT.Modify, listener);
373
		display.addFilter(SWT.Activate, listener);		
347
		display.addFilter(SWT.Activate, listener);
374
		display.addFilter(SWT.Close, listener);
348
		display.addFilter(SWT.Close, listener);
375
		display.addFilter(SWT.FocusIn, listener);		
349
		display.addFilter(SWT.FocusIn, listener);
376
		IJobManager jobManager = Platform.getJobManager();
350
		IJobManager jobManager = Platform.getJobManager();
377
		jobManager.addJobChangeListener(jobListener);
351
		jobManager.addJobChangeListener(jobListener);
378
	}
352
	}
379
	
353
380
	public void hookPositionBasedListeners(Display display)
354
	public void hookPositionBasedListeners(Display display) {
381
	{	
355
		display.addFilter(SWT.Activate, listener);
382
		display.addFilter(SWT.Activate, listener);		
383
		display.addFilter(SWT.Close, listener);
356
		display.addFilter(SWT.Close, listener);
384
		display.addFilter(SWT.MouseUp, listener);
357
		display.addFilter(SWT.MouseUp, listener);
385
		display.addFilter(SWT.MouseDown, listener);
358
		display.addFilter(SWT.MouseDown, listener);
359
		display.addFilter(SWT.MouseMove, listener);
386
		display.addFilter(SWT.KeyUp, listener);
360
		display.addFilter(SWT.KeyUp, listener);
387
		display.addFilter(SWT.KeyDown, listener);
361
		display.addFilter(SWT.KeyDown, listener);
388
		
362
389
		IJobManager jobManager = Platform.getJobManager();
363
		IJobManager jobManager = Platform.getJobManager();
390
		jobManager.addJobChangeListener(jobListener);
364
		jobManager.addJobChangeListener(jobListener);
391
	}
365
	}
392
366
393
	public void unhookListeners(Display display)
367
	public void unhookListeners(Display display) {
394
	{
395
		display.removeFilter(SWT.MouseUp, listener);
368
		display.removeFilter(SWT.MouseUp, listener);
396
		display.removeFilter(SWT.KeyUp, listener);
369
		display.removeFilter(SWT.KeyUp, listener);
397
		display.removeFilter(SWT.KeyDown, listener);
370
		display.removeFilter(SWT.KeyDown, listener);
Lines 406-427 Link Here
406
		IJobManager jobManager = Platform.getJobManager();
379
		IJobManager jobManager = Platform.getJobManager();
407
		jobManager.removeJobChangeListener(jobListener);
380
		jobManager.removeJobChangeListener(jobListener);
408
	}
381
	}
409
	
382
410
	public void unhookPositionBasedListeners(Display display)
383
	public void unhookPositionBasedListeners(Display display) {
411
	{		
384
		display.removeFilter(SWT.Activate, listener);
412
		display.removeFilter(SWT.Activate, listener);		
413
		display.removeFilter(SWT.Close, listener);
385
		display.removeFilter(SWT.Close, listener);
414
		display.removeFilter(SWT.MouseUp, listener);
386
		display.removeFilter(SWT.MouseUp, listener);
415
		display.removeFilter(SWT.MouseDown, listener);
387
		display.removeFilter(SWT.MouseDown, listener);
388
		display.removeFilter(SWT.MouseMove, listener);
416
		display.removeFilter(SWT.KeyUp, listener);
389
		display.removeFilter(SWT.KeyUp, listener);
417
		display.removeFilter(SWT.KeyDown, listener);
390
		display.removeFilter(SWT.KeyDown, listener);
418
		
391
419
		IJobManager jobManager = Platform.getJobManager();
392
		IJobManager jobManager = Platform.getJobManager();
420
		jobManager.removeJobChangeListener(jobListener);
393
		jobManager.removeJobChangeListener(jobListener);
421
	}
394
	}
422
395
423
	public void shutdown()
396
	public void shutdown() {
424
	{
425
		Display display = PlatformUI.getWorkbench().getDisplay();
397
		Display display = PlatformUI.getWorkbench().getDisplay();
426
		unhookListeners(display);
398
		unhookListeners(display);
427
		unhookPositionBasedListeners(display);
399
		unhookPositionBasedListeners(display);
Lines 430-457 Link Here
430
		currentMacro = null;
402
		currentMacro = null;
431
		artificialWaitOn = false;
403
		artificialWaitOn = false;
432
	}
404
	}
433
	
405
434
	
435
	/**
406
	/**
436
	 * Prepares this macro manager for playback of test cases.  This method should be
407
	 * Prepares this macro manager for playback of test cases. This method
437
	 * invoked to do the required one time initialization before a test suite's test 
408
	 * should be invoked to do the required one time initialization before a
438
	 * cases are played back.
409
	 * test suite's test cases are played back.
439
	 * 
410
	 * 
440
	 * @param objectMineXML The object mine XML
411
	 * @param objectMineXML
441
	 * @throws CoreException In case of any unexpected error
412
	 *            The object mine XML
413
	 * @throws CoreException
414
	 *             In case of any unexpected error
442
	 */
415
	 */
443
	public void prepareForPlayBack(String objectMineXML) throws CoreException
416
	public void prepareForPlayBack(String objectMineXML) throws CoreException {
444
	{	
417
		try {
445
		try
418
			setObjectMine(MacroObjectDescriptorMineManager.getInstance()
446
		{
419
					.loadObjectMine(objectMineXML));
447
			setObjectMine(ObjectMineManager.getInstance().loadObjectMine(objectMineXML));
420
		} catch (Exception e) {
448
		} catch (Exception e)
421
			AutoGUIUtil.throwCoreException(
449
		{
422
					AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE, 0, e);
450
			AutoGUIUtil.throwCoreException(AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE, 0, e);
423
		}
451
		} 						
452
	}
424
	}
453
	
425
454
	
455
	/**
426
	/**
456
	 * Plays a provided macro stream. The method will close the input stream
427
	 * Plays a provided macro stream. The method will close the input stream
457
	 * upon parsing.
428
	 * upon parsing.
Lines 459-563 Link Here
459
	 * @param is
430
	 * @param is
460
	 * @throws CoreException
431
	 * @throws CoreException
461
	 */
432
	 */
462
	public boolean play(final Display display, final IRunnableContext context, String scriptName, XMLDefaultHandler handler, Boolean shouldBlock) throws CoreException
433
	public boolean play(final Display display, final IRunnableContext context,
463
	{		
434
			String scriptName, XMLDefaultHandler handler, Boolean shouldBlock)
435
			throws CoreException {
464
		Node root = handler.getDocumentElement();
436
		Node root = handler.getDocumentElement();
465
		NodeList children = root.getChildNodes();
437
		NodeList children = root.getChildNodes();
466
		MacroCommandShell.initializeForNewPlay();
438
		MacroCommandShell.initializeForNewPlay();
467
		
439
468
		final Macro macro = new Macro(scriptName);
440
		final Macro macro = new Macro(scriptName);
469
		for (int i = 0; i < children.getLength(); i++)
441
		for (int i = 0; i < children.getLength(); i++) {
470
		{
471
			Node child = children.item(i);
442
			Node child = children.item(i);
472
			if (child.getNodeName().equals(MacroConstants.SHELL_ELEMENT))
443
			if (child.getNodeName().equals(MacroConstants.SHELL_ELEMENT)) {
473
			{
444
				macro.load(child, handler.getLineTable());
474
				macro.addShell(child, handler.getLineTable());
475
			}
445
			}
476
		}
446
		}
477
		// discard the DOM
447
		// discard the DOM
478
		handler = null;
448
		handler = null;
479
449
480
		final boolean[] result = new boolean[1];
450
		final boolean[] result = new boolean[1];
481
		
451
482
		class MacroOperationWrapper implements Runnable
452
		class MacroOperationWrapper implements Runnable {
483
		{
453
484
			private Exception exception;
454
			private Exception exception;
485
			private Object objectToNotify;
455
			private Object objectToNotify;
486
			private boolean isDone;
456
			private boolean isDone;
487
			
457
488
			public MacroOperationWrapper (Object objectToNotify)
458
			public MacroOperationWrapper(Object objectToNotify) {
489
			{
490
				this.objectToNotify = objectToNotify;
459
				this.objectToNotify = objectToNotify;
491
				isDone = false;
460
				isDone = false;
492
			}
461
			}
493
			
462
494
			
463
			public void run() {
495
			public void run()
464
				try {
496
			{
465
					/*
497
				try
466
					 * Ali M.: Unfortunately position-based commands don't work
498
				{					
467
					 * when the macro is played in an IRunnableContext with a
499
					/* Ali M.: Unfortunately position-based commands don't work when the macro is played in an IRunnableContext with
468
					 * progress bar. I had to sacrifice the progress bar for
500
					 * a progress bar.  I had to sacrifice the progress bar for position-based commands to run correctly */
469
					 * position-based commands to run correctly
501
					result[0] = runMacro(macro, display, new NullProgressMonitor());
470
					 */
502
					
471
					result[0] = runMacro(macro, display,
503
					if (objectToNotify != null)
472
							new NullProgressMonitor());
504
					{
473
505
						synchronized(objectToNotify)
474
					if (objectToNotify != null) {
506
						{
475
						synchronized (objectToNotify) {
507
							objectToNotify.notify();
476
							objectToNotify.notify();
508
						}
477
						}
509
					}
478
					}
510
					isDone = true;
479
					isDone = true;
511
				}
480
				} catch (Exception e) {
512
				catch (Exception e)
513
				{
514
					exception = e;
481
					exception = e;
515
					isDone = true;
482
					isDone = true;
516
				}
483
				}
517
			}
484
			}
518
			
485
519
			public void didErrorOccur() throws Exception
486
			public void didErrorOccur() throws Exception {
520
			{
521
				if (exception != null)
487
				if (exception != null)
522
					throw exception;
488
					throw exception;
523
			}
489
			}
524
			
490
525
			public boolean isDone()
491
			public boolean isDone() {
526
			{
527
				return isDone;
492
				return isDone;
528
			}
493
			}
529
		}
494
		}
530
		
495
531
		try
496
		try {
532
		{			
497
			/*
533
			/* Run the macro synchronously or asynchronously depending on the argument passed in */
498
			 * Run the macro synchronously or asynchronously depending on the
534
			if (shouldBlock.booleanValue())
499
			 * argument passed in
535
			{
500
			 */
536
				MacroOperationWrapper macroRunOperation = new MacroOperationWrapper(shouldBlock);
501
			if (shouldBlock.booleanValue()) {
502
				MacroOperationWrapper macroRunOperation = new MacroOperationWrapper(
503
						shouldBlock);
537
				Thread macroRunThread = new Thread(macroRunOperation);
504
				Thread macroRunThread = new Thread(macroRunOperation);
538
				macroRunThread.start();
505
				macroRunThread.start();
539
				
506
540
				while (!macroRunOperation.isDone())
507
				while (!macroRunOperation.isDone()) {
541
				{
508
					synchronized (shouldBlock) {
542
					synchronized (shouldBlock)
543
					{
544
						shouldBlock.wait(500);
509
						shouldBlock.wait(500);
545
					}
510
					}
546
				}
511
				}
547
				
512
548
				macroRunOperation.didErrorOccur();
513
				macroRunOperation.didErrorOccur();
549
			}
514
			} else
550
			else
551
				new Thread(new MacroOperationWrapper(null)).start();
515
				new Thread(new MacroOperationWrapper(null)).start();
552
		}
516
		} catch (Exception e) {
553
		catch (Exception e)
554
		{
555
			/* The cause of this exception would give away the error */
517
			/* The cause of this exception would give away the error */
556
			AutoGUIUtil.throwCoreException(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_RUNNING_T, -1, e);
518
			AutoGUIUtil.throwCoreException(
519
					AutoGUIMessages.AUTO_GUI_ERROR_MACRO_RUNNING_T, -1, e);
557
			result[0] = false;
520
			result[0] = false;
558
		}
521
		} finally {
559
		finally
560
		{
561
			/* Indicate that we were done playing, if this is a blocking call */
522
			/* Indicate that we were done playing, if this is a blocking call */
562
			if (shouldBlock != null && shouldBlock.booleanValue())
523
			if (shouldBlock != null && shouldBlock.booleanValue())
563
				MacroCommandShell.macroStopped();
524
				MacroCommandShell.macroStopped();
Lines 565-900 Link Here
565
		return result[0];
526
		return result[0];
566
	}
527
	}
567
528
568
	private boolean runMacro(final Macro macro, final Display display, IProgressMonitor monitor) throws InvocationTargetException
529
	private boolean runMacro(final Macro macro, final Display display,
569
	{
530
			IProgressMonitor monitor) throws InvocationTargetException {
570
		boolean success = false;
531
		boolean success = false;
571
		try
532
		try {
572
		{
573
			// System.out.println("Start macro: "+macro.getName());
533
			// System.out.println("Start macro: "+macro.getName());
574
			success = macro.playback(display, null, monitor);
534
			success = macro.playback(display, null, monitor);
575
		}
535
		} catch (CoreException e) {
576
		catch (CoreException e)
577
		{
578
			throw new InvocationTargetException(e);
536
			throw new InvocationTargetException(e);
579
		}
537
		} catch (ClassCastException e) {
580
		catch (ClassCastException e)
581
		{
582
			throw new InvocationTargetException(e);
538
			throw new InvocationTargetException(e);
583
		}
539
		} finally {
584
		finally
585
		{
586
			monitor.done();
540
			monitor.done();
587
			// System.out.println("Stop macro: "+macro.getName());
541
			// System.out.println("Stop macro: "+macro.getName());
588
		}
542
		}
589
		return success;
543
		return success;
590
	}
544
	}
591
545
592
	public XMLDefaultHandler createMacroDocument(InputStream is) throws CoreException
546
	public XMLDefaultHandler createMacroDocument(InputStream is)
593
	{
547
			throws CoreException {
594
		XMLDefaultHandler handler = null;
548
		XMLDefaultHandler handler = null;
595
		try
549
		try {
596
		{
597
			handler = MacroUtil.createXMLDocument(is);
550
			handler = MacroUtil.createXMLDocument(is);
551
		} catch (SAXException e) {
552
			AutoGUIUtil.throwCoreException(NLS.bind(
553
					AutoGUIMessages.AUTO_GUI_ERROR_MACRO_PARSING, e
554
							.getLocalizedMessage()), 0, e);
555
		} catch (IOException e) {
556
			AutoGUIUtil.throwCoreException(NLS.bind(
557
					AutoGUIMessages.AUTO_GUI_ERROR_MACRO_PARSING, e
558
							.getLocalizedMessage()), 0, e);
598
		}
559
		}
599
		catch (SAXException e)
560
600
		{
601
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_PARSING, e.getLocalizedMessage()), 0, e);
602
		}
603
		catch (IOException e)
604
		{
605
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_PARSING, e.getLocalizedMessage()), 0, e);
606
		}
607
		
608
		return handler;
561
		return handler;
609
	}
562
	}
610
563
611
564
	private void onEvent(Event event) {
612
	private void onEvent(Event event)
565
		try {
613
	{
566
			/*
614
		try
567
			 * If for any reason the current macro is null, then something has
615
		{				
568
			 * gone wrong. Shut the macro manager down
616
			/* If for any reason the current macro is null, then something has gone wrong.  Shut the macro manager down */
569
			 */
617
			if (currentMacro == null)
570
			if (currentMacro == null) {
618
			{
619
				shutdown();
571
				shutdown();
620
				return;
572
				return;
621
			}
573
			}
622
574
623
575
			synchronized (globalStateLock) {
624
			synchronized (globalStateLock)
576
				if (globalState == ModeConstants.RECORDING_MODE
625
			{
577
						&& (event.type == SWT.Close || event.type == SWT.Activate)
626
				if (globalState == RECORDING_MODE && (event.type == SWT.Close || event.type == SWT.Activate) && !(event.widget instanceof Shell))
578
						&& !(event.widget instanceof Shell))
627
					return;
579
					return;
628
			}
580
			}
629
581
630
			/* If there is an incomming event and there is already a job running in the background
582
			/*
631
			 * then insert a pause command */
583
			 * If there is an incomming event and there is already a job running
632
			if (jobListener.getState() == RUNNING || jobListener.getState() == DONE)
584
			 * in the background then insert a pause command
633
			{
585
			 */
586
			if (jobListener.getState() == RUNNING
587
					|| jobListener.getState() == DONE) {
634
				currentMacro.addPause();
588
				currentMacro.addPause();
635
				jobListener.reset();
589
				jobListener.reset();
636
			}
590
			}
637
591
638
			/* Check the global state here.  If we're in the verification mode, then 
592
			/*
639
			 * redirect the events to the verification command. */
593
			 * Check the global state here. If we're in the verification mode,
640
			synchronized (globalStateLock)
594
			 * then redirect the events to the verification command.
641
			{
595
			 */
642
				if (globalState == RECORDING_MODE)
596
			synchronized (globalStateLock) {
643
				{
597
				if (globalState == ModeConstants.RECORDING_MODE) {
598
					currentMacro.addEvent(event);
599
				} else if (globalState == ModeConstants.POSITION_BASED_REC_MODE) {
600
					/*
601
					 * We'll tag the event with a detail constant that will
602
					 * identify the event as position based
603
					 */
604
					event.detail = EventConstants.EVENT_DETAIL__POSITION_BASED_EVENT;
605
					currentMacro.addEvent(event);
606
				} else if (globalState == ModeConstants.VERIFICATION_MODE) {
607
					/*
608
					 * We'll tag the event with a detail constant that will
609
					 * identify the event as verification hook insertion related
610
					 * command
611
					 */
612
					event.detail = EventConstants.EVENT_DETAIL__VERIFICATION_HOOK_INSERTION_EVENT;
644
					currentMacro.addEvent(event);
613
					currentMacro.addEvent(event);
645
				}
646
				else if (globalState == POSITION_BASED_REC_MODE)
647
				{
648
					/* We'll tag the event with a detail constant that will identify the event as position based */
649
					event.detail = POSITION_BASED_EVENT;
650
					currentMacro.addEvent (event);
651
				}
652
				else if (globalState == VERIFICATION_MODE)
653
				{					
654
					verificationCommand = VerificationCommand.constructInstance(null, event);
655
					
656
					/* If we get events that can possibly change our shell stack, then fire off to the current macro
657
					 * to handle it */				
658
					if (event.type == SWT.Activate && event.widget instanceof Shell)
659
					{
660
						currentMacro.addEvent(event);
661
					}
662
663
					/* Something went wrong.  Inform the user with some feedback */
664
					if (verificationCommand == null)
665
					{
666
						String error = VerificationCommand.getError();
667
						if (error != null && !error.equals(""))
668
							notifyVerificationListener(error);
669
					}
670
671
					/* The normal flow */
672
					else
673
					{
674
						MacroCommandShell topShell = currentMacro.getTopShell();					
675
						
676
						/* There is a chance that the macro does not have a top shell.  We'll
677
						 * attempt to resolve its top shell, if unsuccessful, then we'll prompt
678
						 * the user with an error. */
679
						
680
						if (topShell == null && event.widget instanceof Control)
681
						{
682
							Event artificialEvent = new Event();
683
							artificialEvent.type = SWT.Activate;
684
							artificialEvent.display = event.widget.getDisplay();
685
							artificialEvent.widget = ((Control) event.widget).getShell();
686
							currentMacro.addEvent(artificialEvent);
687
						}
688
689
						/* If the resolve attempt failed, then notify the user */
690
						topShell = currentMacro.getTopShell();
691
						if (topShell == null)
692
						{
693
							setGlobalState(SUSPEND_MODE);
694
							showError(AutoGUIMessages.AUTO_GUI_ERROR_VER_TOP_SHELL_T, AutoGUIMessages.AUTO_GUI_ERROR_VER_TOP_SHELL);
695
							setGlobalState(RECORDING_MODE);
696
							return;
697
						}
698
614
699
						verificationCommand.setParent (topShell);
615
					// see if the insertion was successful, notify the listener
700
						topShell.addVerificationCommand(verificationCommand);
616
					// about the result
701
						notifyVerificationListener(verificationCommand);
617
					if (currentMacro.getTopShell() == null) {
618
						setGlobalState(ModeConstants.SUSPEND_MODE);
619
						showError(
620
								AutoGUIMessages.AUTO_GUI_ERROR_VER_TOP_SHELL_T,
621
								AutoGUIMessages.AUTO_GUI_ERROR_VER_TOP_SHELL);
622
						setGlobalState(ModeConstants.RECORDING_MODE);
702
					}
623
					}
703
				}
624
				}
704
			}
625
			}
705
626
706
		}
627
		} catch (Exception e) {
707
		catch (Exception e)
628
			AutoGUIUtil.openErrorWithDetail(
708
		{
629
					AutoGUIMessages.AUTO_GUI_COMMON_UNKNOWN, e.getMessage(), e);
709
			e.printStackTrace();
630
			e.printStackTrace();
710
			stopRecording(true);
631
			stopRecording(true);
711
		}
632
		}
712
	}
633
	}
713
634
714
	/**
635
	/**
715
	 * Show an error message 
636
	 * Show an error message
716
	 * @param title The title of the error message
637
	 * 
717
	 * @param errorMsg The actual error message
638
	 * @param title
639
	 *            The title of the error message
640
	 * @param errorMsg
641
	 *            The actual error message
718
	 */
642
	 */
719
	private void showError(final String title, final String errorMsg)
643
	public void showError(final String title, final String errorMsg) {
720
	{
721
		final IWorkbench workbench = PlatformUI.getWorkbench();
644
		final IWorkbench workbench = PlatformUI.getWorkbench();
722
		workbench.getDisplay().syncExec(new Runnable()
645
		workbench.getDisplay().syncExec(new Runnable() {
723
		{
646
724
			public void run()
647
			public void run() {
725
			{
726
				IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
648
				IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
727
				if (window != null)
649
				if (window != null) {
728
				{
729
					MessageDialog.openError(window.getShell(), title, errorMsg);
650
					MessageDialog.openError(window.getShell(), title, errorMsg);
730
				}
651
				}
731
			}
652
			}
732
		});
653
		});
733
	}
654
	}
734
655
735
	private void notifyVerificationListener(VerificationCommand verificationCommand)
656
	protected void notifyVerificationListener(
736
	{
657
			VerificationCommand verificationCommand) {
737
		if (verificationHooksListener != null)
658
		if (verificationHooksListener != null)
738
			verificationHooksListener.instanceReady(verificationCommand);
659
			verificationHooksListener.instanceReady(verificationCommand);
739
660
740
	}
661
	}
741
662
742
	private void notifyVerificationListener(String error)
663
	protected void notifyVerificationListener(String error) {
743
	{
744
		if (verificationHooksListener != null)
664
		if (verificationHooksListener != null)
745
			verificationHooksListener.error(error);
665
			verificationHooksListener.error(error);
746
	}
666
	}
747
	
748
	
749
	/**
750
	 * Return the widget id resolved by the widget resolver whose id is passed in.
751
	 * If in case the resolverId is null, then step through the widget resolvers starting
752
	 * from index inx and return the results of the first resolver that is able to resolve
753
	 * the widget that is passed in.
754
	 *   
755
	 * @param widget The widget to be resolved
756
	 * @param resolverId The resolver id.  It can be null
757
	 * @param inx The index of the resolvers that the search should begin from.  This is 
758
	 * declared as an array because this method needs to preserve the change in value.  The
759
	 * array is of size 1 and its value must always be >= 0. 
760
	 * 
761
	 * @return The resolved widget id or null if none can be found 
762
	 */	
763
	public IWidgetId resolveWidget (Widget parent, Object object, String resolverId, int[] inx)
764
	{		
765
		/* Load the widget if neccessary */
766
		if (resolverIds == null)
767
		{
768
			loadWidgetResolvers();
769
		}
770
		
771
		/* We have a valid resolver id */
772
		if (resolverId != null)
773
		{
774
			WidgetResolverLoader widgetResolverLoader = (WidgetResolverLoader)widgetResolvers.get(resolverId);
775
			if (widgetResolverLoader == null)
776
			{
777
				return null;
778
			}
779
			return widgetResolverLoader.getWidgetResolver().getUniqueId(parent, object);
780
		}
781
		
782
		/* Otherwise, we'll need to step through the resolvers */
783
		if (inx[0] < 0 || inx[0] >= resolverIds.length)
784
			return null;
785
		
786
		for (int i = inx[0]; i < resolverIds.length; i++)
787
		{			
788
			WidgetResolverLoader widgetResolverLoader = (WidgetResolverLoader)widgetResolvers.get(resolverIds[i]);
789
			IWidgetId widgetId = widgetResolverLoader.getWidgetResolver().getUniqueId(parent, object);
790
			inx[0]++;
791
			if (widgetId != null)
792
				return widgetId;
793
		}
794
				
795
		return null;
796
	}
797
	
798
	
799
	public Hashtable getWidgetResolvers()
800
	{
801
		if (resolverIds == null)
802
			loadWidgetResolvers();
803
		
804
		return widgetResolvers;
805
	}
806
	
807
	public IWidgetId resolveWidget (Widget widget, String resolverId, int[] inx)
808
	{
809
		return resolveWidget (widget instanceof Control ? ((Control)widget).getParent() : null, widget, resolverId, inx);
810
	}
811
812
	/**
813
	 * Load the registered widget resolvers.  The widget resolvers are ordered in the descending order of their priority
814
	 */
815
	private void loadWidgetResolvers()
816
	{
817
		IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor("org.eclipse.tptp.test.auto.gui.widgetResolver");
818
		Vector tempContainer = new Vector(elements.length);
819
		
820
		for (int i = 0; i < elements.length; i++)
821
		{
822
			WidgetResolverLoader widgetResolverReg = WidgetResolverLoader.constructInstance(elements[i]);
823
			if (widgetResolverReg != null)
824
			{
825
				tempContainer.add(findIndex(widgetResolverReg.getPriority(), tempContainer), widgetResolverReg);
826
				widgetResolvers.put(widgetResolverReg.getId(), widgetResolverReg);
827
			}
828
		}
829
		
830
		resolverIds = new String[tempContainer.size()];
831
		for (int i = 0; i < resolverIds.length; i++)
832
		{
833
			resolverIds[i] = ((WidgetResolverLoader)tempContainer.get(i)).getId();
834
		}
835
	}
836
837
	private int findIndex(int desiredPriority, Vector container, int startIntervalInx, int endIntervalInx, int length) 
838
	{		
839
		if (startIntervalInx == endIntervalInx || startIntervalInx == endIntervalInx - 1)
840
		{
841
			if (length > 0)
842
			{
843
				WidgetResolverLoader widgetResolverReg = (WidgetResolverLoader)container.get(startIntervalInx);
844
				int priority = widgetResolverReg.getPriority();
845
				if (desiredPriority < priority)
846
					return startIntervalInx;
847
			}
848
			return endIntervalInx;
849
		}
850
		
851
		/* What's in the middle? */
852
		int middleInx = startIntervalInx + (int) Math.ceil((endIntervalInx - startIntervalInx)/2);
853
		WidgetResolverLoader widgetResolverReg = (WidgetResolverLoader)container.get(middleInx);
854
		int middleElementPriority = widgetResolverReg.getPriority();
855
		
856
		if (middleElementPriority > desiredPriority)
857
			endIntervalInx = middleInx;
858
		else if (middleElementPriority < desiredPriority)
859
			startIntervalInx = middleInx;
860
		else
861
			return middleInx;
862
		return findIndex(desiredPriority, container, startIntervalInx, endIntervalInx, length);
863
	}
864
	
865
	private int findIndex(int priority, Vector container)
866
	{
867
		int length = container.size();
868
		return findIndex (priority, container, 0, length, length);
869
	}
870
667
871
	
872
	/**
668
	/**
873
	 * Pre-condition:
669
	 * Pre-condition:
874
	 * <ul>
670
	 * <ul>
875
	 * 	<li> To guarantee that this field is not changed while it is being used, it must be locked </li>
671
	 * <li> To guarantee that this field is not changed while it is being used,
672
	 * it must be locked </li>
876
	 * </ul>
673
	 * </ul>
877
	 *  
674
	 * 
878
	 * @return The global state of the macro manager. 
675
	 * @return The global state of the macro manager.
879
	 */
676
	 */
880
	public byte getGlobalState()
677
	public byte getGlobalState() {
881
	{	
882
		return globalState;
678
		return globalState;
883
	}
679
	}
884
	
885
680
886
	public void setGlobalState(byte globalState)
681
	public void setGlobalState(byte globalState) {
887
	{
682
		synchronized (globalStateLock) {
888
		synchronized (globalStateLock)
889
		{
890
			byte oldState = this.globalState;
683
			byte oldState = this.globalState;
891
			this.globalState = globalState;
684
			this.globalState = globalState;
892
685
893
			if (globalStateListeners != null && oldState != this.globalState)
686
			if (globalStateListeners != null && oldState != this.globalState) {
894
			{
687
				for (int i = 0; i < globalStateListeners.size(); i++) {
895
				for (int i = 0; i < globalStateListeners.size(); i++)
688
					GlobalStateListener gsl = (GlobalStateListener) globalStateListeners
896
				{
689
							.get(i);
897
					GlobalStateListener gsl = (GlobalStateListener) globalStateListeners.get(i);
898
					if (gsl.isListenerOn())
690
					if (gsl.isListenerOn())
899
						gsl.globalStateChange(oldState, this.globalState);
691
						gsl.globalStateChange(oldState, this.globalState);
900
				}
692
				}
Lines 902-1097 Link Here
902
			}
694
			}
903
		}
695
		}
904
	}
696
	}
905
	
697
906
	public void setGlobalStateWithoutLock(byte globalState)
698
	public void setGlobalStateWithoutLock(byte globalState) {
907
	{
908
		byte oldState = this.globalState;
699
		byte oldState = this.globalState;
909
		this.globalState = globalState;
700
		this.globalState = globalState;
910
	
701
911
		if (globalStateListeners != null && oldState != this.globalState)
702
		if (globalStateListeners != null && oldState != this.globalState) {
912
		{
703
			for (int i = 0; i < globalStateListeners.size(); i++) {
913
			for (int i = 0; i < globalStateListeners.size(); i++)
704
				GlobalStateListener gsl = (GlobalStateListener) globalStateListeners
914
			{
705
						.get(i);
915
				GlobalStateListener gsl = (GlobalStateListener) globalStateListeners.get(i);
916
				if (gsl.isListenerOn())
706
				if (gsl.isListenerOn())
917
					gsl.globalStateChange(oldState, this.globalState);
707
					gsl.globalStateChange(oldState, this.globalState);
918
			}
708
			}
919
	
709
920
		}
710
		}
921
	}
711
	}
922
712
923
	public void setVerListener(VerificationHookListener verHookListener)
713
	public void setVerListener(VerificationHookListener verHookListener) {
924
	{
925
		verificationHooksListener = verHookListener;
714
		verificationHooksListener = verHookListener;
926
	}
715
	}
927
716
928
	public void removeVerListener()
717
	public void removeVerListener() {
929
	{
930
		verificationHooksListener = null;
718
		verificationHooksListener = null;
931
	}
719
	}
932
720
933
	public void registerGlobalStateListener(GlobalStateListener gsl)
721
	public void registerGlobalStateListener(GlobalStateListener gsl) {
934
	{
935
		if (this.globalStateListeners == null)
722
		if (this.globalStateListeners == null)
936
			this.globalStateListeners = new Vector(2);
723
			this.globalStateListeners = new Vector(2);
937
724
938
		this.globalStateListeners.add(gsl);
725
		this.globalStateListeners.add(gsl);
939
	}
726
	}
940
727
941
	public void removeGlobalStateListener(GlobalStateListener gsl)
728
	public void removeGlobalStateListener(GlobalStateListener gsl) {
942
	{
729
		if (this.globalStateListeners != null) {
943
		if (this.globalStateListeners != null)
944
		{
945
			this.globalStateListeners.remove(gsl);
730
			this.globalStateListeners.remove(gsl);
946
			if (this.globalStateListeners.size() == 0)
731
			if (this.globalStateListeners.size() == 0)
947
				this.globalStateListeners = null;
732
				this.globalStateListeners = null;
948
		}
733
		}
949
	}
734
	}
950
735
951
	public void setDependecies(Vector dependecies)
736
	public void setDependecies(Vector dependecies) {
952
	{
953
		this.dependecies = dependecies;
737
		this.dependecies = dependecies;
954
	}
738
	}
955
739
956
	public Vector getDependecies()
740
	public Vector getDependecies() {
957
	{
958
		return this.dependecies;
741
		return this.dependecies;
959
	}
742
	}
960
743
961
	public AutoGUIRunner getRunner()
744
	public AutoGUIRunner getRunner() {
962
	{
963
		return runner;
745
		return runner;
964
	}
746
	}
965
747
966
	public void setRunner(AutoGUIRunner runner)
748
	public void setRunner(AutoGUIRunner runner) {
967
	{
968
		this.runner = runner;
749
		this.runner = runner;
969
	}
750
	}
970
	
751
971
	
972
	/**
752
	/**
973
	 * This method is invoked to toggle the position based recording option on or off.
753
	 * This method is invoked to toggle the position based recording option on
974
	 * Turning on position based recording will only record position-based commands. 
754
	 * or off. Turning on position based recording will only record
975
	 * This is only recommended where object based recording cannot be used. (e.g. User
755
	 * position-based commands. This is only recommended where object based
976
	 * clicking at a specific location of a canvas)
756
	 * recording cannot be used. (e.g. User clicking at a specific location of a
977
	 * 
757
	 * canvas)
978
	 * @param state True indicates that position based recording should be turned on and false indicates
758
	 * 
979
	 * that it should be turned off
759
	 * @param state
760
	 *            True indicates that position based recording should be turned
761
	 *            on and false indicates that it should be turned off
980
	 * 
762
	 * 
981
	 * @return true if operation is successful; false otherwise
763
	 * @return true if operation is successful; false otherwise
982
	 */
764
	 */
983
	public synchronized boolean togglePositionBasedRec(boolean state) 
765
	public synchronized boolean togglePositionBasedRec(boolean state) {
984
	{
766
985
	
767
		synchronized (globalStateLock) {
986
		synchronized (globalStateLock)
987
		{
988
			Display currentDisplay = PlatformUI.getWorkbench().getDisplay();
768
			Display currentDisplay = PlatformUI.getWorkbench().getDisplay();
989
			
769
990
			/* We're required to turn on position based recoridng */
770
			/* We're required to turn on position based recoridng */
991
			if (state)
771
			if (state) {
992
			{
772
				if (currentDisplay != null) {
993
				if (currentDisplay != null)
994
				{
995
					unhookListeners(currentDisplay);
773
					unhookListeners(currentDisplay);
996
					hookPositionBasedListeners(currentDisplay);
774
					hookPositionBasedListeners(currentDisplay);
997
					
775
998
					globalState = POSITION_BASED_REC_MODE;
776
					globalState = ModeConstants.POSITION_BASED_REC_MODE;
999
				}
777
				} else
1000
				else 
1001
					return false;
778
					return false;
1002
			}
779
			}
1003
			/* Otherwise turn the option off */
780
			/* Otherwise turn the option off */
1004
			else if (!state)
781
			else if (!state) {
1005
			{
782
				if (currentDisplay != null) {
1006
				if (currentDisplay != null)
1007
				{
1008
					unhookPositionBasedListeners(currentDisplay);
783
					unhookPositionBasedListeners(currentDisplay);
1009
					hookListeners(currentDisplay);
784
					hookListeners(currentDisplay);
1010
					
785
1011
					globalState = RECORDING_MODE;
786
					globalState = ModeConstants.RECORDING_MODE;
1012
				}
787
				} else
1013
				else
1014
					return false;
788
					return false;
1015
			}
789
			}
1016
				
790
1017
		}
791
		}
1018
		
792
1019
		return true;
793
		return true;
1020
		
794
1021
	}
795
	}
1022
	
796
1023
	public boolean isArtificialWaitOn() 
797
	public boolean isArtificialWaitOn() {
1024
	{
1025
		return artificialWaitOn;
798
		return artificialWaitOn;
1026
	}
799
	}
1027
800
1028
	public void setArtificialWaitOn(boolean artificialWaitOn) 
801
	public void setArtificialWaitOn(boolean artificialWaitOn) {
1029
	{
1030
		this.artificialWaitOn = artificialWaitOn;
802
		this.artificialWaitOn = artificialWaitOn;
1031
	}
803
	}
1032
	
804
1033
	
1034
	/**
805
	/**
1035
	 * @return the objectMine
806
	 * @return the objectMine
1036
	 */
807
	 */
1037
	public IObjectMine getObjectMine()
808
	public MacroObjectDescriptorMine getObjectMine() {
1038
	{
1039
		return objectMine;
809
		return objectMine;
1040
	}
810
	}
1041
811
1042
	/**
812
	/**
1043
	 * @param objectMine the objectMine to set
813
	 * @param objectMine
814
	 *            the objectMine to set
1044
	 */
815
	 */
1045
	public void setObjectMine(IObjectMine objectMine)
816
	public void setObjectMine(MacroObjectDescriptorMine objectMine) {
1046
	{
1047
		this.objectMine = objectMine;
817
		this.objectMine = objectMine;
1048
	}
818
	}
1049
	
819
1050
	
1051
	/**
820
	/**
1052
	 * Used to register classes as listeners that are awaiting the creation of a VerificationCommand
821
	 * Used to register classes as listeners that are awaiting the creation of a
1053
	 * from a focus command of an editor or a viewer.
822
	 * VerificationCommand from a focus command of an editor or a viewer.
1054
	 * 
823
	 * 
1055
	 * @author Ali Mehregani
824
	 * @author Ali Mehregani
1056
	 */
825
	 */
1057
	public interface VerificationHookListener
826
	public interface VerificationHookListener {
1058
	{
827
1059
		/**
828
		/**
1060
		 * Reports any error while attempting to construct object
829
		 * Reports any error while attempting to construct object
1061
		 * 
830
		 * 
1062
		 * @param error A descriptive error message 
831
		 * @param error
832
		 *            A descriptive error message
1063
		 */
833
		 */
1064
		public void error(String error);
834
		public void error(String error);
1065
835
1066
		/**
836
		/**
1067
		 * Invoked when there is an instance ready
837
		 * Invoked when there is an instance ready
1068
		 * 
838
		 * 
1069
		 * @param verificationCommand The instance of verification command created as a result of an event.
839
		 * @param verificationCommand
840
		 *            The instance of verification command created as a result
841
		 *            of an event.
1070
		 */
842
		 */
1071
		public void instanceReady(VerificationCommand verificationCommand);
843
		public void instanceReady(VerificationCommand verificationCommand);
1072
	}
844
	}
1073
845
1074
	/**
846
	/**
1075
	 * A gateway for client to determine the global state changes of the macro recorder.
847
	 * A gateway for client to determine the global state changes of the macro
848
	 * recorder.
1076
	 * 
849
	 * 
1077
	 * @author amehregani
850
	 * @author amehregani
1078
	 */
851
	 */
1079
	public interface GlobalStateListener
852
	public interface GlobalStateListener {
1080
	{
853
1081
		/**
854
		/**
1082
		 * Indicates whether the listener is interested in listening 
855
		 * Indicates whether the listener is interested in listening for a
1083
		 * for a global state change.
856
		 * global state change.
1084
		 * 
857
		 * 
1085
		 * @return True if the listener's globalStateChange method should be
858
		 * @return True if the listener's globalStateChange method should be
1086
		 * invoke upon a global state change; false otherwise.
859
		 *         invoke upon a global state change; false otherwise.
1087
		 */
860
		 */
1088
		public boolean isListenerOn();
861
		public boolean isListenerOn();
1089
862
1090
		/**
863
		/**
1091
		 * Invoked when the global state of the macro manager has changed
864
		 * Invoked when the global state of the macro manager has changed
1092
		 * 
865
		 * 
1093
		 * @param oldState The old state
866
		 * @param oldState
1094
		 * @param newState The new state
867
		 *            The old state
868
		 * @param newState
869
		 *            The new state
1095
		 */
870
		 */
1096
		public void globalStateChange(byte oldState, byte newState);
871
		public void globalStateChange(byte oldState, byte newState);
1097
	}
872
	}
Lines 1103-1130 Link Here
1103
	public void setCommandTimeoutThreshold(int commandTimeoutThreshold) {
878
	public void setCommandTimeoutThreshold(int commandTimeoutThreshold) {
1104
		this.commandTimeoutThreshold = commandTimeoutThreshold;
879
		this.commandTimeoutThreshold = commandTimeoutThreshold;
1105
	}
880
	}
1106
	
881
1107
	public int getOutstandShellCommands()
882
	public int getOutstandShellCommands() {
1108
	{
1109
		return MacroCommandShell.getMacroCommandsBeingPlayed().size();
883
		return MacroCommandShell.getMacroCommandsBeingPlayed().size();
1110
	}
884
	}
1111
885
1112
	/**
886
	/**
1113
	 * @return the objectMineOn
887
	 * @return the objectMineOn
1114
	 */
888
	 */
1115
	public boolean isObjectMineOn()
889
	public boolean isObjectMineOn() {
1116
	{
1117
		return objectMineOn;
890
		return objectMineOn;
1118
	}
891
	}
1119
892
1120
	/**
893
	/**
1121
	 * @param objectMineOn the objectMineOn to set
894
	 * @param objectMineOn
895
	 *            the objectMineOn to set
1122
	 */
896
	 */
1123
	public void setObjectMineOn(boolean objectMineOn)
897
	public void setObjectMineOn(boolean objectMineOn) {
1124
	{
1125
		this.objectMineOn = objectMineOn;
898
		this.objectMineOn = objectMineOn;
1126
	}
899
	}
1127
900
901
	public IMacroCommandFactory getMacroCommandFactory() {
902
		if (commandFactory == null) {
903
			// see if we have a contribution via the macroCommandFactory
904
			// extension point
905
			return MacroCommandFactoryLoader.getHighestPriorityFactory();
906
		}
907
		return commandFactory;
908
	}
1128
909
1129
	
1130
}
910
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/Macro.java (-206 / +230 lines)
Lines 21-53 Link Here
21
import org.eclipse.jface.dialogs.Dialog;
21
import org.eclipse.jface.dialogs.Dialog;
22
import org.eclipse.jface.window.Window;
22
import org.eclipse.jface.window.Window;
23
import org.eclipse.swt.SWT;
23
import org.eclipse.swt.SWT;
24
import org.eclipse.swt.widgets.Composite;
25
import org.eclipse.swt.widgets.Control;
24
import org.eclipse.swt.widgets.Control;
26
import org.eclipse.swt.widgets.Display;
25
import org.eclipse.swt.widgets.Display;
27
import org.eclipse.swt.widgets.Event;
26
import org.eclipse.swt.widgets.Event;
28
import org.eclipse.swt.widgets.Shell;
27
import org.eclipse.swt.widgets.Shell;
29
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
28
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
30
import org.eclipse.tptp.test.auto.gui.internal.commands.MacroCommandShell;
29
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObjectIdentifier;
31
import org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine;
30
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObject;
32
import org.eclipse.tptp.test.auto.gui.internal.core.IPlayable;
31
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptor;
33
import org.eclipse.tptp.test.auto.gui.internal.core.IUIObject;
32
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine;
34
import org.eclipse.tptp.test.auto.gui.internal.core.IWritable;
33
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine.IDCollisionException;
35
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
34
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine.UIObjectNotFound;
36
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMine.IDCollisionException;
35
import org.eclipse.tptp.test.auto.gui.internal.macroobject.resolver.MacroObjectResolver;
37
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMine.UIObjectNotFound;
36
import org.eclipse.tptp.test.auto.gui.internal.uiobject.UIObject;
38
import org.eclipse.ui.PlatformUI;
37
import org.eclipse.ui.PlatformUI;
39
import org.w3c.dom.Node;
38
import org.w3c.dom.Node;
40
39
41
/**
40
/**
42
 * Models a macro
41
 * Models a macro
43
 */
42
 */
44
public class Macro implements IWritable, IPlayable
43
public class Macro implements IPersistable, IPlayable {
45
{
44
46
	private static final String SYNTAX_VERSION = "1.0";
45
	public static final String SYNTAX_VERSION = "1.1";
47
48
	/* Custom event types */
49
	/* Indicates that a workbnech part has been closed */
50
	public static final int WORKBENCH_PART_CLOSED = -1;
51
46
52
	/* An array of shells */
47
	/* An array of shells */
53
	private ArrayList shells;
48
	private ArrayList shells;
Lines 57-310 Link Here
57
52
58
	/* Keeps track of the stack of shells (This is used during recording) */
53
	/* Keeps track of the stack of shells (This is used during recording) */
59
	private Stack shellStack;
54
	private Stack shellStack;
60
	
55
61
	public Macro()
56
	public Macro() {
62
	{
63
		shells = new ArrayList();
57
		shells = new ArrayList();
64
	}
58
	}
65
59
66
	public Macro(String name)
60
	public Macro(String name) {
67
	{
68
		this();
61
		this();
69
		this.name = name;
62
		this.name = name;
70
	}
63
	}
71
64
72
	protected void addShell(Node node, Hashtable lineTable) throws CoreException
65
	/**
73
	{
66
	 * {@inheritDoc}
67
	 * 
68
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.IReadable#load(org.w3c.dom.Node,
69
	 *      java.util.Hashtable)
70
	 */
71
	public void load(Node node, Hashtable lineTable) throws CoreException {
74
		MacroCommandShell shell = new MacroCommandShell(null, null, null);
72
		MacroCommandShell shell = new MacroCommandShell(null, null, null);
75
		shell.load(node, lineTable);
73
		shell.load(node, lineTable);
76
		shells.add(shell);
74
		shells.add(shell);
77
	}
75
	}
78
76
79
	public void initializeForRecording(Display display)
77
	public void initializeForRecording(Display display) {
80
	{
81
		shellStack = new Stack();
78
		shellStack = new Stack();
82
		shells.clear();
79
		shells.clear();
83
		Shell currentShell = display.getActiveShell();
80
		Shell currentShell = display.getActiveShell();
84
81
85
		if (currentShell == null)
82
		if (currentShell == null)
86
			return;
83
			return;
87
		
84
88
		/* In case we are suppose to ignore the shell, then don't add it to our stack */
85
		/*
86
		 * In case we are suppose to ignore the shell, then don't add it to our
87
		 * stack
88
		 */
89
		Object data = currentShell.getData(MacroManager.IGNORE);
89
		Object data = currentShell.getData(MacroManager.IGNORE);
90
		
90
91
		if (data != null && data instanceof Boolean && ((Boolean)data).booleanValue())
91
		if (data != null && data instanceof Boolean
92
				&& ((Boolean) data).booleanValue())
92
			return;
93
			return;
93
		
94
95
		// hook the workbench listener
96
		MacroUtil.hookWorkbenchPartListener(currentShell);
97
94
		pushStack(createCommandShell(currentShell));
98
		pushStack(createCommandShell(currentShell));
95
	}
99
	}
96
100
97
	private MacroCommandShell createCommandShell(Shell shell)
101
	private MacroCommandShell createCommandShell(Shell shell) {
98
	{
102
		IMacroObjectIdentifier wi = null;
99
		WidgetIdentifier wi = MacroUtil.getWidgetIdentifier(shell);
103
		try {
104
			wi = MacroObjectResolver.resolve(shell, new MacroObject(
105
					new UIObject(shell)));
106
		} catch (Exception e) {
107
			e.printStackTrace();
108
		}
100
		if (wi == null)
109
		if (wi == null)
101
			return null;
110
			return null;
102
		return new MacroCommandShell(null, shell, wi);
111
		return new MacroCommandShell(null, shell, wi);
103
	}
112
	}
104
113
105
	private boolean isCurrent(Shell shell)
114
	private boolean isCurrent(Shell shell) {
106
	{
107
		if (shellStack.isEmpty())
115
		if (shellStack.isEmpty())
108
			return false;
116
			return false;
109
		MacroCommandShell cshell = (MacroCommandShell) shellStack.peek();
117
		MacroCommandShell cshell = (MacroCommandShell) shellStack.peek();
110
		return cshell.tracks(shell);
118
		return cshell.tracks(shell);
111
	}
119
	}
112
120
113
	public void stopRecording()
121
	public void stopRecording() {
114
	{
115
		reset();
122
		reset();
116
	}
123
	}
117
124
118
	public boolean addEvent(Event event) throws Exception
125
	public void addEvent(Event event) throws Exception {
119
	{
126
		if (MacroUtil.isIgnorableEvent(event)) {
120
		if (MacroUtil.isIgnorableEvent(event))
127
			return;
121
			return false;
128
		}
122
		try
129
123
		{			
130
		if (event.type != EventConstants.EVENT_TYPE__WORKBENCH_PART_CLOSED) {
124
			/*
131
			// hook the workbench listener, if not already registered at the
125
			 * A new shell is in the picture now (i.e. a new shell is closed or
132
			// widget
126
			 * activated). We need to modify the shell stack
133
			MacroUtil.hookWorkbenchPartListener(event.widget);
127
			 */
134
		}
128
			if (event.widget instanceof Shell)
135
129
			{
136
		/*
130
				switch (event.type)
137
		 * A new shell is in the picture now (i.e. a new shell is closed or
131
				{
138
		 * activated). We need to modify the shell stack
132
				case SWT.Activate:
139
		 */
133
					activateShell((Shell) event.widget);
140
		if (event.widget instanceof Shell) {
134
					break;
141
			switch (event.type) {
135
				case SWT.Close:
142
			case SWT.Activate:
136
					boolean stop = closeShell((Shell) event.widget);
143
				activateShell((Shell) event.widget);
137
					if (stop)
144
				break;
138
						return true;
145
			case SWT.Close:
139
					break;
146
				boolean stop = closeShell((Shell) event.widget);
140
				}
147
				if (stop)
148
					return;
149
				break;
141
			}
150
			}
151
		}
142
152
143
			/* Otherwise we have performed a command within the current shell */
153
		// TODO: See if the following can be simplified
144
			else 
154
		/* Otherwise we have performed a command within the current shell */
145
			{
155
		if (!(event.widget instanceof Shell)
146
				/* Make sure that the command sent over belongs to the top shell */
156
				&& event.detail != EventConstants.EVENT_DETAIL__VERIFICATION_HOOK_INSERTION_EVENT) {
147
				MacroCommandShell topCommandShell = getTopShell();
157
			/* Make sure that the command sent over belongs to the top shell */
148
				if (topCommandShell != null)
158
			MacroCommandShell topCommandShell = getTopShell();
149
				{
159
			if (topCommandShell != null) {
150
					Shell topShell = topCommandShell.getShell();
160
				Shell topShell = topCommandShell.getShell();
151
					Shell widgetShell = (!(event.widget instanceof Control) ? null : ((Control)event.widget).getShell());
161
				Shell widgetShell = (!(event.widget instanceof Control) ? null
152
					
162
						: ((Control) event.widget).getShell());
153
					/* Add the event only if the widget shell could not be resolved or the widget shell is the same
163
154
					 * as the top shell */
164
				/*
155
					if (widgetShell == null || topShell == widgetShell)
165
				 * Add the event only if the widget shell could not be resolved
156
					{
166
				 * or the widget shell is the same as the top shell
157
						topCommandShell.addEvent(event);
167
				 */
158
					}
168
				if (widgetShell == null || topShell == widgetShell) {
169
					topCommandShell.addEvent(event);
159
				}
170
				}
160
			}
171
			}
161
		} catch (Exception e)
172
		} else if (event.detail == EventConstants.EVENT_DETAIL__VERIFICATION_HOOK_INSERTION_EVENT) {
162
		{
173
			MacroCommandShell topShell = getTopShell();
163
			throw e;
174
			/*
175
			 * There is a chance that the macro does not have a top shell. We'll
176
			 * attempt to resolve its top shell, if unsuccessful, then we'll
177
			 * prompt the user with an error.
178
			 */
179
			if (topShell == null && event.widget instanceof Control) {
180
				Event artificialEvent = new Event();
181
				artificialEvent.type = SWT.Activate;
182
				artificialEvent.display = event.widget.getDisplay();
183
				artificialEvent.widget = ((Control) event.widget).getShell();
184
				addEvent(artificialEvent);
185
				topShell = getTopShell();
186
			}
187
			if (topShell != null) {
188
				topShell.addEvent(event);
189
			}
190
164
		}
191
		}
165
		return false;
192
		return;
166
	}
193
	}
167
194
168
195
	public void addPause() {
169
170
	public void addPause()
171
	{
172
		MacroCommandShell topShell = getTopShell();
196
		MacroCommandShell topShell = getTopShell();
173
		if (topShell != null)
197
		if (topShell != null)
174
			topShell.addPause();
198
			topShell.addPause();
175
	}
199
	}
176
200
177
201
	public MacroCommandShell getTopShell() {
178
	public MacroCommandShell getTopShell()
179
	{
180
		if (shellStack.isEmpty())
202
		if (shellStack.isEmpty())
181
			return null;
203
			return null;
182
		return (MacroCommandShell) shellStack.peek();
204
		return (MacroCommandShell) shellStack.peek();
183
	}
205
	}
184
206
185
	private void activateShell(Shell shell)
207
	private void activateShell(Shell shell) {
186
	{
187
		if (shell.isDisposed())
208
		if (shell.isDisposed())
188
			return;
209
			return;
189
		
210
190
		Object data = shell.getData();
211
		Object data = shell.getData();
191
		if (data instanceof Dialog)
212
		if (data instanceof Dialog) {
192
		{
213
			if (!isCurrent(shell)) {
193
			if (!isCurrent(shell))
214
				/*
194
			{
215
				 * Before adding the shell to the stack, make sure that it is
195
				/* Before adding the shell to the stack, make sure that it is not a parent of the current shell */
216
				 * not a parent of the current shell
217
				 */
196
				MacroCommandShell parentOfCurrentShell = null;
218
				MacroCommandShell parentOfCurrentShell = null;
197
				if (shellStack.size() - 2 >= 0)
219
				if (shellStack.size() - 2 >= 0) {
198
				{
220
					parentOfCurrentShell = (MacroCommandShell) shellStack
199
					parentOfCurrentShell = (MacroCommandShell)shellStack.get(shellStack.size() - 2);
221
							.get(shellStack.size() - 2);
200
				}
222
				}
201
				
223
202
				/* If the new shell happens to be the parent of the current shell, then we just need to pop the stack */
224
				/*
203
				if (parentOfCurrentShell != null && parentOfCurrentShell.tracks(shell))
225
				 * If the new shell happens to be the parent of the current
204
				{
226
				 * shell, then we just need to pop the stack
227
				 */
228
				if (parentOfCurrentShell != null
229
						&& parentOfCurrentShell.tracks(shell)) {
205
					popStack();
230
					popStack();
206
				}			
231
				} else {
207
				else
232
208
				{
209
					
210
					MacroCommandShell commandShell = createCommandShell(shell);
233
					MacroCommandShell commandShell = createCommandShell(shell);
211
					
234
212
					/* Initialize for recording failed to find the top shell */
235
					/* Initialize for recording failed to find the top shell */
213
					if (getTopShell() == null)
236
					if (getTopShell() == null) {
214
					{
237
						pushStack(commandShell);
215
						pushStack(commandShell);			
238
					} else {
216
					}
217
					else
218
					{						
219
						getTopShell().addCommandShell(commandShell);
239
						getTopShell().addCommandShell(commandShell);
220
						shellStack.push(commandShell);
240
						shellStack.push(commandShell);
221
						updateObjectMine(commandShell);				
241
						updateObjectMine(commandShell);
222
					}
242
					}
223
				}
243
				}
224
			}
244
			}
225
		}
245
		} else if (data instanceof Window) {
226
		else if (data instanceof Window)
227
		{				
228
			updateStack();
246
			updateStack();
229
			if (!isCurrent(shell))
247
			if (!isCurrent(shell)) {
230
			{
231
				popStack();
248
				popStack();
232
				
249
233
				MacroCommandShell newCommandShell = createCommandShell(shell);
250
				MacroCommandShell newCommandShell = createCommandShell(shell);
234
				MacroCommandShell topCommandShell = getTopShell();
251
				MacroCommandShell topCommandShell = getTopShell();
235
				if (topCommandShell == null || !topCommandShell.getWidgetId().getObjectId().equals(newCommandShell.getWidgetId().getObjectId()))
252
				if (topCommandShell == null
236
				{					
253
						|| !topCommandShell.getMacroObjectIdentifier()
254
								.getObjectIdentifier().getWidgetId().equals(
255
										newCommandShell
256
												.getMacroObjectIdentifier()
257
												.getObjectIdentifier()
258
												.getWidgetId())) {
237
					pushStack(createCommandShell(shell));
259
					pushStack(createCommandShell(shell));
238
				}			
260
				}
239
			}
261
			}
240
262
241
		}
263
		}
242
	}
264
	}
243
265
244
	private void popStack()
266
	private void popStack() {
245
	{
246
		if (shellStack.isEmpty())
267
		if (shellStack.isEmpty())
247
			return;
268
			return;
248
		MacroCommandShell top = (MacroCommandShell) shellStack.pop();
269
		MacroCommandShell top = (MacroCommandShell) shellStack.pop();
249
		top.extractExpectedReturnCode();
270
		top.extractExpectedReturnCode();
250
		updateObjectMine(getTopShell());
271
		updateObjectMine(getTopShell());
251
	}
272
	}
252
	
273
253
	
274
	private void pushStack(MacroCommandShell commandShell) {
254
	private void pushStack(MacroCommandShell commandShell)
255
	{		
256
		shellStack.push(commandShell);
275
		shellStack.push(commandShell);
257
		shells.add(commandShell);
276
		shells.add(commandShell);
258
		updateObjectMine(commandShell);
277
		updateObjectMine(commandShell);
259
	}
278
	}
260
279
261
	private void updateObjectMine(MacroCommandShell commandShell)
280
	private void updateObjectMine(MacroCommandShell commandShell) {
262
	{
281
		MacroObjectDescriptorMine objectMine = MacroManager.getInstance()
263
		IObjectMine objectMine = MacroManager.getInstance().getObjectMine();
282
				.getObjectMine();
264
		MacroCommandShell macroCommandShell = getTopShell();
283
		MacroCommandShell macroCommandShell = getTopShell();
265
		final String SHELL = "Shell";
284
		final String SHELL = "Shell";
266
		IUIObject shellObject = null;
285
		MacroObjectDescriptor shellObject = null;
267
		if (objectMine != null && macroCommandShell != null)
286
		if (objectMine != null && macroCommandShell != null) {
268
		{
287
			try {
269
			try
288
				IMacroObjectIdentifier macroShellObjectId = macroCommandShell
270
			{
289
						.getMacroObjectIdentifier();
271
				String macroShellObjectId = macroCommandShell.getWidgetId().getObjectId().toString();
290
				shellObject = objectMine.lookupMacroObjectDescriptor(null,
272
				shellObject = objectMine.lookupUIObject(null, null, macroShellObjectId);
291
						null, macroShellObjectId.getObjectIdentifier()
273
				if (shellObject == null)
292
								.getWidgetId(), null);
274
				{
293
				if (shellObject == null) {
275
					shellObject = new UIObject(null);
294
					shellObject = new MacroObjectDescriptor(null);
276
					shellObject.setDescriptive(SHELL + (macroCommandShell.getDescriptiveField() == null ? MacroConstants.EMPTY_STRING : ": " + macroCommandShell.getDescriptiveField()));
295
					((MacroObjectDescriptor) shellObject)
277
					shellObject.setObjectId(macroShellObjectId);
296
							.setDescriptive(SHELL
278
					shellObject.setReferenceId(objectMine.getUniqueReferenceId());
297
									+ (macroCommandShell.getDescriptiveField() == null ? MacroConstants.EMPTY_STRING
279
					shellObject.setResolver(macroCommandShell.getWidgetId().getResolverId());
298
											: ": "
280
					shellObject = objectMine.registerObject(shellObject);					
299
													+ macroCommandShell
300
															.getDescriptiveField()));
301
					((MacroObjectDescriptor) shellObject)
302
							.setWidgetId(macroShellObjectId
303
									.getObjectIdentifier().getWidgetId());
304
					((MacroObjectDescriptor) shellObject)
305
					.setObjectId(macroShellObjectId
306
							.getObjectIdentifier().getObjectId());
307
					((MacroObjectDescriptor) shellObject)
308
							.setResolver(macroCommandShell
309
									.getMacroObjectIdentifier()
310
									.getObjectIdentifier().getResolverId());
311
					shellObject = objectMine
312
							.registerObject((MacroObjectDescriptor) shellObject);
281
				}
313
				}
282
				objectMine.setActiveObject(shellObject);
314
				objectMine.setActiveObject(shellObject);
283
			} 
315
			} catch (UIObjectNotFound e) {
284
			catch (UIObjectNotFound e)
285
			{
286
				/* Shouldn't happen */
316
				/* Shouldn't happen */
287
				e.printStackTrace();
317
				e.printStackTrace();
288
			} catch (IDCollisionException e)
318
			} catch (IDCollisionException e) {
289
			{
290
				/* Shouldn't happen */
319
				/* Shouldn't happen */
291
				e.printStackTrace();
320
				e.printStackTrace();
292
			} catch (CoreException e)
321
			} catch (CoreException e) {
293
			{
294
				/* Shouldn't happen */
322
				/* Shouldn't happen */
295
				e.printStackTrace();
323
				e.printStackTrace();
296
			}
324
			}
297
		}
325
		}
298
		
326
299
		/* Update the reference id of the widget identifier for the macro command shell */
327
		/*
300
		if (shellObject != null)
328
		 * Update the reference id of the widget identifier for the macro
301
		{
329
		 * command shell
302
			commandShell.getWidgetId().setReferenceId(shellObject.getReferenceId());
330
		 */
331
		if (shellObject != null) {
332
			// seems to be more appropriate to set the corrsponding object for
333
			// the shell
334
			commandShell.setCorrespondingMacroObjectDescriptor(shellObject);
335
			// CHANGED BY ANY:
336
			// commandShell.getWidgetId().setReferenceId(shellObject.getReferenceId());
303
		}
337
		}
304
	}
338
	}
305
339
306
	private boolean closeShell(Shell shell)
340
	private boolean closeShell(Shell shell) {
307
	{
308
		if (shellStack.isEmpty())
341
		if (shellStack.isEmpty())
309
			return false;
342
			return false;
310
		MacroCommandShell top = (MacroCommandShell) shellStack.peek();
343
		MacroCommandShell top = (MacroCommandShell) shellStack.peek();
Lines 313-322 Link Here
313
		return shellStack.isEmpty();
346
		return shellStack.isEmpty();
314
	}
347
	}
315
348
316
	private void updateStack()
349
	private void updateStack() {
317
	{
350
		while (shellStack.size() > 0) {
318
		while (shellStack.size() > 0)
319
		{
320
			MacroCommandShell top = getTopShell();
351
			MacroCommandShell top = getTopShell();
321
			if (top.isDisposed())
352
			if (top.isDisposed())
322
				popStack();
353
				popStack();
Lines 325-405 Link Here
325
		}
356
		}
326
	}
357
	}
327
358
328
	public boolean playback(Display display, Composite parent, IProgressMonitor monitor) throws CoreException
359
	public boolean playback(Display display, Shell parent,
329
	{
360
			IProgressMonitor monitor) throws CoreException {
330
		reset();
361
		reset();
331
		String mname = name != null ? name : "macro";
362
		String mname = name != null ? name : "macro";
332
		monitor.beginTask(AutoGUIMessages.AUTO_GUI_MACRO_EXECUTING + mname + " ...", shells.size());
363
		monitor.beginTask(AutoGUIMessages.AUTO_GUI_MACRO_EXECUTING + mname
333
		for (int i = 0; i < shells.size(); i++)
364
				+ " ...", shells.size());
334
		{
365
		for (int i = 0; i < shells.size(); i++) {
335
			MacroCommandShell shell = (MacroCommandShell) shells.get(i);
366
			MacroCommandShell shell = (MacroCommandShell) shells.get(i);
336
			final Shell[] sh = new Shell[1];
367
			final Shell[] sh = new Shell[1];
337
			display.syncExec(new Runnable()
368
			display.syncExec(new Runnable() {
338
			{
369
339
				public void run()
370
				public void run() {
340
				{
371
					sh[0] = PlatformUI.getWorkbench()
341
					sh[0] = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell();
372
							.getActiveWorkbenchWindow().getShell();
342
				}
373
				}
343
			});
374
			});
344
			try
375
			try {
345
			{
376
				boolean result = shell.playback(display, sh[0],
346
				boolean result = shell.playback(display, sh[0], new SubProgressMonitor(monitor, 1));
377
						new SubProgressMonitor(monitor, 1));
347
				if (!result)
378
				if (!result)
348
					return false;
379
					return false;
349
			} catch (CoreException e)
380
			} catch (CoreException e) {
350
			{				
351
				throw e;
381
				throw e;
352
			}
382
			}
353
		}
383
		}
354
		return true;
384
		return true;
355
	}
385
	}
356
386
357
	private void reset()
387
	private void reset() {
358
	{
359
		shellStack = null;
388
		shellStack = null;
360
	}
389
	}
361
390
362
	public void write(int indent, PrintWriter writer)
391
	public void write(int indent, PrintWriter writer) {
363
	{
364
		StringBuffer sb = new StringBuffer();
392
		StringBuffer sb = new StringBuffer();
365
		write (indent, sb);
393
		write(indent, sb);
366
		writer.write(sb.toString());
394
		writer.write(sb.toString());
367
	}
395
	}
368
396
369
	public void write(int indent, StringBuffer sb)
397
	public void write(int indent, StringBuffer sb) {
370
	{
371
		/* Add <macro version="..." */
398
		/* Add <macro version="..." */
372
		MacroUtil.addElement(sb, indent, MacroConstants.MACRO_ELEMENT, false, false);
399
		MacroUtil.addElement(sb, indent, MacroConstants.MACRO_ELEMENT, false,
373
		MacroUtil.addAttribute(sb, new String[] {MacroConstants.VERSION_ATTRIBUTE}, new String[] {SYNTAX_VERSION}, false, true);
400
				false);
401
		MacroUtil.addAttribute(sb,
402
				new String[] { MacroConstants.VERSION_ATTRIBUTE },
403
				new String[] { SYNTAX_VERSION }, false, true);
374
404
375
		int cindent = 1;
405
		int cindent = 1;
376
		/* For every macro command shell */
406
		/* For every macro command shell */
377
		for (int i = 0; i < shells.size(); i++)
407
		for (int i = 0; i < shells.size(); i++) {
378
		{
379
			MacroCommandShell cshell = (MacroCommandShell) shells.get(i);
408
			MacroCommandShell cshell = (MacroCommandShell) shells.get(i);
380
			cshell.write(cindent, sb);
409
			cshell.write(cindent, sb);
381
		}
410
		}
382
		MacroUtil.addElement(sb, 0, MacroConstants.MACRO_ELEMENT, true, true);		
411
		MacroUtil.addElement(sb, 0, MacroConstants.MACRO_ELEMENT, true, true);
383
	}
412
	}
384
	
413
385
	
414
	public String getName() {
386
	public String getName()
387
	{
388
		return name;
415
		return name;
389
	}
416
	}
390
417
391
	public void writeStart(int indent, StringBuffer writer)
418
	public void writeStart(int indent, StringBuffer writer) {
392
	{
419
		/* Doesn't need to be implemented */
393
		/* Doesn't need to be implemented */		
420
	}
421
422
	public void writeFinish(int indent, StringBuffer writer) {
423
		/* Doesn't need to be implemented */
394
	}
424
	}
395
425
396
	public void writeFinish(int indent, StringBuffer writer)
426
	public int getShellStackSize() {
397
	{
398
		/* Doesn't need to be implemented */	
399
	}
400
	
401
	public int getShellStackSize()
402
	{
403
		return shellStack.size();
427
		return shellStack.size();
404
	}
428
	}
405
429
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/MacroObjectLocator.java (-916 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macro;
12
13
import java.util.ArrayList;
14
import java.util.Enumeration;
15
import java.util.Hashtable;
16
import java.util.Iterator;
17
import java.util.Vector;
18
19
import org.eclipse.core.runtime.CoreException;
20
import org.eclipse.core.runtime.IPath;
21
import org.eclipse.core.runtime.Path;
22
import org.eclipse.jface.action.CoolBarManager;
23
import org.eclipse.jface.action.IContributionItem;
24
import org.eclipse.jface.action.ICoolBarManager;
25
import org.eclipse.jface.action.IMenuManager;
26
import org.eclipse.jface.action.IToolBarManager;
27
import org.eclipse.jface.action.MenuManager;
28
import org.eclipse.jface.action.ToolBarContributionItem;
29
import org.eclipse.jface.action.ToolBarManager;
30
import org.eclipse.jface.window.ApplicationWindow;
31
import org.eclipse.jface.window.Window;
32
import org.eclipse.jface.wizard.IWizardPage;
33
import org.eclipse.jface.wizard.WizardDialog;
34
import org.eclipse.osgi.util.NLS;
35
import org.eclipse.swt.SWT;
36
import org.eclipse.swt.widgets.Composite;
37
import org.eclipse.swt.widgets.Control;
38
import org.eclipse.swt.widgets.Decorations;
39
import org.eclipse.swt.widgets.Event;
40
import org.eclipse.swt.widgets.Item;
41
import org.eclipse.swt.widgets.Menu;
42
import org.eclipse.swt.widgets.MenuItem;
43
import org.eclipse.swt.widgets.Shell;
44
import org.eclipse.swt.widgets.ToolBar;
45
import org.eclipse.swt.widgets.ToolItem;
46
import org.eclipse.swt.widgets.Widget;
47
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
48
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
49
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
50
import org.eclipse.tptp.test.auto.gui.internal.commands.CommandTarget;
51
import org.eclipse.tptp.test.auto.gui.internal.commands.EditorCommandTarget;
52
import org.eclipse.tptp.test.auto.gui.internal.commands.ViewCommandTarget;
53
import org.eclipse.tptp.test.auto.gui.internal.commands.WindowCommandTarget;
54
import org.eclipse.tptp.test.auto.gui.internal.commands.WizardCommandTarget;
55
import org.eclipse.tptp.test.auto.gui.internal.core.IUIObject;
56
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
57
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetResolverLoader;
58
import org.eclipse.ui.IActionBars;
59
import org.eclipse.ui.IEditorPart;
60
import org.eclipse.ui.IEditorReference;
61
import org.eclipse.ui.IViewPart;
62
import org.eclipse.ui.IViewSite;
63
import org.eclipse.ui.IWorkbenchPage;
64
import org.eclipse.ui.IWorkbenchPart;
65
import org.eclipse.ui.IWorkbenchWindow;
66
import org.eclipse.ui.PartInitException;
67
import org.eclipse.ui.testing.IWorkbenchPartTestable;
68
import org.w3c.dom.Node;
69
70
/**
71
 * A utility class used to locate different objects needed when playing back 
72
 * commands.
73
 * 
74
 * @author Ali Mehregani
75
 */
76
public class MacroObjectLocator
77
{
78
79
	public static CommandTarget[] locateCommandTarget(Composite parent, WidgetIdentifier wid, ArrayList parents, int line) throws CoreException
80
	{
81
		Shell shell = (Shell) parent;
82
		
83
		IPath contextId = wid.getContextId();
84
		
85
		String firstToken = contextId.segment(0);		
86
		Iterator iter = parents != null ? parents.iterator() : null;
87
		String id = contextId.segment(1);
88
		
89
		if (MacroConstants.MENUS_VALUE.equals(firstToken))
90
		{
91
			return new CommandTarget[]{locateMenuBarItem(shell, wid, iter, line)};
92
		}
93
		else if (MacroConstants.POPUP_VALUE.equals(firstToken))
94
		{
95
			return new CommandTarget[]{ locatePopupMenuItem(shell, wid, iter, line)};
96
		}
97
		else if (MacroConstants.TOOLBAR_VALUE.equals(firstToken))
98
		{
99
			return new CommandTarget[]{ locateToolItem(shell, wid, line)};
100
		}
101
		else if (MacroConstants.LOCAL_TOOLBAR_VALUE.equals(firstToken))
102
		{
103
			return new CommandTarget[]{ locateLocalToolItem(shell, wid, line)};
104
		}
105
		else if (MacroConstants.LOCAL_TOOLBAR_MENU_VALUE.equals(firstToken))
106
		{
107
			return new CommandTarget[] {locateToolBarMenuItem(shell, wid, line)};
108
		}
109
		else if (MacroConstants.WIZARD_VALUE.equals(firstToken))
110
		{
111
			return locateWizardControl(shell, wid, line);
112
		}
113
		else if (MacroConstants.SHELL_VALUE.equals(firstToken))
114
		{
115
			return locateShellControl(shell, wid, line);
116
		}		
117
		else if (MacroConstants.WIZARD_PAGE_VALUE.equals(firstToken))
118
		{
119
			return locateWizardPageControl(shell, id, wid, line);
120
		}
121
		else if (MacroConstants.VIEW_VALUE.equals(firstToken))
122
		{
123
			return locateViewControl(shell, id, wid, line);
124
		}
125
		else if (MacroConstants.EDITOR_VALUE.equals(firstToken))
126
		{
127
			String inputName = contextId.segment(2);
128
			return locateEditorControl(shell, id, inputName, wid, line);
129
		}
130
		
131
		
132
		return null;
133
	}
134
135
	public static CommandTarget[] locateCommandTarget(Composite parent, WidgetIdentifier wid, int line) throws CoreException
136
	{
137
		return locateCommandTarget(parent, wid, null, line);
138
	}
139
140
	/**
141
	 * Used to located the editor part with the passed id.
142
	 * 
143
	 * @param shell
144
	 *            The current shell
145
	 * @param id
146
	 *            The id of the editor part
147
	 * @param line
148
	 *            The line number of the script (used to indicate the line
149
	 *            number if we throw a core exception. Mark as -1 if a script is
150
	 *            not being used)
151
	 * @param input
152
	 *            If not null, then it attempts to match the input of the
153
	 *            identified editor with the input that is passed it.
154
	 * 
155
	 * @return The editor part with the passed 'id'
156
	 * 
157
	 * @throws CoreException
158
	 *             If the editor part cannot be located.
159
	 */
160
	public static IEditorPart locateEditor(Shell shell, String id, int line, String input) throws CoreException
161
	{
162
		Object data = shell.getData();
163
		IEditorPart editor = null;
164
	
165
		try
166
		{
167
			if (data instanceof IWorkbenchWindow)
168
			{
169
				IWorkbenchWindow window = (IWorkbenchWindow) data;
170
				IWorkbenchPage page = window.getActivePage();
171
	
172
				if (page != null)
173
				{
174
					IEditorReference[] erefs = page.getEditorReferences();
175
	
176
					for (int i = 0; i < erefs.length; i++)
177
					{
178
						IEditorReference eref = erefs[i];
179
						if (eref.getId().equals(id))
180
						{
181
							// check the input
182
							IEditorPart part = eref.getEditor(true);
183
							if (input == null)
184
							{
185
								editor = part;
186
								break;
187
							}
188
							else if (part.getEditorInput().getName().equals(input))
189
							{
190
								editor = part;
191
								break;
192
							}							
193
						}
194
					}
195
				}
196
			}
197
		}
198
		catch (Throwable t)
199
		{
200
			
201
		}
202
		if (editor != null)
203
		{			
204
			editor.getSite().getPage().activate(editor);
205
			return editor;
206
		}
207
	
208
		AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_EDITOR, id), line);
209
		return null;
210
	}
211
212
	private static EditorCommandTarget[] locateEditorControl(Shell shell, String id, String inputName, WidgetIdentifier wid, int line) throws CoreException
213
	{
214
		Control[] controls = null;
215
		
216
		try
217
		{			
218
			IEditorPart editor = locateEditor(shell, id, line, inputName);
219
	
220
			if (editor != null)
221
			{
222
				Composite c = getWorkbenchPartControl(editor);
223
				controls = locateVisibleChild(c, null, wid);
224
				if (controls != null)
225
				{
226
					EditorCommandTarget[] editorCommandTargets = new EditorCommandTarget[controls.length];
227
					for (int i = 0; i < controls.length; i++)
228
					{
229
						editorCommandTargets[i] = new EditorCommandTarget(controls[i], editor);
230
					}
231
					
232
					return editorCommandTargets;
233
				}
234
			}
235
		}
236
		catch (Throwable t)
237
		{
238
			t.printStackTrace();
239
		}
240
		if (controls == null)
241
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_EDITOR_CON, wid.getObjectId().toString()), line);
242
	
243
		return null;
244
	}
245
246
	private static CommandTarget locateLocalToolItem(Shell shell, WidgetIdentifier wid, int line) throws CoreException
247
	{
248
		try
249
		{			
250
			IPath wpath = wid.getContextId().removeFirstSegments(1);
251
			String firstToken = wpath.segment(0);
252
			IWorkbenchPart workbenchPart = null;
253
			Composite parent = null;
254
			CommandTarget target = null;
255
			
256
			if (MacroConstants.VIEW_VALUE.equals(firstToken))
257
			{
258
				String id = wpath.segment(1);
259
				workbenchPart = locateView(shell, id, line);
260
			}
261
			else if (MacroConstants.EDITOR_VALUE.equals(firstToken))
262
			{
263
				String id = wpath.segment(1);
264
				workbenchPart = locateEditor(shell, id, line, null);
265
			}
266
			else if (MacroConstants.SHELL_VALUE.equals(firstToken))
267
			{
268
				parent = shell;
269
			}
270
			
271
			if (workbenchPart != null)
272
			{
273
				Composite comp = getWorkbenchPartControl(workbenchPart);
274
				MacroUtil.processDisplayEvents(shell.getDisplay());
275
				parent = comp.getParent();
276
			}
277
			
278
			if (parent != null)
279
			{
280
				WidgetIdentifier widgetIdentifier = new WidgetIdentifier(wid.getContextId(), new Path(wid.getContextId().lastSegment()), wid.getResolverId());
281
				Control[] controls = locateVisibleChild(parent, null, widgetIdentifier);
282
				if (controls != null && controls.length > 0 && controls[0] instanceof ToolBar)
283
				{
284
					target = locateToolItem((ToolBar)controls[0], wid, line);
285
				}				
286
			}
287
			
288
			if (target != null)
289
				return target;
290
			
291
		}
292
		catch (Throwable t)
293
		{
294
			/* The next line will throw an exception */
295
			t.printStackTrace();
296
		}
297
		
298
		AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_TOOL_BAR, wid.getFullyQualifiedId().toString()), line);
299
		return null;
300
	}
301
302
	private static CommandTarget locateMenuBarItem(Shell shell, WidgetIdentifier wid, Iterator parents, int line) throws CoreException
303
	{
304
		try
305
		{
306
			MenuItem item = null;
307
			Object data = shell.getData();
308
			Menu menuBar = shell.getMenuBar();
309
	
310
			if (data instanceof ApplicationWindow && parents != null)
311
			{
312
				ApplicationWindow window = (ApplicationWindow) data;
313
				MenuManager manager = window.getMenuBarManager();
314
				item = locateMenuItem(manager, wid.getResolverId(), wid.getObjectId().toString(), parents, line);
315
			}
316
			else
317
			{
318
				item = locateMenuItem(menuBar, wid.getResolverId(), wid.getObjectId().toString(), line);
319
			}
320
			if (item != null)
321
				return new CommandTarget(item, menuBar);
322
			
323
		}
324
		catch (Throwable t)
325
		{
326
			/* The next line will throw exception */			
327
		}
328
		AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_MENU, wid.getObjectId().toString()), line);
329
		return null;
330
	}
331
332
	private static MenuItem locateMenuItem(Menu menu, String resolverId, String id, int line)
333
	{
334
		MenuItem[] items = menu.getItems();
335
	
336
		for (int i = 0; i < items.length; i++)
337
		{
338
			MenuItem item = items[i];
339
	
340
			Menu submenu = item.getMenu();
341
			if (submenu != null)
342
			{
343
				/* Ali M.: We have to force the menu to open, since its items may not have already been created */
344
				forceMenuOpen(null, submenu);
345
				MenuItem hit = locateMenuItem(submenu, resolverId, id, line);
346
				if (hit != null)
347
					return hit;
348
			}
349
			else
350
			{
351
				if (foundItem(item, resolverId, id))
352
					return item;
353
			}
354
		}
355
		return null;
356
	}
357
358
	
359
	private static MenuItem locateMenuItem(MenuManager mng, String resolverId, String id, Iterator parents, int line)
360
	{
361
		IContributionItem[] items = mng.getItems();
362
	
363
		String parentId = null;
364
		if (parents.hasNext())
365
			parentId = (String) parents.next();
366
	
367
		for (int i = 0; i < items.length; i++)
368
		{
369
			IContributionItem citem = items[i];
370
	
371
			if (citem instanceof MenuManager)
372
			{
373
				MenuManager submenu = (MenuManager) citem;
374
				String subId = submenu.getId();
375
	
376
				if (subId.equals(parentId))
377
				{
378
					// show this menu to force dynamic items
379
					// to show
380
					Menu menu = submenu.getMenu();
381
					forceMenuOpen(null, menu);
382
	
383
					MenuItem hit = locateMenuItem(submenu, resolverId, id, parents, line);
384
					forceMenuClosed(menu);
385
					if (hit != null)
386
						return hit;
387
				}
388
			}
389
			else
390
			{
391
				/* Ali M.: I believe that the first line and the following block were for optimization purposes only */
392
				//String itemId = getActionId(citem);
393
				//if (itemId != null && id.equals(itemId))
394
				//{
395
				MenuItem hit = locateMenuItem(mng.getMenu(), resolverId, id, line);
396
				if (hit != null)
397
					return hit;
398
				//}
399
			}
400
		}
401
		return null;
402
	}
403
404
	private static CommandTarget locatePopupMenuItem(Shell shell, WidgetIdentifier wid, Iterator parents, int line) throws CoreException
405
	{
406
		try
407
		{
408
			IPath contextPath = wid.getContextId().removeFirstSegments(1);
409
			IPath wpath = new Path(getLastSegment(contextPath));
410
			
411
			int widgetPathInx = contextPath.toString().indexOf(wpath.toString());
412
			if (widgetPathInx > 0)
413
				contextPath = new Path(contextPath.toString().substring(0, widgetPathInx - 1));
414
			CommandTarget[] targets = locateCommandTarget(shell, new WidgetIdentifier(contextPath, wpath, null), line);
415
			if (targets != null)
416
			{
417
				for (int i = 0; i < targets.length; i++)
418
				{
419
					Control control = (Control) targets[i].getWidget();
420
					Menu popupMenu = control.getMenu();
421
					if (popupMenu != null)
422
					{
423
						forceMenuOpen(control, popupMenu);
424
						MenuItem menuItem = locateMenuItem(popupMenu, wid.getResolverId(), wid.getObjectId().toString(), line);
425
						forceMenuClosed(popupMenu);
426
						if (menuItem != null)
427
						{
428
							return new CommandTarget(menuItem, control);
429
						}
430
					}
431
				}
432
			}
433
		}
434
		catch (Throwable t)
435
		{
436
			/* The next line will throw an exception */			
437
		}
438
		AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_MENU, wid.getObjectId().toString()), line);
439
		return null;
440
	}
441
442
	private static CommandTarget locateToolBarMenuItem(Shell shell, WidgetIdentifier wid, int line) throws CoreException
443
	{
444
		try
445
		{
446
			IPath contextPath = wid.getContextId().removeFirstSegments(1);
447
			
448
			/* The context is a menu */
449
			IViewPart viewPart = null;
450
			if (MacroConstants.VIEW_VALUE.equals(contextPath.segment(0)))
451
			{
452
				viewPart = locateView(shell, contextPath.segment(1), line);
453
			}
454
455
			
456
			IViewSite viewSite = viewPart == null ? null : viewPart.getViewSite();
457
			IMenuManager menuManager = null;
458
			if (viewSite != null)
459
			{
460
				IActionBars actionBar = viewSite.getActionBars();
461
				actionBar.updateActionBars();
462
				menuManager = actionBar.getMenuManager();
463
			}
464
			
465
			if (menuManager instanceof MenuManager)
466
			{
467
				
468
				Menu menu = ((MenuManager)menuManager).getMenu();
469
				if (menu == null)
470
				{
471
					menu = ((MenuManager)menuManager).createMenuBar((Decorations)shell);
472
				}
473
				if (menu != null)
474
				{
475
					forceMenuOpen(null, menu);
476
					MenuItem menuItem = locateMenuItem(menu, wid.getResolverId(), wid.getObjectId().toString(), line);
477
					forceMenuClosed(menu);
478
					if (menuItem != null)
479
					{
480
						return new CommandTarget(menuItem, null);
481
					}
482
				}
483
			}
484
		}
485
		catch (Throwable t)
486
		{
487
			/* The next line will throw an exception */			
488
		}
489
		AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_MENU, wid.getObjectId().toString()), line);
490
		return null;
491
	}
492
	private static String getLastSegment(IPath contextPath)
493
	{
494
		String[] segments = contextPath.segments();
495
		String candidate = "";
496
		for (int i = segments.length - 1; i >= 0; i--)
497
		{
498
			if (candidate.length() > 0)
499
				candidate = "/" + candidate;
500
			candidate = segments[i] + candidate;
501
			int openingBracesInx = candidate.indexOf('{');
502
			int closingBracesInx = candidate.indexOf('}');
503
			if ((openingBracesInx == -1 && closingBracesInx == -1) || (openingBracesInx >= 0 && openingBracesInx < closingBracesInx))
504
				return candidate;
505
		}
506
		
507
		return "";
508
	}
509
	
510
	private static WindowCommandTarget[] locateShellControl(Shell shell, WidgetIdentifier wid, int line) throws CoreException
511
	{
512
		Control[] controls = null;
513
		Window window = null;
514
		try
515
		{
516
			window = (Window) shell.getData();
517
			controls = locateVisibleChild(shell, null, wid);
518
		}
519
		catch (Throwable t)
520
		{
521
			
522
		}
523
		if (controls == null)
524
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_SHELL, wid.getObjectId().toString()), line);
525
		
526
		WindowCommandTarget[] windowCommandTarget = new WindowCommandTarget[controls.length];
527
		for (int i = 0; i < controls.length; i++)
528
		{
529
			if (controls[i].isDisposed())
530
				AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_SHELL_DIS, wid.getObjectId().toString()), line);
531
			windowCommandTarget[i] = new WindowCommandTarget(controls[i], window);
532
		}
533
			
534
		return windowCommandTarget;
535
	}
536
537
	private static CommandTarget locateToolItem(ICoolBarManager coolMng, WidgetIdentifier wid, int line)
538
	{
539
		IContributionItem[] items = coolMng.getItems();
540
		for (int i = 0; i < items.length; i++)
541
		{
542
			if (items[i] instanceof ToolBarContributionItem)
543
			{
544
				ToolBarContributionItem item = (ToolBarContributionItem) items[i];
545
				IToolBarManager toolMng = item.getToolBarManager();
546
				CommandTarget target = locateToolItem((ToolBarManager) toolMng, wid, line);
547
				if (target != null)
548
					return target;
549
			}
550
		}
551
		return null;
552
	}
553
	
554
	private static CommandTarget locateToolItem(ToolBarManager toolMng, WidgetIdentifier wid, int line)
555
	{
556
		return locateToolItem(toolMng.getControl(), wid, line);
557
	}
558
	
559
560
	private static CommandTarget locateToolItem(Shell shell, WidgetIdentifier wid, int line) throws CoreException
561
	{
562
		CommandTarget target = null;
563
		try
564
		{
565
			Object data = shell.getData();			
566
			if (data instanceof ApplicationWindow)
567
			{
568
				ApplicationWindow window = (ApplicationWindow) data;
569
				CoolBarManager coolMng = window.getCoolBarManager();
570
				if (coolMng != null)
571
				{
572
					target = locateToolItem(coolMng, wid, line);
573
				}
574
				ToolBarManager toolMng = window.getToolBarManager();
575
				if (toolMng != null)
576
				{
577
					target = locateToolItem(toolMng, wid, line);
578
				}
579
			}
580
		}
581
		catch (Throwable t)
582
		{
583
			/* The next line will throw an exception */
584
			target = null;
585
		}
586
		if (target == null)
587
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_TOOL, wid.getObjectId().toString()), line);
588
		return target;
589
	}
590
591
	private static CommandTarget locateToolItem(ToolBar toolBar, WidgetIdentifier wid, int line)
592
	{
593
		if (toolBar == null)
594
			return null;
595
		ToolItem[] items = toolBar.getItems();
596
		for (int i = 0; i < items.length; i++)
597
		{
598
			ToolItem item = items[i];
599
			if (foundItem(item, wid.getResolverId(), wid.getObjectId().toString()))
600
				return new CommandTarget(item, toolBar);
601
		}
602
		return null;
603
	}
604
605
606
	/**
607
	 * Used to located the view part with the passed id.
608
	 * 
609
	 * @param shell
610
	 *            The current shell
611
	 * @param id
612
	 *            The id of the view part
613
	 * @param line
614
	 *            The line number of the script (used to indicate the line
615
	 *            number if we throw a core exception. Mark as -1 if a script is
616
	 *            not being used)
617
	 * 
618
	 * @return The view part with the passed 'id'
619
	 * 
620
	 * @throws CoreException
621
	 *             If the view part cannot be located.
622
	 */
623
	public static IViewPart locateView(Shell shell, String id, int line) throws CoreException
624
	{
625
		try
626
		{
627
			Object data = shell.getData();
628
	
629
			if (data instanceof IWorkbenchWindow)
630
			{
631
				IWorkbenchWindow window = (IWorkbenchWindow) data;				
632
				IWorkbenchPage page = window.getActivePage();
633
				if (page != null)
634
				{
635
					IViewPart view = page.findView(id);
636
				
637
					if (view == null)
638
					{
639
						try
640
						{
641
							view = page.showView(id);
642
							
643
						}
644
						catch (PartInitException pie)
645
						{
646
							/* Do a thorough search */												
647
							IWorkbenchWindow[] windows = GuiPlugin.getDefault().getWorkbench().getWorkbenchWindows();
648
							
649
							/* For every workbench window */
650
							for (int i = 0; i < windows.length && view == null; i++)
651
							{
652
								/* For every page of a workbench window */
653
								IWorkbenchPage[] pages = windows[i].getPages();
654
								for (int j = 0; j < pages.length && view == null; j++)
655
								{
656
									view = pages[j].findView(id);
657
									
658
								}
659
							}
660
							//need to mke sure that even if it is found in another page, we show it.
661
							
662
						}
663
				}
664
					// added for defcet 175320 in order to ensure the page is 
665
					//given focus no matter where it is found
666
					page.showView(id);
667
					return view;
668
				}
669
		}
670
		}
671
		catch (Throwable t)
672
		{
673
			/* The next line will throw an exception */
674
		}
675
		AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_VIEW, id), line);
676
		return null;
677
	}
678
679
	private static ViewCommandTarget[] locateViewControl(Shell shell, String id, WidgetIdentifier wid, int line) throws CoreException
680
	{
681
		Control[] controls = null;
682
		try
683
		{
684
			IViewPart view = locateView(shell, id, line);
685
			if (view != null)
686
			{
687
				Composite c = getWorkbenchPartControl(view);
688
				controls = locateVisibleChild((Composite) c, null, wid);
689
				// controls will never be null but might be empty
690
				// This way the error is caught here and will reflect the view not found
691
				if (controls.length >0)
692
				{
693
					ViewCommandTarget[] viewCommandTarget = new ViewCommandTarget[controls.length];
694
					for (int i = 0; i < controls.length; i++)
695
					{
696
						viewCommandTarget[i] = new ViewCommandTarget(controls[i], view);
697
					}
698
					return viewCommandTarget;
699
				}
700
			}
701
		}
702
		catch (Throwable t)
703
		{
704
			
705
		}
706
		AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_VIEW_CON, wid.getObjectId().toString()), line);
707
		return null;
708
	}
709
710
	private static Control[] locateVisibleChild(Composite parent, Composite skip, WidgetIdentifier widgetId)
711
	{
712
		int[] counter = new int[1];
713
		counter[0] = 0;
714
		String wid = widgetId.getObjectId().toString();
715
		int sloc = wid.indexOf('#');
716
		String wclassName = null;
717
		if (sloc != -1)
718
			wclassName = wid.substring(0, sloc);
719
		
720
		/* https://bugs.eclipse.org/bugs/show_bug.cgi?id=147766: We need to return all possible matches */
721
		Vector matches = new Vector();
722
		Vector indices = new Vector();
723
		locateVisibleChild(parent, skip, widgetId, wclassName, counter, matches, indices);
724
		Control[] matchedControls = new Control[matches.size()];
725
		matches.toArray(matchedControls);
726
		return matchedControls;
727
	}
728
729
	private static Control locateVisibleChild(Composite parent, Composite skip, WidgetIdentifier id, String wclassName, int[] index, Vector matches, Vector indices)
730
	{
731
		return MacroUtil.recursiveSearch(parent, skip, null, id, wclassName, index, matches, indices);
732
	}
733
734
	private static WizardCommandTarget[] locateWizardControl(Shell shell, WidgetIdentifier wid, int line) throws CoreException
735
	{
736
		WizardDialog wdialog  = null;
737
		Control[] controls  = null;
738
		try
739
		{
740
			wdialog = (WizardDialog) shell.getData();
741
			IWizardPage page = wdialog.getCurrentPage();
742
			Composite pparent = (Composite) page.getControl();
743
			controls = locateVisibleChild(shell, pparent, wid);
744
		}
745
		catch (Throwable t)
746
		{
747
			
748
		}
749
		if (controls == null)
750
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_WIZARD, wid.getObjectId().toString()), line);
751
		
752
		WizardCommandTarget[] wizardCommandTarget = new WizardCommandTarget[controls.length];
753
		for (int i = 0; i < controls.length; i++)
754
		{
755
			if (controls[i].isDisposed())
756
				AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_SHELL_DIS, wid.getObjectId().toString()), line);
757
			wizardCommandTarget[i] = new WizardCommandTarget(controls[i], wdialog);
758
		}
759
			
760
		return wizardCommandTarget;		
761
	}
762
763
	private static WizardCommandTarget[] locateWizardPageControl(Shell shell, String id, WidgetIdentifier wid, int line) throws CoreException
764
	{
765
		Control[] controls = null;
766
		try
767
		{
768
			Object data = shell.getData();
769
			if (data instanceof WizardDialog)
770
			{
771
				WizardDialog wdialog = (WizardDialog) data;
772
				IWizardPage page = wdialog.getCurrentPage();
773
				// assert page
774
				// if (pname.equals(id)==false)
775
				// throwCoreException("Unexpected wizard page: "+pname+", expected
776
				// "+id, line);
777
				Composite pparent = (Composite) page.getControl();
778
				controls = locateVisibleChild(pparent, null, wid);
779
				if (controls != null)
780
				{
781
					WizardCommandTarget[] wizardCommandTarget = new WizardCommandTarget[controls.length];
782
					for (int i = 0; i < controls.length; i++)
783
					{
784
						wizardCommandTarget[i] = new WizardCommandTarget(controls[i], wdialog);
785
					}
786
					return wizardCommandTarget;
787
				}
788
			}
789
		}
790
		catch (Throwable t)
791
		{
792
			
793
		}
794
		if (controls == null)
795
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_WIZARD_CON, wid.getObjectId().toString()), line);
796
		return null;
797
	}
798
		
799
	private static void forceMenuOpen(Control c, Menu menu)
800
	{
801
		Event e = new Event();
802
		e.type = SWT.Show;
803
		e.widget = menu;
804
805
		menu.notifyListeners(e.type, e);
806
		MacroUtil.processDisplayEvents(menu.getDisplay());
807
	}
808
809
	private static void forceMenuClosed(Menu menu)
810
	{
811
		Event e = new Event();
812
		e.type = SWT.Hide;
813
		e.widget = menu;
814
		
815
		menu.notifyListeners(e.type, e);
816
		MacroUtil.processDisplayEvents(menu.getDisplay());
817
	}	
818
	
819
	
820
	/**
821
	 * If the node passed in has a reference id, then this method looks up the id in 
822
	 * the object mine and attempts to find the object that is referenced.
823
	 * 
824
	 * @param node Represents the XML node
825
	 * @param lineTable Contains line level information
826
	 * 
827
	 * @return A String[] of length 2, where String[0] = context id and String[1] = object
828
	 * id.  If the node does not have a reference id, then null is returned.
829
	 * 
830
	 * @throws CoreException If the node contains a reference id attribute but the 
831
	 * corresponding object mine does not have any such object.
832
	 */
833
	public static IUIObject lookupReferenceId(IUIObject parent, Node node, Hashtable lineTable) throws CoreException
834
	{
835
		String referenceId =  MacroUtil.getAttribute(node, MacroConstants.REFERENCE_ID_ATTRIBUTE);
836
		if (referenceId == null)
837
			return null;
838
		
839
		IUIObject correspondingObject = MacroManager.getInstance().getObjectMine().lookupUIObject(parent, referenceId);
840
		if (correspondingObject == null)
841
		{
842
			Integer[] lineLevelDetail = (Integer[]) lineTable.get(node);
843
			AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_OBJ_MINE_NF, referenceId), lineLevelDetail == null ? 0 : lineLevelDetail[0].intValue());
844
		}
845
		else
846
		{
847
			return correspondingObject;
848
		}
849
		
850
		/* Code not reached beyond this point */
851
		return null;
852
	}
853
	
854
	
855
	/**
856
	 * We have to use internal APIs here to get the controls of a part
857
	 */
858
	public static Composite getWorkbenchPartControl (IWorkbenchPart part)
859
	{
860
		IWorkbenchPartTestable testable = (IWorkbenchPartTestable)part.getSite().getAdapter(IWorkbenchPartTestable.class);
861
		return testable.getControl().getParent();
862
	}
863
	
864
	/**
865
	 * Returns true if the id computed for 'item' matches 'id'
866
	 * 
867
	 * @param item The tool item
868
	 * @param resolverId The resolver id -- can be null
869
	 * @param id The id that should be matched against
870
	 * @return true if there is a match, and false otherwise
871
	 */
872
	public static boolean foundItem(Item item, String resolverId, Object id) 
873
	{
874
		/* Try the widget resolvers first */
875
		if (foundWidget(item, resolverId, id))
876
			return true;
877
		
878
		/* Give the old policy a try */
879
		String toolItemIdStr = MacroUtil.getActionId(item).toString();
880
		if (toolItemIdStr != null && toolItemIdStr.equals(id))
881
			return true;
882
		
883
		return false;
884
	}
885
886
	/**
887
	 * Returns true iff the widget matches the id passed in.
888
	 * 
889
	 * @param widget The widget
890
	 * @param resolverId The resolver id -- can be null
891
	 * @param id The id
892
	 * @return true iff the widget matches the id passed in.
893
	 */
894
	public static boolean foundWidget(Widget widget, String resolverId, Object id)
895
	{			
896
		MacroManager macroManager = MacroManager.getInstance();
897
		Hashtable widgetResolvers = macroManager.getWidgetResolvers();
898
		
899
		if (resolverId != null)
900
		{
901
			WidgetResolverLoader loader = (WidgetResolverLoader)widgetResolvers.get(resolverId);
902
			if (loader != null)
903
				return loader.getWidgetResolver().foundWidget(widget, id);
904
			return false;
905
		}
906
		
907
		Enumeration keys = widgetResolvers.keys();
908
		while (keys.hasMoreElements())
909
		{
910
			if (((WidgetResolverLoader)widgetResolvers.get(keys.nextElement())).getWidgetResolver().foundWidget(widget, id))
911
				return true;
912
		}		
913
		return false;
914
	}
915
916
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/AbstractMacroInstruction.java (-90 / +41 lines)
Lines 14-123 Link Here
14
import java.util.Map;
14
import java.util.Map;
15
15
16
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.tptp.test.auto.gui.internal.core.IMacroInstruction;
18
import org.eclipse.tptp.test.auto.gui.internal.core.IUIObject;
19
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier;
20
import org.w3c.dom.Node;
17
import org.w3c.dom.Node;
21
18
22
/**
19
/**
23
 * Provides an abstract implementation of {@link IMacroInstruction}.  Contributors
20
 * Provides an abstract implementation of {@link IMacroInstruction}. Contributors can subclass {@link AbstractMacroInstruction} or provide a direct
24
 * can subclass {@link AbstractMacroInstruction} or provide a direct implementaion 
21
 * implementaion of {@link IMacroInstruction}.
25
 * of {@link IMacroInstruction}.
26
 * 
22
 * 
27
 * @author Ali Mehregani
23
 * @author Ali Mehregani
28
 */
24
 */
29
public abstract class AbstractMacroInstruction implements IMacroInstruction
25
public abstract class AbstractMacroInstruction implements IMacroInstruction {
30
{      
26
31
	/** The widget id associated with this command */
27
	/** The line range of this macro instruction relative to the macro script */
32
	private WidgetIdentifier widgetId;
28
	private int[] range;
33
		
29
34
    /** The corresponding UI object for this macro instruction*/
30
	/**
35
	private IUIObject uiObject;
31
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.IMacroInstruction#load(org.w3c.dom.Node, java.util.Hashtable)
36
32
	 */
37
	/** The line range of this macro instruction relative to the macro script */ 
33
	public void load(Node node, Hashtable lineTable) throws CoreException {
38
    private int [] range;
34
		bindSourceLocation(node,
39
    
35
			lineTable);
40
    
41
    /**
42
     * @see org.eclipse.tptp.test.auto.gui.internal.core.IMacroInstruction#load(org.w3c.dom.Node, java.util.Hashtable)
43
     */
44
	public void load(Node node, Hashtable lineTable) throws CoreException
45
	{        
46
        bindSourceLocation(node, lineTable);        
47
	}
36
	}
48
37
49
	
50
	/**
38
	/**
51
	 * Binds the line details with this macro instruction
39
	 * Binds the line details with this macro instruction
52
	 * 
40
	 * 
53
	 * @param node The node of this instruction
41
	 * @param node
54
	 * @param lineTable The line level information
42
	 *            The node of this instruction
43
	 * @param lineTable
44
	 *            The line level information
55
	 */
45
	 */
56
    protected void bindSourceLocation(Node node, Map lineTable) 
46
	protected void bindSourceLocation(Node node, Map lineTable) {
57
    {
47
		Integer[] lines = (Integer[]) lineTable.get(node);
58
        Integer[] lines = (Integer[]) lineTable.get(node);
48
		if (lines != null) {
59
        if (lines != null) {
49
			range = new int[2];
60
            range = new int[2];
50
			range[0] = lines[0].intValue();
61
            range[0] = lines[0].intValue();
51
			range[1] = lines[1].intValue();
62
            range[1] = lines[1].intValue();
52
		}
63
        }
64
    }
65
66
    
67
    /**
68
     * @see org.eclipse.tptp.test.auto.gui.internal.core.IMacroInstruction#getStartLine()
69
     */
70
    public int getStartLine() 
71
    {
72
        if (range == null)
73
            return -1;
74
        return range[0];
75
    }
76
    
77
    
78
    /**
79
     * @see org.eclipse.tptp.test.auto.gui.internal.core.IMacroInstruction#getStopLine()
80
     */
81
    public int getStopLine() 
82
    {
83
        if (range == null)
84
            return -1;
85
        return range[1];
86
    }
87
 
88
    
89
    /**
90
     * @see org.eclipse.tptp.test.auto.gui.internal.core.IMacroInstruction#getCorrespondingObject()
91
     */
92
    public IUIObject getCorrespondingObject()
93
    {
94
    	return uiObject;
95
    }
96
    
97
    
98
    /**
99
     * @see org.eclipse.tptp.test.auto.gui.internal.core.IMacroInstruction#setCorrespondingObject(org.eclipse.tptp.test.auto.gui.internal.core.IUIObject)
100
     */
101
    public void setCorrespondingObject(IUIObject uiObject)
102
    {
103
    	this.uiObject = uiObject;
104
    }
105
    
106
    
107
    /**
108
     * @see org.eclipse.tptp.test.auto.gui.internal.core.IMacroInstruction#getWidgetId()
109
     */
110
	public WidgetIdentifier getWidgetId()
111
	{
112
		return widgetId;
113
	}
53
	}
114
		
54
115
	
116
	/**
55
	/**
117
	 * @see org.eclipse.tptp.test.auto.gui.internal.core.IMacroInstruction#setWidgetId(org.eclipse.tptp.test.auto.gui.internal.core.WidgetIdentifier)
56
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.IMacroInstruction#getStartLine()
118
	 */
57
	 */
119
	public void setWidgetId(WidgetIdentifier widgetIdentifier)
58
	public int getStartLine() {
120
	{
59
		if (range == null)
121
		this.widgetId = widgetIdentifier;
60
			return -1;
61
		return range[0];
122
	}
62
	}
63
64
	/**
65
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.IMacroInstruction#getStopLine()
66
	 */
67
	public int getStopLine() {
68
		if (range == null)
69
			return -1;
70
		return range[1];
71
	}
72
73
	
123
}
74
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/XMLDefaultHandler.java (-166 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2003, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macro;
12
13
import java.util.Hashtable;
14
import java.util.Stack;
15
16
import javax.xml.parsers.DocumentBuilderFactory;
17
import javax.xml.parsers.ParserConfigurationException;
18
19
import org.w3c.dom.Element;
20
import org.w3c.dom.Node;
21
import org.w3c.dom.Text;
22
import org.xml.sax.Attributes;
23
import org.xml.sax.Locator;
24
import org.xml.sax.helpers.DefaultHandler;
25
26
public class XMLDefaultHandler extends DefaultHandler
27
{
28
29
	private org.w3c.dom.Document fDocument;
30
31
	private Locator fLocator;
32
33
	private Hashtable fLineTable;
34
35
	private Element fRootElement;
36
37
	private Stack fElementStack = new Stack();
38
	
39
	/* Indicates whether a CDATA section is reached */
40
	private boolean cdataStarted;
41
42
	public XMLDefaultHandler()
43
	{
44
		fLineTable = new Hashtable();
45
	}
46
47
	public void startElement(String uri, String localName, String qName, Attributes attributes)
48
	{
49
		Element element = fDocument.createElement(qName);
50
		for (int i = 0; i < attributes.getLength(); i++)
51
		{
52
			element.setAttribute(attributes.getQName(i), attributes.getValue(i));
53
		}
54
55
		Integer lineNumber = new Integer(fLocator.getLineNumber());
56
		Integer[] range = new Integer[] { lineNumber, new Integer(-1) };
57
		fLineTable.put(element, range);
58
		if (fRootElement == null)
59
			fRootElement = element;
60
		else
61
			((Element) fElementStack.peek()).appendChild(element);
62
		fElementStack.push(element);
63
	}
64
65
	public void endElement(String uri, String localName, String qName)
66
	{
67
		Integer[] range = (Integer[]) fLineTable.get(fElementStack.pop());
68
		range[1] = new Integer(fLocator.getLineNumber());
69
	}
70
71
	/*
72
	 * (non-Javadoc)
73
	 * 
74
	 * @see org.xml.sax.helpers.DefaultHandler#setDocumentLocator(org.xml.sax.Locator)
75
	 */
76
	public void setDocumentLocator(Locator locator)
77
	{
78
		fLocator = locator;
79
	}
80
81
	/*
82
	 * (non-Javadoc)
83
	 * 
84
	 * @see org.xml.sax.helpers.DefaultHandler#startDocument()
85
	 */
86
	public void startDocument()
87
	{
88
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
89
		try
90
		{
91
			fDocument = factory.newDocumentBuilder().newDocument();
92
		}
93
		catch (ParserConfigurationException e)
94
		{
95
		}
96
	}
97
98
	/*
99
	 * (non-Javadoc)
100
	 * 
101
	 * @see org.xml.sax.helpers.DefaultHandler#endDocument()
102
	 */
103
	public void endDocument()
104
	{
105
		fDocument.appendChild(fRootElement);
106
	}
107
108
	/*
109
	 * (non-Javadoc)
110
	 * 
111
	 * @see org.xml.sax.helpers.DefaultHandler#processingInstruction(java.lang.String,
112
	 *      java.lang.String)
113
	 */
114
	public void processingInstruction(String target, String data)
115
	{
116
		fDocument.appendChild(fDocument.createProcessingInstruction(target, data));
117
	}
118
119
	/*
120
	 * (non-Javadoc)
121
	 * 
122
	 * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
123
	 */
124
	public void characters(char[] characters, int start, int length)
125
	{
126
		StringBuffer buff = new StringBuffer();
127
		for (int i = 0; i < length; i++)
128
		{
129
			buff.append(characters[start + i]);
130
		}
131
132
		String buffValue = buff.toString();	
133
		boolean isBufferJustWhiteSpace = buffValue.trim().equals("");
134
		boolean isBufferEmpty = buffValue.length() <= 0;
135
		
136
		if ((cdataStarted && isBufferEmpty) || (!cdataStarted && isBufferJustWhiteSpace))
137
		{
138
			cdataStarted = false;
139
			return;
140
		}
141
				
142
		Text text = fDocument.createTextNode(buffValue);
143
		cdataStarted = true;
144
		if (fRootElement == null)
145
			fDocument.appendChild(text);
146
		else
147
			((Element) fElementStack.peek()).appendChild(text);
148
	}
149
	
150
	public Node getDocumentElement()
151
	{
152
		fDocument.getDocumentElement().normalize();
153
		return fDocument.getDocumentElement();
154
	}
155
156
	public org.w3c.dom.Document getDocument()
157
	{
158
		fDocument.getDocumentElement().normalize();
159
		return fDocument;
160
	}
161
162
	public Hashtable getLineTable()
163
	{
164
		return fLineTable;
165
	}
166
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/messages.properties (-1 / +9 lines)
Lines 143-148 Link Here
143
AUTO_GUI_ERROR_MACRO_MENU		= Cannot locate menu item: {0}
143
AUTO_GUI_ERROR_MACRO_MENU		= Cannot locate menu item: {0}
144
AUTO_GUI_ERROR_MACRO_TOOL		= Cannot locate tool item: {0}
144
AUTO_GUI_ERROR_MACRO_TOOL		= Cannot locate tool item: {0}
145
AUTO_GUI_ERROR_MACRO_TOOL_BAR	= Cannot locate local tool bar item: {0}
145
AUTO_GUI_ERROR_MACRO_TOOL_BAR	= Cannot locate local tool bar item: {0}
146
AUTO_GUI_ERROR_MACRO_TAB        = Cannot locate tab item: {0}
146
AUTO_GUI_ERROR_MACRO_WIZARD		= Cannot locate wizard control: {0}
147
AUTO_GUI_ERROR_MACRO_WIZARD		= Cannot locate wizard control: {0}
147
AUTO_GUI_ERROR_MACRO_WIZARD_CON = Cannot locate wizard page control: {0} 
148
AUTO_GUI_ERROR_MACRO_WIZARD_CON = Cannot locate wizard page control: {0} 
148
AUTO_GUI_ERROR_MACRO_SHELL		= Cannot locate shell control: {0}
149
AUTO_GUI_ERROR_MACRO_SHELL		= Cannot locate shell control: {0}
Lines 199-205 Link Here
199
AUTO_GUI_ERROR_TST_WRONG_SRC	= The second last segment of the verification hook class path must be a source folder
200
AUTO_GUI_ERROR_TST_WRONG_SRC	= The second last segment of the verification hook class path must be a source folder
200
AUTO_GUI_ERROR_TST_OBJ_MINE_T	= Error loading object mine...
201
AUTO_GUI_ERROR_TST_OBJ_MINE_T	= Error loading object mine...
201
AUTO_GUI_ERROR_TST_OBJ_MINE		= Error parsing the object mine of the test suite
202
AUTO_GUI_ERROR_TST_OBJ_MINE		= Error parsing the object mine of the test suite
202
AUTO_GUI_ERROR_TST_OBJ_MINE_REF = The reference id of the object {0} is missing or invalid
203
AUTO_GUI_ERROR_TST_OBJ_MINE_REF = The reference id of the UI object with widget id {0} and object id {1} is missing or invalid
203
AUTO_GUI_ERROR_TST_OBJ_MINE_ID	= The object id reference, {0}, collides with another object that already exists
204
AUTO_GUI_ERROR_TST_OBJ_MINE_ID	= The object id reference, {0}, collides with another object that already exists
204
AUTO_GUI_ERROR_TST_OBJ_MINE_REG	= Error registering an object with the object mine of the test suite
205
AUTO_GUI_ERROR_TST_OBJ_MINE_REG	= Error registering an object with the object mine of the test suite
205
206
Lines 208-213 Link Here
208
AUTO_GUI_CONTROL_DIALOG_TITLE 	= Test Case Control Center
209
AUTO_GUI_CONTROL_DIALOG_TITLE 	= Test Case Control Center
209
AUTO_GUI_CONTROL_VER_HOOK		= Verification Hooks
210
AUTO_GUI_CONTROL_VER_HOOK		= Verification Hooks
210
AUTO_GUI_CONTROL_VER_INSERT		= &Insert
211
AUTO_GUI_CONTROL_VER_INSERT		= &Insert
212
AUTO_GUI_CONTROL_VER_INCLUDE_UI_OBJECT = Check this if you do not only want to have the context (Editor, View, Shell) but also the selected UI Object (Button, MenuItem, ...) passed as parameter to the verfication hook method.
211
AUTO_GUI_CONTROL_TERMINATE		= Terminate
213
AUTO_GUI_CONTROL_TERMINATE		= Terminate
212
AUTO_GUI_CONTROL_RESTART		= Restart
214
AUTO_GUI_CONTROL_RESTART		= Restart
213
AUTO_GUI_CONTROL_POSITION_BASED = Toggle On/Off Position Based Recording
215
AUTO_GUI_CONTROL_POSITION_BASED = Toggle On/Off Position Based Recording
Lines 226-228 Link Here
226
AUTO_GUI_DETAILS_STARTPT		= Starting Point:
228
AUTO_GUI_DETAILS_STARTPT		= Starting Point:
227
229
228
AUTO_GUI_UNDOABLE_TEXT_OPERATION_LABEL = Undoable Text Operation
230
AUTO_GUI_UNDOABLE_TEXT_OPERATION_LABEL = Undoable Text Operation
231
232
AUTO_GUI_ERROR_MACRO_OBJECT_RESOLVE = The macro object {0} could not be resolved.
233
234
AUTO_GUI_UI_OBJECT_IDENTIFIER_AMBIGUOUS = The UI object with widget id {0} and object id {1} could not be unambigously identified.
235
AUTO_GUI_RESOLVER_IDENTIFIER_MISSING = The resolver {0} did not set its id on the resolved UI object identifier.
236
(-)src/org/eclipse/tptp/test/auto/gui/internal/AutoGUIImages.java (-1 / +6 lines)
Lines 20-25 Link Here
20
 * 
20
 * 
21
 * 
21
 * 
22
 * @author      Paul E. Slauenwhite
22
 * @author      Paul E. Slauenwhite
23
 * @author 		Alexander Nyssen
23
 * @version     March 5, 2008
24
 * @version     March 5, 2008
24
 * @since       August 19, 2005
25
 * @since       August 19, 2005
25
 */
26
 */
Lines 56-61 Link Here
56
	public static final String IMG_NEW_AUTO_GUI					= "new_atestsuite.gif"; 
57
	public static final String IMG_NEW_AUTO_GUI					= "new_atestsuite.gif"; 
57
	public static final String OBJECT_MINE						= "object_mine.gif"; 	
58
	public static final String OBJECT_MINE						= "object_mine.gif"; 	
58
	public static final String POSITION_BASED					= "position_based.gif"; 
59
	public static final String POSITION_BASED					= "position_based.gif"; 
60
	public static final String VERIFICATION_HOOK				= "verification_hook.gif";
59
	public static final String VARS								= "variables.gif"; 		
61
	public static final String VARS								= "variables.gif"; 		
60
	public static final String VAR_ITEM							= "variable.gif"; 		
62
	public static final String VAR_ITEM							= "variable.gif"; 		
61
	public static final String TERMINATE						= "terminate.gif"; 	
63
	public static final String TERMINATE						= "terminate.gif"; 	
Lines 100-105 Link Here
100
		
102
		
101
		add("d", T_TOOL, POSITION_BASED);
103
		add("d", T_TOOL, POSITION_BASED);
102
		add("e", T_TOOL, POSITION_BASED);
104
		add("e", T_TOOL, POSITION_BASED);
105
		
106
		add("d", T_TOOL, VERIFICATION_HOOK);
107
		add("e", T_TOOL, VERIFICATION_HOOK);
103
108
104
		add("d", T_TOOL, TERMINATE);
109
		add("d", T_TOOL, TERMINATE);
105
		add("e", T_TOOL, TERMINATE);
110
		add("e", T_TOOL, TERMINATE);
Lines 166-169 Link Here
166
		/* wizban */
171
		/* wizban */
167
		add(T_WIZBAN, IMG_NEW_AUTO_GUI_WIZBAN);					
172
		add(T_WIZBAN, IMG_NEW_AUTO_GUI_WIZBAN);					
168
	}
173
	}
169
}
174
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/AutoGUIMessages.java (-1 / +9 lines)
Lines 19-24 Link Here
19
 * 
19
 * 
20
 * 
20
 * 
21
 * @author      Paul E. Slauenwhite
21
 * @author      Paul E. Slauenwhite
22
 * @author      Alexander Nyssen
22
 * @version     July 14, 2008
23
 * @version     July 14, 2008
23
 * @since       August 19, 2005
24
 * @since       August 19, 2005
24
 */
25
 */
Lines 154-159 Link Here
154
	public static String AUTO_GUI_ERROR_MACRO_MENU;		
155
	public static String AUTO_GUI_ERROR_MACRO_MENU;		
155
	public static String AUTO_GUI_ERROR_MACRO_TOOL;		
156
	public static String AUTO_GUI_ERROR_MACRO_TOOL;		
156
	public static String AUTO_GUI_ERROR_MACRO_TOOL_BAR;	
157
	public static String AUTO_GUI_ERROR_MACRO_TOOL_BAR;	
158
	public static String AUTO_GUI_ERROR_MACRO_TAB;
157
	public static String AUTO_GUI_ERROR_MACRO_WIZARD;		
159
	public static String AUTO_GUI_ERROR_MACRO_WIZARD;		
158
	public static String AUTO_GUI_ERROR_MACRO_WIZARD_CON; 
160
	public static String AUTO_GUI_ERROR_MACRO_WIZARD_CON; 
159
	public static String AUTO_GUI_ERROR_MACRO_SHELL;		
161
	public static String AUTO_GUI_ERROR_MACRO_SHELL;		
Lines 218-224 Link Here
218
	
220
	
219
	public static String AUTO_GUI_CONTROL_DIALOG_TITLE; 
221
	public static String AUTO_GUI_CONTROL_DIALOG_TITLE; 
220
	public static String AUTO_GUI_CONTROL_VER_HOOK;		
222
	public static String AUTO_GUI_CONTROL_VER_HOOK;		
221
	public static String AUTO_GUI_CONTROL_VER_INSERT;		
223
	public static String AUTO_GUI_CONTROL_VER_INSERT;
224
	public static String AUTO_GUI_CONTROL_VER_INCLUDE_UI_OBJECT;	
222
	public static String AUTO_GUI_CONTROL_TERMINATE;		
225
	public static String AUTO_GUI_CONTROL_TERMINATE;		
223
	public static String AUTO_GUI_CONTROL_RESTART;
226
	public static String AUTO_GUI_CONTROL_RESTART;
224
	public static String AUTO_GUI_CONTROL_POSITION_BASED;
227
	public static String AUTO_GUI_CONTROL_POSITION_BASED;
Lines 238-243 Link Here
238
	
241
	
239
	public static String AUTO_GUI_UNDOABLE_TEXT_OPERATION_LABEL;
242
	public static String AUTO_GUI_UNDOABLE_TEXT_OPERATION_LABEL;
240
	
243
	
244
	public static String AUTO_GUI_ERROR_MACRO_OBJECT_RESOLVE;
245
	
246
	public static String AUTO_GUI_UI_OBJECT_IDENTIFIER_AMBIGUOUS;
247
	public static String AUTO_GUI_RESOLVER_IDENTIFIER_MISSING;
248
	
241
	static {
249
	static {
242
		NLS.initializeMessages(BUNDLE_NAME, AutoGUIMessages.class);
250
		NLS.initializeMessages(BUNDLE_NAME, AutoGUIMessages.class);
243
	}
251
	}
(-)src/org/eclipse/tptp/test/auto/gui/internal/AutoGUIUtil.java (-1 / +11 lines)
Lines 72-77 Link Here
72
 * A primitive utility class that is commonly shared between the auto gui classes
72
 * A primitive utility class that is commonly shared between the auto gui classes
73
 * 
73
 * 
74
 * @author Ali Mehregani
74
 * @author Ali Mehregani
75
 * @author Alexander Nyssen
75
 */
76
 */
76
public class AutoGUIUtil
77
public class AutoGUIUtil
77
{
78
{
Lines 178-185 Link Here
178
		IProject[] workspaceProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
179
		IProject[] workspaceProjects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
179
		for (int i = 0; i < workspaceProjects.length; i++)
180
		for (int i = 0; i < workspaceProjects.length; i++)
180
		{
181
		{
181
			if (workspaceProjects[i].getNature(JavaCore.NATURE_ID) == null)
182
			// fix for bug #206768 
183
			if (!workspaceProjects[i].isOpen())
182
				continue;
184
				continue;
185
			
186
			if( workspaceProjects[i].getNature(JavaCore.NATURE_ID) == null)
187
				continue;
188
			
183
			IJavaProject javaProject = JavaCore.create(workspaceProjects[i]);
189
			IJavaProject javaProject = JavaCore.create(workspaceProjects[i]);
184
			
190
			
185
			if (javaProject == null || !javaProject.exists())
191
			if (javaProject == null || !javaProject.exists())
Lines 602-607 Link Here
602
		throwCoreException(message, 0, null);
608
		throwCoreException(message, 0, null);
603
	}
609
	}
604
	
610
	
611
	public static void throwCoreException(String message, Throwable t) throws CoreException
612
	{
613
		throwCoreException(message, 0, t);
614
	}	
605
	
615
	
606
	public static void throwCoreException(String message, int line) throws CoreException
616
	public static void throwCoreException(String message, int line) throws CoreException
607
	{
617
	{
(-)src/org/eclipse/tptp/test/auto/gui/internal/dialogs/AutoGUITestControllerDialog.java (-455 / +498 lines)
Lines 46-157 Link Here
46
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
46
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
47
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
47
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
48
48
49
50
/**
49
/**
51
 * This dialog is displayed while the user is recording their macro.
50
 * This dialog is displayed while the user is recording their macro. It is used
52
 * It is used to control the test case that is being recorded.
51
 * to control the test case that is being recorded.
53
 * 
52
 * 
54
 * @author      Ali Mehregani
53
 * @author      Ali Mehregani
55
 * @author      Paul E. Slauenwhite
54
 * @author      Paul E. Slauenwhite
55
 * @author      Alexander Nyssen
56
 * @version     March 5, 2008
56
 * @version     March 5, 2008
57
 * @since       July 10, 2006
57
 * @since       July 10, 2006
58
 */
58
 */
59
public class AutoGUITestControllerDialog extends Dialog 
59
public class AutoGUITestControllerDialog extends Dialog implements
60
implements SelectionListener, MouseListener, MouseMoveListener, KeyListener, DisposeListener
60
		SelectionListener, MouseListener, MouseMoveListener, KeyListener,
61
{
61
		DisposeListener {
62
62
63
	private Shell sShell;  //  @jve:decl-index=0:visual-constraint="10,10"
63
	private Shell sShell; // @jve:decl-index=0:visual-constraint="10,10"
64
	private Composite toolbarComposite;
64
	private Composite toolbarComposite;
65
	private Group verificationGrp;
65
	private Group verificationGrp;
66
	private Group controlGrp;
66
	private Group controlGrp;
67
	private ToolBar toolBar;
67
	private ToolBar toolBar;
68
	private Text verificationName;
68
69
	private Button insertButton;
69
	/* verification group */
70
	private Label nameLbl;
70
	private Label verficationHookNameLabel;
71
	private Text verificationHookNameText;
72
	private ToolBar verificationScopExtensionToolBar;
73
	private ToolItem verificationScopeExtensionToolItem;
74
	private Button verificationHookInsertionButton;
75
71
	private ToolItem terminate;
76
	private ToolItem terminate;
72
	private ToolItem restart;
77
	private ToolItem restart;
73
	private ToolItem positionBasedRecording;
78
	private ToolItem positionBasedRecording;
74
	private ToolItem recordWaitTime;
79
	private ToolItem recordWaitTime;
75
	
80
76
	private Composite statusComposite;
81
	private Composite statusComposite;
77
	private Label statuslbl;
82
	private Label statuslbl;
78
	
83
79
	/* Listener container */
84
	/* Listener container */
80
	private Vector listenerBucket;
85
	private Vector listenerBucket;
81
	
86
82
	/* Global coordinates of the shell - everything else is defined relative to this */
87
	/*
88
	 * Global coordinates of the shell - everything else is defined relative to
89
	 * this
90
	 */
83
	private Point shellBounds;
91
	private Point shellBounds;
84
	
92
85
	/* Indicates that the mouse button is pushed on the shell */ 
93
	/* Indicates that the mouse button is pushed on the shell */
86
	private boolean isMouseDown;
94
	private boolean isMouseDown;
87
	
95
88
	/* The dialog is moved relative to this position */
96
	/* The dialog is moved relative to this position */
89
	private Point originalPosition;
97
	private Point originalPosition;
90
	
98
91
	/* Indicates whether the control center shell is disposed or not */	
99
	/* Indicates whether the control center shell is disposed or not */
92
	private boolean isShellDisposed;
100
	private boolean isShellDisposed;
93
	
101
94
	/* The real parent that the dialog is suppose to have.  This may not necessarily be the actual parent
102
	/*
95
	 * of the shell if it is forced to go to the background */
103
	 * The real parent that the dialog is suppose to have. This may not
104
	 * necessarily be the actual parent of the shell if it is forced to go to
105
	 * the background
106
	 */
96
	private Shell realParent;
107
	private Shell realParent;
97
	
108
98
	/* The actual parent of the dialog.  This should always return the same result as getParent() */
109
	/*
110
	 * The actual parent of the dialog. This should always return the same
111
	 * result as getParent()
112
	 */
99
	private Shell actualParent;
113
	private Shell actualParent;
100
114
101
	/* The first control center dialog will have this set and the successive ones will not */
115
	/*
116
	 * The first control center dialog will have this set and the successive
117
	 * ones will not
118
	 */
102
	private boolean isRoot;
119
	private boolean isRoot;
103
	
120
104
	/* The control root (set only if isRoot is false) */
121
	/* The control root (set only if isRoot is false) */
105
	private AutoGUITestControllerDialog rootControl;
122
	private AutoGUITestControllerDialog rootControl;
106
	
123
107
	/* The control delegator (maybe set only if isRoot is true) */
124
	/* The control delegator (maybe set only if isRoot is true) */
108
	private AutoGUITestControllerDialog delegator;
125
	private AutoGUITestControllerDialog delegator;
109
	
126
110
	/* The display listener that will be listening in for new active shells (set only if isRoot is true) */
127
	/*
111
	private DisplayListener displayListener; 
128
	 * The display listener that will be listening in for new active shells (set
112
	
129
	 * only if isRoot is true)
130
	 */
131
	private DisplayListener displayListener;
132
113
	/* The last status of the control center dialog */
133
	/* The last status of the control center dialog */
114
	private String lastStatus;
134
	private String lastStatus;
115
	
135
116
	/* The last location of the control dialog box */
136
	/* The last location of the control dialog box */
117
	private Point lastLocation;
137
	private Point lastLocation;
118
	
138
119
	/* Indicates whether position based should be on (should be set before shell is created)*/
139
	/*
140
	 * Indicates whether position based should be on (should be set before shell
141
	 * is created)
142
	 */
120
	private boolean positionBasedOn;
143
	private boolean positionBasedOn;
121
	
144
122
	/* Indicates whether wait times should be recorded */
145
	/* Indicates whether wait times should be recorded */
123
	private boolean waitTimeOn;
146
	private boolean waitTimeOn;
124
	
147
125
	/* Stores the root's parent.  At any time this dialog will either have its parent set to 
148
	/*
126
	 * the root's parent or the active shell */
149
	 * Indicates wether the generated verification hook method should contain a
150
	 * second parameter for the UI object that was selected inside the context
151
	 */
152
	private boolean verificationScopeExtended;
153
154
	/*
155
	 * Stores the root's parent. At any time this dialog will either have its
156
	 * parent set to the root's parent or the active shell
157
	 */
127
	private static Shell rootParent;
158
	private static Shell rootParent;
128
	
159
129
	/* Indicates whether this dialog has purposely been sent to back */
160
	/* Indicates whether this dialog has purposely been sent to back */
130
	private boolean forceToBack;
161
	private boolean forceToBack;
131
	
162
132
	/* Indicates whether the dialog is activated or not */
163
	/* Indicates whether the dialog is activated or not */
133
	private static boolean activated;
164
	private static boolean activated;
134
	
165
135
	/* Event types */
166
	/* Event types */
136
	public final static byte TERMINATE 						= 0x01;
167
	public final static byte TERMINATE = 0x01;
137
	public final static byte VERIFICATION_HOOK_INSERT		= 0x02;
168
	public final static byte RESTART = 0x02;
138
	public final static byte RESTART						= 0x03;
169
	public final static byte POSITION_BASED = 0x03;
139
	public final static byte POSITION_BASED					= 0x04;
170
	public final static byte WAIT_TIME = 0x04;
140
	public final static byte WAIT_TIME						= 0x05;
171
	public final static byte VERIFICATION_HOOK_INSERT = 0x05;
141
	
172
142
	private final static int DO_NOT_DISPOSE = 1020;
173
	private final static int DO_NOT_DISPOSE = 1020;
143
	
174
144
	/* At all times, there should only be one active dialog displayed to the user */
175
	/*
176
	 * At all times, there should only be one active dialog displayed to the
177
	 * user
178
	 */
145
	private static AutoGUITestControllerDialog activeControlDialog;
179
	private static AutoGUITestControllerDialog activeControlDialog;
146
	
180
147
	/**
181
	/**
148
	 * This constructor is used to create dialogs that are opened when the active shell changes.
182
	 * This constructor is used to create dialogs that are opened when the
183
	 * active shell changes.
149
	 * 
184
	 * 
150
	 * @param parentShell The parent shell
185
	 * @param parentShell
151
	 * @param rootControl The control center that all the tasks will be delegated to.
186
	 *            The parent shell
187
	 * @param rootControl
188
	 *            The control center that all the tasks will be delegated to.
152
	 */
189
	 */
153
	public AutoGUITestControllerDialog(Shell parentShell, AutoGUITestControllerDialog rootControl)
190
	public AutoGUITestControllerDialog(Shell parentShell,
154
	{
191
			AutoGUITestControllerDialog rootControl) {
155
		super(parentShell);
192
		super(parentShell);
156
		isShellDisposed = false;
193
		isShellDisposed = false;
157
		realParent = parentShell;
194
		realParent = parentShell;
Lines 159-170 Link Here
159
		isRoot = false;
196
		isRoot = false;
160
		this.rootControl = rootControl;
197
		this.rootControl = rootControl;
161
		this.positionBasedOn = false;
198
		this.positionBasedOn = false;
162
		
199
163
	}
200
	}
164
	
201
165
	
202
	public AutoGUITestControllerDialog(Shell parent) {
166
	public AutoGUITestControllerDialog(Shell parent)
167
	{
168
		super(parent);
203
		super(parent);
169
		isShellDisposed = false;
204
		isShellDisposed = false;
170
		realParent = parent;
205
		realParent = parent;
Lines 172-192 Link Here
172
		isRoot = true;
207
		isRoot = true;
173
		activated = true;
208
		activated = true;
174
	}
209
	}
175
	
210
176
	
211
	public void openDialog() {
177
	public void openDialog()
178
	{
179
		openDialog(null);
212
		openDialog(null);
180
	}
213
	}
181
	
214
182
	/**
215
	/**
183
	 * Equivalent to openDialog (true)
216
	 * Equivalent to openDialog (true)
184
	 */
217
	 */
185
	public void openDialog(final Shell activeShell)
218
	public void openDialog(final Shell activeShell) {
186
	{
219
		shellBounds = new Point(317, 105);
187
		shellBounds = new Point (317, 105);
188
		originalPosition = new Point(0, 0);
220
		originalPosition = new Point(0, 0);
189
		sShell = new Shell(getParent(), SWT.MODELESS); 
221
		sShell = new Shell(getParent(), SWT.MODELESS);
190
		sShell.setText(AutoGUIMessages.AUTO_GUI_CONTROL_DIALOG_TITLE);
222
		sShell.setText(AutoGUIMessages.AUTO_GUI_CONTROL_DIALOG_TITLE);
191
		sShell.setLayout(new GridLayout());
223
		sShell.setLayout(new GridLayout());
192
		sShell.setSize(shellBounds);
224
		sShell.setSize(shellBounds);
Lines 195-883 Link Here
195
		sShell.addMouseListener(this);
227
		sShell.addMouseListener(this);
196
		sShell.addMouseMoveListener(this);
228
		sShell.addMouseMoveListener(this);
197
		sShell.addDisposeListener(this);
229
		sShell.addDisposeListener(this);
198
		
230
199
		/* We would like the macro recorder to ignore this shell */
231
		/* We would like the macro recorder to ignore this shell */
200
		sShell.setData(MacroManager.IGNORE, Boolean.TRUE);
232
		sShell.setData(MacroManager.IGNORE, Boolean.TRUE);
201
		
233
202
		sShell.setFocus();		
234
		sShell.setFocus();
203
		createToolbarComposite();
235
		createToolbarComposite();
204
		createStatusComposite();
236
		createStatusComposite();
205
				
237
206
		ActivationListener activationListener = null;
238
		ActivationListener activationListener = null;
207
		/* We need to always stay on top of every shell */
239
		/* We need to always stay on top of every shell */
208
		if (isRoot)
240
		if (isRoot) {
209
		{
210
			rootParent = getParent();
241
			rootParent = getParent();
211
			displayListener = new DisplayListener();
242
			displayListener = new DisplayListener();
212
			Display.getCurrent().addFilter(SWT.Activate, displayListener);
243
			Display.getCurrent().addFilter(SWT.Activate, displayListener);
213
		}
244
		}
214
		
245
215
		else
246
		else {
216
		{
247
			/*
217
			/* Defect #113543: Under the RedHat linux environment, if a modeless dialog is opened with an application modal dialog as its
248
			 * Defect #113543: Under the RedHat linux environment, if a modeless
218
			 * parent, the modality of the opened dialog will be restricted to application modal (blocking the parent dialog).  We'll
249
			 * dialog is opened with an application modal dialog as its parent,
219
			 * need to dispose and open the control center dialog based on activation and deactivation events.  This is very expensive and
250
			 * the modality of the opened dialog will be restricted to
220
			 * it is only performed on non-windows environments.
251
			 * application modal (blocking the parent dialog). We'll need to
221
			 */ 
252
			 * dispose and open the control center dialog based on activation
253
			 * and deactivation events. This is very expensive and it is only
254
			 * performed on non-windows environments.
255
			 */
222
			final String WINDOWS_OS = "windows";
256
			final String WINDOWS_OS = "windows";
223
			String platformOS = System.getProperty("os.name");
257
			String platformOS = System.getProperty("os.name");
224
			 
258
225
			if (platformOS == null || platformOS.toLowerCase().indexOf(WINDOWS_OS) == -1)
259
			if (platformOS == null
226
			{
260
					|| platformOS.toLowerCase().indexOf(WINDOWS_OS) == -1) {
227
				activationListener = new ActivationListener(false);
261
				activationListener = new ActivationListener(false);
228
			}
262
			}
229
		}
263
		}
230
		
264
231
		/* Open the dialog */
265
		/* Open the dialog */
232
		activeControlDialog = this;
266
		activeControlDialog = this;
233
 		sShell.open(); 		
267
		sShell.open();
234
 		
235
 		if (activationListener != null)
236
 		{
237
 			sShell.addListener(SWT.Activate, activationListener);
238
 			sShell.addListener(SWT.Deactivate, activationListener); 			
239
 			
240
 			final ActivationListener finalActivationListener = activationListener;
241
 			GuiPlugin.getDefault().getWorkbench().getDisplay().timerExec(100, new Runnable(){
242
268
243
				public void run() {
269
		if (activationListener != null) {
244
					if (activeShell != null && !activeShell.isDisposed())
270
			sShell.addListener(SWT.Activate, activationListener);
245
						activeShell.setActive();
271
			sShell.addListener(SWT.Deactivate, activationListener);
246
						
272
247
					finalActivationListener.setEnable(true);
273
			final ActivationListener finalActivationListener = activationListener;
248
					
274
			GuiPlugin.getDefault().getWorkbench().getDisplay().timerExec(100,
249
				}});
275
					new Runnable() {
250
 		}
276
251
 		
277
						public void run() {
252
 		
278
							if (activeShell != null
253
279
									&& !activeShell.isDisposed())
254
	}
280
								activeShell.setActive();
255
	
281
256
	
282
							finalActivationListener.setEnable(true);
257
	/**
283
258
	 * This method initializes toolbarComposite	
284
						}
259
	 *
285
					});
260
	 */    
286
		}
287
288
	}
289
290
	/**
291
	 * This method initializes toolbarComposite
292
	 * 
293
	 */
261
	private void createToolbarComposite() {
294
	private void createToolbarComposite() {
262
		GridLayout gridLayout = new GridLayout();
295
		GridLayout gridLayout = new GridLayout();
263
		gridLayout.numColumns = 2;
296
		gridLayout.numColumns = 2;
264
		toolbarComposite = new Composite(sShell, SWT.NONE);		   
297
		toolbarComposite = new Composite(sShell, SWT.NONE);
265
		createControlGrp();
298
		createControlGrp();
266
		createVerificationGrp();
299
		createVerificationGrp();
267
		toolbarComposite.setLayoutData(GridDataUtil.createHorizontalFill());
300
		toolbarComposite.setLayoutData(GridDataUtil.createHorizontalFill());
268
		toolbarComposite.addMouseListener(this);
301
		toolbarComposite.addMouseListener(this);
269
		toolbarComposite.addMouseMoveListener(this);
302
		toolbarComposite.addMouseMoveListener(this);
270
		toolbarComposite.setLayout(gridLayout);		
303
		toolbarComposite.setLayout(gridLayout);
271
	}
304
	}
272
	
305
273
	private void createStatusComposite()
306
	private void createStatusComposite() {
274
	{
275
		GridData gd = new GridData();
307
		GridData gd = new GridData();
276
		gd.horizontalAlignment = SWT.CENTER;
308
		gd.horizontalAlignment = SWT.CENTER;
277
		
309
278
		GridLayout gridLayout = new GridLayout();
310
		GridLayout gridLayout = new GridLayout();
279
		statusComposite = new Composite (sShell, SWT.NONE);		   
311
		statusComposite = new Composite(sShell, SWT.NONE);
280
		statusComposite.setLayout(gridLayout);
312
		statusComposite.setLayout(gridLayout);
281
		statusComposite.setLayoutData(gd);
313
		statusComposite.setLayoutData(gd);
282
		statusComposite.addMouseListener(this);
314
		statusComposite.addMouseListener(this);
283
		statusComposite.addMouseMoveListener(this);
315
		statusComposite.addMouseMoveListener(this);
284
		
316
285
		GridData gd2 = new GridData();
317
		GridData gd2 = new GridData();
286
		gd2.horizontalAlignment = SWT.CENTER;
318
		gd2.horizontalAlignment = SWT.CENTER;
287
		gd2.grabExcessHorizontalSpace = true;
319
		gd2.grabExcessHorizontalSpace = true;
288
		gd2.widthHint = (int)(shellBounds.x * 0.8);
320
		gd2.widthHint = (int) (shellBounds.x * 0.8);
289
		statuslbl = new Label (statusComposite, SWT.NONE);
321
		statuslbl = new Label(statusComposite, SWT.NONE);
290
		statuslbl.setAlignment(SWT.CENTER);
322
		statuslbl.setAlignment(SWT.CENTER);
291
		statuslbl.setLayoutData(gd2);
323
		statuslbl.setLayoutData(gd2);
292
		statuslbl.addMouseListener(this);
324
		statuslbl.addMouseListener(this);
293
		statuslbl.addMouseMoveListener(this);
325
		statuslbl.addMouseMoveListener(this);
294
	}
326
	}
295
	
327
296
	
297
	/**
328
	/**
298
	 * This method initializes verificationGrp	
329
	 * This method initializes verificationGrp
299
	 *
330
	 * 
300
	 */    
331
	 */
301
	private void createVerificationGrp() {
332
	private void createVerificationGrp() {
302
		GridLayout gridLayout1 = new GridLayout();
333
		GridLayout gridLayout1 = new GridLayout();
303
		gridLayout1.numColumns = 3;
334
		gridLayout1.numColumns = 4;
304
		verificationGrp = new Group(toolbarComposite, SWT.NONE);		   
335
		verificationGrp = new Group(toolbarComposite, SWT.NONE);
305
		verificationGrp.setText(AutoGUIMessages.AUTO_GUI_CONTROL_VER_HOOK);
336
		verificationGrp.setText(AutoGUIMessages.AUTO_GUI_CONTROL_VER_HOOK);
306
		verificationGrp.setLayout(gridLayout1);
337
		verificationGrp.setLayout(gridLayout1);
307
		verificationGrp.setLayoutData (GridDataUtil.createHorizontalFill());
338
		verificationGrp.setLayoutData(GridDataUtil.createHorizontalFill());
308
		verificationGrp.addMouseListener(this);
339
		verificationGrp.addMouseListener(this);
309
		verificationGrp.addMouseMoveListener(this);
340
		verificationGrp.addMouseMoveListener(this);
310
		nameLbl = new Label(verificationGrp, SWT.NONE);
341
311
		nameLbl.setText(AutoGUIMessages.AUTO_GUI_NEW_DIALOG_NAME);
342
		verficationHookNameLabel = new Label(verificationGrp, SWT.NONE);
312
		nameLbl.addMouseListener(this);
343
		verficationHookNameLabel
313
		nameLbl.addMouseMoveListener(this);
344
				.setText(AutoGUIMessages.AUTO_GUI_NEW_DIALOG_NAME);
314
		verificationName = new Text(verificationGrp, SWT.BORDER);
345
		verficationHookNameLabel.addMouseListener(this);
315
		verificationName.setLayoutData (GridDataUtil.createHorizontalFill());
346
		verficationHookNameLabel.addMouseMoveListener(this);
316
		verificationName.addKeyListener(this);
347
317
		insertButton = new Button(verificationGrp, SWT.NONE);
348
		verificationHookNameText = new Text(verificationGrp, SWT.BORDER);
318
		insertButton.setText(AutoGUIMessages.AUTO_GUI_CONTROL_VER_INSERT);
349
		verificationHookNameText.setLayoutData(GridDataUtil
319
		insertButton.addSelectionListener(this);
350
				.createHorizontalFill());
320
		insertButton.setEnabled(false);
351
		verificationHookNameText.addKeyListener(this);
321
		sShell.setDefaultButton(insertButton);
352
322
	}
353
		verificationScopExtensionToolBar = new ToolBar(verificationGrp,
323
	/**
354
				SWT.NONE);
324
	 * This method initializes controlGrp	
355
		verificationScopeExtensionToolItem = new ToolItem(
325
	 *
356
				verificationScopExtensionToolBar, SWT.CHECK);
326
	 */    
357
		verificationScopeExtensionToolItem.setImage(AutoGUIImages.getInstance()
358
				.getImage("e", AutoGUIImages.VERIFICATION_HOOK));
359
		verificationScopeExtensionToolItem
360
				.setToolTipText(AutoGUIMessages.AUTO_GUI_CONTROL_VER_INCLUDE_UI_OBJECT);
361
		verificationScopeExtensionToolItem
362
				.setSelection(verificationScopeExtended);
363
		verificationScopeExtensionToolItem.addSelectionListener(this);
364
		verificationScopeExtensionToolItem.setEnabled(false);
365
366
		verificationHookInsertionButton = new Button(verificationGrp, SWT.NONE);
367
		verificationHookInsertionButton
368
				.setText(AutoGUIMessages.AUTO_GUI_CONTROL_VER_INSERT);
369
		verificationHookInsertionButton.addSelectionListener(this);
370
		verificationHookInsertionButton.setEnabled(false);
371
		sShell.setDefaultButton(verificationHookInsertionButton);
372
	}
373
374
	/**
375
	 * This method initializes controlGrp
376
	 * 
377
	 */
327
	private void createControlGrp() {
378
	private void createControlGrp() {
328
		controlGrp = new Group(toolbarComposite, SWT.NONE);		   
379
		controlGrp = new Group(toolbarComposite, SWT.NONE);
329
		controlGrp.setLayout(new GridLayout());
380
		controlGrp.setLayout(new GridLayout());
330
		controlGrp.addMouseListener(this);
381
		controlGrp.addMouseListener(this);
331
		controlGrp.addMouseMoveListener(this);
382
		controlGrp.addMouseMoveListener(this);
332
		createToolBar();
383
		createToolBar();
333
		controlGrp.setText(AutoGUIMessages.AUTO_GUI_CONTROL_CONT);
384
		controlGrp.setText(AutoGUIMessages.AUTO_GUI_CONTROL_CONT);
334
	}
385
	}
386
335
	/**
387
	/**
336
	 * This method initializes toolBar	
388
	 * This method initializes toolBar
337
	 *
389
	 * 
338
	 */    
390
	 */
339
	private void createToolBar() {
391
	private void createToolBar() {
340
		GridData gridData = new GridData();
392
		GridData gridData = new GridData();
341
		gridData.horizontalAlignment = SWT.CENTER;
393
		gridData.horizontalAlignment = SWT.CENTER;
342
		gridData.grabExcessHorizontalSpace = true;
394
		gridData.grabExcessHorizontalSpace = true;
343
		toolBar = new ToolBar(controlGrp, SWT.NONE);		   
395
		toolBar = new ToolBar(controlGrp, SWT.NONE);
344
		
396
345
		/* The terminate button */
397
		/* The terminate button */
346
		terminate = new ToolItem(toolBar, SWT.PUSH);
398
		terminate = new ToolItem(toolBar, SWT.PUSH);
347
		terminate.setImage(AutoGUIImages.getInstance().getImage("e", AutoGUIImages.TERMINATE));
399
		terminate.setImage(AutoGUIImages.getInstance().getImage("e",
400
				AutoGUIImages.TERMINATE));
348
		terminate.setToolTipText(AutoGUIMessages.AUTO_GUI_CONTROL_TERMINATE);
401
		terminate.setToolTipText(AutoGUIMessages.AUTO_GUI_CONTROL_TERMINATE);
349
		terminate.addSelectionListener(this);
402
		terminate.addSelectionListener(this);
350
		
403
351
		/* The restart button */
404
		/* The restart button */
352
		restart = new ToolItem(toolBar, SWT.PUSH);
405
		restart = new ToolItem(toolBar, SWT.PUSH);
353
		restart.setImage(AutoGUIImages.getInstance().getImage(AutoGUIImages.RESTART));
406
		restart
407
				.setImage(AutoGUIImages.getInstance()
408
						.getImage(AutoGUIImages.RESTART));
354
		restart.setToolTipText(AutoGUIMessages.AUTO_GUI_CONTROL_RESTART);
409
		restart.setToolTipText(AutoGUIMessages.AUTO_GUI_CONTROL_RESTART);
355
		restart.addSelectionListener(this);
410
		restart.addSelectionListener(this);
356
		
411
357
		/* A separator */
412
		/* A separator */
358
		ToolItem sep = new ToolItem(toolBar, SWT.SEPARATOR);
413
		ToolItem sep = new ToolItem(toolBar, SWT.SEPARATOR);
359
		sep.setText("");
414
		sep.setText("");
360
		
415
361
		/* The position-based recording button */
416
		/* The position-based recording button */
362
		positionBasedRecording = new ToolItem (toolBar, SWT.CHECK);
417
		positionBasedRecording = new ToolItem(toolBar, SWT.CHECK);
363
		positionBasedRecording.setImage(AutoGUIImages.getInstance().getImage("e", AutoGUIImages.POSITION_BASED));
418
		positionBasedRecording.setImage(AutoGUIImages.getInstance().getImage("e",
364
		positionBasedRecording.setToolTipText(AutoGUIMessages.AUTO_GUI_CONTROL_POSITION_BASED);
419
				AutoGUIImages.POSITION_BASED));
420
		positionBasedRecording
421
				.setToolTipText(AutoGUIMessages.AUTO_GUI_CONTROL_POSITION_BASED);
365
		positionBasedRecording.setSelection(positionBasedOn);
422
		positionBasedRecording.setSelection(positionBasedOn);
366
		positionBasedRecording.addSelectionListener(this);
423
		positionBasedRecording.addSelectionListener(this);
367
				
424
368
		/* The wait time toggle buttong */		
425
		/* The wait time toggle buttong */
369
		recordWaitTime = new ToolItem (toolBar, SWT.CHECK);
426
		recordWaitTime = new ToolItem(toolBar, SWT.CHECK);
370
		recordWaitTime .setImage(AutoGUIImages.getInstance().getImage(AutoGUIImages.WAIT_TIME));
427
		recordWaitTime.setImage(AutoGUIImages.getInstance()
371
		recordWaitTime.setToolTipText(AutoGUIMessages.AUTO_GUI_CONTROL_WAIT_TIME);
428
				.getImage(AutoGUIImages.WAIT_TIME));
429
		recordWaitTime
430
				.setToolTipText(AutoGUIMessages.AUTO_GUI_CONTROL_WAIT_TIME);
372
		recordWaitTime.setSelection(waitTimeOn);
431
		recordWaitTime.setSelection(waitTimeOn);
373
		recordWaitTime.addSelectionListener(this);
432
		recordWaitTime.addSelectionListener(this);
374
		
433
375
		
376
		toolBar.setLayoutData(gridData);
434
		toolBar.setLayoutData(gridData);
377
	}
435
	}
378
	
436
379
	
380
	/**
437
	/**
381
	 * Used to register listeners with the control dialog box
438
	 * Used to register listeners with the control dialog box See event types
382
	 * See event types for the type of events that the listener
439
	 * for the type of events that the listener will be invoked with.
383
	 * will be invoked with.
384
	 */
440
	 */
385
	public void registerListener (AutoGUIControllerListener listener)
441
	public void registerListener(AutoGUIControllerListener listener) {
386
	{
387
		if (listenerBucket == null)
442
		if (listenerBucket == null)
388
			listenerBucket = new Vector();
443
			listenerBucket = new Vector();
389
		if (listener != null && !listenerBucket.contains(listener))
444
		if (listener != null && !listenerBucket.contains(listener))
390
			listenerBucket.add(listener);
445
			listenerBucket.add(listener);
391
	}
446
	}
392
	
447
393
	public void terminate()
448
	public void terminate() {
394
	{
449
		if (rootControl != null) {
395
		if (rootControl != null)
396
		{
397
			rootControl.terminate();
450
			rootControl.terminate();
398
		}
451
		} else if (isRoot) {
399
		else if (isRoot)
400
		{
401
			Display.getCurrent().removeFilter(SWT.Activate, displayListener);
452
			Display.getCurrent().removeFilter(SWT.Activate, displayListener);
402
			activeControlDialog.dispose();
453
			activeControlDialog.dispose();
403
			notifyListeners (TERMINATE, null);
454
			notifyListeners(TERMINATE, null);
404
		}
455
		}
405
456
406
	}
457
	}
407
458
408
	public void widgetSelected(SelectionEvent e)
459
	public void widgetSelected(SelectionEvent e) {
409
	{
410
		byte eventType = 0;
460
		byte eventType = 0;
411
		
461
412
		/* Determine the type of event */
462
		/* Determine the type of event */
413
		if (e.widget == terminate)
463
		if (e.widget == terminate) {
414
		{
415
			eventType = TERMINATE;
464
			eventType = TERMINATE;
416
			notifyListeners (eventType, null);			
465
			notifyListeners(eventType, null);
417
			
466
418
			if (e.detail != DO_NOT_DISPOSE)
467
			if (e.detail != DO_NOT_DISPOSE)
419
				dispose();
468
				dispose();
420
			
469
421
			return;
470
			return;
422
		}
471
		}
423
		/* This is the verification insertion event */
472
		/* This is the verification insertion event */
424
		else if (e.widget == insertButton)
473
		else if (e.widget == verificationHookInsertionButton)
425
			eventType = VERIFICATION_HOOK_INSERT;
474
			eventType = VERIFICATION_HOOK_INSERT;
426
		else if (e.widget == restart)
475
		else if (e.widget == verificationScopeExtensionToolItem) {
476
			verificationScopeExtended = ((ToolItem) e.widget).getSelection();
477
		} else if (e.widget == restart)
427
			eventType = RESTART;
478
			eventType = RESTART;
428
		else if (e.widget == positionBasedRecording)
479
		else if (e.widget == positionBasedRecording) {
429
		{
480
			positionBasedOn = ((ToolItem) e.widget).getSelection();
430
			positionBasedOn = ((ToolItem)e.widget).getSelection();
431
			eventType = POSITION_BASED;
481
			eventType = POSITION_BASED;
432
		}
482
		} else if (e.widget == recordWaitTime) {
433
		else if (e.widget == recordWaitTime)
483
			waitTimeOn = ((ToolItem) e.widget).getSelection();
434
		{
435
			waitTimeOn = ((ToolItem)e.widget).getSelection();
436
			eventType = WAIT_TIME;
484
			eventType = WAIT_TIME;
437
		}
485
		}
438
		
486
439
		if (eventType != 0)
487
		if (eventType != 0)
440
			notifyListeners (eventType, verificationName.getText());
488
			notifyListeners(eventType, verificationHookNameText.getText());
441
	}
489
	}
442
	
490
443
	
491
	public void widgetDisposed(DisposeEvent e) {
444
	public void widgetDisposed(DisposeEvent e) 
492
		if (!isShellDisposed && isRoot) {
445
	{
446
		if (!isShellDisposed && isRoot)
447
		{
448
			isShellDisposed = true;
493
			isShellDisposed = true;
449
			
494
450
			/* The shell is been disposed.  Simulate a termination */
495
			/* The shell is been disposed. Simulate a termination */
451
			Event event = new Event();
496
			Event event = new Event();
452
			event.widget = terminate;
497
			event.widget = terminate;
453
			event.detail = DO_NOT_DISPOSE;
498
			event.detail = DO_NOT_DISPOSE;
454
			widgetSelected(new SelectionEvent(event));			
499
			widgetSelected(new SelectionEvent(event));
455
		}
500
		}
456
		
501
457
	}	
502
	}
458
	
503
459
	/**
504
	/**
460
	 * A helper method used to notify the registered listeners
505
	 * A helper method used to notify the registered listeners
461
	 * 
506
	 * 
462
	 * @param eventType The type of event that caused this invokation
507
	 * @param eventType
508
	 *            The type of event that caused this invokation
463
	 */
509
	 */
464
	protected void notifyListeners (byte eventType, Object value)
510
	protected void notifyListeners(byte eventType, Object value) {
465
	{
511
466
		
512
		/*
467
		/* If we're not the root control center, then we're expected to delegate the tasks */
513
		 * If we're not the root control center, then we're expected to delegate
468
		if (!isRoot)
514
		 * the tasks
469
		{
515
		 */
470
			rootControl.notifyListeners(eventType, value);			
516
		if (!isRoot) {
471
		}
517
			rootControl.notifyListeners(eventType, value);
472
		else
518
		} else {
473
		{
474
			/* Remove the listener if we were terminated */
519
			/* Remove the listener if we were terminated */
475
			if (eventType == TERMINATE)
520
			if (eventType == TERMINATE)
476
				Display.getCurrent().removeFilter(SWT.Activate, displayListener);
521
				Display.getCurrent()
477
			
522
						.removeFilter(SWT.Activate, displayListener);
478
			/* Update appropriate fields if delegator updated the position-based or wait-time-recording options */
523
479
			if (delegator != null)
524
			/*
480
			{
525
			 * Update appropriate fields if delegator updated the position-based
526
			 * or wait-time-recording options
527
			 */
528
			if (delegator != null) {
481
				if (eventType == POSITION_BASED)
529
				if (eventType == POSITION_BASED)
482
					positionBasedOn = delegator.isPositionBasedOn();
530
					positionBasedOn = delegator.isPositionBasedOn();
483
				else if (eventType == WAIT_TIME)
531
				else if (eventType == WAIT_TIME)
484
					waitTimeOn = delegator.isWaitTimeOn();
532
					waitTimeOn = delegator.isWaitTimeOn();
485
			}
533
			}
486
			
534
487
			/* Start notifying the listeners */
535
			/* Start notifying the listeners */
488
			int size = listenerBucket.size();
536
			int size = listenerBucket.size();
489
			for (int i = 0; i < size; i++)
537
			for (int i = 0; i < size; i++) {
490
			{
538
				((AutoGUIControllerListener) listenerBucket.get(i))
491
				((AutoGUIControllerListener)listenerBucket.get(i)).handleEvent(eventType, value);
539
						.handleEvent(eventType, value);
492
			}
540
			}
493
		}
541
		}
494
	}
542
	}
495
543
544
	public void widgetDefaultSelected(SelectionEvent e) {
545
		/* Doesn't need to be implemented */
546
	}
496
547
497
	public void widgetDefaultSelected(SelectionEvent e)
548
	/**
498
	{
549
	 * A chance to clean up after our self
499
		/* Doesn't need to be implemented */		
550
	 */
500
	}
551
	public void dispose() {
501
	
552
		isShellDisposed = true;
502
	
553
		if (sShell != null && !sShell.isDisposed()) {
503
	/**
504
	 * A chance to clean up after our self 
505
	 */
506
	public void dispose()
507
	{		
508
		isShellDisposed = true;		
509
		if (sShell != null && !sShell.isDisposed())
510
		{
511
			sShell.close();
554
			sShell.close();
512
			toolBar.dispose();
555
			toolBar.dispose();
513
			verificationName.dispose();
556
			verificationHookNameText.dispose();
514
			insertButton.dispose();
557
			verificationScopeExtensionToolItem.dispose();
515
			nameLbl.dispose();
558
			verificationHookInsertionButton.dispose();
559
			verficationHookNameLabel.dispose();
516
			terminate.dispose();
560
			terminate.dispose();
517
			restart.dispose();
561
			restart.dispose();
518
			positionBasedRecording.dispose();
562
			positionBasedRecording.dispose();
519
			verificationGrp.dispose();
563
			verificationGrp.dispose();
520
			controlGrp.dispose();
564
			controlGrp.dispose();
521
			toolbarComposite.dispose();
565
			toolbarComposite.dispose();
522
			sShell.dispose();  //  @jve:decl-index=0:visual-constraint="10,10"
566
			sShell.dispose(); // @jve:decl-index=0:visual-constraint="10,10"
523
		}
567
		}
524
		
568
525
		toolBar = null;
569
		toolBar = null;
526
		verificationName = null;
570
		verificationHookNameText = null;
527
		insertButton = null;
571
		verificationScopeExtensionToolItem = null;
528
		nameLbl = null;
572
		verificationHookInsertionButton = null;
529
		terminate = null; 
573
		verficationHookNameLabel = null;
574
		terminate = null;
530
		verificationGrp = null;
575
		verificationGrp = null;
531
		controlGrp = null;
576
		controlGrp = null;
532
		toolbarComposite = null;
577
		toolbarComposite = null;
533
		sShell = null;  //  @jve:decl-index=0:visual-constraint="10,10"
578
		sShell = null; // @jve:decl-index=0:visual-constraint="10,10"
534
		
579
535
		shellBounds = null;
580
		shellBounds = null;
536
		originalPosition = null;
581
		originalPosition = null;
537
	}
582
	}
538
	
583
539
	public void mouseDoubleClick(MouseEvent e)
584
	public void mouseDoubleClick(MouseEvent e) {
540
	{
541
		/* Doesn't need to be implemented */
585
		/* Doesn't need to be implemented */
542
	}
586
	}
543
	
587
544
	public void mouseDown(MouseEvent e)
588
	public void mouseDown(MouseEvent e) {
545
	{
546
		isMouseDown = true;
589
		isMouseDown = true;
547
		originalPosition.x = e.x;
590
		originalPosition.x = e.x;
548
		originalPosition.y = e.y;
591
		originalPosition.y = e.y;
549
	}
592
	}
550
593
551
594
	public void mouseUp(MouseEvent e) {
552
	public void mouseUp(MouseEvent e)
553
	{
554
		isMouseDown = false;
595
		isMouseDown = false;
555
	}
596
	}
556
597
557
558
	/**
598
	/**
559
	 * Move the dialog box when the user clicks on the shell and moves the cursor
599
	 * Move the dialog box when the user clicks on the shell and moves the
600
	 * cursor
560
	 */
601
	 */
561
	public void mouseMove(MouseEvent e)
602
	public void mouseMove(MouseEvent e) {
562
	{
603
		if (isMouseDown) {
563
		if (isMouseDown)
564
		{
565
			int xMove = e.x - originalPosition.x;
604
			int xMove = e.x - originalPosition.x;
566
			int yMove = e.y - originalPosition.y;
605
			int yMove = e.y - originalPosition.y;
567
			
606
568
			Point currentLocation = sShell.getLocation();
607
			Point currentLocation = sShell.getLocation();
569
			sShell.setLocation(currentLocation.x + xMove, currentLocation.y + yMove);
608
			sShell.setLocation(currentLocation.x + xMove, currentLocation.y
609
					+ yMove);
570
			lastLocation = sShell.getLocation();
610
			lastLocation = sShell.getLocation();
571
		}		
611
		}
572
	}
612
	}
573
613
574
	/**
614
	/**
575
	 * Updates the status of the control dialog center
615
	 * Updates the status of the control dialog center
576
	 * 
616
	 * 
577
	 * @param status The status to be printed
617
	 * @param status
618
	 *            The status to be printed
578
	 */
619
	 */
579
	public void setStatus (String status)
620
	public void setStatus(String status) {
580
	{	
621
581
		
582
		/* The delegator has to handle this (if one exists) */
622
		/* The delegator has to handle this (if one exists) */
583
		if (isRoot && delegator != null && !delegator.isShellDisposed)
623
		if (isRoot && delegator != null && !delegator.isShellDisposed) {
584
		{
585
			delegator.setStatus(status);
624
			delegator.setStatus(status);
586
			return;
625
			return;
587
		}
626
		}
588
		//added for defect 173451 to ensure that in case where the widget is disposed
627
		// added for defect 173451 to ensure that in case where the widget is
628
		// disposed
589
		// we switch to the correct reference (for Linux platform)
629
		// we switch to the correct reference (for Linux platform)
590
		// Liz Dancy
630
		// Liz Dancy
591
		else if (statuslbl.isDisposed() && delegator.isShellDisposed){
631
		else if (statuslbl.isDisposed() && delegator.isShellDisposed) {
592
			
632
593
			this.updateDelegator(this.realParent, this.realParent);
633
			this.updateDelegator(this.realParent, this.realParent);
594
			statuslbl = this.delegator.statuslbl;
634
			statuslbl = this.delegator.statuslbl;
595
		}	
635
		}
596
		if (status == null)
636
		if (status == null)
597
			return;
637
			return;
598
		
638
599
		lastStatus = status;
639
		lastStatus = status;
600
		String finalStatus = AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_BASE + status;
640
		String finalStatus = AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_BASE
641
				+ status;
601
		boolean toolong = false;
642
		boolean toolong = false;
602
		if (finalStatus.length() > 30)
643
		if (finalStatus.length() > 30)
603
			toolong = true;
644
			toolong = true;
604
		
645
605
	
606
		statuslbl.setToolTipText(finalStatus);
646
		statuslbl.setToolTipText(finalStatus);
607
		if (toolong)
647
		if (toolong)
608
			finalStatus = finalStatus.substring (0, 30) + "...";
648
			finalStatus = finalStatus.substring(0, 30) + "...";
609
			
649
610
		statuslbl.setText (finalStatus);
650
		statuslbl.setText(finalStatus);
611
	}
651
	}
612
	
652
613
	public String getLastStatus()
653
	public String getLastStatus() {
614
	{
615
		if (isRoot && delegator != null)
654
		if (isRoot && delegator != null)
616
			return delegator.getLastStatus();
655
			return delegator.getLastStatus();
617
		return lastStatus;
656
		return lastStatus;
618
	}
657
	}
619
	
658
620
	
621
	/**
659
	/**
622
	 * A primitive listener class
660
	 * A primitive listener class
623
	 */
661
	 */
624
	public interface AutoGUIControllerListener
662
	public interface AutoGUIControllerListener {
625
	{
626
		/**
663
		/**
627
		 * Invoked when there is an event caused by the user interacting with the control center.
664
		 * Invoked when there is an event caused by the user interacting with
665
		 * the control center.
628
		 * 
666
		 * 
629
		 * @param event The event type
667
		 * @param event
630
		 * @param value The value associated with the event.  It can be null if no value is associated with
668
		 *            The event type
631
		 * the event type. 
669
		 * @param value
670
		 *            The value associated with the event. It can be null if no
671
		 *            value is associated with the event type.
632
		 */
672
		 */
633
		public void handleEvent (byte event, Object value);
673
		public void handleEvent(byte event, Object value);
634
	}
674
	}
635
675
636
676
	public void keyPressed(KeyEvent e) {
637
	public void keyPressed(KeyEvent e)
677
		keyReleased(null);
638
	{
639
		keyReleased (null);
640
	}
678
	}
641
679
642
680
	public void keyReleased(KeyEvent e) {
643
	public void keyReleased(KeyEvent e)
681
		if (verificationHookNameText.getText().trim().equals("")) {
644
	{		
682
			verificationHookInsertionButton.setEnabled(false);
645
		if (verificationName.getText().trim().equals(""))
683
			verificationScopeExtensionToolItem.setEnabled(false);
646
		{
647
			insertButton.setEnabled(false);
648
			return;
684
			return;
649
		}
685
		}
650
		insertButton.setEnabled(true);		
686
		verificationHookInsertionButton.setEnabled(true);
687
		verificationScopeExtensionToolItem.setEnabled(true);
651
	}
688
	}
652
	
689
653
	public Point getLastLocation ()
690
	public Point getLastLocation() {
654
	{
655
		if (isRoot && delegator != null)
691
		if (isRoot && delegator != null)
656
			return delegator.getLastLocation();
692
			return delegator.getLastLocation();
657
		if (sShell != null && !sShell.isDisposed())
693
		if (sShell != null && !sShell.isDisposed())
658
			return sShell.getLocation();
694
			return sShell.getLocation();
659
		
695
660
		return lastLocation;
696
		return lastLocation;
661
	}
697
	}
662
	
698
663
	public void setLocation (Point location)
699
	public void setLocation(Point location) {
664
	{
665
		lastLocation = location;
700
		lastLocation = location;
666
	}
701
	}
667
	
702
668
	
669
	public void setPositionBasedOn(boolean isPositionBasedOn) {
703
	public void setPositionBasedOn(boolean isPositionBasedOn) {
670
		this.positionBasedOn = isPositionBasedOn;
704
		this.positionBasedOn = isPositionBasedOn;
671
	}
705
	}
672
706
673
674
	public boolean isPositionBasedOn() {
707
	public boolean isPositionBasedOn() {
675
		return positionBasedOn;
708
		return positionBasedOn;
676
	}
709
	}
677
710
711
	public boolean isVerficationScopeExtended() {
712
		return verificationScopeExtended;
713
	}
678
714
679
	public boolean isWaitTimeOn() {
715
	public boolean isWaitTimeOn() {
680
		return waitTimeOn;
716
		return waitTimeOn;
681
	}
717
	}
682
718
683
684
	public void setWaitTimeOn(boolean waitTimeOn) {
719
	public void setWaitTimeOn(boolean waitTimeOn) {
685
		this.waitTimeOn = waitTimeOn;
720
		this.waitTimeOn = waitTimeOn;
686
	}
721
	}
687
	
722
688
	
723
	public synchronized void updateDelegator(Shell guardian, Shell realParent) {
689
	public synchronized void updateDelegator (Shell guardian, Shell realParent)
724
		updateDelegator(guardian, realParent, null);
690
	{
725
	}
691
		updateDelegator (guardian, realParent, null);
726
692
	}	
727
	public void updateDelegator(Shell guardian, Shell realParent,
693
	
728
			Shell activeShell) {
694
	public void updateDelegator (Shell guardian, Shell realParent, Shell activeShell)
695
	{
696
		if (guardian.isDisposed())
729
		if (guardian.isDisposed())
697
			return;
730
			return;
698
		
731
699
		Point location = getLastLocation();	
732
		Point location = getLastLocation();
700
		String lastStatus = getLastStatus();
733
		String lastStatus = getLastStatus();
701
		
734
702
		AutoGUITestControllerDialog rootControl = null;
735
		AutoGUITestControllerDialog rootControl = null;
703
		if (isRoot)
736
		if (isRoot)
704
			rootControl = this;
737
			rootControl = this;
705
		
738
706
		else
739
		else
707
			rootControl = this.rootControl;
740
			rootControl = this.rootControl;
708
		
741
709
		AutoGUITestControllerDialog delegator = rootControl.getDelegator();
742
		AutoGUITestControllerDialog delegator = rootControl.getDelegator();
710
		/* Get rid of the last delegator */					
743
		/* Get rid of the last delegator */
711
		if (activeControlDialog != null ){
744
		if (activeControlDialog != null) {
712
			activeControlDialog.dispose();
745
			activeControlDialog.dispose();
713
			
746
714
		}
747
		}
715
		
748
716
		delegator = new AutoGUITestControllerDialog(guardian, AutoGUITestControllerDialog.this);																
749
		delegator = new AutoGUITestControllerDialog(guardian,
750
				AutoGUITestControllerDialog.this);
717
		delegator.setLocation(location);
751
		delegator.setLocation(location);
718
		delegator.setPositionBasedOn(isPositionBasedOn());
752
		delegator.setPositionBasedOn(isPositionBasedOn());
719
		delegator.setWaitTimeOn(isWaitTimeOn());
753
		delegator.setWaitTimeOn(isWaitTimeOn());
720
		delegator.openDialog(activeShell);
754
		delegator.openDialog(activeShell);
721
		delegator.setStatus(lastStatus);	
755
		delegator.setStatus(lastStatus);
722
		delegator.actualParent = guardian;
756
		delegator.actualParent = guardian;
723
		delegator.realParent = realParent;
757
		delegator.realParent = realParent;
724
		
758
725
		rootControl.setDelegator(delegator);
759
		rootControl.setDelegator(delegator);
726
	}
760
	}
727
	
761
728
	public AutoGUITestControllerDialog getDelegator()
762
	public AutoGUITestControllerDialog getDelegator() {
729
	{
730
		return delegator;
763
		return delegator;
731
	}
764
	}
732
	
765
733
	public void setDelegator(AutoGUITestControllerDialog delegator)
766
	public void setDelegator(AutoGUITestControllerDialog delegator) {
734
	{
735
		this.delegator = delegator;
767
		this.delegator = delegator;
736
	}
768
	}
737
	
769
738
	
770
	private class DisplayListener implements Listener {
739
	private class DisplayListener implements Listener
771
		public void handleEvent(final Event event) {
740
	{
772
741
		public void handleEvent(final Event event) 
773
			class ChangeDialogParentOp implements Runnable {
742
		{				
743
				
744
			class ChangeDialogParentOp implements Runnable
745
			{
746
				private DisplayListener listener;
774
				private DisplayListener listener;
747
				public ChangeDialogParentOp(DisplayListener listener)
775
748
				{
776
				public ChangeDialogParentOp(DisplayListener listener) {
749
					this.listener = listener;
777
					this.listener = listener;
750
				}
778
				}
751
				
779
752
				public void run() 
780
				public void run() {
753
				{
781
					try {
754
					try
755
					{
756
						if (forceToBack)
782
						if (forceToBack)
757
							return;
783
							return;
758
						
784
759
						boolean isNewShellPresent = event.widget instanceof Shell && 										/* The widget is a shell */
785
						boolean isNewShellPresent = event.widget instanceof Shell
760
													!event.widget.isDisposed() && 											/* It hasn't been disposed */
786
								&& /* The widget is a shell */
761
													event.widget.getData(MacroManager.IGNORE) == null &&  					/* It shouldn't be ignored */
787
								!event.widget.isDisposed()
762
													(realParent.isDisposed() || !event.widget.equals(realParent)) &&		/* It's not the current shell that we have as our parent */
788
								&& /* It hasn't been disposed */
763
													!isComboBox(actualParent = (Shell)event.widget);						/* It's not a combo box */
789
								event.widget.getData(MacroManager.IGNORE) == null
790
								&& /* It shouldn't be ignored */
791
								(realParent.isDisposed() || !event.widget
792
										.equals(realParent))
793
								&& /*
794
									 * It's not the current shell that we have
795
									 * as our parent
796
									 */
797
								!isComboBox(actualParent = (Shell) event.widget); /*
798
																					 * It's
799
																					 * not
800
																					 * a
801
																					 * combo
802
																					 * box
803
																					 */
764
						if (!isNewShellPresent)
804
						if (!isNewShellPresent)
765
							return;
805
							return;
806
						// need to check for activated
807
						// bugzilla_184767
808
						// Liz Dancy
809
						if (activated)
810
							updateDelegator(actualParent, actualParent,
811
									actualParent);
766
812
767
						updateDelegator (actualParent, actualParent, actualParent);
768
						
769
						if (actualParent != rootParent)
813
						if (actualParent != rootParent)
770
							activated = true;
814
							activated = true;
771
						AutoGUITestControllerDialog.this.realParent = actualParent;
815
						AutoGUITestControllerDialog.this.realParent = actualParent;
772
					}
816
					}
773
817
774
					catch (Throwable t)
818
					catch (Throwable t) {
775
					{
819
						/*
776
						/* If at any point an error occurs, then de-register this listener */
820
						 * If at any point an error occurs, then de-register
777
						Display.getCurrent().removeFilter(SWT.Activate, listener);
821
						 * this listener
822
						 */
823
						Display.getCurrent().removeFilter(SWT.Activate,
824
								listener);
778
					}
825
					}
779
				
826
780
				}
827
				}
781
828
782
				private boolean isComboBox(Shell shell) 
829
				private boolean isComboBox(Shell shell) {
783
				{
784
					Control[] children = shell.getChildren();
830
					Control[] children = shell.getChildren();
785
					return children.length == 1 && children[0] instanceof List;
831
					return children.length == 1 && children[0] instanceof List;
786
				}
832
				}
787
			};
833
			}
788
		
834
			;
789
			/* We need to run this as a timer operation because it may otherwise cause a widget disposed exeception.  The exception
790
			 * is caused in cases where we get an activation event on shells that are activated only for short periods of time.  Running
791
			 * this operation as a timer operation will guarantee that an activated shell is present and not disposed after 50 milliseconds.  
792
			 * This ultimately avoids processing activated shells that have a very short life span. */
793
			GuiPlugin.getDefault().getWorkbench().getDisplay().timerExec(50, new ChangeDialogParentOp(this));
794
		}		
795
	}
796
835
836
			/*
837
			 * We need to run this as a timer operation because it may otherwise
838
			 * cause a widget disposed exeception. The exception is caused in
839
			 * cases where we get an activation event on shells that are
840
			 * activated only for short periods of time. Running this operation
841
			 * as a timer operation will guarantee that an activated shell is
842
			 * present and not disposed after 50 milliseconds. This ultimately
843
			 * avoids processing activated shells that have a very short life
844
			 * span.
845
			 */
846
			GuiPlugin.getDefault().getWorkbench().getDisplay().timerExec(50,
847
					new ChangeDialogParentOp(this));
848
		}
849
	}
797
850
798
	public class ActivationListener implements Listener
851
	public class ActivationListener implements Listener {
799
	{
800
		private boolean enable;
852
		private boolean enable;
801
		
853
802
		public ActivationListener(boolean enable)
854
		public ActivationListener(boolean enable) {
803
		{
804
			this.enable = enable;
855
			this.enable = enable;
805
		}
856
		}
806
		
857
807
		
858
		public void handleEvent(Event event) {
808
		public void handleEvent(Event event)
809
		{
810
			if (!enable)
859
			if (!enable)
811
				return;
860
				return;
812
			
861
813
			
862
			switch (event.type) {
814
			switch (event.type)
863
			case SWT.Activate:
815
			{
864
				controlCenterDialogActivated();
816
				case SWT.Activate:
865
				break;
817
					controlCenterDialogActivated();
866
			case SWT.Deactivate:
818
					break;
867
				controlCenterDialogDeactivated();
819
				case SWT.Deactivate:
868
				break;
820
					controlCenterDialogDeactivated();
821
					break;				
822
			}
869
			}
823
			
870
824
		}
871
		}
825
872
826
		private void controlCenterDialogActivated() 
873
		private void controlCenterDialogActivated() {
827
		{								
874
			/*
828
			/* If the parent of the control center dialog is a modal dialog but it was sent back, then we'll need to 
875
			 * If the parent of the control center dialog is a modal dialog but
829
			 * bring the control center dialog to the front */			
876
			 * it was sent back, then we'll need to bring the control center
830
			if (isModalParent() && actualParent == rootParent && !activated)
877
			 * dialog to the front
831
			{	
878
			 */
832
				activated = true;
879
			if (isModalParent() && actualParent == rootParent && !activated) {
880
				activated = false;
833
				forceToBack = false;
881
				forceToBack = false;
834
				enable = false;
882
				enable = false;
835
				updateDelegator (realParent, realParent);
883
				updateDelegator(realParent, realParent);
836
				enable = true;
884
				enable = true;
837
				
885
838
			}
886
			}
839
			
887
840
		}
888
		}
841
		
889
842
		private void controlCenterDialogDeactivated() 
890
		private void controlCenterDialogDeactivated() {
843
		{	
891
			/*
844
			/* If the parent of the control center dialog is modal, then we need to send it back */			
892
			 * If the parent of the control center dialog is modal, then we need
845
			if (isModalParent() && actualParent == realParent && activated)
893
			 * to send it back
846
			{
894
			 */
895
			if (isModalParent() && actualParent == realParent && activated) {
847
				activated = false;
896
				activated = false;
848
				forceToBack = true;
897
				forceToBack = true;
849
				enable = false;		
898
				enable = false;
850
				
899
851
				Shell realParent = null;
900
				Shell realParent = null;
852
				if (delegator != null){
901
				if (delegator != null) {
853
					realParent = delegator.realParent;
902
					realParent = delegator.realParent;
854
				}
903
				} else
855
				else 
856
					realParent = AutoGUITestControllerDialog.this.realParent;
904
					realParent = AutoGUITestControllerDialog.this.realParent;
857
					
858
				updateDelegator(rootParent, realParent, realParent);
905
				updateDelegator(rootParent, realParent, realParent);
859
				
906
860
				
861
				enable = true;
907
				enable = true;
862
			}
908
			}
863
		}
909
		}
864
910
865
911
		private boolean isModalParent() {
866
		private boolean isModalParent()
867
		{
868
			if (realParent == null || realParent.isDisposed())
912
			if (realParent == null || realParent.isDisposed())
869
				return false;
913
				return false;
870
			
914
871
			int parentStyle = realParent.getStyle();
915
			int parentStyle = realParent.getStyle();
872
			return 	(parentStyle & SWT.SYSTEM_MODAL) != 0 ||
916
			return (parentStyle & SWT.SYSTEM_MODAL) != 0
873
					(parentStyle & SWT.PRIMARY_MODAL) != 0 || 
917
					|| (parentStyle & SWT.PRIMARY_MODAL) != 0
874
					(parentStyle & SWT.APPLICATION_MODAL) != 0;
918
					|| (parentStyle & SWT.APPLICATION_MODAL) != 0;
875
		}
919
		}
876
		
920
877
		private void setEnable (boolean enable)
921
		private void setEnable(boolean enable) {
878
		{
879
			this.enable = enable;
922
			this.enable = enable;
880
		}
923
		}
881
		
924
882
	}
925
	}
883
}
926
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/codegen/AutoGUIGenerator.java (-4 / +4 lines)
Lines 38-43 Link Here
38
 * The code generator for auto gui test suites 
38
 * The code generator for auto gui test suites 
39
 * 
39
 * 
40
 * @author Ali Mehregani
40
 * @author Ali Mehregani
41
 * @author Alexander Nyssen
41
 */
42
 */
42
public class AutoGUIGenerator extends JavaGenerator
43
public class AutoGUIGenerator extends JavaGenerator
43
{
44
{
Lines 101-107 Link Here
101
	 * @param argument The argument of the method (see restriction above)
102
	 * @param argument The argument of the method (see restriction above)
102
	 * @throws Exception 
103
	 * @throws Exception 
103
	 */
104
	 */
104
	public void createMethod (String methodName, String argument) throws Exception
105
	public void createMethod (String methodName, String[] arguments) throws Exception
105
	{
106
	{
106
		IFile javaFile = getFileHandle(getTestSuite());
107
		IFile javaFile = getFileHandle(getTestSuite());
107
		ICompilationUnit cu = JavaCore.createCompilationUnitFrom(javaFile);
108
		ICompilationUnit cu = JavaCore.createCompilationUnitFrom(javaFile);
Lines 117-124 Link Here
117
		
118
		
118
		
119
		
119
		cu.becomeWorkingCopy(null, new NullProgressMonitor());
120
		cu.becomeWorkingCopy(null, new NullProgressMonitor());
120
		String[] args = {argument};
121
		IMethod method = mainClass.getMethod(methodName, arguments);
121
		IMethod method = mainClass.getMethod(methodName, args);
122
		
122
		
123
		try
123
		try
124
		{
124
		{
Lines 128-134 Link Here
128
				Helper helper = new Helper();
128
				Helper helper = new Helper();
129
				String packageName = helper.getPackageName(getTestSuite());
129
				String packageName = helper.getPackageName(getTestSuite());
130
				helper.setImportManager(new ImportManager(packageName));
130
				helper.setImportManager(new ImportManager(packageName));
131
				method = createTestMethod(mainClass, testCaseName, testCaseDescription, helper, methodName, args);
131
				method = createTestMethod(mainClass, testCaseName, testCaseDescription, helper, methodName, arguments);
132
				
132
				
133
				helper.emitSortedImports(cu);
133
				helper.emitSortedImports(cu);
134
134
(-)src/org/eclipse/tptp/test/auto/gui/internal/codegen/AutoGUILaunchGenerator.java (-6 / +6 lines)
Lines 35-44 Link Here
35
import org.eclipse.hyades.test.tools.core.internal.common.codegen.Helper;
35
import org.eclipse.hyades.test.tools.core.internal.common.codegen.Helper;
36
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
36
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
37
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
37
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
38
import org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine;
39
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
38
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
40
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
39
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
41
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMineManager;
40
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine;
41
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMineManager;
42
42
43
43
44
/**
44
/**
Lines 108-120 Link Here
108
	 * @param objectMine The object mine
108
	 * @param objectMine The object mine
109
	 * @param buffer The buffer that will be used to write the object mine to
109
	 * @param buffer The buffer that will be used to write the object mine to
110
	 */
110
	 */
111
	private static void serializeObjectMine(IObjectMine objectMine, StringBuffer buffer)
111
	private static void serializeObjectMine(MacroObjectDescriptorMine objectMine, StringBuffer buffer)
112
	{
112
	{
113
		/* Walk through each of the included object mines of the test suite */
113
		/* Walk through each of the included object mines of the test suite */
114
		List includes = objectMine.getIncludes();
114
		List includes = objectMine.getIncludes();
115
		for (int i = 0, includeCount = includes.size(); i < includeCount; i++)
115
		for (int i = 0, includeCount = includes.size(); i < includeCount; i++)
116
		{
116
		{
117
			serializeObjectMine((IObjectMine)includes.get(i), buffer);
117
			serializeObjectMine((MacroObjectDescriptorMine)includes.get(i), buffer);
118
		}
118
		}
119
		
119
		
120
		/* Add the object that have been directly registered with the object mine passed in */
120
		/* Add the object that have been directly registered with the object mine passed in */
Lines 124-133 Link Here
124
124
125
	private static String resolveObjectMine(ITestSuite testSuite)
125
	private static String resolveObjectMine(ITestSuite testSuite)
126
	{
126
	{
127
		IObjectMine objectMine = null;
127
		MacroObjectDescriptorMine objectMine = null;
128
		try
128
		try
129
		{
129
		{
130
			objectMine = ObjectMineManager.getInstance().loadObjectMine(testSuite);
130
			objectMine = MacroObjectDescriptorMineManager.getInstance().loadObjectMine(testSuite);
131
		} 
131
		} 
132
		catch (Exception e)
132
		catch (Exception e)
133
		{
133
		{
(-)src/org/eclipse/tptp/test/auto/gui/internal/codegen/VerificationHookMethodGenerator.java (-11 lines)
Lines 1-14 Link Here
1
/**********************************************************************
2
 * Copyright (c) 2007, 2008 IBM Corporation and others.
3
 * All rights reserved.   This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * $Id: VerificationHookMethodGenerator.java,v 1.18 2008/04/18 20:32:50 paules Exp $
8
 * 
9
 * Contributors: 
10
 * IBM Corporation - initial API and implementation
11
 **********************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.codegen;
1
package org.eclipse.tptp.test.auto.gui.internal.codegen;
13
2
14
import org.eclipse.hyades.test.tools.core.internal.common.codegen.Helper;
3
import org.eclipse.hyades.test.tools.core.internal.common.codegen.Helper;
(-)src/org/eclipse/tptp/test/auto/gui/internal/codegen/TestSuiteToXMLConvertor.java (-11 lines)
Lines 1-14 Link Here
1
/**********************************************************************
2
 * Copyright (c) 2007, 2008 IBM Corporation and others.
3
 * All rights reserved.   This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * $Id: TestSuiteToXMLConvertor.java,v 1.19 2008/04/18 20:32:50 paules Exp $
8
 * 
9
 * Contributors: 
10
 * IBM Corporation - initial API and implementation
11
 **********************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.codegen;
1
package org.eclipse.tptp.test.auto.gui.internal.codegen;
13
2
14
import java.util.HashSet;
3
import java.util.HashSet;
(-)src/org/eclipse/tptp/test/auto/gui/internal/codegen/VerificationHookClassGenerator.java (-11 lines)
Lines 1-14 Link Here
1
/**********************************************************************
2
 * Copyright (c) 2007, 2008 IBM Corporation and others.
3
 * All rights reserved.   This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * $Id: VerificationHookClassGenerator.java,v 1.17 2008/04/18 20:32:50 paules Exp $
8
 * 
9
 * Contributors: 
10
 * IBM Corporation - initial API and implementation
11
 **********************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.codegen;
1
package org.eclipse.tptp.test.auto.gui.internal.codegen;
13
2
14
import org.eclipse.hyades.models.common.facades.behavioral.ITestSuite;
3
import org.eclipse.hyades.models.common.facades.behavioral.ITestSuite;
(-)src/org/eclipse/tptp/test/auto/gui/internal/editor/AutoGUIObjectMineTreeStructure.java (-537 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006, 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.editor;
12
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.Iterator;
16
import java.util.List;
17
18
import org.eclipse.core.runtime.IStatus;
19
import org.eclipse.emf.ecore.EStructuralFeature;
20
import org.eclipse.hyades.models.common.facades.behavioral.ITestSuite;
21
import org.eclipse.hyades.models.common.facades.behavioral.impl.HyadesUtil;
22
import org.eclipse.hyades.test.common.util.XMLUtil;
23
import org.eclipse.hyades.test.ui.adapter.TestWorkbenchAdapter;
24
import org.eclipse.hyades.test.ui.internal.editor.form.util.EObjectTreeContentProvider;
25
import org.eclipse.hyades.ui.editor.IEditorExtension;
26
import org.eclipse.hyades.ui.internal.provider.WorkbenchAdapterLabelProvider;
27
import org.eclipse.jface.action.Action;
28
import org.eclipse.jface.action.IMenuManager;
29
import org.eclipse.jface.dialogs.IDialogConstants;
30
import org.eclipse.jface.resource.ImageDescriptor;
31
import org.eclipse.jface.viewers.IContentProvider;
32
import org.eclipse.jface.viewers.ILabelProvider;
33
import org.eclipse.jface.viewers.IStructuredSelection;
34
import org.eclipse.jface.viewers.Viewer;
35
import org.eclipse.osgi.util.NLS;
36
import org.eclipse.swt.SWT;
37
import org.eclipse.swt.graphics.Image;
38
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIImages;
39
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
40
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
41
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
42
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
43
import org.eclipse.tptp.test.auto.gui.internal.core.IObjectMine;
44
import org.eclipse.tptp.test.auto.gui.internal.core.IUIObject;
45
import org.eclipse.tptp.test.auto.gui.internal.dialogs.AutoGUITestSuiteDialog;
46
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCaseTreeStructure.MessageUIElement;
47
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
48
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMineManager;
49
50
/**
51
 * Represents the object mine tree that is displayed in the test
52
 * case page of the editor.
53
 * 
54
 * @author      Ali Mehregani
55
 * @author      Paul E. Slauenwhite
56
 * @version     March 7, 2008
57
 * @since       July 10, 2006
58
 */
59
public class AutoGUIObjectMineTreeStructure extends AutoGUIAbstractTreeStructure
60
{
61
	/** Represents the root element in the object mine tree */
62
	private static final RootUIObjectMineTreeNode ROOT_ELEMENT = new RootUIObjectMineTreeNode();
63
64
	/** The test case form */
65
	private AutoGUITestCasesForm testCaseForm;
66
67
	/** The content provider */
68
	private ObjectMineTreeContentProvider contentProvider;
69
	
70
	/** The label provider */
71
	private ObjectMineLabelProvider labelProvider;
72
	
73
	/** The line number and offset relation.  The index of the list represents the line
74
	 * number and the value is an object of type Integer[0] indicating the start
75
	 * and end offset */
76
	private List lineOffsetRelation;
77
	
78
	/** The include object mine menu item */
79
	private IncludeObjectMineAction includeObjectMineAction;
80
	
81
	/** Change output menu item */
82
	private ChangeOutputAction changeOutputAction;
83
			
84
	/** Keeps track of the test suite used as input */
85
	private ITestSuite testSuiteInput;
86
	
87
	/** Stores any error that occurred while loading the object mine */
88
	private Object[] error;
89
	
90
	public AutoGUIObjectMineTreeStructure(AutoGUITestCasesForm testCaseForm, IEditorExtension editorPart)
91
	{
92
		super(editorPart, null);
93
		this.testCaseForm = testCaseForm;
94
		lineOffsetRelation = new ArrayList();
95
		includeObjectMineAction = new IncludeObjectMineAction();
96
		changeOutputAction = new ChangeOutputAction();
97
	}
98
	
99
	/**
100
	 * Overwrite this method so that a custom content provider can be 
101
	 * registered with the tree
102
	 */
103
	protected IContentProvider createContentProvider()
104
	{
105
		if (contentProvider == null)
106
			contentProvider = new ObjectMineTreeContentProvider(editorPart, getEStructuralFeature());
107
		return contentProvider;
108
	}
109
		
110
	
111
	/**
112
	 * Overwrite this method so that a custom label provider can be 
113
	 * registered with the tree
114
	 * 
115
	 * @return The label provider for the object mine tree
116
	 */
117
	protected ILabelProvider createLabelProvider()
118
	{
119
		if (labelProvider == null)
120
			labelProvider = new ObjectMineLabelProvider(TestWorkbenchAdapter.class);
121
		return labelProvider;
122
	}
123
124
	
125
	
126
	/**
127
	 * Overwrite this method so that custom buttons can be added beside the 
128
	 * object mine tree.
129
	 */
130
	protected void adjustButtonLabels(String addLabel)
131
	{
132
		setButtonLabels (new String[0]);
133
	}
134
	
135
	
136
	/**
137
	 * Need to overwrite this method since there are no buttons whose status need
138
	 * to be updated.
139
	 */
140
	protected void updateActionsAndButtons(IStructuredSelection structuredSelection)
141
	{
142
		/* purposely left blank */
143
	}
144
	
145
	
146
	/**
147
	 * Refreshes the content of this tree by forcing the test suite to reload its
148
	 * object mine.
149
	 */
150
	public void refresh()
151
	{
152
		ObjectMineManager.getInstance().clearCache();
153
		loadObjectMine(testSuiteInput, false);
154
		getTreeViewer().refresh();
155
	}
156
	
157
	
158
	public List getLineOffsetRelation()
159
	{
160
		return lineOffsetRelation;
161
	}
162
	
163
	
164
	/**
165
	 * Needs to be overwritten to modify the default tree style 
166
	 */
167
	public int getTreeStryle()
168
	{
169
		return super.getTreeStryle() | SWT.BORDER;
170
	}
171
	
172
	
173
	private Object[] createErrorItem(String prefix, Exception e)
174
	{
175
		Throwable cause = AutoGUIUtil.findCause(e);
176
		prefix += prefix == null ? "": ": ";
177
		prefix += (cause.getMessage() == cause.getClass().getName() ? "" : " " + cause.getMessage());
178
		prefix += ": " + e.getStackTrace()[0].getClassName() + ":" + e.getStackTrace()[0].getLineNumber(); 
179
		return new Object[]{new MessageUIElement(IStatus.ERROR, prefix)};
180
	}
181
	
182
	
183
	/**
184
	 * Overwrite this method so that custom menu items can be added to the entries that are
185
	 * displayed in the object mine tree.
186
	 * 
187
	 * @param menuManager The menu manager
188
	 */
189
	protected void fillContextMenu(IMenuManager menuManager)
190
	{
191
		IStructuredSelection selection = getStructuredSelection();
192
		if (!selection.isEmpty() && selection.size() == 1 && selection.getFirstElement() instanceof RootUIObjectMineTreeNode)
193
		{
194
			menuManager.add(includeObjectMineAction);
195
			menuManager.add(changeOutputAction);
196
		}
197
	}
198
	
199
	
200
	private IObjectMine loadObjectMine(ITestSuite testSuite, boolean showError)
201
	{
202
		IObjectMine input = null;
203
		if (testSuite == null)
204
		{
205
			testSuiteInput = null;				
206
			return null;
207
		}
208
		
209
		try
210
		{				
211
			testSuiteInput =(ITestSuite)testSuite;
212
			input = ObjectMineManager.getInstance().loadObjectMine(testSuiteInput);
213
			String objectMineXML = HyadesUtil.getTestSuiteVariable(testSuiteInput, GlobalConstants.TEST_SUITE_PROPERTY_OBJECT_MINE);
214
			lineOffsetRelation = AutoGUIObjectMineTreeStructure.this.findLineOffsetIndicator(objectMineXML);
215
			error = null;
216
		}
217
		catch (Exception e)
218
		{	
219
			if (showError)
220
			{
221
				AutoGUIUtil.openErrorWithDetail(
222
						AutoGUIMessages.AUTO_GUI_COMMON_ERROR, 
223
						AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE + ": " + testSuite.getName(), 
224
						e);
225
			}
226
			else
227
			{
228
				error = createErrorItem(AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE, e);
229
			}
230
			
231
			input = null;
232
		}
233
		
234
		return input;
235
	}
236
	
237
	
238
	/**
239
	 * The content provider for the object mine tree.
240
	 * 
241
	 * @author Ali Mehregani
242
	 */
243
	private class ObjectMineTreeContentProvider extends EObjectTreeContentProvider
244
	{				
245
		public ObjectMineTreeContentProvider(IEditorExtension editorPart, EStructuralFeature eStructuralFeature)
246
		{
247
			super(editorPart, eStructuralFeature);
248
		}		
249
250
		public Object[] getElements(Object inputElement)
251
		{			
252
			return new Object[]{ROOT_ELEMENT};
253
		}
254
255
		
256
		/**
257
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
258
		 */
259
		public Object[] getChildren(Object parentElement)
260
		{	
261
			IObjectMine input = loadObjectMine(testSuiteInput, false);
262
			if (input == null)
263
			{	
264
				if (parentElement == ROOT_ELEMENT && error != null)
265
					return error;		
266
			}
267
			
268
			/* If the test suite doesn't have an object mine then return an empty list */
269
			String objectMineXML = null;
270
			if (testSuiteInput == null || (objectMineXML = HyadesUtil.getTestSuiteVariable(testSuiteInput, GlobalConstants.TEST_SUITE_PROPERTY_OBJECT_MINE)) == null || objectMineXML.length() <= 0)
271
				return null;
272
273
274
			if (parentElement == ROOT_ELEMENT)
275
			{
276
				return input.getChildren();
277
			}
278
			else if (parentElement instanceof IUIObject)
279
			{
280
				return ((IUIObject)parentElement).getChildren();
281
			}
282
						
283
			return null;
284
		}
285
	
286
287
		public boolean hasChildren(Object parentElement)
288
		{
289
			IObjectMine input = loadObjectMine(testSuiteInput, false);
290
			if (parentElement == ROOT_ELEMENT)
291
			{
292
				return input == null ? error != null : input.getChildren().length > 0;
293
			}
294
			else if (parentElement instanceof IUIObject)
295
			{
296
				return ((IUIObject)parentElement).childCount() > 0;
297
			}
298
			
299
			return false;
300
		}
301
		
302
		/**
303
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
304
		 */
305
		public Object getParent(Object element)
306
		{
307
			if (element instanceof IUIObject)
308
			{
309
				IUIObject parent = ((IUIObject)element).getParent(); 
310
				return parent == null ? (Object)ROOT_ELEMENT : parent;
311
			}
312
			return null;
313
		}
314
		
315
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
316
		{
317
			if (!(newInput instanceof ITestSuite))
318
				return;
319
			
320
			loadObjectMine((ITestSuite)newInput, false);
321
322
		}
323
	}
324
	
325
	
326
	private class ObjectMineLabelProvider extends WorkbenchAdapterLabelProvider
327
	{
328
329
		public ObjectMineLabelProvider(Class cl) throws IllegalArgumentException
330
		{
331
			super(cl);
332
		}
333
		
334
	    public String getText(Object element)
335
	    {
336
	    	if (element == ROOT_ELEMENT)
337
	    	{
338
	    		return AutoGUIMessages.TST_SUITE_AUTO_MACRO_OBJ_MINE;
339
	    	}
340
	    	else if (element instanceof IUIObject)
341
	    	{
342
	    		String descriptiveField = ((IUIObject)element).getDescriptive();
343
	    		return descriptiveField == null ? AutoGUIMessages.TST_SUITE_AUTO_MACRO_OBJ_OBJECT : XMLUtil.removeXMLSymbols(descriptiveField);
344
	    	}
345
	    	else if (element instanceof MessageUIElement)
346
	    	{
347
	    		String message = ((MessageUIElement)element).getText();	    		
348
	    		return message == null ? AutoGUIMessages.TST_SUITE_AUTO_MACRO_MESSAGE : message;
349
	    	}
350
	    	
351
	    	return MacroConstants.EMPTY_STRING;	    	
352
	    }
353
		
354
	    public Image getImage(Object element)
355
	    {	    	
356
	    	if (element == ROOT_ELEMENT)
357
	    	{
358
	    		return AutoGUIImages.getInstance().getImage(AutoGUIImages.OBJECT_MINE);
359
	    	}
360
	    	else if (element instanceof IUIObject)
361
	    	{
362
	    		IUIObject parent  = ((IUIObject)element).getParent();
363
	    		return parent == null ? AutoGUIImages.getInstance().getImage(AutoGUIImages.SHELL) : AutoGUIImages.getInstance().getImage(AutoGUIImages.WIDGET);
364
	    	}
365
	    	else if (element instanceof MessageUIElement)
366
	    	{
367
	    		return ((MessageUIElement)element).getIcon();
368
	    	}
369
	    	
370
	    	return null;
371
	    }
372
	}
373
	
374
	
375
	/**
376
	 * A dummy class that represents the root element in the object mine
377
	 * tree.
378
	 */
379
	private static class RootUIObjectMineTreeNode
380
	{	
381
	}
382
	
383
	
384
	/**
385
	 * The include object mine action.  The purpose of this action is to allow
386
	 * the user to include object mines under the test suite's object mine
387
	 * 
388
	 * @author Ali Mehregani
389
	 */
390
	private class IncludeObjectMineAction extends Action
391
	{
392
		/**
393
		 * Perform the action.
394
		 * 
395
		 */
396
		public void run() 
397
		{			
398
			/* Display the test suite list dialog */
399
			AutoGUITestSuiteDialog autoGUITestSuiteDialog = new AutoGUITestSuiteDialog(
400
					GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(), 
401
					testSuiteInput, 
402
					AutoGUIMessages.AUTO_GUI_TST_DIALOG_TREE_ITITLE, 
403
					false);
404
			
405
			if(autoGUITestSuiteDialog.open() == IDialogConstants.CANCEL_ID)
406
				return;
407
			
408
			
409
			/* Get the selected test suites and include them as part of this test suite's object mine */
410
			Collection tests = autoGUITestSuiteDialog.getTests();
411
			IObjectMine input = loadObjectMine(testSuiteInput, true);
412
			boolean markdirty = false;
413
			for (Iterator testIterator = tests.iterator(); testIterator.hasNext();)
414
			{
415
				Object currentTestSuite = testIterator.next();
416
				if (!(currentTestSuite instanceof ITestSuite))
417
					continue;
418
							
419
				ITestSuite testSuite = (ITestSuite)currentTestSuite;
420
				try
421
				{
422
					IObjectMine objectMine = ObjectMineManager.getInstance().loadObjectMine(testSuite);
423
					if (objectMine != null && !input.getIncludes().contains(objectMine))
424
					{
425
						markdirty = true;
426
						input.addInclude(objectMine);
427
					}						
428
				} 
429
				catch (Exception e)
430
				{
431
					/* Display an error */
432
					AutoGUIUtil.openErrorWithDetail(
433
							AutoGUIMessages.AUTO_GUI_COMMON_ERROR, 
434
							NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_DIALOG_TST_INCL, testSuite.getName()), 
435
							e);
436
				} 
437
			}
438
			
439
			if (markdirty)
440
			{
441
				testCaseForm.updateTestProperty(null, input.serializeToString(), true);
442
				getTreeViewer().setSelection(getTreeViewer().getSelection());
443
			}
444
		}
445
		
446
		
447
		public boolean isEnabled() 
448
		{
449
			return testSuiteInput != null;
450
		}
451
		
452
		public String getText() 
453
		{
454
			return AutoGUIMessages.AUTO_GUI_TST_DIALOG_TREE_INCL;
455
		}
456
		
457
		public ImageDescriptor getImageDescriptor() 
458
		{
459
			return AutoGUIImages.getInstance().getImageDescriptor("e", AutoGUIImages.INCLUDE);
460
		}
461
	}
462
	
463
	
464
	/**
465
	 * This action changes the output of the object mine to another test suite.
466
	 * 
467
	 * @author Ali Mehregani
468
	 */
469
	private class ChangeOutputAction extends Action
470
	{
471
		/**
472
		 * Perform the action.
473
		 */
474
		public void run() 
475
		{			
476
			/* Display the test suite list dialog */
477
			AutoGUITestSuiteDialog autoGUITestSuiteDialog = new AutoGUITestSuiteDialog(
478
					GuiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell(), 
479
					testSuiteInput, 
480
					AutoGUIMessages.AUTO_GUI_TST_DIALOG_TREE_ITITLE, 
481
					true);
482
			
483
			if(autoGUITestSuiteDialog.open() == IDialogConstants.CANCEL_ID)
484
				return;
485
			
486
			
487
			/* Get the selected test suites and include them as part of this test suite's object mine */
488
			Collection tests = autoGUITestSuiteDialog.getTests();			
489
			if (tests == null)
490
				return;
491
			
492
			Object[] selectedTestContainer = tests.toArray();
493
			if (selectedTestContainer.length != 1 || !(selectedTestContainer[0] instanceof ITestSuite))
494
				return;
495
			
496
			IObjectMine input = loadObjectMine(testSuiteInput, true);
497
			IObjectMine oldOutputObjectMine = input.getOutputSource();
498
			ITestSuite oldOutput = oldOutputObjectMine == null ? null : oldOutputObjectMine.getOwner();
499
			ITestSuite newOutput = (ITestSuite)selectedTestContainer[0];			
500
			if (oldOutput == null || (!oldOutput.getId().equals(newOutput.getId())))
501
			{
502
				IObjectMine objectMine = null;
503
				try
504
				{
505
					objectMine = ObjectMineManager.getInstance().loadObjectMine(newOutput);
506
					input.setOutputSource(objectMine);
507
					testCaseForm.updateTestProperty(null, input.serializeToString(), true);
508
					getTreeViewer().setSelection(getTreeViewer().getSelection());
509
				} 
510
				catch (Exception e)
511
				{
512
					input.setOutputSource(null);
513
					AutoGUIUtil.openErrorWithDetail(
514
							AutoGUIMessages.AUTO_GUI_COMMON_ERROR, 
515
							NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_OBJ_MINE_OUTPUT, newOutput.getName()), 
516
							e);
517
				} 
518
			}						
519
		}
520
		
521
		
522
		public boolean isEnabled() 
523
		{
524
			return testSuiteInput != null;
525
		}
526
		
527
		public String getText() 
528
		{
529
			return AutoGUIMessages.AUTO_GUI_TST_DIALOG_TREE_OUPUT;
530
		}
531
		
532
		public ImageDescriptor getImageDescriptor() 
533
		{
534
			return AutoGUIImages.getInstance().getImageDescriptor("e", AutoGUIImages.OUTPUT);
535
		}
536
	}
537
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/editor/AutoGUITestCasesForm.java (-8 / +8 lines)
Lines 95-103 Link Here
95
import org.eclipse.tptp.test.auto.gui.internal.actions.AutoGUIRefreshAction;
95
import org.eclipse.tptp.test.auto.gui.internal.actions.AutoGUIRefreshAction;
96
import org.eclipse.tptp.test.auto.gui.internal.actions.AutoGUITestCaseAction;
96
import org.eclipse.tptp.test.auto.gui.internal.actions.AutoGUITestCaseAction;
97
import org.eclipse.tptp.test.auto.gui.internal.actions.AutoGUIUpdateTestCaseAction;
97
import org.eclipse.tptp.test.auto.gui.internal.actions.AutoGUIUpdateTestCaseAction;
98
import org.eclipse.tptp.test.auto.gui.internal.core.IUIObject;
99
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCaseTreeStructure.MacroUIInstruction;
98
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCaseTreeStructure.MacroUIInstruction;
100
import org.eclipse.tptp.test.auto.gui.internal.macro.ObjectMineManager;
99
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptor;
100
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMineManager;
101
import org.eclipse.ui.IActionBars;
101
import org.eclipse.ui.IActionBars;
102
import org.eclipse.ui.actions.ActionFactory;
102
import org.eclipse.ui.actions.ActionFactory;
103
import org.eclipse.ui.forms.IManagedForm;
103
import org.eclipse.ui.forms.IManagedForm;
Lines 177-183 Link Here
177
	private Text startingPttxt;
177
	private Text startingPttxt;
178
	
178
	
179
	/* The object mine tree */
179
	/* The object mine tree */
180
	private AutoGUIObjectMineTreeStructure objectMineTree;
180
	private AutoGUIMacroObjectDescriptorMineTreeStructure objectMineTree;
181
181
182
	/* The object mine listener */
182
	/* The object mine listener */
183
	private ObjectMineTreeListener objectMineListener;
183
	private ObjectMineTreeListener objectMineListener;
Lines 213-219 Link Here
213
		lastTreeHierarchySelected = new LinkedList();
213
		lastTreeHierarchySelected = new LinkedList();
214
		logicalTreeRepresentaion = new AutoGUITestCaseTreeStructure (editor, Common_TestprofilePackage.eINSTANCE.getTPFTestSuite_TestCases());
214
		logicalTreeRepresentaion = new AutoGUITestCaseTreeStructure (editor, Common_TestprofilePackage.eINSTANCE.getTPFTestSuite_TestCases());
215
		logicalRepresentationListener = new LogicalRepresentationListener();
215
		logicalRepresentationListener = new LogicalRepresentationListener();
216
		objectMineTree = new AutoGUIObjectMineTreeStructure(this, editor);		
216
		objectMineTree = new AutoGUIMacroObjectDescriptorMineTreeStructure(this, editor);		
217
		linearOperationHistory = new DefaultOperationHistory();		
217
		linearOperationHistory = new DefaultOperationHistory();		
218
		context = new Hashtable();
218
		context = new Hashtable();
219
		isOperationHistory = true;
219
		isOperationHistory = true;
Lines 1013-1020 Link Here
1013
			{
1013
			{
1014
				Object[] selectedItems = ((StructuredSelection)selectedEntity).toArray();
1014
				Object[] selectedItems = ((StructuredSelection)selectedEntity).toArray();
1015
				Integer[] lineLevelDetail = null;
1015
				Integer[] lineLevelDetail = null;
1016
				if (selectedItems.length == 1 && selectedItems[0] instanceof IUIObject)
1016
				if (selectedItems.length == 1 && selectedItems[0] instanceof MacroObjectDescriptor)
1017
					lineLevelDetail = (Integer[])((IUIObject)selectedItems[0]).getData();
1017
					lineLevelDetail = (Integer[])((MacroObjectDescriptor)selectedItems[0]).getData();
1018
				
1018
				
1019
				/* Select the XML fragment if the line level information is available */
1019
				/* Select the XML fragment if the line level information is available */
1020
				if (lineLevelDetail != null)
1020
				if (lineLevelDetail != null)
Lines 1036-1042 Link Here
1036
				return;
1036
				return;
1037
								
1037
								
1038
			/* Update the offest that each tree item keeps track */
1038
			/* Update the offest that each tree item keeps track */
1039
			ObjectMineManager.getInstance().markObjectMineDirty (getTestSuite());
1039
			MacroObjectDescriptorMineManager.getInstance().markObjectMineDirty (getTestSuite());
1040
			if (isOperationHistory)
1040
			if (isOperationHistory)
1041
			{
1041
			{
1042
				objectMineTree.updateOffsetRelation(AutoGUITestCasesForm.this, objectMineTree.getLineOffsetRelation(), event.length, event.replacedText.length());
1042
				objectMineTree.updateOffsetRelation(AutoGUITestCasesForm.this, objectMineTree.getLineOffsetRelation(), event.length, event.replacedText.length());
Lines 1076-1082 Link Here
1076
		}
1076
		}
1077
	}
1077
	}
1078
	
1078
	
1079
	public AutoGUIObjectMineTreeStructure getObjectMineTreeStruct()
1079
	public AutoGUIMacroObjectDescriptorMineTreeStructure getObjectMineTreeStruct()
1080
	{
1080
	{
1081
		return objectMineTree;
1081
		return objectMineTree;
1082
	}
1082
	}
(-)src/org/eclipse/tptp/test/auto/gui/internal/editor/AutoGUITestCaseTreeStructure.java (-1 / +1 lines)
Lines 36-42 Link Here
36
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCasesForm.GUITestCaseProperties;
36
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCasesForm.GUITestCaseProperties;
37
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
37
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
38
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
38
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
39
import org.eclipse.tptp.test.auto.gui.internal.macro.XMLDefaultHandler;
39
import org.eclipse.tptp.test.auto.gui.internal.util.XMLDefaultHandler;
40
import org.w3c.dom.Node;
40
import org.w3c.dom.Node;
41
import org.w3c.dom.NodeList;
41
import org.w3c.dom.NodeList;
42
42
(-)META-INF/MANIFEST.MF (-4 / +13 lines)
Lines 1-8 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
Bundle-ManifestVersion: 2
2
Bundle-ManifestVersion: 2
3
Bundle-Name: %pluginName
3
Bundle-Name: %pluginName
4
Bundle-SymbolicName: org.eclipse.tptp.test.auto.gui; singleton:=true
4
Bundle-SymbolicName: org.eclipse.tptp.test.auto.gui;singleton:=true
5
Bundle-Version: 4.3.100.qualifier
5
Bundle-Version: 4.5.000.qualifier
6
Bundle-ClassPath: autogui.jar
6
Bundle-ClassPath: autogui.jar
7
Bundle-Activator: org.eclipse.tptp.test.auto.gui.internal.GuiPlugin
7
Bundle-Activator: org.eclipse.tptp.test.auto.gui.internal.GuiPlugin
8
Bundle-Vendor: %providerName
8
Bundle-Vendor: %providerName
Lines 11-22 Link Here
11
 org.eclipse.tptp.test.auto.gui.internal.actions,
11
 org.eclipse.tptp.test.auto.gui.internal.actions,
12
 org.eclipse.tptp.test.auto.gui.internal.codegen,
12
 org.eclipse.tptp.test.auto.gui.internal.codegen,
13
 org.eclipse.tptp.test.auto.gui.internal.commands,
13
 org.eclipse.tptp.test.auto.gui.internal.commands,
14
 org.eclipse.tptp.test.auto.gui.internal.commands.factory,
14
 org.eclipse.tptp.test.auto.gui.internal.core,
15
 org.eclipse.tptp.test.auto.gui.internal.core,
15
 org.eclipse.tptp.test.auto.gui.internal.dialogs,
16
 org.eclipse.tptp.test.auto.gui.internal.dialogs,
16
 org.eclipse.tptp.test.auto.gui.internal.editor,
17
 org.eclipse.tptp.test.auto.gui.internal.editor,
17
 org.eclipse.tptp.test.auto.gui.internal.macro,
18
 org.eclipse.tptp.test.auto.gui.internal.macro,
18
 org.eclipse.tptp.test.auto.gui.internal.resolvers,
19
 org.eclipse.tptp.test.auto.gui.internal.macroobject,
20
 org.eclipse.tptp.test.auto.gui.internal.macroobject.mine,
21
 org.eclipse.tptp.test.auto.gui.internal.macroobject.resolver,
19
 org.eclipse.tptp.test.auto.gui.internal.runner,
22
 org.eclipse.tptp.test.auto.gui.internal.runner,
23
 org.eclipse.tptp.test.auto.gui.internal.uiobject,
24
 org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver,
25
 org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate,
26
 org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.deresolvingsupport,
27
 org.eclipse.tptp.test.auto.gui.internal.util,
20
 org.eclipse.tptp.test.auto.gui.internal.wizard
28
 org.eclipse.tptp.test.auto.gui.internal.wizard
21
Require-Bundle: org.eclipse.ui;bundle-version="[3.2.0,4.0.0)",
29
Require-Bundle: org.eclipse.ui;bundle-version="[3.2.0,4.0.0)",
22
 org.junit;bundle-version="[3.2.0,4.0.0)",
30
 org.junit;bundle-version="[3.2.0,4.0.0)",
Lines 32-38 Link Here
32
 org.eclipse.hyades.test.tools.core;bundle-version="[4.1.0,5.0.0)",
40
 org.eclipse.hyades.test.tools.core;bundle-version="[4.1.0,5.0.0)",
33
 org.eclipse.ui.forms;bundle-version="[3.2.0,4.0.0)",
41
 org.eclipse.ui.forms;bundle-version="[3.2.0,4.0.0)",
34
 org.eclipse.debug.ui;bundle-version="[3.2.0,4.0.0)",
42
 org.eclipse.debug.ui;bundle-version="[3.2.0,4.0.0)",
43
 org.eclipse.ui.testing;bundle-version="[3.2.0,4.0.0)",
35
 org.eclipse.hyades.trace.ui;bundle-version="[4.1.0,5.0.0)",
44
 org.eclipse.hyades.trace.ui;bundle-version="[4.1.0,5.0.0)",
36
 org.eclipse.jdt.ui
45
 org.eclipse.jdt.ui
37
Eclipse-LazyStart: true
38
Bundle-RequiredExecutionEnvironment: J2SE-1.4
46
Bundle-RequiredExecutionEnvironment: J2SE-1.4
47
Bundle-ActivationPolicy: lazy
(-)schema/widgetResolver.exsd (+3 lines)
Lines 12-17 Link Here
12
12
13
   <element name="extension">
13
   <element name="extension">
14
      <annotation>
14
      <annotation>
15
         <appInfo>
16
            <meta.element deprecated="true" replacement="uiObjectResolverDelegate" />
17
         </appInfo>
15
         <documentation>
18
         <documentation>
16
            The following internal extension provides the mean for defining custom widget resolvers.
19
            The following internal extension provides the mean for defining custom widget resolvers.
17
         </documentation>
20
         </documentation>
(-)src/org/eclipse/tptp/test/auto/gui/internal/runner/AutoGUIRunner.java (-3 / +3 lines)
Lines 65-76 Link Here
65
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
65
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
66
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
66
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
67
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
67
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
68
import org.eclipse.tptp.test.auto.gui.internal.macro.XMLDefaultHandler;
69
import org.eclipse.tptp.test.auto.gui.internal.runner.ExtendedScriptParser.ExtendedTestCase;
68
import org.eclipse.tptp.test.auto.gui.internal.runner.ExtendedScriptParser.ExtendedTestCase;
70
import org.eclipse.tptp.test.auto.gui.internal.runner.ExtendedScriptParser.ExtendedTestInvocation;
69
import org.eclipse.tptp.test.auto.gui.internal.runner.ExtendedScriptParser.ExtendedTestInvocation;
71
import org.eclipse.tptp.test.auto.gui.internal.runner.ExtendedScriptParser.ExtendedTestSuite;
70
import org.eclipse.tptp.test.auto.gui.internal.runner.ExtendedScriptParser.ExtendedTestSuite;
72
import org.eclipse.tptp.test.auto.gui.internal.runner.ExtendedScriptParser.GeneralPropertyRetriever;
71
import org.eclipse.tptp.test.auto.gui.internal.runner.ExtendedScriptParser.GeneralPropertyRetriever;
73
import org.eclipse.tptp.test.auto.gui.internal.runner.VariableSubstitution.Variable;
72
import org.eclipse.tptp.test.auto.gui.internal.runner.VariableSubstitution.Variable;
73
import org.eclipse.tptp.test.auto.gui.internal.util.XMLDefaultHandler;
74
import org.eclipse.ui.IStartup;
74
import org.eclipse.ui.IStartup;
75
import org.eclipse.ui.IWorkbench;
75
import org.eclipse.ui.IWorkbench;
76
import org.eclipse.ui.IWorkbenchWindow;
76
import org.eclipse.ui.IWorkbenchWindow;
Lines 1232-1242 Link Here
1232
	}
1232
	}
1233
1233
1234
	/**
1234
	/**
1235
	 * Runs a verificaiton hook
1235
	 * Runs a verification hook
1236
	 * 
1236
	 * 
1237
	 * @param verfHook The verification hook
1237
	 * @param verfHook The verification hook
1238
	 */
1238
	 */
1239
	public void runVerificaitonHook(IHyadesTest verificationHook)
1239
	public void runVerificationHook(IHyadesTest verificationHook)
1240
	{
1240
	{
1241
		/* Set the root, if it hasn't already been set */
1241
		/* Set the root, if it hasn't already been set */
1242
		if (super.getRoot() == null)
1242
		if (super.getRoot() == null)
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/resolver/UIObjectResolver.java (+81 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver;
13
14
import org.eclipse.core.runtime.CoreException;
15
import org.eclipse.osgi.util.NLS;
16
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
17
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
18
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObject;
19
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
20
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.IUIObjectResolverDelegate;
21
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.NonTrivialUIObjectResolverDelegate;
22
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.UIObjectResolverDelegateRegistry;
23
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.UIObjectResolverDelegateLoader;
24
25
/**
26
 * This is a facade that encapsulates resolving/deresolving of UI objects. It
27
 * delegates to the respective UIObjectDelegateResolvers that can be plugged in
28
 * via the respective extension point
29
 * <code>org.eclipse.tptp.auto.gui.uiObjectResolverDelegate</code>.
30
 * 
31
 * @author Alexander Nyssen
32
 * 
33
 */
34
public class UIObjectResolver {
35
36
	public static IUIObjectIdentifier resolve(Object context, IUIObject uiObject)
37
			throws CoreException {
38
39
		IUIObjectResolverDelegate[] delegateResolvers = UIObjectResolverDelegateRegistry
40
				.getDelegateResolvers();
41
		IUIObjectIdentifier identifier = null;
42
		for (int i = 0; i < delegateResolvers.length && identifier == null; i++) {
43
			identifier = delegateResolvers[i].resolve(context, uiObject);
44
45
			if (identifier != null) {
46
				// check if the resolver delegate has set its id into the
47
				// returned
48
				// identifier
49
				if (identifier.getResolverId() == null) {
50
					AutoGUIUtil
51
							.throwCoreException(NLS
52
									.bind(
53
											AutoGUIMessages.AUTO_GUI_RESOLVER_IDENTIFIER_MISSING,
54
											delegateResolvers[i]));
55
					return null;
56
				}
57
			}
58
		}
59
60
		return identifier;
61
	}
62
63
	public static IUIObject deresolve(Object context,
64
			IUIObjectIdentifier uiObjectIdentifier) throws CoreException {
65
		// we need to obtain the resolver id to be able to delegate to the
66
		// respective UIObjectResolverDelegate
67
		String resolverId = uiObjectIdentifier.getResolverId();
68
		if (resolverId == null) {
69
			// if we do not have a resolver id, use one of the old registered
70
			// ones, as they all
71
			// have the same deprecated deresolving mechanism
72
			return UIObjectResolverDelegateRegistry.getDelegateResolver(
73
					NonTrivialUIObjectResolverDelegate.ID).deresolve(context,
74
					uiObjectIdentifier);
75
		}
76
		return UIObjectResolverDelegateRegistry.getDelegateResolver(resolverId)
77
				.deresolve(context, uiObjectIdentifier);
78
79
	}
80
81
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/IPlayable.java (+21 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macro;
12
13
import org.eclipse.core.runtime.CoreException;
14
import org.eclipse.core.runtime.IProgressMonitor;
15
import org.eclipse.swt.widgets.Display;
16
import org.eclipse.swt.widgets.Shell;
17
18
public interface IPlayable {
19
20
	boolean playback(Display display, Shell parent, IProgressMonitor monitor) throws CoreException;
21
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/ModeConstants.java (+28 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.macro;
13
14
15
/**
16
 * @author Alexander Nyssen
17
 */
18
public interface ModeConstants {
19
20
	/* Global states */
21
	public static final byte RECORDING_MODE = 0x00; /* Recording mode */
22
	public static final byte VERIFICATION_MODE = 0x01; /* Verification mode */
23
	public static final byte SUSPEND_MODE = 0x02; /* Suspend mode */
24
	public static final byte QUICK_RUN_MODE = 0x03; /* Quick run mode (when current workbench is used as the context) */
25
	public static final byte EXECUTION_RUN_MODE = 0x04; /* Execution run mode (when proper launch configuration is used) */
26
	public static final byte IDLE_MODE = 0x05; /* Idle mode */
27
	public static final byte POSITION_BASED_REC_MODE = 0x06; /* Position based recording */
28
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macroobject/IMacroObjectIdentifier.java (+27 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.macroobject;
13
14
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
15
16
/**
17
 * 
18
 * @author Alexander Nyssen
19
 * 
20
 */
21
public interface IMacroObjectIdentifier {
22
23
	public String getContextIdentifier();
24
25
	public IUIObjectIdentifier getObjectIdentifier();
26
27
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macroobject/mine/MacroObjectDescriptorMine.java (+616 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macroobject.mine;
12
13
import java.util.ArrayList;
14
import java.util.Hashtable;
15
import java.util.LinkedList;
16
import java.util.List;
17
18
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.hyades.models.common.facades.behavioral.ITestSuite;
20
import org.eclipse.osgi.util.NLS;
21
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
22
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
23
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
24
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
25
import org.eclipse.tptp.test.auto.gui.internal.util.XMLDefaultHandler;
26
import org.w3c.dom.NamedNodeMap;
27
import org.w3c.dom.Node;
28
29
/**
30
 * 
31
 * @author Ali Mehregani
32
 */
33
public class MacroObjectDescriptorMine {
34
	/** The root node of the tree structure that contains the objects */
35
	private MacroObjectDescriptor root;
36
37
	/** Included object mines */
38
	private ArrayList includes;
39
40
	/** The test suite that owns this object mine */
41
	private ITestSuite owner;
42
43
	/** The output object mine */
44
	private MacroObjectDescriptorMine outputObjectMine;
45
46
	/** The active object */
47
	private MacroObjectDescriptor activeObject;
48
49
	/**
50
	 * Keeps track of the maximum reference id in use. This is used to generate
51
	 * a unique reference id when requested
52
	 */
53
	private int maximumRefId;
54
55
	/** The xml handler used to parse the object mine */
56
	private XMLDefaultHandler defaultXMLHandler;
57
58
	public MacroObjectDescriptorMine(ITestSuite testSuite,
59
			XMLDefaultHandler defaultXMLHandler) {
60
		owner = testSuite;
61
		root = new MacroObjectDescriptor(null);
62
		includes = new ArrayList();
63
		this.defaultXMLHandler = defaultXMLHandler;
64
	}
65
66
	public void addInclude(MacroObjectDescriptorMine objectMine) {
67
		includes.add(objectMine);
68
		if (outputObjectMine != null) {
69
			MacroObjectDescriptorMine foundObjectMine = findIncludedObjectMine(outputObjectMine);
70
			outputObjectMine = foundObjectMine == null ? outputObjectMine
71
					: foundObjectMine;
72
		}
73
	}
74
75
	public MacroObjectDescriptor lookupMacroObjectDescriptor(
76
			MacroObjectDescriptor parent, String referenceId) {
77
		MacroObjectDescriptor uiObject = lookupIncludes(parent, referenceId);
78
		if (uiObject != null)
79
			return uiObject;
80
81
		uiObject = lookupMacroObjectDescriptor(parent);
82
		if (uiObject == null)
83
			return null;
84
85
		uiObject = uiObject.findChild(referenceId);
86
		return uiObject;
87
	}
88
89
	private MacroObjectDescriptor lookupMacroObjectDescriptor(
90
			MacroObjectDescriptor object, boolean requiresPresence)
91
			throws UIObjectNotFound {
92
		if (object == null) {
93
			return root;
94
		}
95
96
		LinkedList relationship = object.getHierarchicalRelation();
97
		MacroObjectDescriptor currentNode = root;
98
		for (int i = 0, height = relationship.size(); currentNode != null
99
				&& i < height; i++) {
100
			currentNode = currentNode
101
					.findChild(((MacroObjectDescriptor) relationship.get(i))
102
							.getReferenceId());
103
		}
104
105
		if (currentNode == null && requiresPresence)
106
			throw new UIObjectNotFound(NLS.bind(
107
					AutoGUIMessages.AUTO_GUI_ERROR_OBJ_MINE_NF, object
108
							.getReferenceId()));
109
110
		return currentNode;
111
	}
112
113
	public MacroObjectDescriptor lookupMacroObjectDescriptor(
114
			MacroObjectDescriptor parent, String contextId, String widgetId,
115
			String objectId) {
116
		MacroObjectDescriptor uiObject = lookupIncludes(parent, contextId,
117
				widgetId, objectId);
118
		if (uiObject != null)
119
			return uiObject;
120
121
		MacroObjectDescriptor parentNode = lookupMacroObjectDescriptor(parent);
122
		if (parentNode == null)
123
			return null;
124
125
		MacroObjectDescriptor[] children = parentNode.getChildren();
126
		for (int i = 0; i < children.length; i++) {
127
			if (((contextId == null && children[i].getContextId() == null) || (contextId != null && contextId
128
					.equals(children[i].getContextId())))
129
					&& widgetId.equals(children[i].getWidgetId())
130
					&& ((objectId == null && children[i].getObjectId() == null) || (objectId != null && objectId
131
							.equals(children[i].getObjectId())))) {
132
				return children[i];
133
			}
134
135
		}
136
		return null;
137
	}
138
139
	public MacroObjectDescriptor[] getChildren() {
140
		return root.getChildren();
141
	}
142
143
	private MacroObjectDescriptor lookupMacroObjectDescriptor(
144
			MacroObjectDescriptor parent) {
145
		try {
146
			return lookupMacroObjectDescriptor(parent, false);
147
		} catch (UIObjectNotFound e) {
148
			return null;
149
		}
150
	}
151
152
	/**
153
	 * Looks up the included object mine to determine if they have a
154
	 * corresponding object with the reference id passed in.
155
	 * 
156
	 * @param parent
157
	 *            The parent of the object
158
	 * @param referenceId
159
	 *            The reference id of the object
160
	 * 
161
	 * @return The object with the reference id passed in; null if none is
162
	 *         found.
163
	 * @throws UIObjectNotFound
164
	 *             In case the parent can't be found.
165
	 */
166
	private MacroObjectDescriptor lookupIncludes(MacroObjectDescriptor parent,
167
			String referenceId) {
168
		MacroObjectDescriptor[] uiObject = lookupIncludes(parent, referenceId,
169
				null, null, null);
170
		return uiObject != null && uiObject.length > 0 ? uiObject[0] : null;
171
	}
172
173
	/**
174
	 * Looks up the included object mine to determine if they have a
175
	 * corresponding object with the contextId id and object id passed in.
176
	 * 
177
	 * @param parent
178
	 *            The parent of the object
179
	 * @param contextId
180
	 *            The context id of the object
181
	 * @param widgetId
182
	 *            The id of the object
183
	 * 
184
	 * @return The object with the matching context and object id passed in;
185
	 *         null if none is found.
186
	 * @throws UIObjectNotFound
187
	 *             In case the parent can't be found.
188
	 */
189
	private MacroObjectDescriptor lookupIncludes(MacroObjectDescriptor parent,
190
			String contextId, String widgetId, String objectId) {
191
		MacroObjectDescriptor[] uiObject = lookupIncludes(parent, null,
192
				contextId, widgetId, objectId);
193
		return uiObject != null && uiObject.length > 0 ? uiObject[0] : null;
194
	}
195
196
	/**
197
	 * Looks up the included object mines to find an object that has been
198
	 * requested. If reference id happens to be null, then context/object id are
199
	 * used.
200
	 * 
201
	 * @param parent
202
	 *            The parent of the object
203
	 * @param referenceId
204
	 *            The reference id of the object.
205
	 * @param contextId
206
	 *            The context id of the object
207
	 * @param widgetId
208
	 *            The id of the object
209
	 * 
210
	 * @return The objects to look for
211
	 */
212
	private MacroObjectDescriptor[] lookupIncludes(
213
			MacroObjectDescriptor parent, String referenceId, String contextId,
214
			String widgetId, String objectId) {
215
		boolean useReferenceId = referenceId != null;
216
		boolean useObjectId = widgetId != null;
217
218
		MacroObjectDescriptor objectRequested = null;
219
		MacroObjectDescriptor[] children = null;
220
		for (int i = 0, includeCount = includes.size(); i < includeCount; i++) {
221
			MacroObjectDescriptorMine objectMine = (MacroObjectDescriptorMine) includes
222
					.get(i);
223
			if (useReferenceId) {
224
				objectRequested = objectMine.lookupMacroObjectDescriptor(
225
						parent, referenceId);
226
			} else if (useObjectId) {
227
				objectRequested = objectMine.lookupMacroObjectDescriptor(
228
						parent, contextId, widgetId, objectId);
229
			}
230
231
			children = objectRequested == null ? children
232
					: new MacroObjectDescriptor[] { objectRequested };
233
			if (children != null) {
234
				return children;
235
			}
236
		}
237
238
		return null;
239
	}
240
241
	public MacroObjectDescriptor getRoot() {
242
		return root;
243
	}
244
245
	public MacroObjectDescriptor registerObject(MacroObjectDescriptor parent,
246
			Node objectNode) throws IDCollisionException, UIObjectNotFound,
247
			CoreException {
248
		NamedNodeMap attributes = objectNode.getAttributes();
249
		MacroObjectDescriptor macroObjectDescriptor = new MacroObjectDescriptor(
250
				parent);
251
252
		MacroObjectDescriptor node = lookupMacroObjectDescriptor(parent, true);
253
254
		/* Set the attributes of the object */
255
		String referenceIdStr = getAttribute(attributes,
256
				MacroConstants.REFERENCE_ID_ATTRIBUTE);
257
		updateMaxReferenceId(referenceIdStr);
258
259
		Hashtable lineLevelDetail = null;
260
		if (defaultXMLHandler != null)
261
			lineLevelDetail = defaultXMLHandler.getLineTable();
262
		macroObjectDescriptor.setReferenceId(referenceIdStr);
263
		macroObjectDescriptor.setContextId(getAttribute(attributes,
264
				MacroConstants.CONTEXT_ID_ATTRIBUTE));
265
		// for backwards compatibility, also search for an ID attribute (old
266
		// format). Otherwise read the widget and object id
267
		if (getAttribute(attributes, MacroConstants.ID_ATTRIBUTE) != null) {
268
			macroObjectDescriptor.setWidgetId(getAttribute(attributes,
269
					MacroConstants.ID_ATTRIBUTE));
270
		} else {
271
			macroObjectDescriptor.setWidgetId(getAttribute(attributes,
272
					MacroConstants.WIDGET_ID_ATTRIBUTE));
273
			macroObjectDescriptor.setObjectId(getAttribute(attributes,
274
					MacroConstants.OBJECT_ID_ATTRIBUTE));
275
		}
276
		macroObjectDescriptor.setDescriptive(getAttribute(attributes,
277
				MacroConstants.DESCRIPTIVE_ATTRIBUTE));
278
		macroObjectDescriptor.setResolver(getAttribute(attributes,
279
				MacroConstants.RESOLVER_ID_ATTRIBUTE));
280
		if (lineLevelDetail != null)
281
			macroObjectDescriptor.setData(((Integer[]) lineLevelDetail
282
					.get(objectNode)));
283
		node.addChild(macroObjectDescriptor);
284
285
		return macroObjectDescriptor;
286
	}
287
288
	public MacroObjectDescriptor registerObject(MacroObjectDescriptor uiObject)
289
			throws IDCollisionException, UIObjectNotFound, CoreException {
290
		// assign a new unique id to the MacroObjectDescriptor
291
		String uniqueId = getUniqueReferenceId();
292
		updateMaxReferenceId(uniqueId);
293
		uiObject.setReferenceId(uniqueId);
294
295
		MacroObjectDescriptor parentObject = uiObject.getParent();
296
297
		/*
298
		 * If the object that is about to be registered happens to be at the
299
		 * first level (i.e. it is an infant), then it needs to be registered
300
		 * with the output destination of this object mine
301
		 */
302
		if (parentObject == null && outputObjectMine != null) {
303
			outputObjectMine.registerObject(uiObject);
304
			includes.contains(outputObjectMine);
305
			return uiObject;
306
		}
307
308
		if (parentObject == null) {
309
			root.addChild(uiObject);
310
		} else {
311
			parentObject.addChild(uiObject);
312
		}
313
314
		return uiObject;
315
	}
316
317
	private void updateMaxReferenceId(String referenceIdStr) {
318
		try {
319
			int referenceId = Integer.parseInt(referenceIdStr);
320
			int maximumIncludedRefId = findMaximumIncludedRefId();
321
			maximumRefId = Math.max(
322
					Math.max(referenceId, maximumIncludedRefId), maximumRefId);
323
324
			if (referenceId == maximumRefId)
325
				maximumRefId++;
326
		} catch (NumberFormatException nfe) {
327
			/* Doesn't need to be handled */
328
		}
329
	}
330
331
	/**
332
	 * Walks through the included object mines of this object mine to determine
333
	 * the unique reference id.
334
	 * 
335
	 * @return A unique reference id that is global to all included object
336
	 *         mines.
337
	 */
338
	private int findMaximumIncludedRefId() {
339
		int uniqueRefId = 0;
340
341
		for (int i = 0, includeCount = includes.size(); i < includeCount; i++) {
342
			MacroObjectDescriptorMine currentObjectMine = (MacroObjectDescriptorMine) includes
343
					.get(i);
344
			try {
345
				uniqueRefId = Math.max(Integer.parseInt(currentObjectMine
346
						.getUniqueReferenceId()), uniqueRefId);
347
			} catch (NumberFormatException nfe) {
348
				/* Ignore the exception */
349
			}
350
		}
351
		return uniqueRefId;
352
	}
353
354
	private String getAttribute(NamedNodeMap attributes, String attributeName) {
355
		Node attr = attributes.getNamedItem(attributeName);
356
		return attr == null ? null : attr.getNodeValue();
357
	}
358
359
	public void setOutputSource(MacroObjectDescriptorMine objectMine) {
360
		outputObjectMine = objectMine == null ? null
361
				: findIncludedObjectMine(objectMine);
362
		if (outputObjectMine == null)
363
			outputObjectMine = objectMine;
364
	}
365
366
	public MacroObjectDescriptorMine getOutputSource() {
367
		return outputObjectMine;
368
	}
369
370
	private MacroObjectDescriptorMine findIncludedObjectMine(
371
			MacroObjectDescriptorMine objectMine) {
372
		for (int i = 0, includeCount = includes.size(); i < includeCount; i++) {
373
			MacroObjectDescriptorMine currentObjectMine = (MacroObjectDescriptorMine) includes
374
					.get(i);
375
			if (currentObjectMine.equals(objectMine))
376
				return currentObjectMine;
377
		}
378
379
		return null;
380
	}
381
382
	public ITestSuite getOwner() {
383
		return owner;
384
	}
385
386
	public static class UIObjectNotFound extends Exception {
387
		static final long serialVersionUID = 4699726279267599112L;
388
389
		public UIObjectNotFound(String message) {
390
			super(message);
391
		}
392
	}
393
394
	public static class IDCollisionException extends Exception {
395
		static final long serialVersionUID = -6526030843455792891L;
396
397
		public IDCollisionException(String message) {
398
			super(message);
399
		}
400
	}
401
402
	public String serializeToString() {
403
		StringBuffer objectMineSerialized = new StringBuffer();
404
		int indent = 0;
405
406
		/* <object-mine> */
407
		MacroUtil.addElement(objectMineSerialized, indent,
408
				MacroConstants.OBJECT_MINE_ELEMENT, false, true);
409
410
		serializeHeader(objectMineSerialized, indent + 1, true);
411
		serializeObjects(objectMineSerialized, indent + 1, true);
412
413
		/* </object-mine> */
414
		MacroUtil.addElement(objectMineSerialized, indent,
415
				MacroConstants.OBJECT_MINE_ELEMENT, true, true);
416
417
		return objectMineSerialized.toString();
418
	}
419
420
	private void serializeHeader(StringBuffer objectMineSerialized, int indent,
421
			boolean includeHeader) {
422
		/* Don't write anything if the header is empty */
423
		if (outputObjectMine == null
424
				&& (includes == null || includes.size() <= 0))
425
			return;
426
427
		boolean outputElement = outputObjectMine != null;
428
429
		/* <header output="..."/> */
430
		if (includeHeader) {
431
			MacroUtil.addElement(objectMineSerialized, indent,
432
					MacroConstants.HEADER_ELEMENT, false, !outputElement);
433
			if (outputElement)
434
				MacroUtil.addAttribute(objectMineSerialized,
435
						new String[] { MacroConstants.OUTPUT_ATTRIBUTE },
436
						new String[] { AutoGUIUtil
437
								.resolveTestSuitePath(outputObjectMine
438
										.getOwner()) }, false, true);
439
		}
440
441
		/* Add the <include .../> elements */
442
		for (int i = 0, includeCount = includes.size(); i < includeCount; i++) {
443
			MacroObjectDescriptorMine currentInclude = (MacroObjectDescriptorMine) includes
444
					.get(i);
445
			ITestSuite testSuite = currentInclude.getOwner();
446
			String path = AutoGUIUtil.resolveTestSuitePath(testSuite);
447
448
			if (path != null) {
449
				MacroUtil.addElement(objectMineSerialized, indent + 1,
450
						MacroConstants.INCLUDE_ELEMENT, false, false);
451
				MacroUtil.addAttribute(objectMineSerialized,
452
						new String[] { MacroConstants.PATH_ATTRIBUTE },
453
						new String[] { path }, true, true);
454
			}
455
		}
456
457
		if (includeHeader) {
458
			MacroUtil.addElement(objectMineSerialized, indent,
459
					MacroConstants.HEADER_ELEMENT, true, true);
460
		}
461
	}
462
463
	private void serializeObjects(StringBuffer objectMineSerialized,
464
			int indent, boolean includeHeader) {
465
		MacroObjectDescriptor[] rootChildren = root.getChildren();
466
		if (rootChildren == null || rootChildren.length <= 0)
467
			return;
468
469
		/* Add the objects */
470
		if (includeHeader) {
471
			MacroUtil.addElement(objectMineSerialized, indent,
472
					MacroConstants.OBJECTS_ELEMENT, false, true);
473
			addObject(objectMineSerialized, indent + 1, rootChildren);
474
			MacroUtil.addElement(objectMineSerialized, indent,
475
					MacroConstants.OBJECTS_ELEMENT, true, true);
476
			return;
477
		}
478
479
		addObject(objectMineSerialized, indent + 1, rootChildren);
480
	}
481
482
	/**
483
	 * @see org.eclipse.tptp.test.auto.gui.internal.util.MacroObjectDescriptorMine#serializeHeaderToString()
484
	 */
485
	public String serializeHeaderToString() {
486
		StringBuffer sb = new StringBuffer();
487
		serializeHeader(sb, 0, false);
488
		return sb.toString();
489
	}
490
491
	/**
492
	 * @see org.eclipse.tptp.test.auto.gui.internal.util.MacroObjectDescriptorMine#serializeObjetsToString()
493
	 */
494
	public String serializeObjetsToString() {
495
		StringBuffer sb = new StringBuffer();
496
		serializeObjects(sb, 0, false);
497
		return sb.toString();
498
	}
499
500
	private void addObject(StringBuffer objectMapSerialized, int indent,
501
			MacroObjectDescriptor[] rootChildren) {
502
		if (rootChildren == null)
503
			return;
504
505
		for (int i = 0; i < rootChildren.length; i++) {
506
			MacroObjectDescriptor currentMacroObjectDescriptor = rootChildren[i];
507
			MacroObjectDescriptor[] children = rootChildren[i].getChildren();
508
509
			/* If the object is a shell without any children, then skip it */
510
			if (currentMacroObjectDescriptor.getParent() == null
511
					&& (children == null || children.length <= 0))
512
				continue;
513
514
			boolean hasChildren = children != null && children.length > 0;
515
			MacroUtil.addElement(objectMapSerialized, indent,
516
					MacroConstants.OBJECT_ELEMENT, false, false);
517
			MacroUtil.addAttribute(objectMapSerialized, new String[] {
518
					MacroConstants.DESCRIPTIVE_ATTRIBUTE,
519
					MacroConstants.REFERENCE_ID_ATTRIBUTE,
520
					MacroConstants.CONTEXT_ID_ATTRIBUTE,
521
					MacroConstants.RESOLVER_ID_ATTRIBUTE,
522
					MacroConstants.WIDGET_ID_ATTRIBUTE,
523
					MacroConstants.OBJECT_ID_ATTRIBUTE }, new String[] {
524
					currentMacroObjectDescriptor.getDescriptive(),
525
					currentMacroObjectDescriptor.getReferenceId(),
526
					currentMacroObjectDescriptor.getContextId(),
527
					currentMacroObjectDescriptor.getResolverId(),
528
					currentMacroObjectDescriptor.getWidgetId(),
529
					currentMacroObjectDescriptor.getObjectId() }, !hasChildren,
530
					true);
531
			if (hasChildren) {
532
				addObject(objectMapSerialized, indent + 1, rootChildren[i]
533
						.getChildren());
534
				MacroUtil.addElement(objectMapSerialized, indent,
535
						MacroConstants.OBJECT_ELEMENT, true, true);
536
			}
537
		}
538
539
	}
540
541
	public MacroObjectDescriptor getActiveObject() {
542
		return activeObject;
543
	}
544
545
	public void setActiveObject(MacroObjectDescriptor activeObject) {
546
		this.activeObject = activeObject;
547
	}
548
549
	private String getUniqueReferenceId() {
550
		int maximumIncludedRefId = findMaximumIncludedRefId();
551
		maximumRefId = Math.max(maximumIncludedRefId, maximumRefId);
552
553
		/* Restart the reference id */
554
		if (maximumRefId >= Integer.MAX_VALUE - 10) {
555
			maximumRefId = 0;
556
		}
557
		return String.valueOf(maximumRefId);
558
	}
559
560
	public List getIncludes() {
561
		return includes;
562
	}
563
564
	public boolean equals(Object o) {
565
		return o instanceof MacroObjectDescriptorMine ? getOwner().getId()
566
				.equals(((MacroObjectDescriptorMine) o).getOwner().getId())
567
				: false;
568
	}
569
570
	public void setOwner(ITestSuite testSuite) {
571
		this.owner = testSuite;
572
	}
573
574
	/**
575
	 * If the node passed in has a reference id, then this method looks up the
576
	 * id in the object mine and attempts to find the object that is referenced.
577
	 * 
578
	 * @param node
579
	 *            Represents the XML node
580
	 * @param lineTable
581
	 *            Contains line level information
582
	 * 
583
	 * @return A String[] of length 2, where String[0] = context id and
584
	 *         String[1] = object id. If the node does not have a reference id,
585
	 *         then null is returned.
586
	 * 
587
	 * @throws CoreException
588
	 *             If the node contains a reference id attribute but the
589
	 *             corresponding object mine does not have any such object.
590
	 */
591
	public MacroObjectDescriptor lookupReferenceId(
592
			MacroObjectDescriptor parent, Node node, Hashtable lineTable)
593
			throws CoreException {
594
		String referenceId = MacroUtil.getAttribute(node,
595
				MacroConstants.REFERENCE_ID_ATTRIBUTE);
596
		if (referenceId == null)
597
			return null;
598
599
		MacroObjectDescriptor correspondingObject = lookupMacroObjectDescriptor(
600
				parent, referenceId);
601
		if (correspondingObject == null) {
602
			Integer[] lineLevelDetail = (Integer[]) lineTable.get(node);
603
			AutoGUIUtil
604
					.throwCoreException(NLS.bind(
605
							AutoGUIMessages.AUTO_GUI_ERROR_OBJ_MINE_NF,
606
							referenceId), lineLevelDetail == null ? 0
607
							: lineLevelDetail[0].intValue());
608
		} else {
609
			return correspondingObject;
610
		}
611
612
		/* Code not reached beyond this point */
613
		return null;
614
	}
615
616
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/resolver/delegate/UIObjectResolverDelegateLoader.java (+61 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate;
12
13
/**
14
 * Represents each widgetResolver element that appears under a widgetResolver
15
 * extension
16
 * 
17
 * @author Ali Mehregani
18
 * @author Alexander Nyssen
19
 */
20
public class UIObjectResolverDelegateLoader {
21
22
	/** The id of the widget resolver */
23
	private String id;
24
25
	/** The widget resolver class */
26
	private IUIObjectResolverDelegate uiObjectResolverDelegate;
27
28
	/** The priority of this widget resolver registeration */
29
	private int priority;
30
31
	/**
32
	 * Limit the visibility of the constructor
33
	 */
34
	protected UIObjectResolverDelegateLoader(String id,
35
			IUIObjectResolverDelegate resolver, int priority) {
36
		this.id = id;
37
		this.uiObjectResolverDelegate = resolver;
38
		this.priority = priority;
39
	}
40
41
	/**
42
	 * @return the id
43
	 */
44
	public String getId() {
45
		return id;
46
	}
47
48
	/**
49
	 * @return the priority
50
	 */
51
	public int getPriority() {
52
		return priority;
53
	}
54
55
	/**
56
	 * @return the widgetResolver
57
	 */
58
	public IUIObjectResolverDelegate getUIObjectResolverDelegate() {
59
		return uiObjectResolverDelegate;
60
	}
61
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/PrimitiveUIObjectIdentifier.java (+78 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.uiobject;
12
13
/**
14
 * A primitive string UI object identifier. The string object must be an exact
15
 * match for the two given ids to equal. Contributors can extend this class or
16
 * provide a direct implementation of {@link IUIObjectIdentifier}
17
 * 
18
 * @author Ali Mehregani
19
 * @author Alexander Nyssen
20
 */
21
public class PrimitiveUIObjectIdentifier implements IUIObjectIdentifier {
22
23
	/** The resolver objectId */
24
	private String resolverId;
25
	
26
	private String widgetId;
27
28
	/** The string objectId of the object */
29
	private String objectId;
30
31
	public PrimitiveUIObjectIdentifier(String widgetId) {
32
		this.widgetId = widgetId;
33
	}
34
35
	public PrimitiveUIObjectIdentifier(String widgetId, String resolverId) {
36
		this.widgetId = widgetId;
37
		this.resolverId = resolverId;
38
	}
39
	
40
	public PrimitiveUIObjectIdentifier(String widgetId, String objectId, String resolverId) {
41
		this.widgetId = widgetId;
42
		this.objectId = objectId;
43
		this.resolverId = resolverId;
44
	}
45
46
	public String getResolverId() {
47
		return resolverId;
48
	}
49
50
	public void setResolverId(String resolverId) {
51
		this.resolverId = resolverId;
52
	}
53
54
	public String getWidgetId() {
55
		return widgetId;
56
	}
57
	
58
	public String getObjectId(){
59
		return objectId;
60
	}
61
62
	public boolean equals(Object obj) {
63
		if (!(obj instanceof PrimitiveUIObjectIdentifier)) {
64
			return false;
65
		} else {
66
			PrimitiveUIObjectIdentifier other = (PrimitiveUIObjectIdentifier) obj;
67
			boolean equals = (widgetId == null) ? other.widgetId == null
68
					: widgetId.equals(other.widgetId);
69
			return equals;
70
		}
71
	}
72
73
	public String toString() {
74
		return widgetId;
75
	}
76
	
77
78
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macroobject/IMacroObject.java (+25 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.macroobject;
13
14
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObject;
15
16
/**
17
 * @author Alexander Nyssen
18
 */
19
public interface IMacroObject {
20
21
	public abstract Object getContext();
22
23
	public abstract IUIObject getUIObject();
24
25
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/resolver/delegate/UIObjectResolverDelegateRegistry.java (+203 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate;
13
14
import java.util.Hashtable;
15
import java.util.Vector;
16
17
import org.eclipse.core.runtime.CoreException;
18
import org.eclipse.core.runtime.IConfigurationElement;
19
import org.eclipse.core.runtime.Platform;
20
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetResolverLoader;
21
import org.eclipse.tptp.test.auto.gui.internal.core.WidgetResolverLoaderToUIObjectResolverDelegateLoaderAdapter;
22
23
/**
24
 * This class delivers utility methods to load UIObjectResolverDelegates via the
25
 * uiObjectResolverDelegate extension point. It also loads all extensions to the
26
 * deprecated widgetResolver extension point and adapts them to the new
27
 * interface.
28
 * 
29
 * @author Alexander Nyssen
30
 * 
31
 */
32
public class UIObjectResolverDelegateRegistry {
33
34
	private static final String EXTENSION_POINT_NAME = "uiObjectResolverDelegate";
35
	private static final String EXTENSION_POINT_ID = "org.eclipse.tptp.test.auto.gui." 
36
			+ EXTENSION_POINT_NAME;
37
38
	/* Keeps an ordered list of the primitive resolver ids */
39
	private static String[] resolverIds;
40
41
	/*
42
	 * The widget resolver: KEY = resolver id VALUE = A class of type
43
	 * UIObjectResolverDelegateLoader
44
	 */
45
	private static Hashtable uiObjectDelegateResolverLoaders = new Hashtable();
46
47
	/**
48
	 * Load the registered widget resolvers. The widget resolvers are ordered in
49
	 * the descending order of their priority
50
	 */
51
	private static void loadDelegateResolvers() {
52
		IConfigurationElement[] elements = Platform.getExtensionRegistry()
53
				.getConfigurationElementsFor(EXTENSION_POINT_ID);
54
		Vector tempContainer = new Vector(elements.length);
55
56
		for (int i = 0; i < elements.length; i++) {
57
			UIObjectResolverDelegateLoader uiObjectResolverDelegateLoader = constructUIObjectResolverLoaderInstance(elements[i]);
58
			if (uiObjectResolverDelegateLoader != null) {
59
				tempContainer.add(findIndex(uiObjectResolverDelegateLoader
60
						.getPriority(), tempContainer),
61
						uiObjectResolverDelegateLoader);
62
				uiObjectDelegateResolverLoaders.put(
63
						uiObjectResolverDelegateLoader.getId(),
64
						uiObjectResolverDelegateLoader);
65
			}
66
		}
67
68
		// Also add the implementors of the old widgetResolver extension point.
69
		// They are adapted to the new extension point using respective adapters
70
		WidgetResolverLoader[] widgetResolverLoaders = WidgetResolverLoader
71
				.getWidgetResolverLoaders();
72
		for (int i = 0; i < widgetResolverLoaders.length; i++) {
73
			UIObjectResolverDelegateLoader uiObjectResolverDelegateLoader = new WidgetResolverLoaderToUIObjectResolverDelegateLoaderAdapter(
74
					widgetResolverLoaders[i]);
75
			tempContainer.add(findIndex(widgetResolverLoaders[i].getPriority(),
76
					tempContainer), uiObjectResolverDelegateLoader);
77
78
			uiObjectDelegateResolverLoaders.put(uiObjectResolverDelegateLoader
79
					.getId(), uiObjectResolverDelegateLoader);
80
		}
81
82
		resolverIds = new String[tempContainer.size()];
83
		for (int i = 0; i < resolverIds.length; i++) {
84
			resolverIds[i] = ((UIObjectResolverDelegateLoader) tempContainer
85
					.get(i)).getId();
86
		}
87
	}
88
89
	private static int findIndex(int desiredPriority, Vector container,
90
			int startIntervalInx, int endIntervalInx, int length) {
91
		if (startIntervalInx == endIntervalInx
92
				|| startIntervalInx == endIntervalInx - 1) {
93
			if (length > 0) {
94
				UIObjectResolverDelegateLoader widgetResolverReg = (UIObjectResolverDelegateLoader) container
95
						.get(startIntervalInx);
96
				int priority = widgetResolverReg.getPriority();
97
				if (desiredPriority < priority)
98
					return startIntervalInx;
99
			}
100
			return endIntervalInx;
101
		}
102
103
		/* What's in the middle? */
104
		int middleInx = startIntervalInx
105
				+ (int) Math.ceil((endIntervalInx - startIntervalInx) / 2);
106
		UIObjectResolverDelegateLoader widgetResolverReg = (UIObjectResolverDelegateLoader) container
107
				.get(middleInx);
108
		int middleElementPriority = widgetResolverReg.getPriority();
109
110
		if (middleElementPriority > desiredPriority)
111
			endIntervalInx = middleInx;
112
		else if (middleElementPriority < desiredPriority)
113
			startIntervalInx = middleInx;
114
		else
115
			return middleInx;
116
		return findIndex(desiredPriority, container, startIntervalInx,
117
				endIntervalInx, length);
118
	}
119
120
	private static int findIndex(int priority, Vector container) {
121
		int length = container.size();
122
		return findIndex(priority, container, 0, length, length);
123
	}
124
125
	/**
126
	 * This method should not be called by clients. It is only used from 
127
	 * UIObjectDeprecatedDeresolvingSupport 
128
	 * 
129
	 * @return
130
	 */
131
	public static Hashtable getDelegateResolverLoaders() {
132
		if (resolverIds == null) {
133
			UIObjectResolverDelegateRegistry.loadDelegateResolvers();
134
		}
135
		return uiObjectDelegateResolverLoaders;
136
	}
137
138
	/**
139
	 * Returns the list of resolver delegates, sorted by priority
140
	 * 
141
	 * @return
142
	 */
143
	public static IUIObjectResolverDelegate[] getDelegateResolvers() {
144
		if (resolverIds == null) {
145
			UIObjectResolverDelegateRegistry.loadDelegateResolvers();
146
		}
147
148
		IUIObjectResolverDelegate[] resolvers = new IUIObjectResolverDelegate[resolverIds.length];
149
		for (int i = 0; i < resolverIds.length; i++) {
150
			resolvers[i] = ((UIObjectResolverDelegateLoader) uiObjectDelegateResolverLoaders
151
					.get(resolverIds[i])).getUIObjectResolverDelegate();
152
		}
153
		return resolvers;
154
	}
155
156
	public static final IUIObjectResolverDelegate getDelegateResolver(
157
			String resolverId) {
158
		if (resolverIds == null) {
159
			UIObjectResolverDelegateRegistry.loadDelegateResolvers();
160
		}
161
162
		UIObjectResolverDelegateLoader widgetResolverLoader = (UIObjectResolverDelegateLoader) uiObjectDelegateResolverLoaders
163
				.get(resolverId);
164
		return widgetResolverLoader.getUIObjectResolverDelegate();
165
	}
166
167
	/**
168
	 * Constructs an instance of this class based on the configuration element
169
	 * passed in
170
	 * 
171
	 * @param confiugrationElement
172
	 *            The configuration element to be loaded
173
	 * @return An instance of this class based on the configuration element
174
	 *         passed in. null will be returned if there is an error loading the
175
	 *         configuration element.
176
	 */
177
	private static UIObjectResolverDelegateLoader constructUIObjectResolverLoaderInstance(
178
			IConfigurationElement configurationElement) {
179
		String name = configurationElement.getName();
180
		if (!EXTENSION_POINT_NAME.equals(configurationElement.getName()))
181
			return null;
182
183
		try {
184
			String id = configurationElement.getAttribute("id");
185
			IUIObjectResolverDelegate uiObjectResolverDelegate = (IUIObjectResolverDelegate) configurationElement
186
					.createExecutableExtension("class");
187
			int priority = Integer.parseInt(configurationElement
188
					.getAttribute("priority"));
189
190
			if (id == null || uiObjectResolverDelegate == null)
191
				return null;
192
193
			return new UIObjectResolverDelegateLoader(id,
194
					uiObjectResolverDelegate, priority);
195
196
		} catch (CoreException e) {
197
			e.printStackTrace();
198
		}
199
200
		return null;
201
	}
202
203
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/ObjectBasedCommand.java (+321 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.commands;
13
14
import java.util.Hashtable;
15
16
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.core.runtime.IProgressMonitor;
18
import org.eclipse.osgi.util.NLS;
19
import org.eclipse.swt.widgets.Display;
20
import org.eclipse.swt.widgets.Event;
21
import org.eclipse.swt.widgets.Shell;
22
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
23
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
24
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
25
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
26
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
27
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
28
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObject;
29
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObjectIdentifier;
30
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObject;
31
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObjectIdentifier;
32
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptor;
33
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine;
34
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine.IDCollisionException;
35
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine.UIObjectNotFound;
36
import org.eclipse.tptp.test.auto.gui.internal.macroobject.resolver.MacroObjectResolver;
37
import org.eclipse.tptp.test.auto.gui.internal.uiobject.PrimitiveUIObjectIdentifier;
38
import org.eclipse.tptp.test.auto.gui.internal.uiobject.UIObject;
39
import org.w3c.dom.Node;
40
41
/**
42
 * @author Alexander Nyssen
43
 * 
44
 */
45
public abstract class ObjectBasedCommand extends AbstractMacroCommand {
46
47
	/** The macro object of interest to the command */
48
	protected IMacroObject macroObject;
49
50
	/** The macro object id associated with this command */
51
	protected IMacroObjectIdentifier macroObjectIdentifier;
52
53
	/** The corresponding macro object for this object-based macro command */
54
	protected MacroObjectDescriptor macroObjectDescriptor;
55
56
	// used to detect wether a descriptive field has to be detected
57
	boolean needsDescriptiveField = false;
58
59
	/**
60
	 * @param parent
61
	 * @param widgetId
62
	 */
63
	public ObjectBasedCommand(MacroCommandShell parent) {
64
		super(parent);
65
	}
66
67
	protected void preProcessEvent(Event event) throws CoreException {
68
		macroObject = locateMacroObject(event);
69
70
		// retrieve the macro object identifier
71
		IMacroObjectIdentifier identifier = MacroObjectResolver.resolve(
72
				getParent().getShell(), macroObject);
73
		if (identifier == null) {
74
			AutoGUIUtil
75
					.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_MACRO_OBJECT_RESOLVE, macroObject.getUIObject().getWidget()));
76
		}
77
		setMacroObjectIdentifier(identifier);
78
79
		// register with object mine if in use and not already done
80
		MacroObjectDescriptor uiObject = null;
81
		if (useObjectMine()) {
82
			/*
83
			 * Lookup the widget of this command. If it already exists in our
84
			 * object mine, then have it referenced by setting the reference id
85
			 * of the command.
86
			 */
87
			MacroObjectDescriptorMine objectMine = MacroManager.getInstance()
88
					.getObjectMine();
89
90
			try {
91
				MacroObjectDescriptor activeObject = objectMine
92
						.getActiveObject();
93
				uiObject = objectMine.lookupMacroObjectDescriptor(activeObject,
94
						identifier.getContextIdentifier() == null ? null
95
								: identifier.getContextIdentifier(), identifier
96
								.getObjectIdentifier().getWidgetId(), identifier.getObjectIdentifier().getObjectId());
97
98
				/*
99
				 * The object is not registered with the object mine - register
100
				 * it
101
				 */
102
				if (uiObject == null) {
103
					needsDescriptiveField = true;
104
					uiObject = MacroObjectDescriptor.createInstance(this,
105
							activeObject);
106
					objectMine.registerObject((MacroObjectDescriptor) uiObject);
107
				}
108
				setCorrespondingMacroObjectDescriptor(uiObject);
109
			}
110
111
			/*
112
			 * We can't afford to show an error message in case of an unexpected
113
			 * error during registeration. We'll ignore the error and not make
114
			 * use of the object mine.
115
			 */
116
			catch (UIObjectNotFound e) {
117
				/* Should not happen */
118
			} catch (IDCollisionException e) {
119
				/* Should not happen */
120
			} catch (CoreException e) {
121
				/* Should not happen */
122
				e.printStackTrace();
123
			}
124
		}
125
	}
126
127
	protected void doProcessEvent(Event event) throws CoreException {
128
		// nothing to do by default
129
	}
130
131
	protected final void postProcessEvent(Event event) throws CoreException {
132
		// initialize the descriptive field of the associated macro object
133
		// descriptor
134
		if (useObjectMine() && needsDescriptiveField
135
				&& getCorrespondingMacroObjectDescriptor() != null) {
136
			// may safely cast into MacroObjectDescriptor here, as
137
			// needsDescriptiveField is only true if we have created a new one.
138
			((MacroObjectDescriptor) getCorrespondingMacroObjectDescriptor())
139
					.setDescriptive(getObjectClassName(event.widget)
140
							+ (getDescriptiveField() == null ? MacroConstants.EMPTY_STRING
141
									: ": " + getDescriptiveField()));
142
		}
143
	}
144
145
	/**
146
	 * {@inheritDoc}
147
	 * 
148
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.IMacroCommand#processEvent(org.eclipse.swt.widgets.Event)
149
	 */
150
	public final void processEvent(Event event) throws CoreException {
151
		preProcessEvent(event);
152
153
		// let the original implementation do its job (detect the descriptive
154
		// field, for example)
155
		doProcessEvent(event);
156
157
		postProcessEvent(event);
158
	}
159
160
	/**
161
	 * This can be changed by subclasses, if for example a String entry of a
162
	 * combo box has to be checked...
163
	 * 
164
	 * @param event
165
	 * @return
166
	 */
167
	protected IMacroObject locateMacroObject(Event event) {
168
		return new MacroObject(new UIObject(event.widget));
169
	}
170
171
	/**
172
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.IMacroInstruction#getCorrespondingMacroObjectDescriptor()
173
	 */
174
	public MacroObjectDescriptor getCorrespondingMacroObjectDescriptor() {
175
		return macroObjectDescriptor;
176
	}
177
178
	/**
179
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.IMacroInstruction#setCorrespondingMacroObjectDescriptor(org.eclipse.tptp.test.auto.gui.internal.util.MacroObjectDescriptor)
180
	 */
181
	protected void setCorrespondingMacroObjectDescriptor(
182
			MacroObjectDescriptor uiObject) {
183
		this.macroObjectDescriptor = uiObject;
184
	}
185
186
	/**
187
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.IMacroInstruction#getMacroObjectIdentifier()
188
	 */
189
	public IMacroObjectIdentifier getMacroObjectIdentifier() {
190
		return macroObjectIdentifier;
191
	}
192
193
	/**
194
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.IMacroInstruction#setMacroObjectIdentifier(IMacroObjectIdentifier)
195
	 */
196
	protected void setMacroObjectIdentifier(
197
			IMacroObjectIdentifier objectIdentifier) {
198
		this.macroObjectIdentifier = objectIdentifier;
199
	}
200
201
	public void load(Node node, Hashtable lineTable) throws CoreException {
202
		super.load(node, lineTable);
203
204
		loadMacroObjectIdentifier(node, lineTable);
205
	}
206
207
	protected void loadMacroObjectIdentifier(Node node, Hashtable lineTable)
208
			throws CoreException {
209
		MacroObjectDescriptor commandObject = null;
210
		if (MacroManager.getInstance().getObjectMine() != null) {
211
			commandObject = MacroManager.getInstance().getObjectMine().lookupReferenceId(
212
					getParent().getCorrespondingMacroObjectDescriptor(), node,
213
					lineTable);
214
		}
215
		boolean isObjectFound = commandObject != null;
216
		if (isObjectFound) {
217
			setCorrespondingMacroObjectDescriptor(commandObject);
218
		}
219
		
220
		String cid = isObjectFound ? commandObject.getContextId() : MacroUtil
221
				.getAttribute(node, MacroConstants.CONTEXT_ID_ATTRIBUTE);
222
		String wid = isObjectFound ? commandObject.getWidgetId() : MacroUtil
223
				.getAttribute(node, MacroConstants.WIDGET_ID_ATTRIBUTE);
224
		String obj = isObjectFound ? commandObject.getObjectId() : MacroUtil
225
				.getAttribute(node, MacroConstants.OBJECT_ID_ATTRIBUTE);
226
		String rid = isObjectFound ? commandObject.getResolverId() : MacroUtil
227
				.getAttribute(node, MacroConstants.RESOLVER_ID_ATTRIBUTE);
228
229
		if (cid != null && wid != null) {
230
			PrimitiveUIObjectIdentifier objectIdentifier = null;
231
			if (wid == null) {
232
				objectIdentifier = new PrimitiveUIObjectIdentifier(
233
						MacroConstants.EMPTY_STRING, rid);
234
			} else {
235
				objectIdentifier = new PrimitiveUIObjectIdentifier(wid,
236
						obj, rid);
237
			}
238
			setMacroObjectIdentifier(new MacroObjectIdentifier(
239
					cid == null ? MacroConstants.EMPTY_STRING : cid,
240
					objectIdentifier));
241
		}
242
	}
243
244
	public void write(int indent, StringBuffer sb, boolean close, boolean end) {
245
		// let the super implementation write the element, we will just add our
246
		// attributes
247
		super.write(indent, sb, false, false);
248
249
		writeMacroObjectIdentifier(indent, sb, close, end);
250
	}
251
252
	protected void writeMacroObjectIdentifier(int indent, StringBuffer sb,
253
			boolean close, boolean end) {
254
		boolean noWidgetId = getMacroObjectIdentifier() == null;
255
		boolean objectMineInUse = useObjectMine();
256
		MacroUtil
257
				.addAttribute(
258
						sb,
259
						new String[] { MacroConstants.RESOLVER_ID_ATTRIBUTE,
260
								MacroConstants.CONTEXT_ID_ATTRIBUTE,
261
								MacroConstants.WIDGET_ID_ATTRIBUTE,
262
								MacroConstants.OBJECT_ID_ATTRIBUTE,
263
								MacroConstants.REFERENCE_ID_ATTRIBUTE },
264
						new String[] {
265
								objectMineInUse || noWidgetId ? null
266
										: getMacroObjectIdentifier()
267
												.getObjectIdentifier()
268
												.getResolverId(),
269
								objectMineInUse || noWidgetId ? null
270
										: getMacroObjectIdentifier()
271
												.getContextIdentifier(),
272
								objectMineInUse || noWidgetId ? null
273
										: getMacroObjectIdentifier()
274
												.getObjectIdentifier()
275
												.getWidgetId(),
276
								objectMineInUse || noWidgetId ? null
277
										: getMacroObjectIdentifier()
278
												.getObjectIdentifier()
279
												.getObjectId(),
280
								objectMineInUse ? getCorrespondingMacroObjectDescriptor()
281
										.getReferenceId()
282
										: null }, close, end);
283
	}
284
285
	protected boolean useObjectMine() {
286
		return MacroManager.getInstance().isObjectMineOn();
287
	}
288
289
	public boolean playback(Display display, Shell parent,
290
			IProgressMonitor monitor) throws CoreException {
291
		if (getMacroObjectIdentifier() != null) {
292
			macroObject = MacroObjectResolver.deresolve(parent,
293
						getMacroObjectIdentifier());
294
		}
295
		return doPlayback(display, parent, monitor);
296
	}
297
298
	public boolean doPlayback(Display display, Shell parent,
299
			IProgressMonitor monitor) throws CoreException{
300
		// nothing to do by default
301
		return false;
302
	}
303
304
	/**
305
	 * {@inheritDoc}
306
	 * 
307
	 * @see org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand#equals(java.lang.Object)
308
	 */
309
	public boolean equals(Object obj) {
310
		if (!super.equals(obj)) {
311
			return false;
312
		}
313
		if (!(obj instanceof ObjectBasedCommand)) {
314
			return false;
315
		}
316
		ObjectBasedCommand compareWithObj = (ObjectBasedCommand) obj;
317
		return compareWithObj.getMacroObjectIdentifier() != null
318
				&& compareWithObj.getMacroObjectIdentifier().equals(
319
						getMacroObjectIdentifier());
320
	}
321
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/resolver/delegate/NonTrivialUIObjectResolverDelegate.java (+879 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * $Id: NonTrivialUIObjectResolverDelegate.java,v 1.4 2007/05/02 19:35:58 paules Exp $
8
 * 
9
 * Contributors:
10
 *     IBM Corporation - initial API and implementation
11
 *******************************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate;
13
14
import java.util.Vector;
15
16
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.hyades.models.hierarchy.TRCAgentProxy;
18
import org.eclipse.jface.action.ActionContributionItem;
19
import org.eclipse.jface.action.IAction;
20
import org.eclipse.jface.action.IContributionItem;
21
import org.eclipse.jface.window.Window;
22
import org.eclipse.jface.wizard.IWizardPage;
23
import org.eclipse.jface.wizard.WizardDialog;
24
import org.eclipse.swt.custom.CCombo;
25
import org.eclipse.swt.custom.CTabFolder;
26
import org.eclipse.swt.custom.CTabItem;
27
import org.eclipse.swt.graphics.Point;
28
import org.eclipse.swt.widgets.Button;
29
import org.eclipse.swt.widgets.Combo;
30
import org.eclipse.swt.widgets.Composite;
31
import org.eclipse.swt.widgets.Control;
32
import org.eclipse.swt.widgets.Group;
33
import org.eclipse.swt.widgets.Item;
34
import org.eclipse.swt.widgets.Label;
35
import org.eclipse.swt.widgets.Menu;
36
import org.eclipse.swt.widgets.MenuItem;
37
import org.eclipse.swt.widgets.Shell;
38
import org.eclipse.swt.widgets.TabFolder;
39
import org.eclipse.swt.widgets.TabItem;
40
import org.eclipse.swt.widgets.Text;
41
import org.eclipse.swt.widgets.ToolBar;
42
import org.eclipse.swt.widgets.ToolItem;
43
import org.eclipse.swt.widgets.Tree;
44
import org.eclipse.swt.widgets.TreeItem;
45
import org.eclipse.swt.widgets.Widget;
46
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
47
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
48
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObject;
49
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObject;
50
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
51
import org.eclipse.tptp.test.auto.gui.internal.uiobject.PrimitiveUIObjectIdentifier;
52
import org.eclipse.tptp.test.auto.gui.internal.uiobject.UIObject;
53
import org.eclipse.tptp.test.auto.gui.internal.uiobject.WeightedPropertyUIObjectIdentifier;
54
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.UIObjectResolver;
55
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.deresolvingsupport.IUIObjectDeprecatedDeresolvingFacade;
56
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.deresolvingsupport.UIObjectDeprecatedDeresolvingSupport;
57
import org.eclipse.tptp.trace.ui.internal.launcher.core.AnalysisType;
58
import org.eclipse.tptp.trace.ui.internal.launcher.core.DataCollectorTreeContentProvider.ParentChildNode;
59
import org.eclipse.ui.IPluginContribution;
60
import org.eclipse.ui.IViewPart;
61
import org.eclipse.ui.IWorkbenchPage;
62
import org.eclipse.ui.IWorkbenchPart;
63
import org.eclipse.ui.IWorkbenchWindow;
64
import org.eclipse.ui.dialogs.FileSystemElement;
65
import org.eclipse.ui.model.IWorkbenchAdapter;
66
import org.eclipse.ui.views.IViewCategory;
67
68
/**
69
 * <p>
70
 * The purpose of this class is to resolve widgets that cannot be resolved using
71
 * the AdaptiveUIObjectResolverDelegate. These widgets will likely require
72
 * nested calls in order to be determined.
73
 * </p>
74
 * <p>
75
 * Some of the properties used to resolve a widget are locale dependent (e.g.
76
 * the name of a button or the closest label to a text box)
77
 * </p>
78
 * 
79
 * @since 4.1
80
 * @author Ali Mehregani
81
 * @author Alexander Nyssen
82
 */
83
public class NonTrivialUIObjectResolverDelegate implements
84
		IUIObjectResolverDelegate, IUIObjectDeprecatedDeresolvingFacade {
85
86
	/**
87
	 * The id of this resolver -- must be in sync with the id registered with
88
	 * the widgetResolver extension.
89
	 */
90
	public static final String ID = "org.eclipse.tptp.test.auto.gui.nontrivial";
91
92
	public IUIObjectIdentifier resolve(Object context, IUIObject uiObject)
93
			throws CoreException {
94
		Widget widget = uiObject.getWidget();
95
		Object object = uiObject.getObject();
96
97
		Object data = widget.getData();
98
99
		IUIObjectIdentifier widgetId = null;
100
101
		/* Resolve the object based on the data type of the widget */
102
		/* An agent */
103
		if (data instanceof TRCAgentProxy) {
104
			widgetId = resolveAgentProxy(widget);
105
		}
106
		/* A file system element */
107
		else if (data instanceof FileSystemElement) {
108
			widgetId = resolveFileSystemElement(widget);
109
		}
110
		/* A view catgory */
111
		else if (data instanceof IViewCategory) {
112
			String id = ((IViewCategory) data).getId();
113
			if (id != null && id.length() > 0) {
114
				widgetId = new PrimitiveUIObjectIdentifier(id, ID);
115
			}
116
		}
117
		/* Analysis type */
118
		else if (data instanceof ParentChildNode) {
119
			Object child = ((ParentChildNode) data).child;
120
			if (child instanceof AnalysisType) {
121
				widgetId = resolveAnalysisType((AnalysisType) child);
122
			}
123
		}
124
		/* A menu item or a tree item */
125
		else if (widget instanceof MenuItem || widget instanceof TreeItem) {
126
			widgetId = resolveItem((Item) widget);
127
		}
128
		/* A TabItem or CTabItem */
129
		else if (widget instanceof TabItem || widget instanceof CTabItem) {
130
			String itemText = validateText(widget instanceof TabItem ? ((TabItem) widget)
131
					.getText()
132
					: ((CTabItem) widget).getText());
133
			widgetId = itemText != null ? new PrimitiveUIObjectIdentifier(
134
					itemText, ID) : null;
135
		}
136
		/* A tool item */
137
		else if (widget instanceof ToolItem) {
138
			widgetId = resolveToolbarItem((ToolItem) widget);
139
		}
140
		/* A menu (added by ANy) */
141
		else if (widget instanceof Menu) {
142
			widgetId = getActionId((Menu) widget);
143
		}
144
		// controls
145
		else if (widget instanceof Control) {
146
			/* A button */
147
			if (widget instanceof Button) {
148
				widgetId = resolveButton((Button) widget);
149
			}
150
			/* A text box */
151
			else if (widget instanceof Text) {
152
				widgetId = resolveText((Text) widget);
153
			}
154
			/* A toolbar */
155
			else if (widget instanceof ToolBar) {
156
				widgetId = resolveToolBar((ToolBar) widget);
157
			}
158
			/* Resolve the object based on its widget type */
159
			/* A control (added by ANy) */
160
			else if (widget instanceof Shell) {
161
				widgetId = getShellId((Shell) widget);
162
			}
163
164
			if (widgetId == null) {
165
				Control control = (Control) widget;
166
				Shell shell = control.getShell();
167
				Object shellData = shell.getData();
168
				if (shellData instanceof WizardDialog) {
169
					// in wizard
170
					WizardDialog wd = (WizardDialog) shellData;
171
					IWizardPage page = wd.getCurrentPage();
172
					Control pageControl = page.getControl();
173
					widgetId = computeRelativePath((Composite) pageControl,
174
							null, control);
175
					if (widgetId == null) {
176
						// check for wizard buttons
177
						if (control instanceof Button) {
178
							widgetId = computeRelativePath(shell,
179
									(Composite) pageControl, control);
180
						}
181
					}
182
				} else if (shellData instanceof IWorkbenchWindow) {
183
184
					IWorkbenchWindow window = (IWorkbenchWindow) shellData;
185
					IWorkbenchPage page = window.getActivePage();
186
					IWorkbenchPart part = page.getActivePart();
187
188
					Composite paneComposite = MacroUtil
189
							.getWorkbenchPartControl(part);
190
191
					/*
192
					 * If the control we are looking for is a local tool bar, go
193
					 * up one level
194
					 */
195
					if (part instanceof IViewPart && control instanceof ToolBar) {
196
						paneComposite = paneComposite.getParent();
197
					}
198
					widgetId = computeRelativePath(paneComposite, null, control);					
199
				} else {
200
					/* unknown shell - fetch controls starting from the shell */
201
					widgetId = computeRelativePath(shell, null, control);
202
				}
203
204
				// ANy: in case we have items on a combo box or tab folder
205
				if (uiObject.getObject() != null && (widget instanceof Combo
206
						|| widget instanceof CCombo)) {
207
208
					widgetId = new PrimitiveUIObjectIdentifier(widgetId
209
							.getWidgetId(), computeDefaultChoiceId(widget,
210
							uiObject.getObject()).toString(), ID);
211
				}
212
			}
213
		}
214
215
		/*
216
		 * (added by ANy) Defect #: 112668: If we have to resolve an Item try
217
		 * the old policy before giving up
218
		 */
219
		if (widgetId == null && widget instanceof Item) {
220
			widgetId = determineItemId((Item) widget);
221
		}
222
223
		return widgetId;
224
	}
225
226
	public IUIObject deresolve(Object context,
227
			IUIObjectIdentifier uiObjectIdentifier) throws CoreException {
228
		return UIObjectDeprecatedDeresolvingSupport.deresolve(context,
229
				uiObjectIdentifier);
230
	}
231
232
	private IUIObjectIdentifier resolveAnalysisType(AnalysisType analysisType) {
233
		Object[] properties = { new Object[] { analysisType.getId(), "1.0" }, };
234
235
		return WeightedPropertyUIObjectIdentifier.constructId(properties,
236
				(float) 1.0, ID);
237
	}
238
239
	private IUIObjectIdentifier resolveToolBar(ToolBar toolbar) {
240
		int itemCount = toolbar.getItemCount();
241
		String firstItem = itemCount > 1 ? limitText(toolbar.getItem(0)
242
				.getToolTipText()) : null, lastItem = itemCount > 2 ? limitText(toolbar
243
				.getItem(itemCount - 1).getToolTipText())
244
				: null;
245
		int style = toolbar.getStyle();
246
247
		if (firstItem == null && lastItem == null)
248
			return null;
249
250
		Object[] properties = { new Object[] { firstItem, "0.5" },
251
				new Object[] { lastItem, "0.5" },
252
				new Object[] { String.valueOf(itemCount), "0.3" },
253
				new Object[] { String.valueOf(style), "0.2" } };
254
255
		return WeightedPropertyUIObjectIdentifier.constructId(properties,
256
				(float) 1.0, ID);
257
	}
258
259
	private IUIObjectIdentifier resolveToolbarItem(ToolItem item) {
260
		String text = limitText(item.getToolTipText());
261
		String actionId = getActionId(item).toString();
262
		String style = String.valueOf(item.getStyle());
263
264
		Object[] properties = { new Object[] { text, "0.7" },
265
				new Object[] { actionId, "0.7" }, new Object[] { style, "0.3" } };
266
267
		return WeightedPropertyUIObjectIdentifier.constructId(properties,
268
				(float) 1.0, ID);
269
	}
270
271
	private String limitText(String str) {
272
		final int MAX_HOVER_TEXT_SIZE = 20;
273
		if (str != null && str.length() > MAX_HOVER_TEXT_SIZE) {
274
			return str.substring(0, MAX_HOVER_TEXT_SIZE) + "...";
275
		}
276
		return str;
277
	}
278
279
	/*
280
	 * Needed to find buttons, which are identified by a deprecated identifier
281
	 * format
282
	 */
283
	private IUIObjectIdentifier resolveButtonDeprecated(Button button,
284
			IUIObjectIdentifier id) {
285
		String text = null, hoverText = null, size = null, location = null;
286
		if ((text = button.getText()) != null) {
287
			text = text.replaceAll("\\&", "");
288
		}
289
		/* First 20 characters of the hover text */
290
		hoverText = limitText(button.getToolTipText());
291
		Point sizePt = button.getSize();
292
		Point locationPt = button.getLocation();
293
		size = "(" + sizePt.x + "," + sizePt.y + ")";
294
295
		if (id != null && countTokens(id.toString()) == 3) {
296
297
			Object[] properties = { new Object[] { text, "0.5" },
298
					new Object[] { hoverText, "0.5" },
299
					new Object[] { size, "0.5" } };
300
301
			return WeightedPropertyUIObjectIdentifier.constructId(properties,
302
					(float) 1.0, ID);
303
		}
304
		return null;
305
	}
306
307
	private IUIObjectIdentifier resolveButton(Button button) {
308
		String text = null, hoverText = null, size = null, location = null;
309
		if ((text = button.getText()) != null) {
310
			text = text.replaceAll("\\&", "");
311
		}
312
		/* First 20 characters of the hover text */
313
		hoverText = limitText(button.getToolTipText());
314
		Point sizePt = button.getSize();
315
		Point locationPt = button.getLocation();
316
		size = "(" + sizePt.x + "," + sizePt.y + ")";
317
		location = "(" + locationPt.x + "," + locationPt.y + ")";
318
319
		if (button.getParent() != null) {
320
			// Control[] children = ((Composite)parent).getChildren();
321
			Control[] children = button.getParent().getChildren();
322
			int buttonInx = 0;
323
324
			/* Find the index of the button */
325
			for (int i = 0; i < children.length; i++) {
326
				if (button == children[i]) {
327
					buttonInx = i;
328
					break;
329
				}
330
			}
331
332
			Object[] properties = { new Object[] { text, "0.3" },
333
					new Object[] { hoverText, "0.3" },
334
					new Object[] { String.valueOf(children.length), "0.3" },
335
					new Object[] { size, "0.2" },
336
					new Object[] { location, "0.1" },
337
					new Object[] { String.valueOf(buttonInx), "0.2" }, };
338
339
			float threshold = 0.7f;
340
			threshold += text != null ? 0.3 : 0;
341
			threshold += hoverText != null ? 0.3 : 0;
342
343
			if (threshold >= 1.0)
344
				return WeightedPropertyUIObjectIdentifier.constructId(
345
						properties, (float) 1.0, ID);
346
		}
347
348
		return null;
349
	}
350
351
	/**
352
	 * The text of the closest label to a text box is used as a unique
353
	 * identifier of the text box. The label must be in a limited vicinity of
354
	 * the text box for its text to be considered as an identifier. If the text
355
	 * box is owned by a group and the group only owns one text box, then the
356
	 * group text is used to identify the widget.
357
	 * 
358
	 * @param text
359
	 *            The text box
360
	 * @return The widget id for text
361
	 */
362
	private IUIObjectIdentifier resolveText(Text text) {
363
		Composite parent = text.getParent();
364
		Control[] children = parent.getChildren();
365
366
		String groupText = null;
367
		if (parent instanceof Group
368
				&& (groupText = ((Group) parent).getText()) != null
369
				&& (groupText = groupText.replaceAll("\\&", "")).length() > 0) {
370
			int textBoxNum = 0;
371
			for (int i = 0; i < children.length && textBoxNum <= 1; i++) {
372
				if (children[i] instanceof Text)
373
					textBoxNum++;
374
			}
375
376
			if (textBoxNum <= 1)
377
				return new PrimitiveUIObjectIdentifier(groupText, ID);
378
		}
379
380
		Label closestLabel = null;
381
		Point textLocation = text.getLocation();
382
		Point currentDistance = new Point(0, 0);
383
		Point tempDistance = new Point(0, 0);
384
		for (int i = 0; i < children.length; i++) {
385
			Point childLocation = children[i].getLocation();
386
			if (children[i] instanceof Label
387
					&& (closestLabel == null || (tempDistance = isLabelCloser(
388
							childLocation, currentDistance, textLocation)) != null)) {
389
				boolean firstLabel = closestLabel == null;
390
				closestLabel = (Label) children[i];
391
				;
392
				if (firstLabel) {
393
					currentDistance = new Point(Math.abs(childLocation.x
394
							- textLocation.x), Math.abs(childLocation.y
395
							- textLocation.y));
396
				} else {
397
					currentDistance = tempDistance;
398
				}
399
			}
400
		}
401
402
		String closestLabelText = null;
403
		if (closestLabel != null
404
				&& currentDistance.x + currentDistance.y <= 100
405
				&& closestLabel.getText() != null
406
				&& (closestLabelText = closestLabel.getText().replaceAll("\\&",
407
						"")).length() > 0)
408
			return new PrimitiveUIObjectIdentifier(closestLabelText, ID);
409
		return null;
410
	}
411
412
	private Point isLabelCloser(Point newlblLocation, Point currentDistance,
413
			Point textLocation) {
414
		Point tempLocation = new Point(Math.abs(newlblLocation.x
415
				- textLocation.x), Math.abs(newlblLocation.y - textLocation.y));
416
		if (tempLocation.x + tempLocation.y < currentDistance.x
417
				+ currentDistance.y)
418
			return tempLocation;
419
		return null;
420
	}
421
422
	public static String validateText(String text) {
423
		if (text != null && (text = text.replaceAll("\\&", "")).length() > 0)
424
			return text;
425
		return null;
426
	}
427
428
	/**
429
	 * Computes the item id based on the following properties and weights. The
430
	 * threshold is set to 1.0:
431
	 * 
432
	 * <ul>
433
	 * <li> (Descriptive name of the item, 1.0) </li>
434
	 * </ul>
435
	 * 
436
	 * @param item
437
	 *            The item
438
	 * @return The weighted id
439
	 */
440
	private IUIObjectIdentifier resolveItem(Item item) {
441
		StringBuffer descriptiveText = new StringBuffer();
442
		findItemText(item, descriptiveText);
443
444
		/* Remove the ampersands */
445
		String itemText = descriptiveText.toString().replaceAll("\\&", "");
446
447
		Object[] properties = { new Object[] { itemText, "1.0" }, };
448
449
		return WeightedPropertyUIObjectIdentifier.constructId(properties,
450
				(float) 1.0, ID);
451
	}
452
453
	/**
454
	 * Walk through the item and return a descriptive text that corresponds to
455
	 * all item selections leading to the item. (e.g. File-New-Project)
456
	 * 
457
	 * @param item
458
	 *            The item
459
	 * @param descriptiveText
460
	 *            In the end, this buffer will contain a descriptive text of all
461
	 *            items leading to the item that is passed in as argument
462
	 */
463
	private void findItemText(Item item, StringBuffer descriptiveText) {
464
		if (item == null)
465
			return;
466
467
		String descriptiveTextStr = item.getText();
468
		if (descriptiveText.length() > 0)
469
			descriptiveTextStr += "-";
470
471
		descriptiveText.insert(0, descriptiveTextStr);
472
473
		Item parentItem = null;
474
		if (item instanceof MenuItem) {
475
			Menu menu = ((MenuItem) item).getParent();
476
			parentItem = (menu == null ? null : menu.getParentItem());
477
		} else if (item instanceof TreeItem) {
478
			parentItem = ((TreeItem) item).getParentItem();
479
		}
480
481
		if (parentItem != null)
482
			findItemText(parentItem, descriptiveText);
483
	}
484
485
	private IUIObjectIdentifier resolveFileSystemElement(Widget widget) {
486
487
		FileSystemElement fileSystemElement = (FileSystemElement) widget
488
				.getData();
489
		if (fileSystemElement.isDirectory())
490
			return null;
491
492
		Object[] properties = { new Object[] {
493
				((IWorkbenchAdapter) fileSystemElement
494
						.getAdapter(IWorkbenchAdapter.class)).getLabel(null),
495
				"1.0" } };
496
497
		return WeightedPropertyUIObjectIdentifier.constructId(properties,
498
				(float) 1.0, ID);
499
	}
500
501
	private WeightedPropertyUIObjectIdentifier resolveAgentProxy(Widget widget) {
502
		StringBuffer treeIndex = new StringBuffer();
503
		if (widget instanceof TreeItem)
504
			findTreeItemIndex((TreeItem) widget, treeIndex);
505
		else
506
			return null;
507
508
		TRCAgentProxy proxy = (TRCAgentProxy) widget.getData();
509
		Object[] properties = {
510
				new Object[] { treeIndex.toString(), "0.4" },
511
				new Object[] { proxy.getProcessProxy().getName(), "0.2" },
512
				new Object[] { proxy.getProcessProxy().getVmArguments(), "0.1" },
513
				new Object[] { proxy.getProcessProxy().getClasspath(), "0.1" },
514
				new Object[] { proxy.getProcessProxy().getLocation(), "0.1" },
515
				new Object[] { proxy.getProcessProxy().getParameters(), "0.1" },
516
				new Object[] { proxy.getProfileFile(), "0.1" },
517
				new Object[] { proxy.getName(), "0.1" },
518
				new Object[] { String.valueOf(proxy.isAttached()), "0.1" },
519
				new Object[] { String.valueOf(proxy.isMonitored()), "0.1" },
520
				new Object[] { String.valueOf(proxy.isToProfileFile()), "0.1" }, };
521
522
		return WeightedPropertyUIObjectIdentifier.constructId(properties,
523
				(float) 0.7, ID);
524
	}
525
526
	private void findTreeItemIndex(TreeItem treeItem, StringBuffer sb) {
527
		TreeItem parentItem = treeItem.getParentItem();
528
		if (parentItem != null) {
529
			int index = parentItem.indexOf(treeItem);
530
			if (index != -1)
531
				sb.append("|" + String.valueOf(index + 1));
532
533
			findTreeItemIndex(parentItem, sb);
534
		}
535
		Tree tree = treeItem.getParent();
536
		int index = tree.indexOf(treeItem);
537
		if (index != -1)
538
			sb.append("|" + String.valueOf(index));
539
540
	}
541
542
	/**
543
	 * @deprecated This can be removed the resolver does not longer depend on
544
	 *             the UIDeprecatedDeresolvingSupport to deresolve UI objects.
545
	 *             {@inheritDoc}
546
	 * @see org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.deresolvingsupport.internal.uiobject.resolver.delegate.IUIObjectDeprecatedDeresolvingFacade#foundWidget(org.eclipse.swt.widgets.Widget,
547
	 *      org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier)
548
	 */
549
	public boolean foundWidget(Widget widget, IUIObjectIdentifier widgetId) {
550
		IUIObjectIdentifier objectId = null;
551
552
		// ANy: It seems that the resolving for buttons was changed. For
553
		// backwards compatibility,
554
		// the foundWidget has to accept the old button identifier format as
555
		// well.
556
		if (widget instanceof Button) {
557
			Button button = (Button) widget;
558
			objectId = resolveButtonDeprecated(button, widgetId);
559
		}
560
561
		if (objectId == null)
562
			try {
563
				objectId = UIObjectResolver.resolve(new MacroObject(
564
						new UIObject(widget)).getContext(),
565
						new UIObject(widget));
566
			} catch (Exception e) {
567
				e.printStackTrace();
568
			}
569
		if (widgetId == null || widgetId.getWidgetId() == null) {
570
			return false;
571
		} else {
572
			if (objectId == null) {
573
				return false;
574
			} else {
575
				return objectId.equals(widgetId);
576
			}
577
		}
578
	}
579
580
	/**
581
	 * Given a string representation of the id, this method will return the
582
	 * number of tokens that it contains. A token is a name, value pair in the
583
	 * format.
584
	 * 
585
	 * @param id
586
	 *            The string representation of the id
587
	 * @return The number of tokens of the id
588
	 */
589
	public static int countTokens(String id) {
590
		if (id == null)
591
			return 0;
592
593
		char[] characters = id.toCharArray();
594
		boolean braceInxHit = false;
595
		int tokenCount = 0;
596
		for (int i = 0; i < characters.length; i++) {
597
			if (characters[i] == '{') {
598
				if (braceInxHit) {
599
					tokenCount++;
600
				} else {
601
					braceInxHit = true;
602
					continue;
603
				}
604
			}
605
			braceInxHit = false;
606
		}
607
608
		return tokenCount / 2;
609
	}
610
611
	/**
612
	 * Defect #: 112668 This method is invoked to retrieve the id of a menu
613
	 * item. Here's the policy that it employs:
614
	 * <ol>
615
	 * <li> Use the contributed widget resolvers </li>
616
	 * <li> If failed, default to what was being used before </li>
617
	 * </ol>
618
	 * 
619
	 * @param item
620
	 *            The menu item
621
	 * @return The id of the passed item.
622
	 */
623
	private IUIObjectIdentifier determineItemId(Item item) {
624
		if (item instanceof ToolItem) {
625
			return getActionId((ToolItem) item);
626
		} else if (item instanceof MenuItem) {
627
			return getActionId((MenuItem) item);
628
		} else if (item instanceof IContributionItem) {
629
			return getActionId((IContributionItem) item);
630
		}
631
		return null;
632
	}
633
634
	/**
635
	 * @param widget
636
	 * @return
637
	 */
638
	public static IUIObjectIdentifier getActionId(Widget widget) {
639
		Object data = widget.getData();
640
		PrimitiveUIObjectIdentifier widgetId = null;
641
		if (data != null && (data instanceof IContributionItem)) {
642
			widgetId = getActionId((IContributionItem) data);
643
			if (widgetId != null
644
					&& !widgetId.toString().equals(MacroConstants.EMPTY_STRING)) {
645
				if (widget instanceof MenuItem) {
646
					String menuInx = findMenuItemIndex((MenuItem) widget, "");
647
					widgetId = new PrimitiveUIObjectIdentifier(widgetId
648
							.toString()
649
							+ menuInx, ID);
650
				}
651
			}
652
		} else {
653
			widgetId = new PrimitiveUIObjectIdentifier(
654
					"readablename/" + ((widget instanceof MenuItem) ? getDisplayName((MenuItem) widget) : getDisplayName((ToolItem) widget)), ID); //$NON-NLS-1$
655
		}
656
657
		return widgetId;
658
	}
659
660
	public static PrimitiveUIObjectIdentifier getActionId(
661
			IContributionItem contrib) {
662
		String id = null;
663
		PrimitiveUIObjectIdentifier widgetId = null;
664
665
		if (contrib instanceof IPluginContribution) {
666
			id = ((IPluginContribution) contrib).getLocalId();
667
		}
668
		id = id == null ? contrib.getId() : id;
669
		if (id != null) {
670
			widgetId = new PrimitiveUIObjectIdentifier("contribid/" + id, ID); //$NON-NLS-1$
671
		} else {
672
			if (contrib instanceof ActionContributionItem) {
673
				ActionContributionItem actionItem = (ActionContributionItem) contrib;
674
				id = actionItem.getId();
675
				if (id != null) {
676
					widgetId = new PrimitiveUIObjectIdentifier(
677
							"actionid/" + id, ID); //$NON-NLS-1$
678
				} else {
679
					IAction action = actionItem.getAction();
680
					id = action.getActionDefinitionId();
681
					if (id != null) {
682
						widgetId = new PrimitiveUIObjectIdentifier(
683
								"defid/" + id, ID); //$NON-NLS-1$
684
					} else {
685
						widgetId = new PrimitiveUIObjectIdentifier(
686
								"actionclass/" + action.getClass().getName(), ID); //$NON-NLS-1$
687
					}
688
				}
689
			} else {
690
				widgetId = new PrimitiveUIObjectIdentifier(
691
						"contribclass/" + contrib.getClass().getName(), ID); //$NON-NLS-1$				
692
			}
693
		}
694
695
		return widgetId;
696
	}
697
698
	/**
699
	 * @deprecated Should not be done here, but in the delegators Walks through
700
	 *             all parent menus of the menuItem and returns an index of
701
	 *             format &lt;num&gt;|&lt;num&gt;|&lt;num&gt;|... For example
702
	 *             assuming menuItem is placed as follows:
703
	 * 
704
	 * item 1 |_item 2 | |_item 4 |_item 3 |_menuItem
705
	 * 
706
	 * then its respective index will be 1|2|1
707
	 * 
708
	 * @param menuItem
709
	 *            The menu item whose index will be determined
710
	 * @return The index of the menu item as described above.
711
	 */
712
	private static String findMenuItemIndex(MenuItem menuItem, String menuInx) {
713
		if (menuItem == null)
714
			return menuInx;
715
716
		if (menuInx.length() > 0)
717
			menuInx = "|" + menuInx;
718
		menuInx = menuItem.getParent().indexOf(menuItem) + menuInx;
719
		return findMenuItemIndex(menuItem.getParent().getParentItem(), menuInx);
720
	}
721
722
	/**
723
	 * Returns an identifier for the given Menu, based on its user-readable
724
	 * strings
725
	 * 
726
	 * @param menu
727
	 * @return
728
	 */
729
	private static String getDisplayName(Menu menu) {
730
731
		MenuItem parentItem = menu.getParentItem();
732
733
		if (parentItem == null) {
734
			return MacroConstants.EMPTY_STRING;
735
		}
736
737
		return getDisplayName(parentItem);
738
	}
739
740
	/**
741
	 * Returns an identifier for the given MenuItem, based on its user-readable
742
	 * strings
743
	 * 
744
	 * @param menuItem
745
	 * @return
746
	 */
747
	private static String getDisplayName(MenuItem menuItem) {
748
		if (menuItem.getParent() == null
749
				|| menuItem.getParent().getParentItem() == null) {
750
			return MacroUtil.removeChar(menuItem.getText(), '&');
751
		}
752
753
		return getDisplayName(menuItem.getParent()) + "/" //$NON-NLS-1$
754
				+ MacroUtil.removeChar(menuItem.getText(), '&');
755
	}
756
757
	/**
758
	 * @param toolItem
759
	 * @return
760
	 */
761
	private static String getDisplayName(ToolItem toolItem) {
762
		String name = toolItem.getText();
763
764
		if (name != null && !name.equals(MacroConstants.EMPTY_STRING)) {
765
			return name;
766
		}
767
768
		name = toolItem.getToolTipText();
769
770
		if (name != null) {
771
			return name;
772
		}
773
774
		return "unknown"; //$NON-NLS-1$
775
	}
776
777
	/**
778
	 * @deprecated Use resolveUIObject instead (move implementation there)
779
	 * @param context
780
	 * @param parent
781
	 * @param skip
782
	 * @param control
783
	 * @return
784
	 */
785
	public static IUIObjectIdentifier computeRelativePath(Composite parent,
786
			Composite skip, Control control) {
787
		int[] counter = MacroUtil.newCounter();
788
		Vector indices = new Vector();
789
		boolean result = computeControlIndex(parent, skip, control, counter,
790
				indices);
791
		if (!result && skip == null)
792
			return null;
793
794
		int index = result ? ((Integer) indices.get(0)).intValue() : 0;
795
		return computeDefaultControlId(control, index);
796
	}
797
798
	/**
799
	 * Determines the index of the desiredControl relative to the parent control
800
	 * sent in. The Index is stored in index[0].
801
	 * 
802
	 * @param parent
803
	 *            The parent control
804
	 * @param skip
805
	 *            Indicates whether a composite should be skipped
806
	 * @param desiredControl
807
	 *            The desired control
808
	 * @param index
809
	 *            The current index calculated thus far (stored in index[0]. The
810
	 *            type of this parameter is an int array because its value needs
811
	 *            to be preserved between recursive calls.
812
	 * 
813
	 * @return true if the index was found; false otherwise.
814
	 */
815
	private static boolean computeControlIndex(Composite parent,
816
			Composite skip, Control desiredControl, int[] index, Vector indices) {
817
		return UIObjectDeprecatedDeresolvingSupport.recursiveSearch(parent,
818
				skip, desiredControl, null, null, index, new Vector(), indices) != null;
819
	}
820
821
	public static IUIObjectIdentifier computeDefaultControlId(Control control,
822
			int controlIndex) {
823
		PrimitiveUIObjectIdentifier primitiveWidgetId = new PrimitiveUIObjectIdentifier(
824
				control.getClass().getName() + "#" + controlIndex, ID);
825
		return primitiveWidgetId;
826
	}
827
828
	/**
829
	 * Moved here from ChoiceCommand
830
	 * 
831
	 * @param widget
832
	 * @param item
833
	 * @return
834
	 */
835
	private IUIObjectIdentifier computeDefaultChoiceId(Widget widget,
836
			Object item) {
837
		int index = -1;
838
		boolean isCombo = widget instanceof Combo;
839
		boolean isCCombo = isCombo ? false : widget instanceof CCombo;
840
		if (isCombo || isCCombo) {
841
			Combo combo = isCombo ? ((Combo) widget) : null;
842
			CCombo ccombo = isCCombo ? ((CCombo) widget) : null;
843
844
			index = isCombo ? combo.indexOf((String) item) : ccombo
845
					.indexOf((String) item);
846
		} else {
847
			boolean isTabFolder = widget instanceof TabFolder;
848
			boolean isCTabFolder = isTabFolder ? false
849
					: widget instanceof CTabFolder;
850
			if (isTabFolder || isCTabFolder) {
851
				index = isTabFolder ? ((TabFolder) widget)
852
						.indexOf((TabItem) item) : ((CTabFolder) widget)
853
						.indexOf((CTabItem) item);
854
			}
855
		}
856
857
		if (index != -1)
858
			return new PrimitiveUIObjectIdentifier("item#" + index, ID);
859
		return null;
860
	}
861
862
	private static IUIObjectIdentifier getShellId(Shell shell) {
863
		return getDefaultShellId(shell);
864
	}
865
866
	private static IUIObjectIdentifier getDefaultShellId(Shell shell) {
867
		Object data = shell.getData();
868
		String id = "";
869
		if (data instanceof WizardDialog) {
870
			id = data.getClass().getName().toString();
871
		} else if (data instanceof Window) {
872
			id = data.getClass().getName().toString();
873
		}
874
875
		PrimitiveUIObjectIdentifier widgetId = new PrimitiveUIObjectIdentifier(
876
				id, ID);
877
		return widgetId;
878
	}
879
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/factory/MacroCommandFactory.java (+619 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.commands.factory;
13
14
import java.util.ArrayList;
15
16
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.core.runtime.Path;
18
import org.eclipse.jface.dialogs.MessageDialog;
19
import org.eclipse.swt.SWT;
20
import org.eclipse.swt.custom.CCombo;
21
import org.eclipse.swt.custom.CTabFolder;
22
import org.eclipse.swt.custom.StyledText;
23
import org.eclipse.swt.widgets.Button;
24
import org.eclipse.swt.widgets.Combo;
25
import org.eclipse.swt.widgets.Control;
26
import org.eclipse.swt.widgets.Event;
27
import org.eclipse.swt.widgets.List;
28
import org.eclipse.swt.widgets.MenuItem;
29
import org.eclipse.swt.widgets.TabFolder;
30
import org.eclipse.swt.widgets.Table;
31
import org.eclipse.swt.widgets.Text;
32
import org.eclipse.swt.widgets.ToolItem;
33
import org.eclipse.swt.widgets.Tree;
34
import org.eclipse.swt.widgets.TreeItem;
35
import org.eclipse.swt.widgets.Widget;
36
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
37
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
38
import org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand;
39
import org.eclipse.tptp.test.auto.gui.internal.commands.BooleanSelectionCommand;
40
import org.eclipse.tptp.test.auto.gui.internal.commands.CheckCommand;
41
import org.eclipse.tptp.test.auto.gui.internal.commands.ChoiceSelectionCommand;
42
import org.eclipse.tptp.test.auto.gui.internal.commands.CloseWorkbenchPartCommand;
43
import org.eclipse.tptp.test.auto.gui.internal.commands.ExpansionCommand;
44
import org.eclipse.tptp.test.auto.gui.internal.commands.FocusCommand;
45
import org.eclipse.tptp.test.auto.gui.internal.commands.IMacroCommand;
46
import org.eclipse.tptp.test.auto.gui.internal.commands.KeyEventCommand;
47
import org.eclipse.tptp.test.auto.gui.internal.commands.ModifyCommand;
48
import org.eclipse.tptp.test.auto.gui.internal.commands.MouseEventCommand;
49
import org.eclipse.tptp.test.auto.gui.internal.commands.ObjectBasedCommand;
50
import org.eclipse.tptp.test.auto.gui.internal.commands.StructuredSelectionCommand;
51
import org.eclipse.tptp.test.auto.gui.internal.commands.VerificationCommand;
52
import org.eclipse.tptp.test.auto.gui.internal.commands.WaitCommand;
53
import org.eclipse.tptp.test.auto.gui.internal.macro.EventConstants;
54
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
55
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
56
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
57
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObjectIdentifier;
58
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObject;
59
import org.eclipse.tptp.test.auto.gui.internal.macroobject.resolver.MacroObjectResolver;
60
import org.eclipse.tptp.test.auto.gui.internal.uiobject.UIObject;
61
62
/**
63
 * @author Alexander Nyssen
64
 * 
65
 */
66
public class MacroCommandFactory implements IMacroCommandFactory {
67
68
	/* The last event received */
69
	protected transient Event lastEvent;
70
71
	/* Indicates user interaction -- Set when a key up event is received */
72
	protected transient boolean isKeyPressed;
73
74
	/* Indicates user interaction -- Set when a mouse up event is received */
75
	protected transient boolean isMousePressed;
76
77
	/* Stores an event that is only acknowledged followed by user interaction. */
78
	protected transient Event toBeAckEvent;
79
80
	/* Set when the stored event in toBeAckEvent is acknowledged */
81
	protected transient boolean ackEvent;
82
83
	/* Stores the time for which a command was last created in */
84
	protected long lastCommandCreationTime;
85
86
	public IMacroCommand createCommand(MacroCommandShell commandShell,
87
			ArrayList commands, Event event) throws CoreException {
88
89
		// see if we can merge the event with the last created command
90
		AbstractMacroCommand lastCommand = getLastCommand(commands);
91
		if (lastEvent != null
92
				&& (lastEvent.detail == EventConstants.EVENT_DETAIL__POSITION_BASED_EVENT || (lastEvent.widget != null
93
						&& lastEvent.widget.equals(event.widget) && (lastEvent.type == event.type || (lastEvent.type == SWT.Selection && event.type == SWT.DefaultSelection))))) {
94
			try {
95
				if (lastCommand != null && lastCommand.mergeEvent(event)) {
96
					return null;
97
				}
98
			} catch (Exception e) {
99
				// simply continue (the last command could not merge the
100
				// event)
101
			}
102
		}
103
104
		AbstractMacroCommand command = null;
105
		if (event.detail == EventConstants.EVENT_DETAIL__POSITION_BASED_EVENT)
106
			command = createPositionBasedCommand(commandShell, event);
107
		else if (event.detail == EventConstants.EVENT_DETAIL__VERIFICATION_HOOK_INSERTION_EVENT) {
108
			command = createVerificationHookInsertionCommand(commandShell,
109
					event);
110
		} else {
111
			command = createObjectBasedCommand(commandShell, commands, event);
112
		}
113
114
		if (command != null) {
115
			/*
116
			 * Take out the last command if it is a focus command and the
117
			 * command just passed in implicitly does a focus
118
			 */
119
			if (lastCommand != null
120
					&& (lastCommand instanceof ObjectBasedCommand
121
							&& command instanceof ObjectBasedCommand
122
							&& ((ObjectBasedCommand) lastCommand)
123
									.getMacroObjectIdentifier()
124
									.equals(
125
											((ObjectBasedCommand) command)
126
													.getMacroObjectIdentifier())
127
							&& lastCommand.getType().equals(FocusCommand.TYPE) && isFocusCommand(command
128
							.getType()))) {
129
				// focus followed by select or modify - focus implied
130
				commands.remove(lastCommand);
131
			}
132
133
			/* Modify the last event accordinggly */
134
			if (ackEvent) {
135
				ackEvent = false;
136
				lastEvent = toBeAckEvent;
137
				toBeAckEvent = null;
138
			} else {
139
				lastEvent = event;
140
			}
141
142
			/* Add the artificial wait time if required */
143
			if (MacroManager.getInstance().isArtificialWaitOn()
144
					&& lastCommandCreationTime > 0) {
145
				long currentTime = System.currentTimeMillis();
146
				long difference = currentTime - lastCommandCreationTime;
147
				command.setTimeDifference(difference);
148
			}
149
150
			lastCommandCreationTime = System.currentTimeMillis();
151
152
			/*
153
			 * Ali M.: The following block of code provides a workaround for a
154
			 * limitation that exists for CloseWorkbenchPartCommand. We are only
155
			 * able to capture this event after the entire part has been
156
			 * disposed. Things would be ideal if this event could be captured
157
			 * right after the user clicks on the close button of the part
158
			 */
159
			if (command instanceof CloseWorkbenchPartCommand) {
160
				int commandSize = commands.size();
161
				if (commandSize > 0) {
162
					/*
163
					 * If the last command corresponds to the message dialog
164
					 * that prompts the user to save an editor, then store it
165
					 * after the close command
166
					 * 
167
					 * ANy: Since Eclipse 3.4 this does not seem to be a
168
					 * MessageDialog any more, but a private anonymous Dialog
169
					 * implementation in org.eclipse.ui.internal.SaveablesList,
170
					 * so I adopted this here.
171
					 */
172
					/* If the last stored command is a shell */
173
					Object lastCommandStored = commands.get(commandSize - 1);
174
					if (lastCommandStored instanceof MacroCommandShell
175
							&&
176
							/*
177
							 * If the part is an editor
178
							 */
179
							((CloseWorkbenchPartCommand) command)
180
									.getMacroObjectIdentifier()
181
									.getContextIdentifier().equals(
182
											MacroConstants.EDITOR_VALUE)
183
							&&
184
							/*
185
							 * If the shell is a MessageDialog or it is a
186
							 * private dialog inside the SaveablesList (Eclipse
187
							 * 3.4)
188
							 */
189
							(((MacroCommandShell) lastCommandStored)
190
									.getMacroObjectIdentifier()
191
									.getObjectIdentifier().getWidgetId()
192
									.startsWith("org.eclipse.ui.internal.SaveablesList"))
193
							|| ((MacroCommandShell) lastCommandStored)
194
									.getMacroObjectIdentifier()
195
									.getObjectIdentifier().getWidgetId()
196
									.equals(MessageDialog.class.getName()))
197
198
					{
199
						commands.add(commandSize - 1, command);
200
					}
201
202
				}
203
204
			} else {
205
				/*
206
				 * Added for defect 164197 in order to add an item-expansion to
207
				 * the parent whenever the child is selected in a case where the
208
				 * parent has been pre-expanded. Liz D.
209
				 */
210
				if (command instanceof StructuredSelectionCommand
211
						&& event.widget instanceof Tree) {
212
					StructuredSelectionCommand s = (StructuredSelectionCommand) command;
213
214
					TreeItem[] items = (TreeItem[]) s.getItemsForEvent(event);
215
					for (int i = 0; i < items.length; i++) {
216
						TreeItem selectedItem = (TreeItem) items[i];
217
218
						while (selectedItem.getParentItem() != null) {
219
							TreeItem parent = selectedItem.getParentItem();
220
							if (parent.getExpanded() == true) {// necessary so
221
								// that
222
								// we only apply
223
								// this in the case
224
								// where the parent
225
								// is already
226
								// expanded
227
								Event expansionEvent = new Event();
228
								expansionEvent.widget = parent;
229
								expansionEvent.item = parent;
230
								ExpansionCommand parentExpand = new ExpansionCommand(
231
										commandShell, s
232
												.getMacroObjectIdentifier());
233
								parentExpand.doProcessEvent(expansionEvent,
234
										true);
235
								commands.add(parentExpand);
236
							}
237
							selectedItem = parent;
238
						}// end while
239
					}
240
				}
241
242
				// add the command at the end of the list
243
				commands.add(command);
244
			}
245
		}
246
		return command;
247
	}
248
249
	/**
250
	 * Handles object-based events
251
	 */
252
	protected AbstractMacroCommand createObjectBasedCommand(
253
			MacroCommandShell commandShell, ArrayList commands, Event event) {
254
		/*
255
		 * A quick way to get out if we're only getting key up or mouse events
256
		 * that have been detected before
257
		 */
258
		if ((isKeyPressed && event.type == SWT.KeyUp)
259
				|| (isMousePressed && event.type == SWT.MouseUp))
260
			return null;
261
262
		ObjectBasedCommand command = null;
263
264
		/* Check to see if we are a drop-down menu selection */
265
		AbstractMacroCommand lastCommand = getLastCommand(commands);
266
		if (lastCommand != null
267
				&& lastCommand.getType() == BooleanSelectionCommand.TYPE
268
				&& ((BooleanSelectionCommand) lastCommand).getDetail() == SWT.DROP_DOWN) {
269
			((BooleanSelectionCommand) lastCommand).setItemSelected(event);
270
			return null;
271
		}
272
273
		if (event.type == EventConstants.EVENT_TYPE__WORKBENCH_PART_CLOSED) {
274
			/*
275
			 * 110810 -- Create the close workbench command only if there is
276
			 * only one frame in our shell stack
277
			 */
278
			if (MacroManager.getInstance().getCurrentMacro()
279
					.getShellStackSize() == 1) {
280
				command = new CloseWorkbenchPartCommand(commandShell);
281
			}
282
		} else {
283
			// process standard SWT event types
284
			switch (event.type) {
285
			case SWT.Modify:
286
				if (!isEditable(event.widget))
287
					return null;
288
289
				/*
290
				 * This block of code is used to avoid displaying the browse
291
				 * native dialog when the user clicks a browse button - it
292
				 * doesn't cover all cases
293
				 */
294
				// ANy: Added check that button is not disposed
295
				if (lastEvent != null && lastEvent.type == SWT.Selection
296
						&& lastEvent.widget instanceof Button
297
						&& !lastEvent.widget.isDisposed()) {
298
					String text = ((Button) lastEvent.widget).getText();
299
					if (text != null) {
300
						text = text.replaceAll("\\&", "");
301
						text = text.toLowerCase();
302
						if (text
303
								.indexOf(AutoGUIMessages.AUTO_GUI_CONTROL_STATUS_BROWSE) != -1) {
304
							int size = 0;
305
							if (commands != null
306
									&& (size = commands.size()) > 0) {
307
								commands.remove(size - 1);
308
								command = new ModifyCommand(commandShell);
309
								break;
310
							}
311
						}
312
					}
313
				}
314
315
				/* Only acknowledge modifies that are followed by a key up event */
316
				toBeAckEvent = event;
317
				break;
318
319
			case SWT.Selection:
320
			case SWT.DefaultSelection:
321
				command = createSelectionCommand(commandShell, event);
322
				break;
323
324
			case SWT.FocusIn:
325
				/**
326
				 * Ali M.: While recording, the SWT display listener has the
327
				 * tendency to report focus events on controls that are actually
328
				 * not visible to the user. When the macro is played back, the
329
				 * control cannot be located. To avoid this problem we only
330
				 * acknowledge focus events that are followed by a mouse up or
331
				 * key up event (i.e. The user explicitly focuses on the
332
				 * control).
333
				 */
334
				toBeAckEvent = event;
335
				break;
336
337
			case SWT.Expand:
338
			case SWT.Collapse:
339
				command = new ExpansionCommand(commandShell);
340
				break;
341
342
			case SWT.KeyUp:
343
				isKeyPressed = true;
344
				if (toBeAckEvent != null && toBeAckEvent.type == SWT.Modify) {
345
					command = new ModifyCommand(commandShell);
346
					ackEvent = true;
347
				} else if (toBeAckEvent != null
348
						&& toBeAckEvent.type == SWT.FocusIn) {
349
					command = new FocusCommand(commandShell);
350
					ackEvent = true;
351
				}
352
				break;
353
354
			case SWT.MouseUp:
355
				isMousePressed = true;
356
				if (toBeAckEvent != null && toBeAckEvent.type == SWT.FocusIn) {
357
					command = new FocusCommand(commandShell);
358
					ackEvent = true;
359
				}
360
				break;
361
			}
362
		}
363
364
		if (event.type != SWT.KeyUp)
365
			isKeyPressed = false;
366
		if (event.type != SWT.MouseUp)
367
			isMousePressed = false;
368
369
		if (command != null) {
370
			try {
371
				if (ackEvent) {
372
					command.processEvent(toBeAckEvent);
373
				} else {
374
					command.processEvent(event);
375
				}
376
			} catch (Exception e) {
377
				e.printStackTrace();
378
				command = null;
379
			}
380
		}
381
382
		/* Ensure that redundant commands are not created */
383
		if (lastCommand != null && command != null
384
				&& command.isRepeatRedundant() && command.equals(lastCommand)) {
385
			return null;
386
		}
387
		return command;
388
	}
389
390
	/**
391
	 * Handles position-based events
392
	 */
393
	protected AbstractMacroCommand createPositionBasedCommand(
394
			MacroCommandShell commandShell, Event event) {
395
		AbstractMacroCommand command = null;
396
397
		switch (event.type) {
398
		case SWT.MouseUp:
399
		case SWT.MouseDown:
400
		case SWT.MouseMove:
401
		case SWT.MouseDoubleClick:
402
			command = new MouseEventCommand(commandShell);
403
			break;
404
405
		case SWT.KeyUp:
406
		case SWT.KeyDown:
407
			command = new KeyEventCommand(commandShell);
408
			break;
409
410
		}
411
412
		if (command != null)
413
			try {
414
				command.processEvent(event);
415
			} catch (Exception e) {
416
				command = null;
417
			}
418
		return command;
419
	}
420
421
	protected ObjectBasedCommand createSelectionCommand(
422
			MacroCommandShell commandShell, Event event) {
423
		if (event.widget instanceof MenuItem
424
				|| event.widget instanceof ToolItem
425
				|| (event.widget instanceof Button
426
				/*
427
				 * A CCombo will cause a button selection followed by a combo
428
				 * selection. We need to ignore the button selection
429
				 */
430
				&& !(event.widget instanceof Control && ((Control) event.widget)
431
						.getParent() instanceof CCombo))) {
432
			ObjectBasedCommand selectionCommand = new BooleanSelectionCommand(
433
					commandShell);
434
			return selectionCommand;
435
		}
436
437
		if (event.widget instanceof Tree || event.widget instanceof Table
438
				|| event.widget instanceof List) {
439
			if (event.detail == SWT.CHECK) {
440
				ObjectBasedCommand selectionCommand = new CheckCommand(
441
						commandShell);
442
				return selectionCommand;
443
			} else {
444
				String type = event.type == SWT.DefaultSelection ? StructuredSelectionCommand.DEFAULT_SELECT
445
						: StructuredSelectionCommand.ITEM_SELECT;
446
				ObjectBasedCommand selectionCommand = new StructuredSelectionCommand(
447
						commandShell, type);
448
				return selectionCommand;
449
			}
450
		}
451
452
		if (event.widget instanceof TabFolder
453
				|| event.widget instanceof CTabFolder) {
454
			ObjectBasedCommand selectionCommand = new ChoiceSelectionCommand(
455
					commandShell);
456
			return selectionCommand;
457
		}
458
		if (event.widget instanceof Combo || event.widget instanceof CCombo) {
459
			ObjectBasedCommand selectionCommand = new ChoiceSelectionCommand(
460
					commandShell);
461
			return selectionCommand;
462
		}
463
		return null;
464
	}
465
466
	/**
467
	 * @param event
468
	 * @return
469
	 */
470
	protected AbstractMacroCommand createVerificationHookInsertionCommand(
471
			MacroCommandShell commandShell, Event event) throws CoreException {
472
473
		VerificationCommand command = null;
474
475
		String error = "";
476
477
		try {
478
			/* Ignore all command except for a focus in command */
479
			switch (event.type) {
480
			case SWT.Activate:
481
			case SWT.Selection:
482
			case SWT.FocusIn:
483
484
				IMacroObjectIdentifier widgetID = MacroObjectResolver.resolve(
485
						commandShell.getShell(), new MacroObject(new UIObject(
486
								event.widget)));
487
				String path = (widgetID == null ? "" : new Path(widgetID
488
						.getContextIdentifier() == null ? "" : widgetID
489
						.getContextIdentifier())
490
						.append(
491
								new Path(widgetID.getObjectIdentifier()
492
										.getWidgetId() == null ? "" : widgetID
493
										.getObjectIdentifier().getWidgetId()))
494
						.toString());
495
496
				if (VerificationCommand.findFocusType(path) == -1) {
497
					error = AutoGUIMessages.AUTO_GUI_ERROR_VER_NOT_SUPP_CON;
498
					break;
499
				}
500
501
				/* We only acknowledge after there is a mouse up event */
502
				toBeAckEvent = event;
503
				break;
504
505
			case SWT.MouseUp:
506
507
				if (toBeAckEvent == null)
508
					break;
509
510
				/* Create the verification command instance */
511
				command = new VerificationCommand(commandShell);
512
				command.processEvent(toBeAckEvent);
513
514
				ackEvent = true;
515
				break;
516
517
			default:
518
				toBeAckEvent = null;
519
				error = AutoGUIMessages.AUTO_GUI_ERROR_VER_WRONG_EVENT;
520
			}
521
		} catch (Exception e) {
522
			error = e.getMessage();
523
			e.printStackTrace();
524
		}
525
526
		if (error != null && !(error.equals(""))) {
527
			AutoGUIUtil.throwCoreException(error);
528
		}
529
		return command;
530
	}
531
532
	AbstractMacroCommand getLastCommand(ArrayList commands) {
533
		if (commands.size() > 0) {
534
			Object item = commands.get(commands.size() - 1);
535
			if (item instanceof AbstractMacroCommand)
536
				return (AbstractMacroCommand) item;
537
		}
538
		return null;
539
	}
540
541
	boolean isFocusCommand(String type) {
542
		return type.equals(BooleanSelectionCommand.TYPE)
543
				|| type.equals(StructuredSelectionCommand.ITEM_SELECT)
544
				|| type.equals(StructuredSelectionCommand.DEFAULT_SELECT)
545
				|| type.equals(ExpansionCommand.TYPE)
546
				|| type.equals(CheckCommand.TYPE)
547
				|| type.equals(ModifyCommand.TYPE);
548
	}
549
550
	private boolean isEditable(Widget widget) {
551
		if (widget instanceof Control) {
552
			Control control = (Control) widget;
553
			if (!control.isEnabled())
554
				return false;
555
			if (control instanceof Text)
556
				return ((Text) control).getEditable();
557
			if (control instanceof Combo || control instanceof CCombo)
558
				return ((control.getStyle() & SWT.READ_ONLY) == 0);
559
			if (control instanceof StyledText)
560
				return ((StyledText) control).getEditable();
561
		}
562
		return true;
563
	}
564
565
	public IMacroCommand createCommand(MacroCommandShell commandShell,
566
			String type) throws CoreException {
567
		// construct a new command dependent on the type
568
		AbstractMacroCommand command = null;
569
570
		if (type.equals(ModifyCommand.TYPE))
571
			command = new ModifyCommand(commandShell);
572
573
		else if (type.equals(BooleanSelectionCommand.TYPE))
574
			command = new BooleanSelectionCommand(commandShell);
575
576
		else if (type.equals(StructuredSelectionCommand.ITEM_SELECT)
577
				|| type.equals(StructuredSelectionCommand.DEFAULT_SELECT))
578
			command = new StructuredSelectionCommand(commandShell, type);
579
580
		else if (type.equals(ExpansionCommand.TYPE))
581
			command = new ExpansionCommand(commandShell);
582
583
		else if (type.equals(CheckCommand.TYPE))
584
			command = new CheckCommand(commandShell);
585
586
		else if (type.equals(FocusCommand.TYPE))
587
			command = new FocusCommand(commandShell);
588
589
		else if (type.equals(ChoiceSelectionCommand.TYPE))
590
			command = new ChoiceSelectionCommand(commandShell);
591
592
		else if (type.equals(WaitCommand.TYPE))
593
			command = new WaitCommand(commandShell);
594
595
		/* The verification command */
596
		else if (type.equals(VerificationCommand.TYPE))
597
			command = new VerificationCommand(commandShell);
598
599
		/* The close workbench part command */
600
		else if (type.equals(CloseWorkbenchPartCommand.TYPE))
601
			command = new CloseWorkbenchPartCommand(commandShell);
602
603
		/* Mouse events */
604
		else if (type.equals(MouseEventCommand.MOUSE_UP)
605
				|| type.equals(MouseEventCommand.MOUSE_DOWN)
606
				|| type.equals(MouseEventCommand.MOUSE_MOVE)
607
				|| type.equals(MouseEventCommand.MOUSE_CLICK))
608
			command = new MouseEventCommand(commandShell);
609
610
		/* Key events */
611
		else if (type.equals(KeyEventCommand.KEY_UP)
612
				|| type.equals(KeyEventCommand.KEY_DOWN)
613
				|| type.equals(KeyEventCommand.KEY_PRESS))
614
			command = new KeyEventCommand(commandShell);
615
616
		return command;
617
	}
618
619
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/factory/IMacroCommandFactory.java (+56 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.commands.factory;
13
14
import java.util.ArrayList;
15
16
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.swt.widgets.Event;
18
import org.eclipse.tptp.test.auto.gui.internal.commands.IMacroCommand;
19
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
20
21
/**
22
 * Factory to create commands to record certain events or to create respective commands during playback
23
 * 
24
 * @author Alexander Nyssen
25
 * 
26
 */
27
public interface IMacroCommandFactory {
28
29
	/**
30
	 * Factory method to create a new IMacroCommand during recording. This
31
	 * method is called by the command shell for every event it processes.
32
	 * Multiple calls to this method for succeeding events may be necessary,
33
	 * before an event is actually created and returned).
34
	 * 
35
	 * @param commandShell
36
	 * @param commands
37
	 * @param event
38
	 * @return
39
	 * @throws CoreException
40
	 */
41
	public IMacroCommand createCommand(MacroCommandShell commandShell,
42
			ArrayList commands, Event event) throws CoreException;
43
	
44
	
45
	/**
46
	 * Factory method to create a command instance for a certain command type. This
47
	 * method is called during playback to obtain a command that can then be played-back.
48
	 * 
49
	 * @param commandShell 
50
	 * @param type
51
	 * @return
52
	 * @throws CoreException
53
	 */
54
	public IMacroCommand createCommand(MacroCommandShell commandShell, String type) throws CoreException;
55
56
}
(-)schema/uiObjectResolverDelegate.exsd (+137 lines)
Added Link Here
1
<?xml version='1.0' encoding='UTF-8'?>
2
<!-- Schema file written by PDE -->
3
<schema targetNamespace="org.eclipse.tptp.test.auto.gui" xmlns="http://www.w3.org/2001/XMLSchema">
4
<annotation>
5
      <appinfo>
6
         <meta.schema plugin="org.eclipse.tptp.test.auto.gui" id="uiObjectResolverDelegate" name="uiObjectResolverDelegate"/>
7
      </appinfo>
8
      <documentation>
9
         Use this extension to define a class that is capable of resolving widgets and nested objects on them.
10
      </documentation>
11
   </annotation>
12
13
   <element name="extension">
14
      <annotation>
15
         <appinfo>
16
            <meta.element />
17
         </appinfo>
18
         <documentation>
19
            The following internal extension provides the mean for defining custom widget resolvers.
20
         </documentation>
21
      </annotation>
22
      <complexType>
23
         <sequence>
24
            <element ref="uiObjectResolverDelegate" minOccurs="1" maxOccurs="unbounded"/>
25
         </sequence>
26
         <attribute name="point" type="string" use="required">
27
            <annotation>
28
               <documentation>
29
                  
30
               </documentation>
31
            </annotation>
32
         </attribute>
33
         <attribute name="id" type="string">
34
            <annotation>
35
               <documentation>
36
                  
37
               </documentation>
38
            </annotation>
39
         </attribute>
40
         <attribute name="name" type="string">
41
            <annotation>
42
               <documentation>
43
                  
44
               </documentation>
45
               <appinfo>
46
                  <meta.attribute translatable="true"/>
47
               </appinfo>
48
            </annotation>
49
         </attribute>
50
      </complexType>
51
   </element>
52
53
   <element name="uiObjectResolverDelegate">
54
      <complexType>
55
         <attribute name="class" type="string" use="required">
56
            <annotation>
57
               <documentation>
58
                  The class that is invoked to resolve a widget or a nested object on a widget.
59
Must implement the following interface: org.eclipse.tptp.test.auto.gui.uiObject.resolver.delegate.IUIObjectResolverDelegate
60
               </documentation>
61
               <appinfo>
62
                  <meta.attribute kind="java" basedOn="org.eclipse.tptp.test.auto.gui.uiObject.resolver.delegate.IUIObjectResolverDelegate"/>
63
               </appinfo>
64
            </annotation>
65
         </attribute>
66
         <attribute name="priority" type="string" use="required">
67
            <annotation>
68
               <documentation>
69
                  This attribute indicates the priority of the resolver delegate relative to the other registered widget resolvers. UIObjectResolverDelegats are invoked in an descending order of their priority (e.g. The resolver delegate with the highest priority attribute will be invoked first).
70
The value of this attribute is expected to be an integer
71
               </documentation>
72
            </annotation>
73
         </attribute>
74
         <attribute name="id" type="string" use="required">
75
            <annotation>
76
               <documentation>
77
                  The unique id of the resolver.  Keeps this id short as it is commonly used in a macro.  The suggested format is CONTRIBUTING_PLUGIN_ID.RESOLVER_NAME e.g. org.eclipse.tptp.test.auto.gui.adaptive.
78
               </documentation>
79
            </annotation>
80
         </attribute>
81
      </complexType>
82
   </element>
83
84
   <annotation>
85
      <appinfo>
86
         <meta.section type="since"/>
87
      </appinfo>
88
      <documentation>
89
         Since TPTP v4.5
90
      </documentation>
91
   </annotation>
92
93
   <annotation>
94
      <appinfo>
95
         <meta.section type="examples"/>
96
      </appinfo>
97
      <documentation>
98
         &lt;!-- Define a UI object resolver delegate with priority 10 --&gt; 
99
  &lt;extension
100
  point=&quot;org.eclipse.tptp.test.auto.gui.uiObjectResolverDelegate&quot;&gt;
101
     &lt;widgetResolver 
102
      id = &quot;org.eclipse.tptp.test.auto.gui.adaptive&quot;
103
      class=&quot;org.eclipse.tptp.test.auto.gui.internal.recorder.AdaptiveWidgetResolver&quot;
104
      priority=&quot;10&quot;
105
     /&gt;
106
  &lt;/extension&gt;
107
      </documentation>
108
   </annotation>
109
110
   <annotation>
111
      <appinfo>
112
         <meta.section type="apiInfo"/>
113
      </appinfo>
114
      <documentation>
115
         [Enter API information here.]
116
      </documentation>
117
   </annotation>
118
119
   <annotation>
120
      <appinfo>
121
         <meta.section type="implementation"/>
122
      </appinfo>
123
      <documentation>
124
         [Enter information about supplied implementation of this extension point.]
125
      </documentation>
126
   </annotation>
127
128
   <annotation>
129
      <appinfo>
130
         <meta.section type="copyright"/>
131
      </appinfo>
132
      <documentation>
133
         Copyright (c) 2005, 2006 IBM Corporation 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 &lt;a href=&quot;http://www.eclipse.org/legal/epl-v10.html&quot;&gt;http://www.eclipse.org/legal/epl-v10.html&lt;/a&gt;
134
      </documentation>
135
   </annotation>
136
137
</schema>
(-)src/org/eclipse/tptp/test/auto/gui/internal/editor/AutoGUIMacroObjectDescriptorMineTreeStructure.java (+510 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006, 2008 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.editor;
12
13
import java.util.ArrayList;
14
import java.util.Collection;
15
import java.util.Iterator;
16
import java.util.List;
17
18
import org.eclipse.core.runtime.IStatus;
19
import org.eclipse.emf.ecore.EStructuralFeature;
20
import org.eclipse.hyades.models.common.facades.behavioral.ITestSuite;
21
import org.eclipse.hyades.models.common.facades.behavioral.impl.HyadesUtil;
22
import org.eclipse.hyades.test.common.util.XMLUtil;
23
import org.eclipse.hyades.test.ui.adapter.TestWorkbenchAdapter;
24
import org.eclipse.hyades.test.ui.internal.editor.form.util.EObjectTreeContentProvider;
25
import org.eclipse.hyades.ui.editor.IEditorExtension;
26
import org.eclipse.hyades.ui.internal.provider.WorkbenchAdapterLabelProvider;
27
import org.eclipse.jface.action.Action;
28
import org.eclipse.jface.action.IMenuManager;
29
import org.eclipse.jface.dialogs.IDialogConstants;
30
import org.eclipse.jface.resource.ImageDescriptor;
31
import org.eclipse.jface.viewers.IContentProvider;
32
import org.eclipse.jface.viewers.ILabelProvider;
33
import org.eclipse.jface.viewers.IStructuredSelection;
34
import org.eclipse.jface.viewers.Viewer;
35
import org.eclipse.osgi.util.NLS;
36
import org.eclipse.swt.SWT;
37
import org.eclipse.swt.graphics.Image;
38
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIImages;
39
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
40
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
41
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
42
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
43
import org.eclipse.tptp.test.auto.gui.internal.dialogs.AutoGUITestSuiteDialog;
44
import org.eclipse.tptp.test.auto.gui.internal.editor.AutoGUITestCaseTreeStructure.MessageUIElement;
45
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
46
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptor;
47
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine;
48
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMineManager;
49
50
/**
51
 * Represents the object mine tree that is displayed in the test case page of
52
 * the editor.
53
 * 
54
 * @author Ali Mehregani
55
 * @author Paul E. Slauenwhite
56
 * @version March 7, 2008
57
 * @since July 10, 2006
58
 */
59
public class AutoGUIMacroObjectDescriptorMineTreeStructure extends
60
		AutoGUIAbstractTreeStructure {
61
	/** Represents the root element in the object mine tree */
62
	private static final RootUMacroObjectDescriptorMineTreeNode ROOT_ELEMENT = new RootUMacroObjectDescriptorMineTreeNode();
63
64
	/** The test case form */
65
	private AutoGUITestCasesForm testCaseForm;
66
67
	/** The content provider */
68
	private ObjectMineTreeContentProvider contentProvider;
69
70
	/** The label provider */
71
	private ObjectMineLabelProvider labelProvider;
72
73
	/**
74
	 * The line number and offset relation. The index of the list represents the
75
	 * line number and the value is an object of type Integer[0] indicating the
76
	 * start and end offset
77
	 */
78
	private List lineOffsetRelation;
79
80
	/** The include object mine menu item */
81
	private IncludeObjectMineAction includeObjectMineAction;
82
83
	/** Change output menu item */
84
	private ChangeOutputAction changeOutputAction;
85
86
	/** Keeps track of the test suite used as input */
87
	private ITestSuite testSuiteInput;
88
89
	/** Stores any error that occurred while loading the object mine */
90
	private Object[] error;
91
92
	public AutoGUIMacroObjectDescriptorMineTreeStructure(
93
			AutoGUITestCasesForm testCaseForm, IEditorExtension editorPart) {
94
		super(editorPart, null);
95
		this.testCaseForm = testCaseForm;
96
		lineOffsetRelation = new ArrayList();
97
		includeObjectMineAction = new IncludeObjectMineAction();
98
		changeOutputAction = new ChangeOutputAction();
99
	}
100
101
	/**
102
	 * Overwrite this method so that a custom content provider can be registered
103
	 * with the tree
104
	 */
105
	protected IContentProvider createContentProvider() {
106
		if (contentProvider == null)
107
			contentProvider = new ObjectMineTreeContentProvider(editorPart,
108
					getEStructuralFeature());
109
		return contentProvider;
110
	}
111
112
	/**
113
	 * Overwrite this method so that a custom label provider can be registered
114
	 * with the tree
115
	 * 
116
	 * @return The label provider for the object mine tree
117
	 */
118
	protected ILabelProvider createLabelProvider() {
119
		if (labelProvider == null)
120
			labelProvider = new ObjectMineLabelProvider(
121
					TestWorkbenchAdapter.class);
122
		return labelProvider;
123
	}
124
125
	/**
126
	 * Overwrite this method so that custom buttons can be added beside the
127
	 * object mine tree.
128
	 */
129
	protected void adjustButtonLabels(String addLabel) {
130
		setButtonLabels(new String[0]);
131
	}
132
133
	/**
134
	 * Need to overwrite this method since there are no buttons whose status
135
	 * need to be updated.
136
	 */
137
	protected void updateActionsAndButtons(
138
			IStructuredSelection structuredSelection) {
139
		/* purposely left blank */
140
	}
141
142
	/**
143
	 * Refreshes the content of this tree by forcing the test suite to reload
144
	 * its object mine.
145
	 */
146
	public void refresh() {
147
		MacroObjectDescriptorMineManager.getInstance().clearCache();
148
		loadObjectMine(testSuiteInput, false);
149
		getTreeViewer().refresh();
150
	}
151
152
	public List getLineOffsetRelation() {
153
		return lineOffsetRelation;
154
	}
155
156
	/**
157
	 * Needs to be overwritten to modify the default tree style
158
	 */
159
	public int getTreeStryle() {
160
		return super.getTreeStryle() | SWT.BORDER;
161
	}
162
163
	private Object[] createErrorItem(String prefix, Exception e) {
164
		Throwable cause = AutoGUIUtil.findCause(e);
165
		prefix += prefix == null ? "" : ": ";
166
		prefix += (cause.getMessage() == cause.getClass().getName() ? "" : " "
167
				+ cause.getMessage());
168
		prefix += ": " + e.getStackTrace()[0].getClassName() + ":"
169
				+ e.getStackTrace()[0].getLineNumber();
170
		return new Object[] { new MessageUIElement(IStatus.ERROR, prefix) };
171
	}
172
173
	/**
174
	 * Overwrite this method so that custom menu items can be added to the
175
	 * entries that are displayed in the object mine tree.
176
	 * 
177
	 * @param menuManager
178
	 *            The menu manager
179
	 */
180
	protected void fillContextMenu(IMenuManager menuManager) {
181
		IStructuredSelection selection = getStructuredSelection();
182
		if (!selection.isEmpty()
183
				&& selection.size() == 1
184
				&& selection.getFirstElement() instanceof RootUMacroObjectDescriptorMineTreeNode) {
185
			menuManager.add(includeObjectMineAction);
186
			menuManager.add(changeOutputAction);
187
		}
188
	}
189
190
	private MacroObjectDescriptorMine loadObjectMine(ITestSuite testSuite,
191
			boolean showError) {
192
		MacroObjectDescriptorMine input = null;
193
		if (testSuite == null) {
194
			testSuiteInput = null;
195
			return null;
196
		}
197
198
		try {
199
			testSuiteInput = (ITestSuite) testSuite;
200
			input = MacroObjectDescriptorMineManager.getInstance()
201
					.loadObjectMine(testSuiteInput);
202
			String objectMineXML = HyadesUtil.getTestSuiteVariable(
203
					testSuiteInput,
204
					GlobalConstants.TEST_SUITE_PROPERTY_OBJECT_MINE);
205
			lineOffsetRelation = AutoGUIMacroObjectDescriptorMineTreeStructure.this
206
					.findLineOffsetIndicator(objectMineXML);
207
			error = null;
208
		} catch (Exception e) {
209
			if (showError) {
210
				AutoGUIUtil.openErrorWithDetail(
211
						AutoGUIMessages.AUTO_GUI_COMMON_ERROR,
212
						AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE + ": "
213
								+ testSuite.getName(), e);
214
			} else {
215
				error = createErrorItem(
216
						AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE, e);
217
			}
218
219
			input = null;
220
		}
221
222
		return input;
223
	}
224
225
	/**
226
	 * The content provider for the object mine tree.
227
	 * 
228
	 * @author Ali Mehregani
229
	 */
230
	private class ObjectMineTreeContentProvider extends
231
			EObjectTreeContentProvider {
232
		public ObjectMineTreeContentProvider(IEditorExtension editorPart,
233
				EStructuralFeature eStructuralFeature) {
234
			super(editorPart, eStructuralFeature);
235
		}
236
237
		public Object[] getElements(Object inputElement) {
238
			return new Object[] { ROOT_ELEMENT };
239
		}
240
241
		/**
242
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
243
		 */
244
		public Object[] getChildren(Object parentElement) {
245
			MacroObjectDescriptorMine input = loadObjectMine(testSuiteInput,
246
					false);
247
			if (input == null) {
248
				if (parentElement == ROOT_ELEMENT && error != null)
249
					return error;
250
			}
251
252
			/*
253
			 * If the test suite doesn't have an object mine then return an
254
			 * empty list
255
			 */
256
			String objectMineXML = null;
257
			if (testSuiteInput == null
258
					|| (objectMineXML = HyadesUtil.getTestSuiteVariable(
259
							testSuiteInput,
260
							GlobalConstants.TEST_SUITE_PROPERTY_OBJECT_MINE)) == null
261
					|| objectMineXML.length() <= 0)
262
				return null;
263
264
			if (parentElement == ROOT_ELEMENT) {
265
				return input.getChildren();
266
			} else if (parentElement instanceof MacroObjectDescriptor) {
267
				return ((MacroObjectDescriptor) parentElement).getChildren();
268
			}
269
270
			return null;
271
		}
272
273
		public boolean hasChildren(Object parentElement) {
274
			MacroObjectDescriptorMine input = loadObjectMine(testSuiteInput,
275
					false);
276
			if (parentElement == ROOT_ELEMENT) {
277
				return input == null ? error != null
278
						: input.getChildren().length > 0;
279
			} else if (parentElement instanceof MacroObjectDescriptor) {
280
				return ((MacroObjectDescriptor) parentElement).childCount() > 0;
281
			}
282
283
			return false;
284
		}
285
286
		/**
287
		 * @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
288
		 */
289
		public Object getParent(Object element) {
290
			if (element instanceof MacroObjectDescriptor) {
291
				MacroObjectDescriptor parent = ((MacroObjectDescriptor) element)
292
						.getParent();
293
				return parent == null ? (Object) ROOT_ELEMENT : parent;
294
			}
295
			return null;
296
		}
297
298
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
299
			if (!(newInput instanceof ITestSuite))
300
				return;
301
302
			loadObjectMine((ITestSuite) newInput, false);
303
304
		}
305
	}
306
307
	private class ObjectMineLabelProvider extends WorkbenchAdapterLabelProvider {
308
309
		public ObjectMineLabelProvider(Class cl)
310
				throws IllegalArgumentException {
311
			super(cl);
312
		}
313
314
		public String getText(Object element) {
315
			if (element == ROOT_ELEMENT) {
316
				return AutoGUIMessages.TST_SUITE_AUTO_MACRO_OBJ_MINE;
317
			} else if (element instanceof MacroObjectDescriptor) {
318
				String descriptiveField = ((MacroObjectDescriptor) element)
319
						.getDescriptive();
320
				return descriptiveField == null ? AutoGUIMessages.TST_SUITE_AUTO_MACRO_OBJ_OBJECT
321
						: XMLUtil.removeXMLSymbols(descriptiveField);
322
			} else if (element instanceof MessageUIElement) {
323
				String message = ((MessageUIElement) element).getText();
324
				return message == null ? AutoGUIMessages.TST_SUITE_AUTO_MACRO_MESSAGE
325
						: message;
326
			}
327
328
			return MacroConstants.EMPTY_STRING;
329
		}
330
331
		public Image getImage(Object element) {
332
			if (element == ROOT_ELEMENT) {
333
				return AutoGUIImages.getInstance().getImage(
334
						AutoGUIImages.OBJECT_MINE);
335
			} else if (element instanceof MacroObjectDescriptor) {
336
				MacroObjectDescriptor parent = ((MacroObjectDescriptor) element)
337
						.getParent();
338
				return parent == null ? AutoGUIImages.getInstance().getImage(
339
						AutoGUIImages.SHELL) : AutoGUIImages.getInstance()
340
						.getImage(AutoGUIImages.WIDGET);
341
			} else if (element instanceof MessageUIElement) {
342
				return ((MessageUIElement) element).getIcon();
343
			}
344
345
			return null;
346
		}
347
	}
348
349
	/**
350
	 * A dummy class that represents the root element in the object mine tree.
351
	 */
352
	private static class RootUMacroObjectDescriptorMineTreeNode {
353
	}
354
355
	/**
356
	 * The include object mine action. The purpose of this action is to allow
357
	 * the user to include object mines under the test suite's object mine
358
	 * 
359
	 * @author Ali Mehregani
360
	 */
361
	private class IncludeObjectMineAction extends Action {
362
		/**
363
		 * Perform the action.
364
		 * 
365
		 */
366
		public void run() {
367
			/* Display the test suite list dialog */
368
			AutoGUITestSuiteDialog autoGUITestSuiteDialog = new AutoGUITestSuiteDialog(
369
					GuiPlugin.getDefault().getWorkbench()
370
							.getActiveWorkbenchWindow().getShell(),
371
					testSuiteInput,
372
					AutoGUIMessages.AUTO_GUI_TST_DIALOG_TREE_ITITLE, false);
373
374
			if (autoGUITestSuiteDialog.open() == IDialogConstants.CANCEL_ID)
375
				return;
376
377
			/*
378
			 * Get the selected test suites and include them as part of this
379
			 * test suite's object mine
380
			 */
381
			Collection tests = autoGUITestSuiteDialog.getTests();
382
			MacroObjectDescriptorMine input = loadObjectMine(testSuiteInput,
383
					true);
384
			boolean markdirty = false;
385
			for (Iterator testIterator = tests.iterator(); testIterator
386
					.hasNext();) {
387
				Object currentTestSuite = testIterator.next();
388
				if (!(currentTestSuite instanceof ITestSuite))
389
					continue;
390
391
				ITestSuite testSuite = (ITestSuite) currentTestSuite;
392
				try {
393
					MacroObjectDescriptorMine objectMine = MacroObjectDescriptorMineManager
394
							.getInstance().loadObjectMine(testSuite);
395
					if (objectMine != null
396
							&& !input.getIncludes().contains(objectMine)) {
397
						markdirty = true;
398
						input.addInclude(objectMine);
399
					}
400
				} catch (Exception e) {
401
					/* Display an error */
402
					AutoGUIUtil
403
							.openErrorWithDetail(
404
									AutoGUIMessages.AUTO_GUI_COMMON_ERROR,
405
									NLS
406
											.bind(
407
													AutoGUIMessages.AUTO_GUI_ERROR_DIALOG_TST_INCL,
408
													testSuite.getName()), e);
409
				}
410
			}
411
412
			if (markdirty) {
413
				testCaseForm.updateTestProperty(null,
414
						input.serializeToString(), true);
415
				getTreeViewer().setSelection(getTreeViewer().getSelection());
416
			}
417
		}
418
419
		public boolean isEnabled() {
420
			return testSuiteInput != null;
421
		}
422
423
		public String getText() {
424
			return AutoGUIMessages.AUTO_GUI_TST_DIALOG_TREE_INCL;
425
		}
426
427
		public ImageDescriptor getImageDescriptor() {
428
			return AutoGUIImages.getInstance().getImageDescriptor("e",
429
					AutoGUIImages.INCLUDE);
430
		}
431
	}
432
433
	/**
434
	 * This action changes the output of the object mine to another test suite.
435
	 * 
436
	 * @author Ali Mehregani
437
	 */
438
	private class ChangeOutputAction extends Action {
439
		/**
440
		 * Perform the action.
441
		 */
442
		public void run() {
443
			/* Display the test suite list dialog */
444
			AutoGUITestSuiteDialog autoGUITestSuiteDialog = new AutoGUITestSuiteDialog(
445
					GuiPlugin.getDefault().getWorkbench()
446
							.getActiveWorkbenchWindow().getShell(),
447
					testSuiteInput,
448
					AutoGUIMessages.AUTO_GUI_TST_DIALOG_TREE_ITITLE, true);
449
450
			if (autoGUITestSuiteDialog.open() == IDialogConstants.CANCEL_ID)
451
				return;
452
453
			/*
454
			 * Get the selected test suites and include them as part of this
455
			 * test suite's object mine
456
			 */
457
			Collection tests = autoGUITestSuiteDialog.getTests();
458
			if (tests == null)
459
				return;
460
461
			Object[] selectedTestContainer = tests.toArray();
462
			if (selectedTestContainer.length != 1
463
					|| !(selectedTestContainer[0] instanceof ITestSuite))
464
				return;
465
466
			MacroObjectDescriptorMine input = loadObjectMine(testSuiteInput,
467
					true);
468
			MacroObjectDescriptorMine oldOutputObjectMine = input
469
					.getOutputSource();
470
			ITestSuite oldOutput = oldOutputObjectMine == null ? null
471
					: oldOutputObjectMine.getOwner();
472
			ITestSuite newOutput = (ITestSuite) selectedTestContainer[0];
473
			if (oldOutput == null
474
					|| (!oldOutput.getId().equals(newOutput.getId()))) {
475
				MacroObjectDescriptorMine objectMine = null;
476
				try {
477
					objectMine = MacroObjectDescriptorMineManager.getInstance()
478
							.loadObjectMine(newOutput);
479
					input.setOutputSource(objectMine);
480
					testCaseForm.updateTestProperty(null, input
481
							.serializeToString(), true);
482
					getTreeViewer()
483
							.setSelection(getTreeViewer().getSelection());
484
				} catch (Exception e) {
485
					input.setOutputSource(null);
486
					AutoGUIUtil
487
							.openErrorWithDetail(
488
									AutoGUIMessages.AUTO_GUI_COMMON_ERROR,
489
									NLS
490
											.bind(
491
													AutoGUIMessages.AUTO_GUI_ERROR_OBJ_MINE_OUTPUT,
492
													newOutput.getName()), e);
493
				}
494
			}
495
		}
496
497
		public boolean isEnabled() {
498
			return testSuiteInput != null;
499
		}
500
501
		public String getText() {
502
			return AutoGUIMessages.AUTO_GUI_TST_DIALOG_TREE_OUPUT;
503
		}
504
505
		public ImageDescriptor getImageDescriptor() {
506
			return AutoGUIImages.getInstance().getImageDescriptor("e",
507
					AutoGUIImages.OUTPUT);
508
		}
509
	}
510
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/SingleSelectionCommand.java (+30 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.commands;
13
14
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroCommandShell;
15
16
17
/**
18
 * @author Alexander Nyssen
19
 *
20
 */
21
public abstract class SingleSelectionCommand extends ObjectBasedCommand {
22
23
	/**
24
	 * @param parent
25
	 * @param widgetId
26
	 */
27
	public SingleSelectionCommand(MacroCommandShell parent) {
28
		super(parent);
29
	}
30
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macroobject/resolver/MacroObjectResolver.java (+763 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.macroobject.resolver;
13
14
import org.eclipse.core.runtime.Assert;
15
import org.eclipse.core.runtime.CoreException;
16
import org.eclipse.core.runtime.IPath;
17
import org.eclipse.core.runtime.Path;
18
import org.eclipse.jface.action.CoolBarManager;
19
import org.eclipse.jface.action.ICoolBarManager;
20
import org.eclipse.jface.action.IMenuManager;
21
import org.eclipse.jface.action.IToolBarManager;
22
import org.eclipse.jface.action.MenuManager;
23
import org.eclipse.jface.action.ToolBarManager;
24
import org.eclipse.jface.window.ApplicationWindow;
25
import org.eclipse.jface.wizard.IWizardPage;
26
import org.eclipse.jface.wizard.WizardDialog;
27
import org.eclipse.osgi.util.NLS;
28
import org.eclipse.swt.custom.CTabFolder;
29
import org.eclipse.swt.custom.CTabItem;
30
import org.eclipse.swt.widgets.Control;
31
import org.eclipse.swt.widgets.Decorations;
32
import org.eclipse.swt.widgets.Menu;
33
import org.eclipse.swt.widgets.MenuItem;
34
import org.eclipse.swt.widgets.Shell;
35
import org.eclipse.swt.widgets.TabFolder;
36
import org.eclipse.swt.widgets.TabItem;
37
import org.eclipse.swt.widgets.ToolBar;
38
import org.eclipse.swt.widgets.ToolItem;
39
import org.eclipse.swt.widgets.Widget;
40
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
41
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
42
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
43
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
44
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObject;
45
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObjectIdentifier;
46
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObject;
47
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObjectIdentifier;
48
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObject;
49
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
50
import org.eclipse.tptp.test.auto.gui.internal.uiobject.PrimitiveUIObjectIdentifier;
51
import org.eclipse.tptp.test.auto.gui.internal.uiobject.UIObject;
52
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.UIObjectResolver;
53
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.DeresolvingAmbiguityException;
54
import org.eclipse.ui.IActionBars;
55
import org.eclipse.ui.IEditorPart;
56
import org.eclipse.ui.IViewPart;
57
import org.eclipse.ui.IViewSite;
58
import org.eclipse.ui.IWorkbenchPart;
59
60
/**
61
 * Provides functionality to resolve a IMacroObject into an
62
 * IMacroObjectIdentifier that can be persistently stored, and to deresolve an
63
 * IMacroObjectIdentifier back into an IMacroObject.
64
 * 
65
 * During resolving a context identifier for the context of the IMacroObject is
66
 * computed and the resolving of the IUIObject nested inside the IMacroObject is
67
 * delegated to the UIObjectResolver (the resulting IUIObjectIdentifier is then
68
 * be nested into the returned IMacroObjectIdentifier).
69
 * 
70
 * During deresolving the context object is first deresolved, then the IUIObject
71
 * nested inside the IMacroObject is deresolved by delegating to the
72
 * IUIObjectResolver again.
73
 * 
74
 * @author Alexander Nyssen
75
 * 
76
 */
77
public final class MacroObjectResolver {
78
79
	/**
80
	 * Resolve a IMacroObject into an IMacroObjectIdentifier representation,
81
	 * that can be persistently stored and that allows to deresolve the
82
	 * IMacroObject during playback. Delegates to UIObjectResolver's resolve()
83
	 * method to obtain the IUIObjectIdentifier part of the
84
	 * IMacroObjectIdentifier
85
	 * 
86
	 * @param macroObject
87
	 * @return
88
	 */
89
	public static IMacroObjectIdentifier resolve(Shell shell,
90
			IMacroObject macroObject) throws CoreException {
91
		// retrieve the context id of the UI object
92
93
		// compute a context identifier based on the context object of the
94
		// macroObject
95
		String contextIdentifier = resolveContextIdentifier(shell, macroObject);
96
97
		// compute the object id by delegating to the UIObjectResolver
98
		IUIObjectIdentifier uiObjectIdentifier = UIObjectResolver.resolve(
99
				macroObject.getContext(), macroObject.getUIObject());
100
101
		IMacroObjectIdentifier identifier = null;
102
		// compute the object id and build a new MacroObjectIdentifier from both
103
		if (contextIdentifier != null && uiObjectIdentifier != null) {
104
			// identifier = new MacroObjectIdentifier(contextIdentifier,
105
			// uiObjectIdentifier);
106
			identifier = checkAnfFixUnambiguousIdentifier(shell, macroObject,
107
					new MacroObjectIdentifier(contextIdentifier,
108
							uiObjectIdentifier));
109
		}
110
		return identifier;
111
	}
112
113
	/**
114
	 * This method implements a workaround for defect #147766. It checks whether
115
	 * the provided IMacroObject can be unambiguously deresolved by using the
116
	 * provided IMacroObjectIdentifier.
117
	 * 
118
	 * As detection of deresolving ambiguities is limited to Control instances,
119
	 * this method does only have an effect, if the passed in macro object
120
	 * contains a control as the widget of its nested UI object.
121
	 * 
122
	 * If the passed in IMacroObjectIdentifier is ambiguous, an index is added
123
	 * to the widget id of the nested UIObjectIdnentifier to ensure unambiguity
124
	 * during deresolving (the locateVisibleChild() method of the
125
	 * UIObjectDeprecatedDeresolvingSupport class handles this case). If the
126
	 * passed in IMacroObjectIdentifier is unambiguous or the deresolving did
127
	 * fail because of any other reason, this method does not have any effect
128
	 * and simply returns the passed in IMacroObjectIdentifier.
129
	 */
130
	private static IMacroObjectIdentifier checkAnfFixUnambiguousIdentifier(
131
			Shell shell, IMacroObject macroObject,
132
			IMacroObjectIdentifier macroObjectIdentifier) throws CoreException {
133
		try {
134
			// ANy: IMPORTANT: I observed that in case of MenuItems, deresolving
135
			// during recording causes the widget to get disposed as a
136
			// side-effect.
137
			// Also because of this, limiting the check to Control instances is
138
			// necessary.
139
			if (macroObject.getUIObject().getWidget() instanceof Control) {
140
				deresolve(shell, new MacroObjectIdentifier(
141
						macroObjectIdentifier.getContextIdentifier(),
142
						macroObjectIdentifier.getObjectIdentifier()));
143
			}
144
		} catch (Throwable t) {
145
			// ANy: IMPORTANT: In case we get a core exception we have to check
146
			// if
147
			// ambiguity of the passed in identifier was the reason.
148
			if (t instanceof CoreException
149
					&& ((CoreException) t).getCause() instanceof DeresolvingAmbiguityException) {
150
				// provide a workaround by adding a respective
151
				// identifier suffix to identify the desired match
152
				IUIObjectIdentifier unambiguousUIObjectIdentifier = computeUnambigousUIObjectIdentifier(
153
						macroObject.getContext(), macroObject.getUIObject(),
154
						macroObjectIdentifier.getObjectIdentifier(),
155
						((DeresolvingAmbiguityException) ((CoreException) t)
156
								.getCause()).getNumberOfMatches());
157
				if (unambiguousUIObjectIdentifier != null) {
158
					// if we were successful, return the new - now unambiguous -
159
					// identifier.
160
					return new MacroObjectIdentifier(macroObjectIdentifier
161
							.getContextIdentifier(),
162
							unambiguousUIObjectIdentifier);
163
				} else {
164
					// throw an exception to notify the user.
165
					AutoGUIUtil
166
							.throwCoreException(
167
									NLS
168
											.bind(
169
													AutoGUIMessages.AUTO_GUI_UI_OBJECT_IDENTIFIER_AMBIGUOUS,
170
													macroObjectIdentifier
171
															.getObjectIdentifier()
172
															.getWidgetId(),
173
													macroObjectIdentifier
174
															.getObjectIdentifier()
175
															.getObjectId()), t
176
											.getCause());
177
					return null;
178
				}
179
			} else {
180
				// All other reasons are ignored here, so return the passed in
181
				// macro object identifier.
182
				return macroObjectIdentifier;
183
			}
184
		}
185
		// if no exeption is thrown, the deresolving worked, so return the
186
		// passed in macro object identifier.
187
		return macroObjectIdentifier;
188
	}
189
190
	private static IUIObjectIdentifier computeUnambigousUIObjectIdentifier(
191
			Object context, IUIObject uiObject,
192
			IUIObjectIdentifier ambigousIdentifier, int numberOfMatches) {
193
		IUIObjectIdentifier unambigousIdentifier = null;
194
		// check each match to see which one is the desired target
195
		for (int i = 0; i < numberOfMatches && unambigousIdentifier == null; i++) {
196
			try {
197
				String uniqueWidgetId = ambigousIdentifier
198
						.getWidgetId()
199
						.concat(
200
								MacroConstants.WIDGET_ID_UNIQUENESS_INDEX_SEPARATOR
201
										+ new Integer(i).toString());
202
				IUIObjectIdentifier modifiedUIObjectIdentifier = new PrimitiveUIObjectIdentifier(
203
						uniqueWidgetId, ambigousIdentifier.getObjectId(),
204
						ambigousIdentifier.getResolverId());
205
				IUIObject deresolvedUIObject = UIObjectResolver.deresolve(
206
						context, modifiedUIObjectIdentifier);
207
				if (deresolvedUIObject != null
208
						&& deresolvedUIObject.getWidget() == uiObject
209
								.getWidget()) {
210
					unambigousIdentifier = modifiedUIObjectIdentifier;
211
				}
212
			} catch (Throwable t) {
213
			}
214
		}
215
		return unambigousIdentifier;
216
	}
217
218
	private static String resolveContextIdentifier(Shell shell,
219
			IMacroObject macroObject) throws CoreException {
220
		Widget widget = macroObject.getUIObject().getWidget();
221
		if (widget instanceof MenuItem) {
222
			if (macroObject.getContext() instanceof Menu) {
223
				IViewPart view = null;
224
				if (MacroUtil.onMenubar((MenuItem) widget)) {
225
					return new Path(MacroConstants.MENUS_VALUE).toString(); //$NON-NLS-1$
226
				} else if ((view = MacroUtil
227
						.onWorkbenchPartToolbar((MenuItem) widget)) != null) {
228
					return new Path(MacroConstants.LOCAL_TOOLBAR_MENU_VALUE)
229
							.append(
230
									new Path(MacroConstants.VIEW_VALUE)
231
											.append(view.getSite().getId()))
232
							.toString();
233
				}
234
				return null;
235
236
			} else if (macroObject.getContext() instanceof Control) {
237
				IMacroObjectIdentifier focusControlIdentifier = resolve(shell,
238
						new MacroObject(new UIObject((Control) macroObject
239
								.getContext())));
240
				if (focusControlIdentifier == null) {
241
					return null;
242
				} else {
243
					// the context id of a popup menu item is the concatenation
244
					// of the
245
					// MacroConstants.POPUP_VALUE keyword followed by the
246
					// IMacroObjectIdentifier
247
					// of the focus control
248
					return new Path(MacroConstants.POPUP_VALUE)
249
							.append(
250
									MacroObjectIdentifier
251
											.serializeMacroObjectIdentifier(focusControlIdentifier))
252
							.toString(); //$NON-NLS-1$
253
				}
254
			}
255
			return null;
256
		} else if (widget instanceof ToolItem) {
257
			/*
258
			 * Check to see if this toolbar belongs to the global toolbar of the
259
			 * workbench
260
			 */
261
			if (macroObject.getContext() instanceof IToolBarManager
262
					|| macroObject.getContext() instanceof ICoolBarManager) {
263
				// global toolbar of the workbench
264
				return new Path(MacroConstants.TOOLBAR_VALUE).toString(); //$NON-NLS-1$
265
			} else if (macroObject.getContext() instanceof ToolBar) {
266
				// Local toolbar somewhere - locate the parent first and use its
267
				// IMacroObjectIdentifier as
268
				// context, as in case of the LOCAL_TOOLBAR_MENU_VALUE
269
				ToolBar toolBar = (ToolBar) macroObject.getContext();
270
				IMacroObjectIdentifier toolBarIdentifier = resolve(shell,
271
						new MacroObject(new UIObject(toolBar)));
272
				if (toolBarIdentifier != null) {
273
					return new Path(MacroConstants.LOCAL_TOOLBAR_VALUE)
274
							.append(
275
									MacroObjectIdentifier
276
											.serializeMacroObjectIdentifier(toolBarIdentifier))
277
							.toString(); //$NON-NLS-1$
278
				} else {
279
					return null;
280
				}
281
			} else {
282
				return null;
283
			}
284
		} else if (widget instanceof TabItem || widget instanceof CTabItem) {
285
			IMacroObjectIdentifier tabFolderIdentifier = null;
286
			if (widget instanceof TabItem) {
287
				TabFolder tabFolder = (TabFolder) macroObject.getContext();
288
				tabFolderIdentifier = resolve(shell, new MacroObject(
289
						new UIObject(tabFolder)));
290
			} else {
291
				CTabFolder tabFolder = (CTabFolder) macroObject.getContext();
292
				tabFolderIdentifier = resolve(shell, new MacroObject(
293
						new UIObject(tabFolder)));
294
			}
295
			if (tabFolderIdentifier != null) {
296
				return new Path(MacroConstants.TAB_VALUE)
297
						.append(
298
								MacroObjectIdentifier
299
										.serializeMacroObjectIdentifier(tabFolderIdentifier))
300
						.toString();
301
			}
302
303
		} else if (widget instanceof Menu) {
304
			// it seems that menus are never resolved (as the deresolver does
305
			// not have any capability to deresolve them)
306
			AutoGUIUtil
307
					.throwCoreException("Menus are not suppported by current implementation");
308
			// return new Path(MacroConstants.MENUS_VALUE).toString();
309
		} else if (widget instanceof Control) {
310
			return resolveControlContextIdentifier(macroObject);
311
		}
312
		return null;
313
	}
314
315
	private static String resolveControlContextIdentifier(
316
			IMacroObject macroObject) {
317
		if (macroObject.getContext() instanceof WizardDialog) {
318
			return new Path(MacroConstants.WIZARD_VALUE).toString();
319
		} else if (macroObject.getContext() instanceof IWizardPage) {
320
			return new Path(MacroConstants.WIZARD_PAGE_VALUE).append(
321
					((IWizardPage) macroObject.getContext()).getName())
322
					.toString();
323
		} else if (macroObject.getContext() instanceof IWorkbenchPart) {
324
			IWorkbenchPart part = (IWorkbenchPart) macroObject.getContext();
325
			if (part instanceof IViewPart) {
326
				return new Path(MacroConstants.VIEW_VALUE).append(
327
						part.getSite().getId()).toString();
328
			} else if (part instanceof IEditorPart) {
329
				String inputName = ((IEditorPart) part).getEditorInput()
330
						.getName();
331
				return new Path(MacroConstants.EDITOR_VALUE).append(
332
						part.getSite().getId()).append(inputName).toString();
333
			} else {
334
				return null;
335
			}
336
		} else if (macroObject.getContext() instanceof Shell) {
337
			return new Path(MacroConstants.SHELL_VALUE).toString();
338
		} else {
339
			return null;
340
		}
341
	}
342
343
	/**
344
	 * TODO: split deresolving of context object from deresolving of UI object,
345
	 * which has to be done by UIObjectResolver....
346
	 * 
347
	 * @param shell
348
	 * @param macroObjectIdentifier
349
	 * @param parents
350
	 * @return
351
	 * @throws CoreException
352
	 */
353
	public static IMacroObject deresolve(Shell shell,
354
			IMacroObjectIdentifier macroObjectIdentifier) throws CoreException {
355
		String contextId = macroObjectIdentifier.getContextIdentifier();
356
357
		String firstToken = new Path(contextId).segment(0);
358
		String id = new Path(contextId).segment(1);
359
360
		Object context = null;
361
362
		if (MacroConstants.MENUS_VALUE.equals(firstToken)) {
363
			context = findMenuContext(shell, macroObjectIdentifier);
364
		} else if (MacroConstants.POPUP_VALUE.equals(firstToken)) {
365
			context = findPopupMenuItemContext(shell, macroObjectIdentifier);
366
		} else if (MacroConstants.TOOLBAR_VALUE.equals(firstToken)) {
367
			context = findToolItemContext(shell, macroObjectIdentifier);
368
		} else if (MacroConstants.LOCAL_TOOLBAR_VALUE.equals(firstToken)) {
369
			context = findLocalToolItemContext(shell, macroObjectIdentifier);
370
		} else if (MacroConstants.LOCAL_TOOLBAR_MENU_VALUE.equals(firstToken)) {
371
			context = findToolBarMenuItemContext(shell, macroObjectIdentifier);
372
		} else if (MacroConstants.TAB_VALUE.equals(firstToken)) {
373
			// ANy: added to properly deresolve TabItems and CTabItems (was done
374
			// locally by commands before)
375
			context = findTabItemContext(shell, macroObjectIdentifier);
376
		} else if (MacroConstants.WIZARD_VALUE.equals(firstToken)) {
377
			context = findWizardContext(shell, macroObjectIdentifier);
378
		} else if (MacroConstants.WIZARD_PAGE_VALUE.equals(firstToken)) {
379
			context = findWizardPageContext(shell, id, macroObjectIdentifier);
380
		} else if (MacroConstants.VIEW_VALUE.equals(firstToken)) {
381
			context = findViewContext(shell, id, macroObjectIdentifier);
382
		} else if (MacroConstants.EDITOR_VALUE.equals(firstToken)) {
383
			String inputName = new Path(contextId).segment(2);
384
			context = findEditorContext(shell, id, inputName,
385
					macroObjectIdentifier);
386
		} else if (MacroConstants.SHELL_VALUE.equals(firstToken)) {
387
			context = shell;
388
		}
389
		// else if (MacroConstants.LOCAL_SHELL_VALUE.equals(firstToken)) {
390
		// context = shell.getData();
391
		// }
392
393
		if (context != null) {
394
			IUIObject uiObject = UIObjectResolver.deresolve(context,
395
					macroObjectIdentifier.getObjectIdentifier());
396
			if (uiObject != null) {
397
				return new MacroObject(context, uiObject);
398
			} else {
399
				return null;
400
			}
401
		}
402
		return null;
403
	}
404
405
	private static Object findTabItemContext(Shell shell,
406
			IMacroObjectIdentifier macroObjectIdentifier) throws CoreException {
407
		IPath contextPath = new Path(macroObjectIdentifier
408
				.getContextIdentifier()).removeFirstSegments(1);
409
410
		IMacroObjectIdentifier tabFolderIdentifier = MacroObjectIdentifier
411
				.deserializeMacroObjectIdentifier(contextPath.toString());
412
		IMacroObject tabFolder = deresolve(shell, tabFolderIdentifier);
413
414
		if (tabFolder != null) {
415
			return tabFolder.getUIObject().getWidget();
416
		}
417
		return null;
418
	}
419
420
	private static Object findEditorContext(Shell shell, String id,
421
			String inputName, IMacroObjectIdentifier wid) throws CoreException {
422
		UIObject control = null;
423
424
		try {
425
			IEditorPart editor = MacroUtil.locateEditor(shell, id, inputName);
426
			return editor;
427
		} catch (Throwable t) {
428
			t.printStackTrace();
429
		}
430
		return null;
431
	}
432
433
	private static Object findLocalToolItemContext(Shell shell,
434
			IMacroObjectIdentifier wid) throws CoreException {
435
		// construct a IMacroObjectIdentifier for the toolbar
436
		// by splitting the context id.
437
438
		// 1) truncate the leading MacroConstants.LOCAL_TOOLBAR_MENU_VALUE
439
		// segment
440
		IPath wpath = new Path(wid.getContextIdentifier())
441
				.removeFirstSegments(1);
442
443
		IMacroObjectIdentifier toolBarIdentifier = MacroObjectIdentifier
444
				.deserializeMacroObjectIdentifier(wpath.toString());
445
446
		// now try to deresolve the toolbar with the given identifier
447
		ToolBar toolbar = null;
448
		try {
449
			IMacroObject toolbarObject = deresolve(shell, toolBarIdentifier);
450
			if (toolbarObject != null) {
451
				toolbar = (ToolBar) toolbarObject.getUIObject().getWidget();
452
			}
453
		} catch (Throwable t) {
454
			t.printStackTrace();
455
		}
456
		return toolbar;
457
		// try{
458
		// String firstToken = wpath.segment(0);
459
		// IWorkbenchPart workbenchPart = null;
460
		// Composite parent = null;
461
		// IMacroObject target = null;
462
		//
463
		// if (MacroConstants.VIEW_VALUE.equals(firstToken)) {
464
		// String id = wpath.segment(1);
465
		// workbenchPart = MacroUtil.locateView(shell, id);
466
		// } else if (MacroConstants.EDITOR_VALUE.equals(firstToken)) {
467
		// String id = wpath.segment(1);
468
		// workbenchPart = MacroUtil.locateEditor(shell, id, null);
469
		// } else if (MacroConstants.SHELL_VALUE.equals(firstToken)) {
470
		// parent = shell;
471
		// }
472
		//
473
		// if (workbenchPart != null) {
474
		// Composite comp = MacroUtil
475
		// .getWorkbenchPartControl(workbenchPart);
476
		// MacroUtil.processDisplayEvents(shell.getDisplay());
477
		// parent = comp.getParent();
478
		// }
479
		//
480
		// if (parent != null) {
481
		// IMacroObjectIdentifier widgetIdentifier = new MacroObjectIdentifier(
482
		// wid.getContextIdentifier(),
483
		// new PrimitiveUIObjectIdentifier(new Path(wid
484
		// .getContextIdentifier()).lastSegment(), wid
485
		// .getObjectIdentifier().getResolverId()));
486
		// UIObject control = UIObjectDeprecatedDeresolvingSupport
487
		// .locateVisibleChild(parent, null, widgetIdentifier);
488
		//
489
		// if (control != null && control.getWidget() instanceof ToolBar) {
490
		// target = locateToolItem((ToolBar) control.getWidget(), wid);
491
		// }
492
		// }
493
		//
494
		// if (target != null)
495
		// return target;
496
		//
497
		// } catch (Throwable t) {
498
		// /* The next line will throw an exception */
499
		// t.printStackTrace();
500
		// }
501
		//
502
		// AutoGUIUtil.throwCoreException(NLS.bind(
503
		// AutoGUIMessages.AUTO_GUI_ERROR_MACRO_TOOL_BAR, wid
504
		// .getContextIdentifier()
505
		// + wid.getObjectIdentifier().getObjectId()));
506
		// return null;
507
	}
508
509
	private static Object findMenuContext(Shell shell,
510
			IMacroObjectIdentifier wid) throws CoreException {
511
		Menu menuBar = shell.getMenuBar();
512
		return menuBar;
513
	}
514
515
	// private static MenuItem locateMenuItem(MenuManager mng,
516
	// IMacroObjectIdentifier widgetId) {
517
	// IContributionItem[] items = mng.getItems();
518
	//		
519
	// String lastSegment = getLastSegment(new
520
	// Path(widgetId.getObjectIdentifier().getObjectId()));
521
	// String parentId = null;
522
	//
523
	// for (int i = 0; i < items.length; i++) {
524
	// IContributionItem citem = items[i];
525
	//
526
	// if (citem instanceof MenuManager) {
527
	// MenuManager submenu = (MenuManager) citem;
528
	// String subId = submenu.getId();
529
	//				
530
	// if (subId.equals(parentId))
531
	// {
532
	//
533
	// // show this menu to force dynamic items
534
	// // to show
535
	// Menu menu = submenu.getMenu();
536
	// forceMenuOpen(null, menu);
537
	//
538
	// MenuItem hit = locateMenuItem(submenu, widgetId);
539
	// forceMenuClosed(menu);
540
	// if (hit != null)
541
	// return hit;
542
	// }
543
	//
544
	// } else {
545
	// /*
546
	// * Ali M.: I believe that the first line and the following block
547
	// * were for optimization purposes only
548
	// */
549
	// String itemId =
550
	// NonTrivialUIObjectResolverDelegate.getActionId(citem).getObjectId();
551
	// if (itemId != null &&
552
	// widgetId.getObjectIdentifier().getObjectId().equals(itemId)) {
553
	// MenuItem hit = locateMenuItem(mng.getMenu(), widgetId);
554
	// if (hit != null)
555
	// return hit;
556
	// }
557
	// }
558
	// }
559
	// return null;
560
	// }
561
562
	private static Object findPopupMenuItemContext(Shell shell,
563
			IMacroObjectIdentifier wid) throws CoreException {
564
		// try {
565
566
		IPath contextPath = new Path(wid.getContextIdentifier())
567
				.removeFirstSegments(1);
568
569
		IMacroObjectIdentifier focusControlIdentifier = MacroObjectIdentifier
570
				.deserializeMacroObjectIdentifier(contextPath.toString());
571
		IMacroObject focusControlObject = deresolve(shell,
572
				focusControlIdentifier);
573
574
		if (focusControlObject != null) {
575
			Control control = (Control) focusControlObject.getUIObject()
576
					.getWidget();
577
			Menu popupMenu = control.getMenu();
578
			return popupMenu;
579
		} else {
580
			return null;
581
		}
582
583
		// IPath wpath = new Path(getLastSegment(contextPath));
584
		//
585
		// int widgetPathInx = contextPath.toString()
586
		// .indexOf(wpath.toString());
587
		// if (widgetPathInx > 0)
588
		// contextPath = new Path(contextPath.toString().substring(0,
589
		// widgetPathInx - 1));
590
		// IMacroObject target = deresolve(shell, new MacroObjectIdentifier(
591
		// contextPath.toString(), new PrimitiveUIObjectIdentifier(
592
		// wpath.toString(), null)));
593
		// if (target != null) {
594
		// // for (int i = 0; i < targets.length; i++) {
595
		// Control control = (Control) target.getUIObject().getWidget();
596
		// Menu popupMenu = control.getMenu();
597
		// if (popupMenu != null) {
598
		// MacroUtil.forceMenuOpen(popupMenu);
599
		// UIObject menuItem = locateMenuItem(popupMenu, wid
600
		// .getObjectIdentifier());
601
		// MacroUtil.forceMenuClosed(popupMenu);
602
		// if (menuItem != null) {
603
		// return new MacroObject(control, menuItem);
604
		// }
605
		// }
606
		// // }
607
		// }
608
		// } catch (Throwable t) {
609
		// /* The next line will throw an exception */
610
		// t.printStackTrace();
611
		// }
612
		// AutoGUIUtil.throwCoreException(NLS.bind(
613
		// AutoGUIMessages.AUTO_GUI_ERROR_MACRO_MENU, wid
614
		// .getObjectIdentifier().getObjectId()));
615
		// return null;
616
	}
617
618
	private static Object findToolBarMenuItemContext(Shell shell,
619
			IMacroObjectIdentifier wid) throws CoreException {
620
		// try {
621
		IPath contextPath = new Path(wid.getContextIdentifier())
622
				.removeFirstSegments(1);
623
624
		/* The context is a menu */
625
		IViewPart view = null;
626
		if (MacroConstants.VIEW_VALUE.equals(contextPath.segment(0))) {
627
			view = MacroUtil.locateView(shell, contextPath.segment(1));
628
		}
629
630
		IViewSite viewSite = view == null ? null : view.getViewSite();
631
		IMenuManager menuManager = null;
632
		if (viewSite != null) {
633
			IActionBars actionBar = viewSite.getActionBars();
634
			actionBar.updateActionBars();
635
			menuManager = actionBar.getMenuManager();
636
		}
637
638
		if (menuManager != null && menuManager instanceof MenuManager) {
639
			Menu menu = ((MenuManager) menuManager).getMenu();
640
			if (menu == null) {
641
				// try to create menu
642
				((MenuManager) menuManager).createMenuBar((Decorations) view
643
						.getSite().getShell());
644
			}
645
			return menu;
646
		} else {
647
			return null;
648
		}
649
	}
650
651
	private static String getLastSegment(IPath contextPath) {
652
		String[] segments = contextPath.segments();
653
		String candidate = "";
654
		for (int i = segments.length - 1; i >= 0; i--) {
655
			if (candidate.length() > 0)
656
				candidate = "/" + candidate;
657
			candidate = segments[i] + candidate;
658
			int openingBracesInx = candidate.indexOf('{');
659
			int closingBracesInx = candidate.indexOf('}');
660
			if ((openingBracesInx == -1 && closingBracesInx == -1)
661
					|| (openingBracesInx >= 0 && openingBracesInx < closingBracesInx))
662
				return candidate;
663
		}
664
665
		return "";
666
	}
667
668
	// private static IMacroObject locateShellControl(Shell shell,
669
	// IMacroObjectIdentifier wid) throws CoreException {
670
	// UIObject control = null;
671
	// Window window = null;
672
	// boolean ambiguous = false;
673
	// try {
674
	// window = (Window) shell.getData();
675
	// control = UIObjectDeprecatedDeresolvingSupport.locateVisibleChild(
676
	// shell, null, wid);
677
	// } catch (Throwable t) {
678
	// if (t instanceof CoreException) {
679
	// AutoGUIUtil.throwCoreException(NLS.bind(
680
	// AutoGUIMessages.AUTO_GUI_MACRO_UI_OBJECT_AMBIGUOUS, wid
681
	// .getObjectIdentifier(), wid
682
	// .getContextIdentifier()));
683
	// }
684
	// }
685
	// if (control == null)
686
	// AutoGUIUtil.throwCoreException(NLS.bind(
687
	// AutoGUIMessages.AUTO_GUI_ERROR_MACRO_SHELL, wid
688
	// .getObjectIdentifier().getObjectId()));
689
	//
690
	// // IMacroObject[] windowCommandTarget = new
691
	// // IMacroObject[controls.length];
692
	// // for (int i = 0; i < controls.length; i++) {
693
	// // if (controls[i].isDisposed())
694
	// // AutoGUIUtil.throwCoreException(NLS.bind(
695
	// // AutoGUIMessages.AUTO_GUI_ERROR_MACRO_SHELL_DIS, wid
696
	// // .getObjectIdentifier().getObjectId()));
697
	// // windowCommandTarget[i] = new MacroObject(window, new UIObject(
698
	// // controls[i]));
699
	// // }
700
	// //
701
	// // return windowCommandTarget;
702
	// return new MacroObject(window, control);
703
	// }
704
705
	private static Object findToolItemContext(Shell shell,
706
			IMacroObjectIdentifier wid) throws CoreException {
707
708
		try {
709
			Object data = shell.getData();
710
			if (data instanceof ApplicationWindow) {
711
				ApplicationWindow window = (ApplicationWindow) data;
712
				CoolBarManager coolMng = window.getCoolBarManager();
713
				if (coolMng != null) {
714
					return coolMng;
715
				}
716
				ToolBarManager toolMng = window.getToolBarManager();
717
				if (toolMng != null) {
718
					return toolMng;
719
				}
720
			}
721
		} catch (Throwable t) {
722
			t.printStackTrace();
723
		}
724
		return null;
725
	}
726
727
	private static Object findViewContext(Shell shell, String id,
728
			IMacroObjectIdentifier wid) throws CoreException {
729
		try {
730
			IViewPart view = MacroUtil.locateView(shell, id);
731
			return view;
732
		} catch (Throwable t) {
733
			t.printStackTrace();
734
		}
735
		return null;
736
	}
737
738
	private static Object findWizardContext(Shell shell,
739
			IMacroObjectIdentifier wid) throws CoreException {
740
		WizardDialog wdialog = null;
741
		if (shell.getData() instanceof WizardDialog) {
742
			wdialog = (WizardDialog) shell.getData();
743
			Assert
744
					.isLegal(
745
							wdialog.getShell() == shell,
746
							"If the current shell is not the shell of the wizard, we have a deresolving problem");
747
		}
748
		return wdialog;
749
	}
750
751
	private static Object findWizardPageContext(Shell shell, String id,
752
			IMacroObjectIdentifier wid) throws CoreException {
753
		IWizardPage page = null;
754
		Object data = shell.getData();
755
		if (data instanceof WizardDialog) {
756
			WizardDialog wdialog = (WizardDialog) data;
757
			page = wdialog.getCurrentPage();
758
		}
759
		return page;
760
761
	}
762
763
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/WidgetResolverToUIObjectResolverDelegateAdapter.java (+48 lines)
Added Link Here
1
package org.eclipse.tptp.test.auto.gui.internal.core;
2
3
4
import org.eclipse.core.runtime.CoreException;
5
import org.eclipse.swt.widgets.Control;
6
import org.eclipse.swt.widgets.MenuItem;
7
import org.eclipse.swt.widgets.Widget;
8
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObject;
9
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
10
import org.eclipse.tptp.test.auto.gui.internal.uiobject.PrimitiveUIObjectIdentifier;
11
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.IUIObjectResolverDelegate;
12
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.deresolvingsupport.IUIObjectDeprecatedDeresolvingFacade;
13
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.deresolvingsupport.UIObjectDeprecatedDeresolvingSupport;
14
15
public class WidgetResolverToUIObjectResolverDelegateAdapter implements
16
		IUIObjectResolverDelegate, IUIObjectDeprecatedDeresolvingFacade {
17
18
	private IWidgetResolver widgetResolver = null;
19
20
	public WidgetResolverToUIObjectResolverDelegateAdapter(IWidgetResolver widgetResolver) {
21
		super();
22
		this.widgetResolver = widgetResolver;
23
	}
24
25
	public boolean foundWidget(Widget object, IUIObjectIdentifier objectId) {
26
		return widgetResolver.foundWidget(object, objectId.getWidgetId());
27
	}
28
29
	public IUIObject deresolve(Object context,
30
			IUIObjectIdentifier uiObjectIdentifier) throws CoreException {
31
		return UIObjectDeprecatedDeresolvingSupport.deresolve(context,
32
				uiObjectIdentifier);
33
	}
34
35
	public IUIObjectIdentifier resolve(Object context, IUIObject uiObject)
36
			throws CoreException {
37
		
38
		IWidgetId widgetId = null;
39
		if(uiObject.getObject() == null){
40
			widgetId = widgetResolver.getUniqueId(uiObject.getWidget() instanceof Control ? ((Control)uiObject.getWidget()).getParent() : null, uiObject.getWidget());
41
		}
42
		else{
43
			widgetId = widgetResolver.getUniqueId(uiObject.getWidget(), uiObject.getObject());
44
		}
45
		return widgetId == null ? null : new PrimitiveUIObjectIdentifier(widgetId.toString(), widgetId.getResolverId());
46
	}
47
48
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macroobject/mine/MacroObjectDescriptor.java (+236 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macroobject.mine;
12
13
import java.util.ArrayList;
14
import java.util.Hashtable;
15
import java.util.LinkedList;
16
import java.util.Map;
17
18
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.osgi.util.NLS;
20
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
21
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
22
import org.eclipse.tptp.test.auto.gui.internal.commands.ObjectBasedCommand;
23
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
24
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObjectIdentifier;
25
26
public class MacroObjectDescriptor {
27
28
	/** The context id */
29
	private String contextId;
30
31
	/** The widget id of the UI object being resolved */
32
	private String widgetId;
33
	
34
	/** The (optional) object id of the UI object to be resolved */
35
	private String objectId;
36
37
	/** The reference id of this object */
38
	private String referenceId;
39
40
	/** The descriptive attribute (a human readable identification) of this UI object */
41
	private String descriptive;
42
43
	/** Keeps track of the hierarchical relationship */
44
	private LinkedList hierarchicalRelation;
45
46
	/** The parent of this UI object */
47
	private MacroObjectDescriptor parent;
48
49
	/** The properties of this UI Object */
50
	private Hashtable properties;
51
52
	/** The id of the resolver that has resolved this object */
53
	private String resolverId;
54
55
	/** The children of this object */
56
	private ArrayList children;
57
58
	/** The associated data of this object */
59
	private Object data;
60
61
	/**
62
	 * Children indexed based on their reference id KEY = Reference id VALUE = MacroObjectDescriptor that is a child of this object
63
	 */
64
	private Hashtable idIndexedChildren;
65
66
	public MacroObjectDescriptor(MacroObjectDescriptor parent) {
67
		this.parent = parent;
68
		properties = new Hashtable();
69
		children = new ArrayList();
70
		idIndexedChildren = new Hashtable();
71
	}
72
73
	/**
74
	 * Creates an instace of this class based on a command passed in.
75
	 * 
76
	 * @param objectMine
77
	 *            The object mine that this object will be registered with
78
	 * @param command
79
	 *            The command that this object will be based on
80
	 * @param parent
81
	 *            The parent of this object
82
	 * 
83
	 * @return An instance of this class based on widgetIdentifier
84
	 */
85
	public static MacroObjectDescriptor createInstance(ObjectBasedCommand command, MacroObjectDescriptor parent) {
86
		IMacroObjectIdentifier macroObjectIdentifier = command.getMacroObjectIdentifier();
87
		MacroObjectDescriptor uiObject = new MacroObjectDescriptor(parent);
88
		uiObject.setContextId(macroObjectIdentifier.getContextIdentifier() != null
89
			? macroObjectIdentifier.getContextIdentifier().toString()
90
			: MacroConstants.EMPTY_STRING);
91
		uiObject.setWidgetId(macroObjectIdentifier.getObjectIdentifier().getWidgetId());
92
		uiObject.setObjectId(macroObjectIdentifier.getObjectIdentifier().getObjectId());
93
		uiObject.setDescriptive(command.getDescriptiveField());
94
		uiObject.setResolver(macroObjectIdentifier.getObjectIdentifier().getResolverId());
95
96
		return uiObject;
97
	}
98
99
	public String getContextId() {
100
		return contextId;
101
	}
102
103
	public String getDescriptive() {
104
		return descriptive;
105
	}
106
107
	public LinkedList getHierarchicalRelation() {
108
		if (hierarchicalRelation != null)
109
			return hierarchicalRelation;
110
111
		hierarchicalRelation = new LinkedList();
112
		findHierarchicalRelation(this);
113
114
		return hierarchicalRelation;
115
	}
116
117
	private void findHierarchicalRelation(MacroObjectDescriptor currentObject) {
118
		if (currentObject == null)
119
			return;
120
		hierarchicalRelation.addFirst(currentObject);
121
		findHierarchicalRelation(currentObject.getParent());
122
	}
123
124
	public String getObjectId(){
125
		return objectId;
126
	}
127
	
128
	public void setObjectId(String objectId){
129
		this.objectId = objectId;
130
	}
131
	
132
	public String getWidgetId() {
133
		return widgetId;
134
	}
135
136
	public Map getProperties() {
137
		return properties;
138
	}
139
140
	public String getProperty(String name) {
141
		return (String) properties.get(name);
142
	}
143
144
	public String getReferenceId() {
145
		return referenceId;
146
	}
147
148
	public void setContextId(String contextId) {
149
		this.contextId = contextId;
150
	}
151
152
	public void setDescriptive(String descriptive) {
153
		this.descriptive = descriptive;
154
	}
155
156
	public void setWidgetId(String id) {
157
		this.widgetId = id;
158
	}
159
160
	public void addProperty(String name, String value) {
161
		properties.put(name,
162
			value);
163
	}
164
165
	public void setReferenceId(String referenceId) {
166
		this.referenceId = referenceId;
167
	}
168
169
	public MacroObjectDescriptor getParent() {
170
		return parent;
171
	}
172
173
	public void setParent(MacroObjectDescriptor parent) {
174
		this.parent = parent;
175
	}
176
177
	public String getResolverId() {
178
		return resolverId;
179
	}
180
181
	public void setResolver(String resolverId) {
182
		this.resolverId = resolverId;
183
	}
184
185
	public void addChild(MacroObjectDescriptor child) throws CoreException {
186
		if (!children.contains(child)) {
187
			try {
188
				/* If there is a collision, then try to resolve it */
189
				int referenceId = Integer.parseInt(child.getReferenceId());
190
				while (idIndexedChildren.get(child.getReferenceId()) != null) {
191
					referenceId++;
192
				}
193
				child.setReferenceId(String.valueOf(referenceId));
194
			}
195
			catch (NumberFormatException nfe) {
196
				/* Ignore the error */
197
			}
198
199
			/* If there is still a collision, then throw an exception */
200
			if (idIndexedChildren.get(child.getReferenceId()) != null)
201
				AutoGUIUtil.throwCoreException(NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE_ID,
202
					child.getReferenceId()));
203
204
			idIndexedChildren.put(child.getReferenceId(),
205
				child);
206
			children.add(child);
207
		}
208
	}
209
210
	public int childCount() {
211
		return children.size();
212
	}
213
214
	public MacroObjectDescriptor[] getChildren() {
215
		MacroObjectDescriptor[] objects = new MacroObjectDescriptor[children.size()];
216
		children.toArray(objects);
217
		return objects;
218
	}
219
220
	public MacroObjectDescriptor removeChild(MacroObjectDescriptor child) {
221
		children.remove(child);
222
		return child;
223
	}
224
225
	public Object getData() {
226
		return data;
227
	}
228
229
	public void setData(Object data) {
230
		this.data = data;
231
	}
232
233
	public MacroObjectDescriptor findChild(String referenceId) {
234
		return (MacroObjectDescriptor) idIndexedChildren.get(referenceId);
235
	}
236
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/IUIObjectIdentifier.java (+42 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.uiobject;
13
14
15
/**
16
 * @author Alexander Nyssen
17
 */
18
public interface IUIObjectIdentifier {
19
20
	/**
21
	 * Returns the id of the widget object to be identified
22
	 * 
23
	 * @return The widget id
24
	 */
25
	public String getWidgetId();
26
	
27
	/**
28
	 * Returns the id of the nested object to be identified on the respective widget,
29
	 * e.g. a String to name an item on a ComboBox.
30
	 * @return The id of the nested object
31
	 */
32
	public String getObjectId();
33
	
34
	/**
35
	 * Returns the id of the ui object resolver delegate that generated this identifier.
36
	 * 
37
	 * @return The id of the ui object resolver delegate that generated this identifier.
38
	 */
39
	public String getResolverId();
40
41
	
42
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macroobject/mine/MacroObjectDescriptorMineManager.java (+403 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macroobject.mine;
12
13
import java.io.ByteArrayInputStream;
14
import java.io.IOException;
15
import java.util.Hashtable;
16
import java.util.List;
17
18
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.core.runtime.IPath;
20
import org.eclipse.core.runtime.Path;
21
import org.eclipse.emf.common.util.URI;
22
import org.eclipse.emf.ecore.EObject;
23
import org.eclipse.emf.ecore.resource.Resource;
24
import org.eclipse.hyades.models.common.facades.behavioral.ITestSuite;
25
import org.eclipse.hyades.models.common.facades.behavioral.impl.HyadesUtil;
26
import org.eclipse.hyades.test.core.util.EMFUtil;
27
import org.eclipse.hyades.test.tools.ui.common.internal.util.FormUtil;
28
import org.eclipse.osgi.util.NLS;
29
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
30
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
31
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
32
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
33
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
34
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine.IDCollisionException;
35
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptorMine.UIObjectNotFound;
36
import org.eclipse.tptp.test.auto.gui.internal.util.XMLDefaultHandler;
37
import org.w3c.dom.NamedNodeMap;
38
import org.w3c.dom.Node;
39
import org.w3c.dom.NodeList;
40
import org.xml.sax.SAXException;
41
42
/**
43
 * In addition to the macro of each test case, a test suite also contains an
44
 * object mine keeps a reference of all resolved objects. The purpose of the
45
 * object mine is to resolve a widget once and use it many times.
46
 * 
47
 * This is a singleton class that can be accessed via <code>getInstance()</code>
48
 * 
49
 * @author Ali Mehregani
50
 */
51
public class MacroObjectDescriptorMineManager {
52
	/** The instance of this class */
53
	private static MacroObjectDescriptorMineManager instance = new MacroObjectDescriptorMineManager();
54
55
	/**
56
	 * Cached object mines KEY = Test suite id VALUE = An object of type
57
	 * MacroObjectDescriptorMine that represents the object mine of the test
58
	 * suite
59
	 */
60
	private Hashtable cachedObjectMines;
61
62
	/**
63
	 * Indicates whether a test suite's object mine is dirty or not KEY = test
64
	 * suite id VALUE = Boolean.TRUE if object mine is dirty; Boolean.FALSE
65
	 * otherwise
66
	 */
67
	private Hashtable dirtyStateTable;
68
69
	/**
70
	 * Restrict the visibility of the constructor
71
	 */
72
	private MacroObjectDescriptorMineManager() {
73
		cachedObjectMines = new Hashtable();
74
		dirtyStateTable = new Hashtable();
75
	}
76
77
	/**
78
	 * Return the instance of this singleton class
79
	 * 
80
	 * @return The instance of this class
81
	 */
82
	public static MacroObjectDescriptorMineManager getInstance() {
83
		return instance;
84
	}
85
86
	/**
87
	 * Load the object mine of the passed in test suite
88
	 * 
89
	 * @param testSuite
90
	 *            The test suite whose object mine is requested
91
	 * @param useCache
92
	 *            Uses the cached value if this is set to true; otherwise the
93
	 *            object mine is reloaded and returned.
94
	 * 
95
	 * @return the object mine of the test suite that is passed in.
96
	 * 
97
	 * @throws UIObjectNotFound
98
	 *             In case an expected object is not found
99
	 * @throws IDCollisionException
100
	 *             In case there is a collision id
101
	 * @throws CoreException
102
	 *             In case of any unexpected error
103
	 */
104
	public MacroObjectDescriptorMine loadObjectMine(ITestSuite testSuite,
105
			boolean useCache) throws UIObjectNotFound, IDCollisionException,
106
			CoreException {
107
		/* Is the object mine in cache? */
108
		String testSuiteId = testSuite.getId();
109
		MacroObjectDescriptorMine objectMine = null;
110
		if (useCache
111
				&& (objectMine = (MacroObjectDescriptorMine) cachedObjectMines
112
						.get(testSuiteId)) != null) {
113
			objectMine.setOwner(testSuite);
114
			return objectMine;
115
		}
116
117
		/*
118
		 * Otherwise, it needs to be loaded. We need: - Get the object mine XML
119
		 * fragment - Parse it and load it
120
		 */
121
		String objectMineXML = HyadesUtil.getTestSuiteVariable(testSuite,
122
				GlobalConstants.TEST_SUITE_PROPERTY_OBJECT_MINE);
123
		if (objectMineXML == null || objectMineXML.length() <= 0) {
124
			/* Return a fresh object mine */
125
			objectMine = new MacroObjectDescriptorMine(testSuite, null);
126
		}
127
128
		if (objectMine == null) {
129
			objectMine = loadObjectMine(testSuite, objectMineXML);
130
		}
131
132
		if (objectMine != null) {
133
			cachedObjectMines.put(testSuiteId, objectMine);
134
		}
135
136
		return objectMine;
137
	}
138
139
	private MacroObjectDescriptorMine loadObjectMine(ITestSuite testSuite,
140
			String objectMineXML) throws UIObjectNotFound,
141
			IDCollisionException, CoreException {
142
		if (objectMineXML == null || objectMineXML.length() <= 0)
143
			return new MacroObjectDescriptorMine(testSuite, null);
144
145
		XMLDefaultHandler handler = null;
146
147
		try {
148
			handler = MacroUtil.createXMLDocument(new ByteArrayInputStream(
149
					objectMineXML.getBytes("UTF-8")));
150
		} catch (SAXException e) {
151
			AutoGUIUtil.throwCoreException(
152
					AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE, 0, e);
153
		} catch (IOException e) {
154
			AutoGUIUtil.throwCoreException(
155
					AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE, 0, e);
156
		}
157
158
		/* Walk through the elemets and parse the document */
159
		Node rootElement = handler.getDocumentElement();
160
		NodeList children = rootElement.getChildNodes();
161
162
		MacroObjectDescriptorMine objectMine = new MacroObjectDescriptorMine(
163
				testSuite, handler);
164
		for (int i = 0, childCount = children.getLength(); i < childCount; i++) {
165
			Node currentChild = children.item(i);
166
			String nodeName = currentChild.getNodeName();
167
			if (MacroConstants.HEADER_ELEMENT.equals(nodeName)) {
168
				loadHeader(objectMine, currentChild);
169
			} else if (MacroConstants.OBJECTS_ELEMENT.equals(nodeName)) {
170
				loadObjects(objectMine, currentChild);
171
			}
172
		}
173
174
		return objectMine;
175
	}
176
177
	/**
178
	 * This method should be used if the object mine will be loaded for reading
179
	 * purposes. Contributors will not be able to use this returned object mine
180
	 * to write any objects.
181
	 * 
182
	 * @param objectMineXML
183
	 *            The XML string representing the object mine
184
	 * 
185
	 * @return the object mine of the test suite that is passed in.
186
	 * 
187
	 * @throws UIObjectNotFound
188
	 *             In case an expected object is not found
189
	 * @throws IDCollisionException
190
	 *             In case there is a collision id
191
	 * @throws CoreException
192
	 *             In case of any unexpected error
193
	 */
194
	public MacroObjectDescriptorMine loadObjectMine(String objectMineXML)
195
			throws UIObjectNotFound, IDCollisionException, CoreException {
196
		return loadObjectMine(null, objectMineXML);
197
	}
198
199
	private void loadHeader(MacroObjectDescriptorMine objectMine,
200
			Node headerNode) throws CoreException, UIObjectNotFound,
201
			IDCollisionException {
202
		/* Let's first read in the contribute attribute */
203
		NamedNodeMap attributes = headerNode.getAttributes();
204
		Node contributeAtt = attributes
205
				.getNamedItem(MacroConstants.OUTPUT_ATTRIBUTE);
206
		if (contributeAtt != null) {
207
			ITestSuite testSuite = loadTestSuite(contributeAtt.getNodeValue());
208
			if (testSuite == null) {
209
				AutoGUIUtil.openErrorWithDetail(
210
						AutoGUIMessages.AUTO_GUI_COMMON_ERROR,
211
						AutoGUIMessages.AUTO_GUI_ERROR_OBJ_MINE_OUT_NF, null);
212
213
			} else {
214
				try {
215
					MacroObjectDescriptorMine outputObjectMine = MacroObjectDescriptorMineManager
216
							.getInstance().loadObjectMine(testSuite);
217
					objectMine.setOutputSource(outputObjectMine);
218
				} catch (Exception e) {
219
					objectMine.setOutputSource(null);
220
					AutoGUIUtil
221
							.openErrorWithDetail(
222
									AutoGUIMessages.AUTO_GUI_COMMON_ERROR,
223
									NLS
224
											.bind(
225
													AutoGUIMessages.AUTO_GUI_ERROR_OBJ_MINE_OUTPUT,
226
													testSuite.getName()), e);
227
				}
228
			}
229
		}
230
231
		/* Now load in all includes */
232
		NodeList children = headerNode.getChildNodes();
233
		for (int i = 0, childCount = children.getLength(); i < childCount; i++) {
234
			Node currentChild = children.item(i);
235
			String nodeName = currentChild.getNodeName();
236
			if (MacroConstants.INCLUDE_ELEMENT.equals(nodeName)) {
237
				Node pathAttribute = currentChild.getAttributes().getNamedItem(
238
						MacroConstants.PATH_ATTRIBUTE);
239
				if (pathAttribute != null) {
240
					ITestSuite testSuite = loadTestSuite(pathAttribute
241
							.getNodeValue());
242
					MacroObjectDescriptorMine includedObjectMine = loadObjectMine(testSuite);
243
					objectMine.addInclude(includedObjectMine);
244
				}
245
			}
246
		}
247
	}
248
249
	private void loadObjects(MacroObjectDescriptorMine objectMine,
250
			Node objectsNode) throws CoreException, UIObjectNotFound,
251
			IDCollisionException {
252
		NodeList children = objectsNode.getChildNodes();
253
		registerObjects(objectMine, null, children);
254
	}
255
256
	private void registerObjects(MacroObjectDescriptorMine objectMine,
257
			MacroObjectDescriptor parent, NodeList children)
258
			throws CoreException, UIObjectNotFound, IDCollisionException {
259
		/* For every object */
260
		for (int i = 0, childCount = children.getLength(); i < childCount; i++) {
261
			Node currentNode = children.item(i);
262
263
			NamedNodeMap attributes = currentNode.getAttributes();
264
			Node referenceIdNode = attributes
265
					.getNamedItem(MacroConstants.REFERENCE_ID_ATTRIBUTE);
266
			String referenceId = null;
267
			if (referenceIdNode == null
268
					|| (referenceId = referenceIdNode.getNodeValue()) == null) {
269
				Node widetIdAttribute = attributes
270
						.getNamedItem(MacroConstants.WIDGET_ID_ATTRIBUTE);
271
				Node objectIdAttribute = attributes
272
						.getNamedItem(MacroConstants.OBJECT_ID_ATTRIBUTE);
273
				String widgetId = widetIdAttribute == null ? AutoGUIMessages.AUTO_GUI_COMMON_UNKNOWN
274
						: widetIdAttribute.getNodeValue();
275
				String objectId = objectIdAttribute == null ? AutoGUIMessages.AUTO_GUI_COMMON_UNKNOWN
276
						: objectIdAttribute.getNodeValue();
277
				AutoGUIUtil.throwCoreException(NLS.bind(
278
						AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE_REF,
279
						widgetId, objectId), 0);
280
			}
281
282
			MacroObjectDescriptor guiObject = objectMine
283
					.lookupMacroObjectDescriptor(parent, referenceId);
284
285
			/* Register the object if it's not yet registered */
286
			if (guiObject == null) {
287
				guiObject = objectMine.registerObject(parent, currentNode);
288
			}
289
			/* Otherwise throw an exception if there is an id collision */
290
			else {
291
				Node contextIdNode = attributes
292
						.getNamedItem(MacroConstants.CONTEXT_ID_ATTRIBUTE);
293
				Node widgetIdNode = attributes
294
						.getNamedItem(MacroConstants.WIDGET_ID_ATTRIBUTE);
295
				Node objectIdNode = attributes
296
						.getNamedItem(MacroConstants.OBJECT_ID_ATTRIBUTE);
297
				String contextId = contextIdNode == null ? null : contextIdNode
298
						.getNodeValue();
299
				String widgetId = widgetIdNode == null ? null : widgetIdNode
300
						.getNodeValue();
301
				String objectId = objectIdNode == null ? null : objectIdNode
302
						.getNodeValue();
303
304
				if (((contextId == null && guiObject.getContextId() != null) || (contextId != null && !contextId
305
						.equals(guiObject.getContextId())))
306
						|| ((widgetId == null && guiObject.getWidgetId() != null) || (widgetId != null && !widgetId
307
								.equals(guiObject.getWidgetId())))
308
						|| ((objectId == null && guiObject.getObjectId() != null) || (objectId != null && !objectId
309
								.equals(guiObject.getObjectId())))) {
310
					throw new IDCollisionException(NLS.bind(
311
							AutoGUIMessages.AUTO_GUI_ERROR_TST_OBJ_MINE_ID,
312
							referenceId));
313
				}
314
			}
315
316
			/* Load the children of this object */
317
			if (currentNode.getChildNodes().getLength() > 0)
318
				registerObjects(objectMine, guiObject, currentNode
319
						.getChildNodes());
320
		}
321
	}
322
323
	private ITestSuite loadTestSuite(String testSuitePath) throws CoreException {
324
		if (testSuitePath == null || testSuitePath.length() <= 0)
325
			return null;
326
327
		IPath path = new Path(testSuitePath);
328
		URI uri = URI.createPlatformResourceURI(path.toString());
329
		EObject[] eObjects = EMFUtil.getEObjects(uri, true);
330
		return eObjects != null && eObjects.length > 0
331
				&& eObjects[0] instanceof ITestSuite ? (ITestSuite) eObjects[0]
332
				: null;
333
	}
334
335
	public void writeObjectMine(MacroObjectDescriptorMine objectMine) {
336
		writeObjectMine(objectMine, false);
337
	}
338
339
	private void writeObjectMine(MacroObjectDescriptorMine objectMine,
340
			boolean autoSave) {
341
		ITestSuite testSuite = objectMine.getOwner();
342
		Resource testSuiteResource = ((EObject) testSuite).eResource();
343
		autoSave = autoSave
344
				&& (testSuiteResource != null && !testSuiteResource
345
						.isModified());
346
347
		String xmlSerialization = objectMine.serializeToString();
348
		HyadesUtil.setTestSuiteVariable(testSuite,
349
				GlobalConstants.TEST_SUITE_PROPERTY_OBJECT_MINE,
350
				xmlSerialization);
351
352
		if (autoSave) {
353
			try {
354
				EMFUtil.save(testSuiteResource);
355
			} catch (Exception e) {
356
				/* Shouldn't happen */
357
				e.printStackTrace();
358
			}
359
		}
360
361
		/*
362
		 * We also need to update all object mines included by the object mine
363
		 * passed in
364
		 */
365
		List includes = objectMine.getIncludes();
366
		for (int i = 0, includeCount = includes.size(); i < includeCount; i++) {
367
			MacroObjectDescriptorMine currentObjectMine = (MacroObjectDescriptorMine) includes
368
					.get(i);
369
			writeObjectMine(currentObjectMine, true);
370
		}
371
372
		dirtyStateTable.put(testSuite.getId(), Boolean.TRUE);
373
	}
374
375
	public MacroObjectDescriptorMine loadObjectMine(ITestSuite testSuite)
376
			throws UIObjectNotFound, IDCollisionException, CoreException {
377
		Boolean dirtyState = (Boolean) dirtyStateTable.get(testSuite.getId());
378
		boolean isObjectMineDirty = dirtyState == null ? false : dirtyState
379
				.booleanValue();
380
		dirtyStateTable.put(testSuite.getId(), Boolean.FALSE);
381
		return loadObjectMine(testSuite, !isObjectMineDirty);
382
	}
383
384
	/**
385
	 * Marks the object mine of the passed in test suite as dirty
386
	 * 
387
	 * @param testSuite
388
	 *            The test suite
389
	 */
390
	public void markObjectMineDirty(ITestSuite testSuite) {
391
		if (testSuite == null)
392
			return;
393
394
		dirtyStateTable.put(testSuite.getId(), Boolean.TRUE);
395
	}
396
397
	/**
398
	 * Removes all entries in cache. This should be carefully used.
399
	 */
400
	public void clearCache() {
401
		cachedObjectMines.clear();
402
	}
403
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/UIObject.java (+47 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.uiobject;
13
14
import org.eclipse.swt.widgets.Widget;
15
16
17
/**
18
 * Represents a widget or a nested object on a widget (e.g. a String item on a ComboBox)
19
 * 
20
 * @author ANy
21
 * @version $Revision$
22
 *
23
 */
24
public class UIObject implements IUIObject {
25
26
	private Widget widget = null;
27
	private Object object = null;
28
	
29
	public UIObject(Widget widget, Object object) {
30
		super();
31
		this.widget = widget;
32
		this.object = object;
33
	}
34
	
35
	public UIObject(Widget widget) {
36
		super();
37
		this.widget = widget;
38
	}
39
40
	public Object getObject() {
41
		return object;
42
	}
43
	
44
	public Widget getWidget() {
45
		return widget;
46
	}	
47
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/resolver/delegate/DeresolvingAmbiguityException.java (+32 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate;
13
14
/**
15
 * Exception to indicate that multiple MacroObjects are found while deresolving an IMacroObjectIdentifier
16
 * @author Alexander Nyssen
17
 *
18
 */
19
public class DeresolvingAmbiguityException extends Exception {
20
21
	private static final long serialVersionUID = 6617530463057206145L;
22
23
	private int numberOfMatches = 0;
24
	
25
	public DeresolvingAmbiguityException(int numberOfMatches) {
26
		this.numberOfMatches = numberOfMatches;
27
	}
28
29
	public int getNumberOfMatches(){
30
		return numberOfMatches;
31
	}
32
}
(-)CHANGES.txt (+59 lines)
Added Link Here
1
1) Total refactoring of the widget resolving mechanism:
2
   	   	
3
   - The former widget resolving mechanism was totally revised. It now works as follows: IMacroObjects are resolved into IMacroObjectIdentifiers during recording in a two step process.
4
   	 First, the context of the IMacroObject is resolved into a contextId (by a newly introduced MacroObjectResolver), then the nested UIObject (widget with optional nested object) is 
5
   	 resolved into a IUIObjectIdentifier (by a newly introduced UIObjectResolver), which contains the info formerly captured in a WidgetIdentifier (widgetId, resolverId, optional objectId). 
6
   	 During playback the deresolving of IMacroObjectIdentifiers is done in the same two step process. The MacroObjectResolver locates (deresolves) the context, and the UIObjectResolver
7
   	 than locates the UIObject (under the given context). He delegates the resolving/deresolving of UIObjects/UIObjectIdentifiers to so called IUIObjectResolverDelegates, which are 
8
   	 loaded via a newly introduced extension point (which is a replacement of the former WigetResolver extension point).
9
   	
10
   - Different to the old WidgetResolvers, the newly introduced IUIObjectResolverDelegates are responsible not only to resolve a respective IUIObjectIdentifier
11
     for a given UIObject, but also to deresolve(i.e. relocating) a respective UIObject during playback (i.e. they take the second part of the two step deresolving mechanism). The old
12
     WidgetResolvers were migrated to the new IUIObjectResolverDelegate interface. A DeprecatedDeresolvingSupport class was introduced to preserve the old implementation that
13
     used the foundWidget method to relocated items. The WidgetIdentifier extension point was marked as deprecated. All extensions are loaded and adapterd dynamically to the new
14
     UIObjectResolverDelegate interface by using DeprecatedDeresolvingSupport
15
     
16
   - The new resolving/deresolving mechanism relies on that the computed IMacroObjectIdentifier are unique, i.e. the desired UIObject can be unambiguously identified in its context during playback. 
17
     An exception is now thrown, if a recorded id cannot be unambiguously resolved. The old implementation contained a hack for bug#147766, which played back commands for all found matches
18
     (or only the first one), which is not a valid solution. Consider the build.properties editor as an example. If checking an item of the SourceBuild-Tree during recording, the old 
19
     implementation would select the respectively named item in the BinaryBuild-Tree, as it plays the command for the first match. 
20
     I therefore propose to reopen bug#147766. It needs a proper fix that computes a unique IMacroObjectIdentifier for such tree items, so that during playback the single selected item 
21
     can be identified unambiguously. 
22
     
23
   - All commands that relied on resolving/deresolving widgets (and nested objects) where migrated to have a common superclass ObjectBasedCommand. All those object-based commands
24
   	 now rely on recording and playing back IMacroObjects. An IMacroObject (formerly CommandTarget) consists of a context and a UIObject, which is a widget or a nested object on 
25
   	 a widget (e.g. a String item on a ComboBox). 
26
     
27
   - The listener registration for Workbench closing events was extracted from the resolving mechanism (was located as a side effect in MacroUtil.getWidgetIdentifier()), the resolving/deresolving
28
     is now side-effect free.
29
     
30
2) Refactored ObjectMining. Renamed UIObject to MacroObjectDescriptor and ObjectMine into MacroObjectMine, UIObjectMineManager into MacroObjectManager to reflect what is actually stored in it. 
31
   - Refactored the identifier providing mechanism; a new MacroObjectDescriptor is now equipped with a unique id internally by the object mine when registering the object
32
   - Removed the unneeded abstraction interface IUIObject (which is now used to represent a UIObject, i.e. a widget and a respective nested object) and unneeded corresponding IUIObjectMine interface.
33
34
4) Refactored VerficationCommand to be handled as all other object-based commands 
35
   - moved static construction method out changed constructor signature of Verification command to be in line with other object-based commands
36
   - refactored loading/writing to rely on super implemenation where possible
37
   - Removed VerficationMetaData which is now not needed any more (as in case of other commands that do not have something like this as well)
38
   - Implemented enhancements to verification hook insertion (i.e. resolved bug #201248). It now supports an extented mode (that is also needed in case of Draw2d). In extended
39
   	 mode, verification does not rely on the context but also on a selected UIObject (i.e. widget and possibly nested object). 
40
   	 
41
5) Introduced a command factory that encapsulates creation of commands (factored respective code out of MacroCommandShell). Introduced a respective extension point
42
   to replace the command factory. This will be needed to add support for draw2d, as the commands are responsible of locating their respective macro objects in a respective event,
43
   and the default implementation of the commands do not pay any interest to nested objects beyond the widget level (e.g. Figures on a FigureCanvas).
44
45
6) Refactored MacroManager
46
   - moved event constants into EventConstants interface, which defines the custom event types and details
47
   - moved mode constants into own ModeConstants interface
48
49
7) Removed unneeded IRecorderListener interface (never used)
50
 
51
8) Fixed that in Eclispe Ganymede, when closing an unsaved editor, the workbench close command was created after the message dialog selection command.
52
53
9) Introduced mouse move commands to explitly capture mouse move events, as needed to test GEF-applications.
54
55
10) Several minor fixes and cleanups.
56
57
TODO:
58
 - Migrate BooleanSelectionCommand and AbstractStructuredCommand to fully use the new resolving/deresolving mechanisms for macro objects (they are still based on parts
59
   of the old resolving mechanism, respectively do resolving/deresolving on their own), which should be taken care of.
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/IUIObject.java (+26 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.uiobject;
13
14
import org.eclipse.swt.widgets.Widget;
15
16
17
/**
18
 * @author Alexander Nyssen
19
 *
20
 */
21
public interface IUIObject {
22
23
	public abstract Widget getWidget();
24
25
	public abstract Object getObject();
26
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/resolver/delegate/IUIObjectResolverDelegate.java (+53 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate;
12
13
import org.eclipse.core.runtime.CoreException;
14
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObject;
15
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
16
17
/**
18
 * This interface is registered using extension point
19
 * <code>org.eclipse.tptp.test.auto.gui.internal.widgetResolver</code> which is
20
 * expected to return a unique identifier from a provided widget. The identifier
21
 * must be reproducable between sessions so that it can be used to locate the
22
 * widget on playback.
23
 * 
24
 * @since 3.1
25
 */
26
public interface IUIObjectResolverDelegate {
27
28
	/**
29
	 * Returns a unique identifier for the provided UI object.
30
	 * 
31
	 * @param context
32
	 *            The context of the UI object (usually retrieved from an
33
	 *            IMacroObject)
34
	 * @param uiObject
35
	 *            The object whose id is suppose to be resolved. The type of
36
	 *            this object is <b>usually</b> a widget, but it can also be a
37
	 *            <code>java.lang.String</code> or any other arbitrary type
38
	 *            depending on the implementation of the widget. For example,
39
	 *            when attempting to resolve a combo box item, parent will point
40
	 *            to the combo box and object will point to a
41
	 *            <code>java.lang.String</code> item representing the item
42
	 *            selected.
43
	 * 
44
	 * @return unique identifier that can be used to locate the UI object within
45
	 *         the context or <code>null</code> if none can be found.
46
	 */
47
	public IUIObjectIdentifier resolve(Object context, IUIObject uiObject)
48
			throws CoreException;
49
50
	public IUIObject deresolve(Object context,
51
			IUIObjectIdentifier uiObjectIdentifier) throws CoreException;
52
53
}
(-).settings/org.eclipse.jdt.core.prefs (+12 lines)
Added Link Here
1
#Tue Jan 22 16:24:58 CET 2008
2
eclipse.preferences.version=1
3
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
4
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.2
5
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
6
org.eclipse.jdt.core.compiler.compliance=1.4
7
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
8
org.eclipse.jdt.core.compiler.debug.localVariable=generate
9
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
10
org.eclipse.jdt.core.compiler.problem.assertIdentifier=warning
11
org.eclipse.jdt.core.compiler.problem.enumIdentifier=warning
12
org.eclipse.jdt.core.compiler.source=1.3
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/WeightedPropertyUIObjectIdentifier.java (+211 lines)
Added Link Here
1
/********************************************************************** 
2
 * Copyright (c) 2005, 2006 IBM Corporation and others. 
3
 * All rights reserved.   This program and the accompanying materials 
4
 * are made available under the terms of the Eclipse Public License v1.0 
5
 * which accompanies this distribution, and is available at 
6
 * http://www.eclipse.org/legal/epl-v10.html         
7
 * $Id: WeightedPropertyUIObjectIdentifier.java,v 1.3 2006/12/04 02:55:08 amehregani Exp $ 
8
 * 
9
 * Contributors: 
10
 * IBM - Initial API and implementation 
11
 **********************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.uiobject;
13
14
import java.util.regex.Matcher;
15
import java.util.regex.Pattern;
16
17
import org.eclipse.hyades.test.common.util.XMLUtil;
18
19
/**
20
 * Defines a widget Id by a set of properties that the widget must have. Each property is assigned a weight and if the total weight exceeds the
21
 * threshold, then the widget is identified as a match
22
 * 
23
 * @author Ali Mehregani
24
 */
25
public class WeightedPropertyUIObjectIdentifier implements IUIObjectIdentifier {
26
27
	private WeightedPropertyUIObjectIdentifier() {
28
	}
29
30
	public WeightedPropertyUIObjectIdentifier(Object[] propertyWeightPair, float threshold, String resolverId) {
31
		this.propertyWeightPair = propertyWeightPair;
32
		this.threshold = threshold;
33
		this.resolverId = resolverId;
34
	}
35
36
	private String resolverId;
37
38
	/*
39
	 * Stored elements are of type Object[2], where the first element is the value returned by the method corresponding to the property and the second
40
	 * value is the weight associated with that property.
41
	 */
42
	private Object[] propertyWeightPair;
43
	private float threshold;
44
45
	private final static Pattern pairPattern = Pattern.compile(".*?\\{\\{([^\\}]+)\\}\\}-\\{\\{([^\\}]+)\\}\\}.*");
46
47
	public boolean equals(Object obj) {
48
		String stringToCompare = null;
49
		boolean compare = false;
50
51
		/* The object is of our own kind */
52
		if (obj instanceof WeightedPropertyUIObjectIdentifier) {
53
			WeightedPropertyUIObjectIdentifier idToCompareWith = (WeightedPropertyUIObjectIdentifier) obj;
54
55
			if (this == idToCompareWith)
56
				return true;
57
58
			compare = true;
59
			stringToCompare = idToCompareWith.toString();
60
		}
61
62
		/* The object is a string (most likely coming from a macro) */
63
		else if (obj instanceof String) {
64
			compare = true;
65
			stringToCompare = (String) obj;
66
		}
67
		// ANy: equals has to be done on strings only, as a weigthed property id becomes a primitive one after loading (during playback)
68
		else if( obj instanceof IUIObjectIdentifier){
69
			compare = true;
70
			stringToCompare = ((IUIObjectIdentifier)obj).getWidgetId();
71
		}
72
73
		if (!compare)
74
			return false;
75
76
		/*
77
		 * Use regular expression to distinguish the returned value of each method from the weight
78
		 */
79
		float accumMatchRate = 0;
80
		int loopIterationNo = -1;
81
82
		while (stringToCompare.length() > 0 && (loopIterationNo + 1) < propertyWeightPair.length) {
83
			loopIterationNo++;
84
			Matcher pairTokenMatcher = pairPattern.matcher(stringToCompare);
85
86
			/* Discontinue if there is no match */
87
			if (!pairTokenMatcher.matches() || pairTokenMatcher.groupCount() != 2)
88
				break;
89
90
			/* Otherwise walk through each token */
91
			String originalProperty = pairTokenMatcher.group(1);
92
			String prop = originalProperty;
93
			if (prop.length() > 0)
94
				prop = XMLUtil.removeXMLSymbols(prop);
95
			float weight = Float.parseFloat(pairTokenMatcher.group(2));
96
97
			/* The ordering of the tokens for the IDs being compared must be the same. */
98
			Object[] propertyWeightPair = (Object[]) this.propertyWeightPair[loopIterationNo];
99
			if (!prop.equals("null") && (prop.length() > 0
100
				? prop.charAt(0) == ((String) propertyWeightPair[0]).charAt(0) || prop.charAt(0) == '&'
101
				: true) && (prop.equals(propertyWeightPair[0]) || prop.replaceAll("\\&",
102
				"").equals(propertyWeightPair[0]) || prop.replace('/',
103
				'\\').equals(propertyWeightPair[0])))
104
				accumMatchRate += Float.parseFloat((String) propertyWeightPair[1]);
105
106
			String currentToken = "{{" + originalProperty + "}}-{{" + weight + "}}";
107
			if (currentToken.equals(stringToCompare))
108
				break;
109
110
			int inx = stringToCompare.indexOf(currentToken);
111
			if (inx != -1)
112
				stringToCompare = stringToCompare.substring(inx + currentToken.length(),
113
					stringToCompare.length());
114
115
			else
116
				break; /* The control flow should never reach this block */
117
118
		}
119
120
		if (accumMatchRate >= threshold)
121
			return true;
122
		return false;
123
	}
124
125
	/**
126
	 * Return a string representation of this identifier. The property, weight information is organized in this format:
127
	 * {{property-value1}}-{{weight1}}{{property-value2}}:{{weight2}}
128
	 */
129
	public String getWidgetId() {
130
		String retValue = "";
131
		for (int i = 0; i < this.propertyWeightPair.length; i++)
132
			retValue += "{{" + ((Object[]) this.propertyWeightPair[i])[0] + "}}-{{" + ((Object[]) this.propertyWeightPair[i])[1] + "}}";
133
134
		return XMLUtil.useXMLSymbols(retValue);
135
	}
136
137
	public String toString() {
138
		return getWidgetId();
139
	}
140
141
	public float getThreshold() {
142
		return threshold;
143
	}
144
145
	// public void setThreshold(float threshold) {
146
	// this.threshold = threshold;
147
	// }
148
149
	public Object[] getPropertyWeightPair() {
150
		return propertyWeightPair;
151
	}
152
153
	// public void setPropertyWeightPair(Object[] propertyWeightPair) {
154
	// this.propertyWeightPair = propertyWeightPair;
155
	// }
156
157
	/**
158
	 * Walk through the properties and return true for as long as one of them is not null.
159
	 * 
160
	 * @return true if at least one property is not null; false otherwise
161
	 */
162
	public boolean noValidProperties() {
163
		if (propertyWeightPair == null)
164
			return true;
165
166
		for (int i = 0; i < propertyWeightPair.length; i++) {
167
			String property = (String) ((Object[]) propertyWeightPair[i])[0];
168
			if (property != null && !property.equals("null"))
169
				return false;
170
		}
171
		return true;
172
	}
173
174
	/**
175
	 * Convenient method available for clients to use in order to construct a weighted property id
176
	 * 
177
	 * @param properties
178
	 *            The (properties, weight) pairs of the item (weights should be a value between (0, 1])
179
	 * @param threshold
180
	 *            The threshold that this property should meet (should be a value between (0-1])
181
	 * @return Returns an instance of this class with the appropriate fields set.
182
	 */
183
	public static WeightedPropertyUIObjectIdentifier constructId(Object[] properties, float threshold, String resolverId) {
184
		/* Step through the properties and replace null values with the literal string null */
185
		for (int i = 0; i < properties.length; i++) {
186
			String property = (String) ((Object[]) properties[i])[0];
187
			if (property == null || property.length() <= 0)
188
				((Object[]) properties[i])[0] = "null";
189
190
		}
191
192
		WeightedPropertyUIObjectIdentifier widgetId = new WeightedPropertyUIObjectIdentifier(properties, threshold, resolverId);
193
194
		if (widgetId.noValidProperties())
195
			return null;
196
		return widgetId;
197
	}
198
199
	public String getResolverId() {
200
		return resolverId;
201
	}
202
	
203
	public String getObjectId(){
204
		// nested objects not supported by this resolver
205
		return null;
206
	}
207
208
	// public void setResolverId(String resolverId) {
209
	// this.resolverId = resolverId;
210
	// }
211
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/commands/factory/MacroCommandFactoryLoader.java (+72 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.commands.factory;
13
14
import org.eclipse.core.runtime.CoreException;
15
import org.eclipse.core.runtime.IConfigurationElement;
16
import org.eclipse.core.runtime.Platform;
17
18
/**
19
 * Helper class to load a IMacroCommandFactory via the respective extension
20
 * point. Only the factory with the highest priority is used. All other
21
 * factories are disregarded.
22
 * 
23
 * @author Alexander Nyssen
24
 * 
25
 */
26
public class MacroCommandFactoryLoader {
27
28
	private static final String EXTENSION_POINT_NAME = "macroCommandFactory";
29
	private static final String EXTENSION_POINT_ID = "org.eclipse.tptp.test.auto.gui."
30
			+ EXTENSION_POINT_NAME;
31
32
	private static IMacroCommandFactory factory = null;
33
34
	/**
35
	 * Retrieves the factory with the highest priority, meaning the lowest
36
	 * priority number, i.e. a priority of 1 is greater than one of 2.
37
	 * 
38
	 * @return
39
	 */
40
	public static IMacroCommandFactory getHighestPriorityFactory() {
41
		if (factory == null) {
42
			factory = retrieveFactoryWithHighestPriority();
43
		}
44
		return factory;
45
	}
46
47
	private static IMacroCommandFactory retrieveFactoryWithHighestPriority() {
48
		IConfigurationElement[] elements = Platform.getExtensionRegistry()
49
				.getConfigurationElementsFor(EXTENSION_POINT_ID);
50
51
		IMacroCommandFactory factory = null;
52
		int priority = Integer.MAX_VALUE;
53
		for (int i = 0; i < elements.length; i++) {
54
			if (EXTENSION_POINT_NAME.equals(elements[i].getName())) {
55
				try {
56
					IMacroCommandFactory currentFactory = (IMacroCommandFactory) elements[i]
57
							.createExecutableExtension("class");
58
					int currentPriority = Integer.parseInt(elements[i]
59
							.getAttribute("priority"));
60
61
					if (currentFactory != null && currentPriority < priority) {
62
						factory = currentFactory;
63
						priority = currentPriority;
64
					}
65
				} catch (CoreException e) {
66
					e.printStackTrace();
67
				}
68
			}
69
		}
70
		return factory;
71
	}
72
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/resolver/delegate/deresolvingsupport/UIObjectDeprecatedDeresolvingSupport.java (+667 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.deresolvingsupport;
13
14
import java.util.Enumeration;
15
import java.util.Hashtable;
16
import java.util.Vector;
17
18
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.jface.action.IContributionItem;
20
import org.eclipse.jface.action.ICoolBarManager;
21
import org.eclipse.jface.action.IToolBarManager;
22
import org.eclipse.jface.action.ToolBarContributionItem;
23
import org.eclipse.jface.action.ToolBarManager;
24
import org.eclipse.jface.wizard.IWizardPage;
25
import org.eclipse.jface.wizard.WizardDialog;
26
import org.eclipse.osgi.util.NLS;
27
import org.eclipse.swt.custom.CCombo;
28
import org.eclipse.swt.custom.CTabFolder;
29
import org.eclipse.swt.custom.CTabItem;
30
import org.eclipse.swt.widgets.Combo;
31
import org.eclipse.swt.widgets.Composite;
32
import org.eclipse.swt.widgets.Control;
33
import org.eclipse.swt.widgets.Item;
34
import org.eclipse.swt.widgets.Menu;
35
import org.eclipse.swt.widgets.MenuItem;
36
import org.eclipse.swt.widgets.Shell;
37
import org.eclipse.swt.widgets.TabFolder;
38
import org.eclipse.swt.widgets.TabItem;
39
import org.eclipse.swt.widgets.ToolBar;
40
import org.eclipse.swt.widgets.ToolItem;
41
import org.eclipse.swt.widgets.Widget;
42
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
43
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
44
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
45
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
46
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObject;
47
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
48
import org.eclipse.tptp.test.auto.gui.internal.uiobject.PrimitiveUIObjectIdentifier;
49
import org.eclipse.tptp.test.auto.gui.internal.uiobject.UIObject;
50
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.DeresolvingAmbiguityException;
51
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.IUIObjectResolverDelegate;
52
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.NonTrivialUIObjectResolverDelegate;
53
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.UIObjectResolverDelegateRegistry;
54
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.UIObjectResolverDelegateLoader;
55
import org.eclipse.ui.IEditorPart;
56
import org.eclipse.ui.IViewPart;
57
58
/**
59
 * This class was merely introduced to be able to migrate the already existing
60
 * WidgetResolvers to the newly introduced IUIObjectResolverDelegate interface
61
 * while preserving the old implementation to deresolve UI objects (via the
62
 * foundWidget method). New IUIObjectResolverDelegates should not build on this
63
 * class and this class should possibly be removed by implementing proper
64
 * deresolving mechanisms in the existing IUIObjectResolverDelegate
65
 * implementations in the future.
66
 * 
67
 * @author Alexander Nyssen
68
 * 
69
 */
70
public class UIObjectDeprecatedDeresolvingSupport {
71
72
	/**
73
	 * Preserves the deprecated algorithm for widget resolving that was used
74
	 * before. Both, the AdaptiveUIObjectResolverDelegate as well as the
75
	 * NonTrivialUIObjectResolverDelegate refer to this implementation of
76
	 * deresolving. All newly introduced resolvers should not reside on this.
77
	 */
78
	public static IUIObject deresolve(Object context,
79
			IUIObjectIdentifier identifier) throws CoreException {
80
81
		IUIObject uiObject = null;
82
		String errorMessage = null;
83
		Throwable cause = null;
84
85
		try {
86
			if (context instanceof Menu) {
87
				// normal menus and popup menus (in the latter case we have to
88
				// ensure the menu is visible
89
				Menu menuBar = (Menu) context;
90
				MacroUtil.forceMenuOpen(menuBar);
91
				uiObject = locateMenuItem(menuBar, identifier);
92
				MacroUtil.forceMenuClosed(menuBar);
93
				if (uiObject == null) {
94
					errorMessage = NLS.bind(
95
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_MENU,
96
							identifier.getWidgetId());
97
				}
98
			} else if (context instanceof ToolBar) {
99
				// deresolve tool item
100
				ToolBar toolbar = (ToolBar) context;
101
				uiObject = locateToolItem(toolbar, identifier);
102
				if (uiObject == null) {
103
					errorMessage = NLS.bind(
104
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_TOOL_BAR,
105
							identifier.getWidgetId());
106
				}
107
			} else if (context instanceof ToolBarManager
108
					|| context instanceof ICoolBarManager) {
109
				if (context instanceof ToolBarManager) {
110
					// Only ToolBarManager can be deresolved, not any
111
					// IToolBarManager implementation,
112
					// as the interface IToolBarManager interface does not allow
113
					// to obtain the control
114
					ToolBarManager toolBarManager = (ToolBarManager) context;
115
					uiObject = locateToolItem(toolBarManager, identifier);
116
				} else {
117
					ICoolBarManager coolBarManager = (ICoolBarManager) context;
118
					uiObject = locateToolItem(coolBarManager, identifier);
119
				}
120
				if (uiObject == null) {
121
					errorMessage = NLS.bind(
122
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_TOOL,
123
							identifier.getWidgetId());
124
				}
125
			} else if (context instanceof TabFolder
126
					|| context instanceof CTabFolder) {
127
				if (context instanceof TabFolder) {
128
					TabFolder tabFolder = (TabFolder) context;
129
					uiObject = locateTabItem(tabFolder, identifier);
130
				} else {
131
					CTabFolder tabFolder = (CTabFolder) context;
132
					uiObject = locateCTabItem(tabFolder, identifier);
133
				}
134
				if (uiObject == null) {
135
					errorMessage = NLS.bind(
136
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_TAB,
137
							identifier.getWidgetId());
138
				}
139
			} else if (context instanceof WizardDialog) {
140
				WizardDialog wd = (WizardDialog) context;
141
142
				IWizardPage page = wd.getCurrentPage();
143
				Composite pparent = (Composite) page.getControl();
144
				uiObject = UIObjectDeprecatedDeresolvingSupport
145
						.locateVisibleChild(wd.getShell(), pparent, identifier);
146
147
				if (uiObject == null) {
148
					errorMessage = NLS.bind(
149
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_WIZARD,
150
							identifier.getWidgetId());
151
				}
152
			} else if (context instanceof IWizardPage) {
153
				IWizardPage page = (IWizardPage) context;
154
155
				Composite pparent = (Composite) page.getControl();
156
				uiObject = UIObjectDeprecatedDeresolvingSupport
157
						.locateVisibleChild(pparent, null, identifier);
158
159
				if (uiObject == null) {
160
					errorMessage = NLS.bind(
161
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_WIZARD_CON,
162
							identifier.getWidgetId());
163
				}
164
			} else if (context instanceof IEditorPart) {
165
				IEditorPart editor = (IEditorPart) context;
166
167
				Composite c = MacroUtil.getWorkbenchPartControl(editor);
168
				uiObject = UIObjectDeprecatedDeresolvingSupport
169
						.locateVisibleChild(c, null, identifier);
170
171
				if (uiObject == null) {
172
					errorMessage = NLS.bind(
173
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_EDITOR_CON,
174
							identifier.getWidgetId());
175
				}
176
			} else if (context instanceof IViewPart) {
177
				IViewPart view = (IViewPart) context;
178
179
				Composite c = MacroUtil.getWorkbenchPartControl(view);
180
				uiObject = UIObjectDeprecatedDeresolvingSupport
181
						.locateVisibleChild((Composite) c, null, identifier);
182
183
				if (uiObject == null) {
184
					errorMessage = NLS.bind(
185
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_VIEW_CON,
186
							identifier.getWidgetId());
187
				}
188
			} else if (context instanceof Shell) {
189
				// locate a shell control
190
				Shell shell = (Shell) context;
191
192
				uiObject = UIObjectDeprecatedDeresolvingSupport
193
						.locateVisibleChild(shell, null, identifier);
194
195
				if (uiObject == null) {
196
					errorMessage = NLS.bind(
197
							AutoGUIMessages.AUTO_GUI_ERROR_MACRO_SHELL,
198
							identifier.getWidgetId());
199
				}
200
			}
201
202
		} catch (Throwable t) {
203
			t.printStackTrace();
204
			if (t.getCause() != null) {
205
				cause = t.getCause();
206
			} else {
207
				cause = t;
208
			}
209
			errorMessage = t.getMessage();
210
		}
211
212
		if (uiObject != null) {
213
			return uiObject;
214
		} else {
215
			AutoGUIUtil.throwCoreException(errorMessage, cause);
216
			return null;
217
		}
218
	}
219
220
	private static IUIObject locateCTabItem(CTabFolder tabFolder,
221
			IUIObjectIdentifier identifier) {
222
		CTabItem tabItem = null;
223
		for (int i = 0; i < tabFolder.getItemCount() && tabItem == null; i++) {
224
			CTabItem currentItem = tabFolder.getItem(i);
225
			String validatedCurrentItemText = NonTrivialUIObjectResolverDelegate
226
					.validateText(currentItem.getText());
227
			if (validatedCurrentItemText != null
228
					&& validatedCurrentItemText
229
							.equals(identifier.getWidgetId())) {
230
				tabItem = currentItem;
231
			}
232
		}
233
		return new UIObject(tabItem);
234
	}
235
236
	private static IUIObject locateTabItem(TabFolder tabFolder,
237
			IUIObjectIdentifier identifier) {
238
		TabItem tabItem = null;
239
		for (int i = 0; i < tabFolder.getItemCount() && tabItem == null; i++) {
240
			TabItem currentItem = tabFolder.getItem(i);
241
			String validatedCurrentItemText = NonTrivialUIObjectResolverDelegate
242
					.validateText(currentItem.getText());
243
			if (validatedCurrentItemText != null
244
					&& validatedCurrentItemText
245
							.equals(identifier.getWidgetId())) {
246
				tabItem = currentItem;
247
			}
248
		}
249
		return new UIObject(tabItem);
250
	}
251
252
	/**
253
	 * @deprecated This method should only be used internally Returns true iff
254
	 *             the widget matches the id passed in.
255
	 * 
256
	 * @param widget
257
	 *            The widget
258
	 * @param objectId
259
	 *            The resolver id -- can be null
260
	 * @return true iff the widget matches the id passed in.
261
	 */
262
	public static boolean foundWidget(Widget widget,
263
			IUIObjectIdentifier widgetId) {
264
		Hashtable widgetResolvers = UIObjectResolverDelegateRegistry
265
				.getDelegateResolverLoaders();
266
267
		if (widgetId != null && widgetId.getResolverId() != null) {
268
			UIObjectResolverDelegateLoader loader = (UIObjectResolverDelegateLoader) widgetResolvers
269
					.get(widgetId.getResolverId());
270
			if (loader != null
271
					&& loader.getUIObjectResolverDelegate() instanceof IUIObjectDeprecatedDeresolvingFacade)
272
				return ((IUIObjectDeprecatedDeresolvingFacade) loader
273
						.getUIObjectResolverDelegate()).foundWidget(widget,
274
						widgetId);
275
			return false;
276
		}
277
278
		Enumeration keys = widgetResolvers.keys();
279
		while (keys.hasMoreElements()) {
280
			IUIObjectResolverDelegate delegateResolver = ((UIObjectResolverDelegateLoader) widgetResolvers
281
					.get(keys.nextElement())).getUIObjectResolverDelegate();
282
			if (delegateResolver instanceof IUIObjectDeprecatedDeresolvingFacade) {
283
				if (((IUIObjectDeprecatedDeresolvingFacade) delegateResolver)
284
						.foundWidget(widget, widgetId)) {
285
					return true;
286
				}
287
			}
288
		}
289
		return false;
290
	}
291
292
	/**
293
	 * @deprecated This method should only be used internally. Returns true if
294
	 *             the id computed for 'item' matches 'id'
295
	 * 
296
	 * @param item
297
	 *            The tool item
298
	 * @param resolverId
299
	 *            The resolver id -- can be null
300
	 * @param id
301
	 *            The id that should be matched against
302
	 * @return true if there is a match, and false otherwise
303
	 */
304
	public static boolean foundItem(Item item, IUIObjectIdentifier objectId) {
305
		/* Try the widget resolvers first */
306
		if (foundWidget(item, objectId))
307
			return true;
308
309
		/* Give the old policy a try */
310
		String toolItemIdStr = NonTrivialUIObjectResolverDelegate.getActionId(
311
				item).toString();
312
		if (toolItemIdStr != null
313
				&& toolItemIdStr.equals(objectId.getWidgetId()))
314
			return true;
315
316
		return false;
317
	}
318
319
	public static Control recursiveSearch(Composite parent, Composite skip,
320
			Control desiredControl, IUIObjectIdentifier id,
321
			String widgetClassName, int[] index, Vector matches, Vector indices) {
322
		boolean searchForControl = id == null;
323
		Control[] children = parent.getChildren();
324
		boolean[] checkTypeAndEquality;
325
		Control searchResult;
326
		// boolean isTabFolder, isCTabFolder;
327
328
		for (int i = 0; i < children.length; i++) {
329
			Control child = children[i];
330
331
			if (!child.isVisible()) {
332
				/*
333
				 * If the control is of the same type, then we'll need to
334
				 * increment the index
335
				 */
336
				if ((widgetClassName != null && child.getClass().getName()
337
						.equals(widgetClassName))
338
						|| (desiredControl != null && desiredControl.getClass()
339
								.getName().equals(child.getClass().getName())))
340
					index[0]++;
341
342
				continue;
343
			}
344
345
			checkTypeAndEquality = searchForControl ? checkTypeAndEqual(
346
					desiredControl, child, index) : checkTypeAndId(child, id,
347
					widgetClassName, index);
348
			if (checkTypeAndEquality[0]) {
349
				if (checkTypeAndEquality[1]) {
350
					addMatch(matches, indices, child, index[0]);
351
				}
352
353
				// ANy: This code is now obsolete, as we have a new deresolving
354
				// policy for
355
				// TabItems and CTabItems (own context info) and the respective
356
				// choice command
357
				// converts existing macro entries to the new format.
358
				// /* Defect 111371 -- We need to step through the items of a
359
				// tab */
360
				// isTabFolder = child instanceof TabFolder;
361
				// isCTabFolder = child instanceof CTabFolder;
362
				// if (isTabFolder || isCTabFolder) {
363
				// Object[] tabItems = isTabFolder ? (Object[]) ((TabFolder)
364
				// child)
365
				// .getItems()
366
				// : ((CTabFolder) child).getItems();
367
				// if (tabItems != null) {
368
				// for (int j = 0; j < tabItems.length; j++) {
369
				// Control tabItemControl = isTabFolder ? ((TabItem)
370
				// tabItems[j])
371
				// .getControl()
372
				// : ((CTabItem) tabItems[j]).getControl();
373
				//
374
				// if (tabItemControl == null)
375
				// continue;
376
				//
377
				// checkTypeAndEquality = searchForControl ? checkTypeAndEqual(
378
				// tabItemControl, desiredControl, index)
379
				// : checkTypeAndId(tabItemControl, id,
380
				// widgetClassName, index);
381
				// if (checkTypeAndEquality[0]
382
				// && checkTypeAndEquality[1]) {
383
				// addMatch(matches, indices, tabItemControl,
384
				// index[0]);
385
				// }
386
				// if ((searchResult = recursiveSearch(tabItemControl,
387
				// skip, desiredControl, id, widgetClassName,
388
				// index, matches, indices)) != null) {
389
				// addMatch(matches, indices, searchResult,
390
				// index[0]);
391
				// }
392
				// }
393
				// }
394
				// }
395
				//
396
			}
397
398
			if ((searchResult = recursiveSearch(child, skip, desiredControl,
399
					id, widgetClassName, index, matches, indices)) != null) {
400
				addMatch(matches, indices, searchResult, index[0]);
401
			}
402
		}
403
404
		if (matches.size() > 0) {
405
			return (Control) matches.get(0);
406
		} else {
407
			return null;
408
		}
409
	}
410
411
	/**
412
	 * A helper method used to indicate whether expected is of the same type as
413
	 * actual. The return value also indicates if expected == actual.
414
	 * 
415
	 * @param expected
416
	 *            The expected control
417
	 * @param actual
418
	 *            The actual control that 'expected' is checked against
419
	 * @param counter
420
	 *            A counter that is used for indexing.
421
	 * 
422
	 * @return This method has the side affect of incrementing counter if the
423
	 *         class types of the two controls are the same. The return value
424
	 *         indicates type and whether expected == actual.
425
	 */
426
	private static boolean[] checkTypeAndEqual(Control expected,
427
			Control actual, int[] counter) {
428
		boolean[] typeAndEqualCheck = new boolean[2];
429
		if (expected.getClass().equals(actual.getClass())) {
430
			typeAndEqualCheck[0] = true;
431
432
			// same type - increment counter
433
			counter[0]++;
434
			if (expected.equals(actual)) {
435
				// bingo
436
				typeAndEqualCheck[1] = true;
437
			}
438
		}
439
440
		return typeAndEqualCheck;
441
	}
442
443
	private static Control recursiveSearch(Control currentSearchPoint,
444
			Composite skip, Control desiredControl,
445
			IUIObjectIdentifier desiredId, String desiredWidgetClassName,
446
			int[] index, Vector matches, Vector indices) {
447
		Control searchResult = null;
448
		if (currentSearchPoint instanceof Composite
449
				&& !(skip != null && currentSearchPoint.equals(skip))
450
				&& currentSearchPoint.isVisible()) {
451
			searchResult = recursiveSearch((Composite) currentSearchPoint,
452
					skip, desiredControl, desiredId, desiredWidgetClassName,
453
					index, matches, indices);
454
		}
455
456
		return searchResult;
457
	}
458
459
	private static void addMatch(Vector container, Vector indices, Object item,
460
			int index) {
461
		if (!container.contains(item)) {
462
			container.add(item);
463
			indices.add(new Integer(index));
464
		}
465
	}
466
467
	private static boolean[] checkTypeAndId(Control presentControl,
468
			IUIObjectIdentifier desiredId, String desiredWidgetClassName,
469
			int[] counter) {
470
		boolean[] checkTypeAndEqualId = new boolean[2];
471
472
		if (desiredWidgetClassName == null
473
				|| presentControl.getClass().getName().equals(
474
						desiredWidgetClassName)) {
475
			// same type - increment counter
476
			if (!presentControl.isVisible())
477
				return checkTypeAndEqualId;
478
479
			checkTypeAndEqualId[0] = true;
480
			counter[0]++;
481
			if (foundWidget(presentControl, desiredId)
482
					|| NonTrivialUIObjectResolverDelegate
483
							.computeDefaultControlId(presentControl, counter[0])
484
							.equals(desiredId.getWidgetId())) {
485
				checkTypeAndEqualId[1] = true;
486
			}
487
		}
488
489
		return checkTypeAndEqualId;
490
	}
491
492
	private static UIObject locateVisibleChild(Composite parent,
493
			Composite skip, IUIObjectIdentifier uiObjectIdentifier)
494
			throws CoreException {
495
		int[] counter = new int[1];
496
		counter[0] = 0;
497
498
		// see if an uniqueness identifier was added by the UIObjectResolver
499
		// because the identifier
500
		// that was computed is not unique (workaround for defect #147766)
501
		String widgetIdentifier = uiObjectIdentifier.getWidgetId();
502
		IUIObjectIdentifier adjustedUIObjectIdentifier = uiObjectIdentifier;
503
		int matchIndex = -1;
504
		if (widgetIdentifier
505
				.indexOf(MacroConstants.WIDGET_ID_UNIQUENESS_INDEX_SEPARATOR) > 0) {
506
			adjustedUIObjectIdentifier = new PrimitiveUIObjectIdentifier(
507
					widgetIdentifier
508
							.substring(
509
									0,
510
									widgetIdentifier
511
											.indexOf(MacroConstants.WIDGET_ID_UNIQUENESS_INDEX_SEPARATOR)),
512
					uiObjectIdentifier.getObjectId(), uiObjectIdentifier
513
							.getResolverId());
514
			matchIndex = new Integer(
515
					widgetIdentifier
516
							.substring(widgetIdentifier
517
									.indexOf(MacroConstants.WIDGET_ID_UNIQUENESS_INDEX_SEPARATOR) + 3))
518
					.intValue();
519
		}
520
521
		int sloc = widgetIdentifier.indexOf('#');
522
		String wclassName = null;
523
		if (sloc != -1)
524
			wclassName = widgetIdentifier.substring(0, sloc);
525
526
		/*
527
		 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=147766: We need to
528
		 * return all possible matches -> ANy: this does not seem to be an
529
		 * adequate solution. It seems as if the resolving mechanism should
530
		 * compute a more appropriate identifier in such a case. We will
531
		 * therefore not tolerate such an anambiguity.
532
		 */
533
		Vector matches = new Vector();
534
		Vector indices = new Vector();
535
		// do not use the extended widget identifier but only the prefix to find
536
		// the widget
537
		locateVisibleChild(parent, skip, adjustedUIObjectIdentifier,
538
				wclassName, counter, matches, indices);
539
540
		// see if we have properly deresolved a control
541
		Control control = null;
542
		if (matches.size() > 0) {
543
			if (matches.size() > 1) {
544
				if (matchIndex != -1) {
545
					control = (Control) matches.get(matchIndex);
546
				} else {
547
					// we have found several matches and no uniqueness
548
					// identifier was added,
549
					// so we cannt unambiguously identify which one was
550
					// selected.
551
					AutoGUIUtil
552
							.throwCoreException(
553
									NLS
554
											.bind(
555
													AutoGUIMessages.AUTO_GUI_UI_OBJECT_IDENTIFIER_AMBIGUOUS,
556
													uiObjectIdentifier
557
															.getWidgetId(),
558
													uiObjectIdentifier
559
															.getObjectId()),
560
									new DeresolvingAmbiguityException(matches
561
											.size()));
562
					return null;
563
				}
564
			} else {
565
				control = (Control) matches.get(0);
566
			}
567
		}
568
569
		// we have located a control, see if we have to further deresolve a
570
		// nested object
571
		if (control != null) {
572
			// added by ANy to resolve beyond the widget level for combo and
573
			// ccombo controls (needed in choice command)
574
			if (adjustedUIObjectIdentifier.getObjectId() != null) {
575
				// find object located at the sub widget level
576
				if (control instanceof Combo || control instanceof CCombo) {
577
					String indexString = adjustedUIObjectIdentifier
578
							.getObjectId().substring(
579
									new String("item#").length());
580
					int index = new Integer(indexString).intValue();
581
					// find the item at the specified index
582
					if (control instanceof Combo) {
583
						String[] items = ((Combo) control).getItems();
584
						return new UIObject(control, items[index]);
585
					} else if (control instanceof CCombo) {
586
						String[] items = ((CCombo) control).getItems();
587
						return new UIObject(control, items[index]);
588
					}
589
					return null;
590
				} else {
591
					// anything else is ignored up to now
592
					return new UIObject(control);
593
				}
594
			} else {
595
				return new UIObject(control);
596
			}
597
		} else {
598
			return null;
599
		}
600
	}
601
602
	private static Control locateVisibleChild(Composite parent, Composite skip,
603
			IUIObjectIdentifier id, String wclassName, int[] index,
604
			Vector matches, Vector indices) {
605
		return recursiveSearch(parent, skip, null, id, wclassName, index,
606
				matches, indices);
607
	}
608
609
	private static IUIObject locateToolItem(ICoolBarManager coolMng,
610
			IUIObjectIdentifier wid) {
611
		IContributionItem[] items = coolMng.getItems();
612
		for (int i = 0; i < items.length; i++) {
613
			if (items[i] instanceof ToolBarContributionItem) {
614
				ToolBarContributionItem item = (ToolBarContributionItem) items[i];
615
				IToolBarManager toolMng = item.getToolBarManager();
616
				IUIObject target = locateToolItem((ToolBarManager) toolMng, wid);
617
				if (target != null)
618
					return target;
619
			}
620
		}
621
		return null;
622
	}
623
624
	private static IUIObject locateToolItem(ToolBarManager toolMng,
625
			IUIObjectIdentifier wid) {
626
		return locateToolItem(toolMng.getControl(), wid);
627
	}
628
629
	private static UIObject locateMenuItem(Menu menu,
630
			IUIObjectIdentifier widgetId) {
631
		MenuItem[] items = menu.getItems();
632
633
		for (int i = 0; i < items.length; i++) {
634
			MenuItem item = items[i];
635
636
			Menu submenu = item.getMenu();
637
			if (submenu != null) {
638
				/*
639
				 * Ali M.: We have to force the menu to open, since its items
640
				 * may not have already been created
641
				 */
642
				MacroUtil.forceMenuOpen(submenu);
643
				UIObject hit = locateMenuItem(submenu, widgetId);
644
				if (hit != null)
645
					return hit;
646
			} else {
647
				if (UIObjectDeprecatedDeresolvingSupport.foundItem(item,
648
						widgetId))
649
					return new UIObject(item);
650
			}
651
		}
652
		return null;
653
	}
654
655
	private static IUIObject locateToolItem(ToolBar toolBar,
656
			IUIObjectIdentifier wid) {
657
		if (toolBar == null)
658
			return null;
659
		ToolItem[] items = toolBar.getItems();
660
		for (int i = 0; i < items.length; i++) {
661
			ToolItem item = items[i];
662
			if (UIObjectDeprecatedDeresolvingSupport.foundItem(item, wid))
663
				return new UIObject(item);
664
		}
665
		return null;
666
	}
667
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/MacroCommandShell.java (+1076 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macro;
12
13
import java.util.ArrayList;
14
import java.util.Hashtable;
15
import java.util.Vector;
16
17
import org.eclipse.core.runtime.CoreException;
18
import org.eclipse.core.runtime.IProgressMonitor;
19
import org.eclipse.core.runtime.IStatus;
20
import org.eclipse.core.runtime.Status;
21
import org.eclipse.core.runtime.SubProgressMonitor;
22
import org.eclipse.jface.window.Window;
23
import org.eclipse.osgi.util.NLS;
24
import org.eclipse.swt.SWT;
25
import org.eclipse.swt.SWTException;
26
import org.eclipse.swt.widgets.Control;
27
import org.eclipse.swt.widgets.Display;
28
import org.eclipse.swt.widgets.Event;
29
import org.eclipse.swt.widgets.Listener;
30
import org.eclipse.swt.widgets.Shell;
31
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
32
import org.eclipse.tptp.test.auto.gui.internal.GlobalConstants;
33
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
34
import org.eclipse.tptp.test.auto.gui.internal.commands.AbstractMacroCommand;
35
import org.eclipse.tptp.test.auto.gui.internal.commands.IMacroCommand;
36
import org.eclipse.tptp.test.auto.gui.internal.commands.MouseEventCommand;
37
import org.eclipse.tptp.test.auto.gui.internal.commands.VerificationCommand;
38
import org.eclipse.tptp.test.auto.gui.internal.commands.WaitCommand;
39
import org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObjectIdentifier;
40
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObject;
41
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObjectIdentifier;
42
import org.eclipse.tptp.test.auto.gui.internal.macroobject.mine.MacroObjectDescriptor;
43
import org.eclipse.tptp.test.auto.gui.internal.macroobject.resolver.MacroObjectResolver;
44
import org.eclipse.tptp.test.auto.gui.internal.uiobject.PrimitiveUIObjectIdentifier;
45
import org.eclipse.tptp.test.auto.gui.internal.uiobject.UIObject;
46
import org.w3c.dom.Node;
47
import org.w3c.dom.NodeList;
48
49
/**
50
 * Keeps track of the macro commands while they are being captured.
51
 * 
52
 * @author Alexander Nyssen (factored creation of commands out into respective
53
 *         factory)
54
 */
55
public class MacroCommandShell extends AbstractMacroInstruction implements
56
		IMacroInstruction {
57
58
	/** The widget id associated with this macro command shell */
59
	private IMacroObjectIdentifier macroObjectIdentifier;
60
61
	/** The corresponding UI object for this macro command shell */
62
	private MacroObjectDescriptor macroObjectDescriptor;
63
64
	/* The commands of this macro shell */
65
	private ArrayList commands;
66
67
	/* The expected return code */
68
	private int expectedReturnCode;
69
70
	/* The display object */
71
	private transient Display display;
72
73
	/* The shell that this macro command shell represents */
74
	private transient Shell shell;
75
76
	/* The reference id of the macro shell object */
77
	// private String referenceId;
78
	/* The title of the shell that this macro command shell represents */
79
	private String shellTitle;
80
81
	private transient Window window;
82
83
	/* Set when there is a listener registered with this MacroCommandShell */
84
	private transient boolean isListenerRegistered;
85
86
	/*
87
	 * A queue of nested shell waiting to be activated (this is used during
88
	 * playback)
89
	 */
90
	private static Vector nestedShellQueue;
91
92
	/* Last index of the nested shell queue */
93
	private static int lastNestedShellInx;
94
95
	/* Stores the last command line executed */
96
	private static int lastCommandLineExecuted;
97
98
	/*
99
	 * Mutual lock used to block when a command is being executed. This lock is
100
	 * used to forcefully wake up the thread that this object is running in if
101
	 * the command has caused a stall
102
	 */
103
	private Boolean mutualLock;
104
105
	/*
106
	 * A mutual lock shared across multiple instances of this class -- It's
107
	 * general purpose is to lock shared static resources
108
	 */
109
	private static Boolean mutualGlobalLock;
110
111
	/*
112
	 * The parent of this macro command shell. This is null if this macro shell
113
	 * command is the root
114
	 */
115
	private MacroCommandShell parent;
116
117
	/*
118
	 * The index of the command being executed -- this will correspond to the
119
	 * last command index if isComplete = true
120
	 */
121
	private int currentCommandInx;
122
123
	/* Indicates if all the commands of this shell has been completed */
124
	private boolean isComplete;
125
126
	/* Indicates that the process needs to be interrupted -- due to an error */
127
	private static boolean interruptProcess;
128
129
	/* Set to true when process has been terminated */
130
	private static boolean processTerminated;
131
132
	/* The exception causing the interruption */
133
	private static Throwable interruptedException;
134
135
	/* A central container for all macro command operation being played */
136
	private static Vector macroCommandsBeingPlayed;
137
138
	/* A central container for all instances of this class */
139
	private static Vector macroCommandShellContainer;
140
141
	/* A central repository for all macro command shells */
142
	static {
143
		nestedShellQueue = new Vector();
144
		macroCommandsBeingPlayed = new Vector();
145
		macroCommandShellContainer = new Vector();
146
		mutualGlobalLock = new Boolean(true);
147
	}
148
149
	public MacroCommandShell(MacroCommandShell parent) {
150
		this(parent, null, null);
151
	}
152
153
	public MacroCommandShell(MacroCommandShell parent, Shell shell,
154
			IMacroObjectIdentifier wid) {
155
		setMacroObjectIdentifier(wid);
156
		commands = new ArrayList();
157
		this.shell = shell;
158
		this.shellTitle = shell == null || shell.isDisposed() ? null : shell
159
				.getText();
160
		hookWindow(false);
161
		expectedReturnCode = -1;
162
		isListenerRegistered = false;
163
		mutualLock = new Boolean(true);
164
		this.parent = parent;
165
		isComplete = false;
166
		macroCommandShellContainer.add(this);
167
	}
168
169
	public IMacroObjectIdentifier getMacroObjectIdentifier() {
170
		return macroObjectIdentifier;
171
	}
172
173
	public void setMacroObjectIdentifier(IMacroObjectIdentifier objectIdentifier) {
174
		this.macroObjectIdentifier = objectIdentifier;
175
	}
176
177
	public MacroObjectDescriptor getCorrespondingMacroObjectDescriptor() {
178
		return macroObjectDescriptor;
179
	}
180
181
	public void setCorrespondingMacroObjectDescriptor(
182
			MacroObjectDescriptor uiObject) {
183
		this.macroObjectDescriptor = uiObject;
184
	}
185
186
	private void hookWindow(boolean playback) {
187
		if (shell != null) {
188
			if (!playback)
189
				doHookWindow();
190
			else
191
				display.syncExec(new Runnable() {
192
193
					public void run() {
194
						doHookWindow();
195
					}
196
				});
197
		}
198
	}
199
200
	private void doHookWindow() {
201
		Object data = shell.getData();
202
		if (data != null && data instanceof Window)
203
			this.window = (Window) data;
204
	}
205
206
	/**
207
	 * @see org.eclipse.tptp.test.auto.gui.internal.macro.AbstractMacroInstruction#load(org.w3c.dom.Node,
208
	 *      java.util.Hashtable)
209
	 */
210
	public void load(Node node, Hashtable lineTable) throws CoreException {
211
		super.load(node, lineTable);
212
213
		/*
214
		 * If the corresponding shell of this command is referenced then attempt
215
		 * to find the corresponding object in the object mine.
216
		 */
217
		if (MacroManager.getInstance().getObjectMine() != null) {
218
			MacroObjectDescriptor descriptor = MacroManager.getInstance()
219
					.getObjectMine().lookupReferenceId(null, node, lineTable);
220
			if (descriptor != null) {
221
				setCorrespondingMacroObjectDescriptor(descriptor);
222
			}
223
		}
224
		boolean useObjectMine = getCorrespondingMacroObjectDescriptor() != null;
225
		setMacroObjectIdentifier(new MacroObjectIdentifier(null,
226
				new PrimitiveUIObjectIdentifier(
227
						useObjectMine ? getCorrespondingMacroObjectDescriptor()
228
								.getWidgetId() : MacroUtil.getAttribute(node,
229
								MacroConstants.WIDGET_ID_ATTRIBUTE),
230
						useObjectMine ? getCorrespondingMacroObjectDescriptor()
231
								.getResolverId() : MacroUtil.getAttribute(node,
232
								MacroConstants.RESOLVER_ID_ATTRIBUTE))));
233
		String codeId = MacroUtil.getAttribute(node,
234
				MacroConstants.RETURN_CODE_ATTRIBUTE);
235
		if (codeId != null) {
236
			try {
237
				expectedReturnCode = new Integer(codeId).intValue();
238
			} catch (NumberFormatException e) {
239
			}
240
		}
241
		NodeList children = node.getChildNodes();
242
		for (int i = 0; i < children.getLength(); i++) {
243
			Node child = children.item(i);
244
			if (child.getNodeType() == Node.ELEMENT_NODE) {
245
				String name = child.getNodeName();
246
				if (name.equals(MacroConstants.COMMAND_ELEMENT))
247
					processCommand(child, lineTable);
248
				else if (name.equals(MacroConstants.SHELL_ELEMENT))
249
					processShell(child, lineTable);
250
			}
251
		}
252
	}
253
254
	/**
255
	 * Used to process the node that is passed in as argument, the lineTable
256
	 * hashtable indicates the range of line numbers that the node corresponds
257
	 * to in the macro script
258
	 * 
259
	 * @param node
260
	 *            The node to be processed
261
	 * @param lineTable
262
	 *            The line number range that the node corresponds to in the
263
	 *            script.
264
	 */
265
	private void processCommand(Node node, Hashtable lineTable)
266
			throws CoreException {
267
268
		String type = MacroUtil.getAttribute(node,
269
				MacroConstants.TYPE_ATTRIBUTE);
270
		if (type == null)
271
			return;
272
273
		IMacroCommand command = MacroManager.getInstance()
274
				.getMacroCommandFactory().createCommand(this, type);
275
276
		if (command != null) {
277
			command.load(node, lineTable);
278
			commands.add(command);
279
		}
280
	}
281
282
	private void processShell(Node node, Hashtable lineTable)
283
			throws CoreException {
284
		MacroCommandShell shell = new MacroCommandShell(this);
285
		shell.load(node, lineTable);
286
		commands.add(shell);
287
	}
288
289
	public void addCommandShell(MacroCommandShell cshell) {
290
		commands.add(cshell);
291
	}
292
293
	public void write(int indent, StringBuffer sb) {
294
		/* If this shell command doesn't have any commands, then exit */
295
		if (commands == null || commands.size() <= 0)
296
			return;
297
298
		/* <shell */
299
		MacroUtil.addElement(sb, indent, MacroConstants.SHELL_ELEMENT, false,
300
				false);
301
		boolean objectMineInUse = MacroManager.getInstance().isObjectMineOn();
302
		MacroUtil.addAttribute(sb, new String[] {
303
				MacroConstants.DESCRIPTIVE_ATTRIBUTE,
304
				MacroConstants.RESOLVER_ID_ATTRIBUTE,
305
				MacroConstants.WIDGET_ID_ATTRIBUTE,
306
				MacroConstants.REFERENCE_ID_ATTRIBUTE,
307
				MacroConstants.RETURN_CODE_ATTRIBUTE }, new String[] {
308
				getDescriptiveField(),
309
				objectMineInUse ? null : getMacroObjectIdentifier()
310
						.getObjectIdentifier().getResolverId(),
311
				objectMineInUse ? null : getMacroObjectIdentifier()
312
						.getObjectIdentifier().getWidgetId(),
313
				objectMineInUse ? getCorrespondingMacroObjectDescriptor()
314
						.getReferenceId() /*
315
											 * CHANGED BY ANY: use the ref id of
316
											 * the corresponing
317
											 * MacroObjectDescriptor rather than
318
											 * the id stored in the widgetId
319
											 */
320
				: null, String.valueOf(expectedReturnCode) }, false, true);
321
		int cindent = indent + 1;
322
		for (int i = 0; i < commands.size(); i++) {
323
			IPersistable persistable = (IPersistable) commands.get(i);
324
			persistable.writeStart(cindent, sb);
325
			persistable.write(cindent, sb);
326
			persistable.writeFinish(cindent, sb);
327
		}
328
		MacroUtil.addElement(sb, indent, MacroConstants.SHELL_ELEMENT, true,
329
				true);
330
	}
331
332
	public String getDescriptiveField() {
333
		return shellTitle == null ? null : MacroUtil
334
				.normalizeDescriptiveField(MacroUtil.boundSize(shellTitle,
335
						IMacroCommand.DESCRIPTIVE_FIELD_BOUND));
336
	}
337
338
	public void addEvent(Event event) {
339
		if (event.widget instanceof Control) {
340
			if (((Control) event.widget).isVisible() == false)
341
				return;
342
		}
343
344
		IMacroCommand command = null;
345
		try {
346
			command = MacroManager.getInstance().getMacroCommandFactory()
347
					.createCommand(this, commands, event);
348
		} catch (CoreException e) {
349
			// it may be the case we are waiting for a verification command to
350
			// be created, so notify a waiting listener (just in case)
351
			MacroManager.getInstance().notifyVerificationListener(
352
					e.getMessage());
353
		}
354
355
		// if we are waiting for a verification command, notify the listener
356
		// that is was correctly created
357
		if (command != null && command instanceof VerificationCommand) {
358
			MacroManager.getInstance().notifyVerificationListener(
359
					(VerificationCommand) command);
360
		}
361
	}
362
363
	/**
364
	 * Adds a wait command for as long as the last command is not already a wait
365
	 * (i.e. duplicate addition of wait commands are avoided through this
366
	 * method)
367
	 */
368
	public void addPause() {
369
		WaitCommand command = new WaitCommand(this);
370
371
		Object lastCommand = null;
372
		int commandSize = commands.size();
373
		boolean isLastCommandWait = false;
374
375
		if (commandSize <= 0)
376
			return;
377
378
		lastCommand = commands.get(commandSize - 1);
379
		int lastCmdInx = 2;
380
381
		/*
382
		 * Avoid MacroCommandShells that have no commands (since these will not
383
		 * be included as part of the macro)
384
		 */
385
		while (lastCommand instanceof MacroCommandShell
386
				&& ((MacroCommandShell) lastCommand).getCommands().size() <= 0) {
387
			if (commandSize - lastCmdInx >= 0)
388
				lastCommand = commands.get(commandSize - lastCmdInx);
389
			else {
390
				lastCommand = null;
391
				break;
392
			}
393
394
			lastCmdInx++;
395
		}
396
397
		AbstractMacroCommand lastMacroCommand = null;
398
		if (lastCommand instanceof AbstractMacroCommand)
399
			lastMacroCommand = (AbstractMacroCommand) lastCommand;
400
401
		isLastCommandWait = lastMacroCommand != null
402
				&& lastMacroCommand.getType() == WaitCommand.TYPE;
403
		if (commands.size() > 0 && !isLastCommandWait) {
404
			commands.add(command);
405
		}
406
	}
407
408
	public void extractExpectedReturnCode() {
409
		if (window != null)
410
			expectedReturnCode = window.getReturnCode();
411
	}
412
413
	public boolean matchesReturnCode() {
414
		if (window != null) {
415
			return window.getReturnCode() == expectedReturnCode;
416
		}
417
		return true;
418
	}
419
420
	public boolean isDisposed() {
421
		return this.shell != null && this.shell.isDisposed();
422
	}
423
424
	public void close() {
425
		if (this.shell != null && !this.shell.isDisposed())
426
			this.shell.close();
427
	}
428
429
	public boolean tracks(Shell shell) {
430
		if (this.shell != null && this.shell.equals(shell))
431
			return true;
432
		return false;
433
	}
434
435
	public boolean playback(final Display display, Shell parent,
436
			final IProgressMonitor monitor) throws CoreException {
437
		if (parent instanceof Shell) {
438
			this.shell = (Shell) parent;
439
			this.display = display;
440
			hookWindow(true);
441
		}
442
443
		NestedShell nestedShell = null;
444
		int commandSize = commands.size();
445
		monitor.beginTask("", commandSize);
446
		final int commandTimeOut;
447
448
		int potentialTimeoutValue = MacroManager.getInstance()
449
				.getCommandTimeoutThreshold();
450
		if (MacroManager.getInstance().getCommandTimeoutThreshold() > 0)
451
			commandTimeOut = potentialTimeoutValue;
452
		else
453
			commandTimeOut = GlobalConstants.DEFAULT_COMMAND_TIME_OUT_PERIOD;
454
455
		for (int i = 0; i < commandSize; i++) {
456
			currentCommandInx = i;
457
			checkForInterruptions();
458
			Object c = commands.get(i);
459
			final IPlayable playable = (IPlayable) c;
460
461
			/*
462
			 * If this is the last command of this macro command shell, then
463
			 * take out its entry in the shell queue
464
			 */
465
			if (isLastCommand(i)) {
466
				if (getNestedShellQueue() != null
467
						&& getNestedShellQueue().size() > 0) {
468
					if (lastNestedShellInx > 0)
469
						lastNestedShellInx--;
470
					removeNestedShell(0);
471
				}
472
			}
473
474
			/*
475
			 * If this command is a nested shell, then we need to wait until it
476
			 * completes before proceeding to the next command.
477
			 */
478
			if (c instanceof MacroCommandShell) {
479
				MacroCommandShell nestedCommandShell = (MacroCommandShell) c;
480
				// System.out.println("NESTED SHELL WAIT: " +
481
				// nestedCommandShell.getId());
482
				Object lastNestedCommand = null;
483
				Object currentNestedCommand = null;
484
				synchronized (nestedCommandShell) {
485
					/*
486
					 * Give each command in the nested shell a maximum of
487
					 * commandTimeOut to execute
488
					 */
489
					while (!nestedCommandShell.isComplete()
490
							&& (currentNestedCommand == null || lastNestedCommand != currentNestedCommand)
491
							&& !interruptProcess) {
492
						try {
493
							nestedCommandShell.wait(commandTimeOut);
494
							lastNestedCommand = currentNestedCommand;
495
							currentNestedCommand = nestedCommandShell
496
									.getCommandBeingExecuted();
497
						} catch (InterruptedException e) {
498
							/* Handled by next set of code */
499
						}
500
					}
501
502
					/* Indicate an error if the nested shell never completed */
503
					if (!nestedCommandShell.isComplete()) {
504
						synchronized (mutualGlobalLock) {
505
							interruptProcess = true;
506
							if (interruptedException == null)
507
								interruptedException = new CoreException(
508
										new Status(
509
												IStatus.ERROR,
510
												GuiPlugin.getID(),
511
												0,
512
												NLS
513
														.bind(
514
																AutoGUIMessages.AUTO_GUI_ERROR_MACRO_NEST_TOUT,
515
																nestedCommandShell
516
																		.getMacroObjectIdentifier()
517
																		.getObjectIdentifier()
518
																		.toString()),
519
												null));
520
						}
521
522
						continue; /* Interrupt the normal flow */
523
					}
524
					// System.out.println("NESTED SHELL FINISH: " +
525
					// nestedCommandShell.getId());
526
				}
527
			}
528
529
			if (i < commandSize - 1) {
530
				/*
531
				 * Ali M.: We need to iterate through all the shell commands and
532
				 * register listeners before it's too late. It's not sufficient
533
				 * to just register a listener with the next command
534
				 */
535
				int counter = 1;
536
				IPlayable next = (IPlayable) commands.get(i + counter);
537
				while (next instanceof MacroCommandShell) {
538
					/*
539
					 * This command will open a new shell. Add a listener before
540
					 * it is too late
541
					 */
542
					MacroCommandShell nestedCommand = (MacroCommandShell) next;
543
544
					if (!nestedCommand.isListenerRegistered()) {
545
						nestedShell = new NestedShell(display, nestedCommand,
546
								new SubProgressMonitor(monitor, 1));
547
						final NestedShell fnestedShell = nestedShell;
548
549
						/*
550
						 * If this is a child of the previous shell, then it
551
						 * takes precedence. If it's a sibling, then it should
552
						 * go to the end of the queue.
553
						 */
554
						nestedCommand.setListenerRegistered(true);
555
						if (nestedShellQueue.size() > 0
556
								&& ((NestedShell) nestedShellQueue.get(0))
557
										.isParent(nestedCommand)) {
558
							addNestedShell(0, fnestedShell);
559
							lastNestedShellInx = 0;
560
						} else {
561
							if (nestedShellQueue.size() > 0)
562
								addNestedShell(++lastNestedShellInx,
563
										fnestedShell);
564
							else
565
								addNestedShell(fnestedShell);
566
						}
567
568
						display.syncExec(new Runnable() {
569
570
							public void run() {
571
								// System.out.println("ADDED");
572
								display.addFilter(SWT.Activate, fnestedShell);
573
							}
574
						});
575
					}
576
					counter++;
577
					next = (i + counter <= commandSize - 1 ? (IPlayable) commands
578
							.get(i + counter)
579
							: null);
580
				}
581
			}
582
			if (playable instanceof AbstractMacroCommand) {
583
				final boolean last = i == commandSize - 1;
584
585
				class WakeUpOperaion implements Runnable {
586
587
					private AbstractMacroCommand command;
588
					private boolean invalidate;
589
590
					public WakeUpOperaion(AbstractMacroCommand command) {
591
						this.command = command;
592
						invalidate = false;
593
					}
594
595
					public void run() {
596
						if (!invalidate
597
								&& MacroCommandShell.lastCommandLineExecuted == command
598
										.getStartLine()) {
599
							/*
600
							 * Ali M.: A command just timed-out. We need to
601
							 * indicate the error and wakeup the thread
602
							 */
603
							synchronized (mutualGlobalLock) {
604
								interruptProcess = true;
605
								if (interruptedException == null)
606
									interruptedException = new CoreException(
607
											new Status(
608
													IStatus.ERROR,
609
													GuiPlugin.getID(),
610
													0,
611
													NLS
612
															.bind(
613
																	AutoGUIMessages.AUTO_GUI_ERROR_MACRO_TIME_OUT,
614
																	command
615
																			.toString()),
616
													null));
617
							}
618
619
							synchronized (mutualLock) {
620
								mutualLock.notify();
621
							}
622
						}
623
					}
624
625
					public void invalidate() {
626
						this.invalidate = true;
627
					}
628
629
				}
630
				WakeUpOperaion wakeupOpt = null;
631
				if (i < commandSize - 1) {
632
					wakeupOpt = new WakeUpOperaion(
633
							(AbstractMacroCommand) playable);
634
					final Runnable wakeupOperation = wakeupOpt;
635
					display.asyncExec(new Runnable() {
636
637
						public void run() {
638
							display.timerExec(commandTimeOut, wakeupOperation);
639
						};
640
641
					});
642
				}
643
644
				class RunCommandOperation implements Runnable {
645
646
					private boolean isComplete;
647
648
					public void run() {
649
						try {
650
							if (!macroCommandsBeingPlayed.contains(this))
651
								macroCommandsBeingPlayed.add(this);
652
653
							lastCommandLineExecuted = ((AbstractMacroCommand) playable)
654
									.getStartLine();
655
							playInGUIThread(display, playable, last, monitor);
656
657
							macroCommandsBeingPlayed.remove(this);
658
							isComplete = true;
659
							synchronized (mutualLock) {
660
								mutualLock.notify();
661
							}
662
						} catch (Throwable e) {
663
							macroCommandsBeingPlayed.remove(this);
664
							synchronized (mutualGlobalLock) {
665
								interruptProcess = true;
666
								if (interruptedException == null)
667
									interruptedException = e;
668
							}
669
							isComplete = true;
670
							synchronized (mutualLock) {
671
								mutualLock.notify();
672
							}
673
						}
674
					}
675
676
					public boolean isComplete() {
677
						return isComplete;
678
					}
679
680
				}
681
682
				RunCommandOperation runCommandOpt = new RunCommandOperation();
683
684
				/* Run the command */
685
				synchronized (mutualLock) {
686
					new Thread(runCommandOpt).start();
687
					long start = System.currentTimeMillis();
688
					long wakeUpTime = start;
689
					long timeToSleep = commandTimeOut;
690
					try {
691
						while (!runCommandOpt.isComplete() && timeToSleep > 0
692
								&& !interruptProcess) {
693
							// System.out.println("WAITING on command: " +
694
							// playable);
695
							mutualLock.wait(timeToSleep);
696
							wakeUpTime = System.currentTimeMillis();
697
							timeToSleep = timeToSleep - (wakeUpTime - start);
698
						}
699
					} catch (InterruptedException e) {
700
						/* Doesn't need to be handled */
701
					}
702
703
					/* Indicate an error if command didn't complete */
704
					if (!runCommandOpt.isComplete()) {
705
						synchronized (mutualGlobalLock) {
706
							interruptProcess = true;
707
							if (interruptedException == null)
708
								interruptedException = new CoreException(
709
										new Status(
710
												IStatus.ERROR,
711
												GuiPlugin.getID(),
712
												0,
713
												NLS
714
														.bind(
715
																AutoGUIMessages.AUTO_GUI_ERROR_MACRO_TIME_OUT,
716
																playable
717
																		.toString()),
718
												null));
719
						}
720
					}
721
					/*
722
					 * Otherwise invalidate the wake up operation that was
723
					 * suppose to wake this command up
724
					 */
725
					else if (wakeupOpt != null)
726
						wakeupOpt.invalidate();
727
728
					// System.out.println("FINISHED WAITING on command: " +
729
					// playable);
730
				}
731
732
				monitor.worked(1);
733
			}
734
		}
735
736
		checkForInterruptions();
737
		shell = null;
738
739
		/*
740
		 * We made it out alive -- mark this as complete and wake any parents
741
		 * that are waiting upon our completion
742
		 */
743
		isComplete = true;
744
		synchronized (this) {
745
			this.notify();
746
		}
747
748
		macroCommandShellContainer.remove(this);
749
		return true;
750
	}
751
752
	private boolean isComplete() {
753
		return isComplete;
754
	}
755
756
	private Object getCommandBeingExecuted() {
757
		if (commands == null || currentCommandInx >= commands.size())
758
			return null;
759
		return commands.get(currentCommandInx);
760
	}
761
762
	private void checkForInterruptions() throws CoreException {
763
		if (interruptProcess) {
764
			/* Wake up all threads in case they are asleep */
765
			if (!processTerminated) {
766
				processTerminated = true;
767
				interruptOperation();
768
				MacroCommandShell.macroStopped();
769
				MacroUtil.closeSecondaryShells(display);
770
			}
771
772
			for (int i = 0; i < macroCommandShellContainer.size(); i++) {
773
				synchronized (mutualLock) {
774
					mutualLock.notify();
775
				}
776
777
				synchronized (macroCommandShellContainer.get(i)) {
778
					macroCommandShellContainer.get(i).notify();
779
				}
780
			}
781
782
			/* Try to close all nested shells */
783
			synchronized (mutualGlobalLock) {
784
				if (interruptedException instanceof CoreException)
785
					throw (CoreException) interruptedException;
786
				throw new CoreException(new Status(IStatus.ERROR, GuiPlugin
787
						.getID(), 0,
788
						interruptedException.getLocalizedMessage(),
789
						interruptedException));
790
			}
791
		}
792
793
	}
794
795
	/**
796
	 * A helper method that walks through all macro command shells and
797
	 * interrupts their normal flow.
798
	 */
799
	private void interruptOperation() {
800
		MacroCommandShell currentMacroShell = this;
801
		while (currentMacroShell != null) {
802
			Boolean lock = currentMacroShell.mutualLock;
803
			synchronized (lock) {
804
				lock.notify();
805
			}
806
807
			currentMacroShell = currentMacroShell.getParent();
808
		}
809
810
	}
811
812
	private boolean isLastCommand(int index) {
813
		for (int i = index + 1; i < commands.size(); i++) {
814
			if (commands.get(i) instanceof AbstractMacroCommand)
815
				return false;
816
		}
817
		return true;
818
	}
819
820
	private void playInGUIThread(final Display display,
821
			final IPlayable playable, boolean last,
822
			final IProgressMonitor monitor) throws CoreException {
823
		final CoreException[] ex = new CoreException[1];
824
825
		Runnable runnable = new Runnable() {
826
827
			public void run() {
828
				try {
829
					boolean status = playable.playback(display,
830
							MacroCommandShell.this.shell, monitor);
831
832
					/* Something went wrong playing this item */
833
					if (!status)
834
						ex[0] = createPlaybackException(playable, null);
835
					else
836
						MacroUtil.processDisplayEvents(display);
837
				} catch (ClassCastException e) {
838
					ex[0] = createPlaybackException(playable, e);
839
				} catch (CoreException e) {
840
					ex[0] = e;
841
				} catch (SWTException e) {
842
					/* Don't handle */
843
				} catch (Throwable error) {
844
					ex[0] = createPlaybackException(playable, error);
845
				}
846
			}
847
		};
848
849
		if (playable instanceof WaitCommand) {
850
			playable.playback(display, this.shell, monitor);
851
		} else {
852
			display.syncExec(runnable);
853
		}
854
855
		try {
856
			Thread.sleep(100);
857
		} catch (InterruptedException e) {
858
		}
859
860
		if (ex[0] != null)
861
			throw ex[0];
862
863
	}
864
865
	private CoreException createPlaybackException(IPlayable playable,
866
			Throwable th) {
867
		IStatus status = new Status(IStatus.ERROR, "org.eclipse.pde.ui.tests",
868
				IStatus.OK, NLS.bind(
869
						AutoGUIMessages.AUTO_GUI_ERROR_MACRO_COMMAND, playable
870
								.toString()), th);
871
		return new CoreException(status);
872
	}
873
874
	public ArrayList getCommands() {
875
		return commands;
876
	}
877
878
	public boolean isListenerRegistered() {
879
		return isListenerRegistered;
880
	}
881
882
	public void setListenerRegistered(boolean isListenerRegistered) {
883
		this.isListenerRegistered = isListenerRegistered;
884
	}
885
886
	public static Vector getNestedShellQueue() {
887
		return nestedShellQueue;
888
	}
889
890
	public static void addNestedShell(int inx, NestedShell nestedShell) {
891
		synchronized (nestedShellQueue) {
892
			if (inx >= 0)
893
				nestedShellQueue.add(inx, nestedShell);
894
			else
895
				nestedShellQueue.add(nestedShell);
896
		}
897
	}
898
899
	private static void addNestedShell(NestedShell fnestedShell) {
900
		addNestedShell(-1, fnestedShell);
901
	}
902
903
	public static void removeNestedShell(int inx) {
904
		synchronized (nestedShellQueue) {
905
			nestedShellQueue.remove(inx);
906
		}
907
	}
908
909
	public static void initializeForNewPlay() {
910
		nestedShellQueue.clear();
911
		lastNestedShellInx = 0;
912
		interruptProcess = false;
913
		processTerminated = false;
914
		interruptedException = null;
915
		MouseEventCommand.init();
916
		macroCommandsBeingPlayed.clear();
917
		macroCommandShellContainer.clear();
918
	}
919
920
	public Shell getShell() {
921
		return shell;
922
	}
923
924
	public void writeStart(int indent, StringBuffer sb) {
925
		/* Doesn't need to be implemented */
926
	}
927
928
	public void writeFinish(int indent, StringBuffer sb) {
929
		/* Doesn't need to be implemented */
930
	}
931
932
	public MacroCommandShell getParent() {
933
		return parent;
934
	}
935
936
	public void setParent(MacroCommandShell parent) {
937
		this.parent = parent;
938
	}
939
940
	public static void macroStopped() {
941
		/* Walk through nested shell listeners and remove them if any exists */
942
		final Display display = GuiPlugin.getDefault().getWorkbench()
943
				.getDisplay();
944
		display.syncExec(new Runnable() {
945
946
			public void run() {
947
				for (int i = 0, nestedShellListenerSize = nestedShellQueue
948
						.size(); i < nestedShellListenerSize; i++) {
949
					display.removeFilter(SWT.Activate,
950
							(NestedShell) nestedShellQueue.get(i));
951
				}
952
			}
953
		});
954
	}
955
956
	public static Vector getMacroCommandsBeingPlayed() {
957
		return macroCommandsBeingPlayed;
958
	}
959
960
	private static class NestedShell implements Listener, Runnable {
961
962
		private MacroCommandShell cshell;
963
964
		private Display display;
965
966
		private Shell nshell;
967
968
		private boolean released;
969
970
		private CoreException exception;
971
972
		private IProgressMonitor monitor;
973
974
		private boolean served;
975
976
		public NestedShell(Display display, MacroCommandShell cshell,
977
				IProgressMonitor monitor) {
978
			this.display = display;
979
			this.cshell = cshell;
980
			this.monitor = monitor;
981
		}
982
983
		public void handleEvent(Event event) {
984
			try {
985
				if (event.widget instanceof Shell) {
986
					// shell activated
987
					Shell shell = (Shell) event.widget;
988
					// ANY: CHANGED: IPath path = new
989
					// Path(UIObjectResolverUtil.getShellId(shell,null).toString());
990
					// String sid = path.toString();
991
					String sid = MacroObjectResolver.resolve(shell,
992
							new MacroObject(new UIObject(shell)))
993
							.getObjectIdentifier().getWidgetId();
994
995
					/* Debug */
996
					// System.out.println();
997
					// System.out.println(sid + " : " + cshell.getId());
998
					// if (MacroCommandShell.getNestedShellQueue() != null &&
999
					// MacroCommandShell.getNestedShellQueue().size() > 0)
1000
					// System.out.println("Is Served: " +
1001
					// ((NestedShell)MacroCommandShell.getNestedShellQueue().get(0)).isServed());
1002
					// System.out.println(this + " : " +
1003
					// MacroCommandShell.getNestedShellQueue().get(0));
1004
					// System.out.println();
1005
					if (sid.equals(cshell.getMacroObjectIdentifier()
1006
							.getObjectIdentifier().getWidgetId())
1007
							&& (MacroCommandShell.getNestedShellQueue() == null
1008
									|| MacroCommandShell.getNestedShellQueue()
1009
											.size() <= 0 || (!((NestedShell) MacroCommandShell
1010
									.getNestedShellQueue().get(0)).isServed() && this
1011
									.equals(MacroCommandShell
1012
											.getNestedShellQueue().get(0))))) {
1013
						// System.out.println("REMOVED FILTER: " +
1014
						// cshell.getId());
1015
						shell.getDisplay().removeFilter(SWT.Activate, this);
1016
						released = true;
1017
						this.nshell = shell;
1018
1019
						/*
1020
						 * We need to start this in a separate thread.
1021
						 * MacroCommandShells should not be played in UI threads
1022
						 * (otherwise wait commands will not work properly)
1023
						 */
1024
						this.setServed(true);
1025
						new Thread(this).start();
1026
					}
1027
				}
1028
			} catch (Throwable t) {
1029
				// System.out.println("REMOVED filter");
1030
				/* Something unexpected has happened -- Remove this listener */
1031
				event.display.removeFilter(SWT.Activate, this);
1032
			}
1033
		}
1034
1035
		public void setServed(boolean served) {
1036
			this.served = served;
1037
		}
1038
1039
		public boolean isServed() {
1040
			return served;
1041
		}
1042
1043
		public boolean getResult() {
1044
			return cshell.matchesReturnCode();
1045
		}
1046
1047
		public boolean isReleased() {
1048
			return released;
1049
		}
1050
1051
		public void run() {
1052
			try {
1053
				cshell.playback(display, nshell, monitor);
1054
			} catch (CoreException e) {
1055
				synchronized (mutualGlobalLock) {
1056
					interruptProcess = true;
1057
					if (interruptedException == null)
1058
						interruptedException = e;
1059
				}
1060
1061
				synchronized (cshell.mutualLock) {
1062
					cshell.mutualLock.notify();
1063
				}
1064
			}
1065
		}
1066
1067
		public CoreException getException() {
1068
			return exception;
1069
		}
1070
1071
		public boolean isParent(MacroCommandShell macroCommandShell) {
1072
			return macroCommandShell.getParent().equals(cshell);
1073
		}
1074
	}
1075
1076
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/resolver/delegate/deresolvingsupport/IUIObjectDeprecatedDeresolvingFacade.java (+38 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.deresolvingsupport;
13
14
import org.eclipse.swt.widgets.Widget;
15
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
16
17
18
/**
19
 * Used to migrate the old WidgetResolvers to the new IUIObjectResolverDelegate interface 
20
 * while preserving their implementation. 
21
 * @author ANy
22
 * @version $Revision$
23
 *
24
 */
25
public interface IUIObjectDeprecatedDeresolvingFacade {
26
27
	/**
28
	 * Given an object and an id, this method should return true if and only if the id of object as determined by this resolver equals the 'id' passed
29
	 * in.
30
	 * 
31
	 * @param object
32
	 *            An object
33
	 * @param objectId
34
	 *            The being searched for
35
	 * @return true iff object's id is equalled to 'id'
36
	 */
37
	public boolean foundWidget(Widget object, IUIObjectIdentifier objectId);
38
}
(-)schema/macroCommandFactory.exsd (+111 lines)
Added Link Here
1
<?xml version='1.0' encoding='UTF-8'?>
2
<!-- Schema file written by PDE -->
3
<schema targetNamespace="org.eclipse.tptp.test.auto.gui">
4
<annotation>
5
      <appInfo>
6
         <meta.schema plugin="org.eclipse.tptp.test.auto.gui" id="macroCommandFactory" name="macroCommandFactory"/>
7
      </appInfo>
8
      <documentation>
9
         Extension point to replace the macro command factory with a custom implementation.
10
      </documentation>
11
   </annotation>
12
13
   <element name="extension">
14
      <complexType>
15
         <sequence>
16
            <element ref="macroCommandFactory"/>
17
         </sequence>
18
         <attribute name="point" type="string" use="required">
19
            <annotation>
20
               <documentation>
21
                  
22
               </documentation>
23
            </annotation>
24
         </attribute>
25
         <attribute name="id" type="string">
26
            <annotation>
27
               <documentation>
28
                  
29
               </documentation>
30
            </annotation>
31
         </attribute>
32
         <attribute name="name" type="string">
33
            <annotation>
34
               <documentation>
35
                  
36
               </documentation>
37
               <appInfo>
38
                  <meta.attribute translatable="true"/>
39
               </appInfo>
40
            </annotation>
41
         </attribute>
42
      </complexType>
43
   </element>
44
45
   <element name="macroCommandFactory">
46
      <complexType>
47
         <attribute name="id" type="string" use="required">
48
            <annotation>
49
               <documentation>
50
                  
51
               </documentation>
52
            </annotation>
53
         </attribute>
54
         <attribute name="class" type="string" use="required">
55
            <annotation>
56
               <documentation>
57
                  
58
               </documentation>
59
               <appInfo>
60
                  <meta.attribute kind="java" basedOn=":org.eclipse.tptp.test.auto.gui.commands.factory.IMacroCommandFactory"/>
61
               </appInfo>
62
            </annotation>
63
         </attribute>
64
         <attribute name="priority" type="string" use="required">
65
            <annotation>
66
               <documentation>
67
                  The priority of the factory. The factory with the highest priority is loaded and used, all others are disregarded.
68
               </documentation>
69
            </annotation>
70
         </attribute>
71
      </complexType>
72
   </element>
73
74
   <annotation>
75
      <appInfo>
76
         <meta.section type="since"/>
77
      </appInfo>
78
      <documentation>
79
         [Enter the first release in which this extension point appears.]
80
      </documentation>
81
   </annotation>
82
83
   <annotation>
84
      <appInfo>
85
         <meta.section type="examples"/>
86
      </appInfo>
87
      <documentation>
88
         [Enter extension point usage example here.]
89
      </documentation>
90
   </annotation>
91
92
   <annotation>
93
      <appInfo>
94
         <meta.section type="apiInfo"/>
95
      </appInfo>
96
      <documentation>
97
         [Enter API information here.]
98
      </documentation>
99
   </annotation>
100
101
   <annotation>
102
      <appInfo>
103
         <meta.section type="implementation"/>
104
      </appInfo>
105
      <documentation>
106
         [Enter information about supplied implementation of this extension point.]
107
      </documentation>
108
   </annotation>
109
110
111
</schema>
(-)src/org/eclipse/tptp/test/auto/gui/internal/core/WidgetResolverLoaderToUIObjectResolverDelegateLoaderAdapter.java (+12 lines)
Added Link Here
1
package org.eclipse.tptp.test.auto.gui.internal.core;
2
3
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.UIObjectResolverDelegateLoader;
4
5
public class WidgetResolverLoaderToUIObjectResolverDelegateLoaderAdapter extends UIObjectResolverDelegateLoader {
6
7
	public WidgetResolverLoaderToUIObjectResolverDelegateLoaderAdapter(WidgetResolverLoader widgetResolverLoader) {
8
		super(widgetResolverLoader.getId(), new WidgetResolverToUIObjectResolverDelegateAdapter(widgetResolverLoader.getWidgetResolver()), widgetResolverLoader.getPriority());
9
	}
10
11
	
12
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/IPersistable.java (+72 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macro;
12
13
import java.util.Hashtable;
14
15
import org.eclipse.core.runtime.CoreException;
16
import org.w3c.dom.Node;
17
18
19
20
/**
21
 * A writable object is capable of serializing itself to string and writing the string
22
 * version to a PrintWriter that is passed to parameters to the methods that are described
23
 * below. It is also capable of loading itself from a given node.
24
 * <br/>
25
 * The ideal order of the method invocations are:
26
 * <ul>
27
 * 	<li> writeStart(String indent, gPrintWriter writer) </li>
28
 * 	<li> write(String indent, PrintWriter writer) </li>
29
 * 	<li> writeFinish(String indent, PrintWriter writer) </li>
30
 * </ul>
31
 */
32
public interface IPersistable 
33
{
34
	/**
35
	 * Invoked at start of the write of a writable object
36
	 * 
37
	 * @param indent The indents
38
	 * @param sb The buffer that the string serialization should be written to
39
	 */
40
	public void writeStart(int indent, StringBuffer sb);
41
	
42
	
43
	/**
44
	 * Invoked after writeStart
45
	 * 
46
	 * @param indent The indents
47
	 * @param sb The buffer that the string serialization should be written to
48
	 */
49
	public void write(int indent, StringBuffer sb);
50
	
51
	
52
	/**
53
	 * Invoked in the end of the write of a writable object
54
	 * 
55
	 * @param indent The indents
56
	 * @param sb The buffer that the string serialization should be written to
57
	 */
58
	public void writeFinish(int indent, StringBuffer sb);
59
	
60
	/**
61
	 * Invoked to load the macro instruction based on its corresponding XML node.
62
	 * 
63
	 * @param node
64
	 *            The XML node representing this macro instruction
65
	 * @param lineTable
66
	 *            Contains line level information
67
	 * 
68
	 * @throws CoreException
69
	 *             In case of an unexpected error
70
	 */
71
	public void load(Node node, Hashtable lineTable) throws CoreException;
72
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/IMacroInstruction.java (+34 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macro;
12
13
14
/**
15
 * Represents a macro instruction. The instruction is expected to both be writable and playable.
16
 * 
17
 * @author Ali Mehregani
18
 */
19
public interface IMacroInstruction extends IPersistable, IPlayable {
20
21
	/**
22
	 * Returns the starting line number of this macro instruction in the macro script that it belongs to.
23
	 * 
24
	 * @return The starting line
25
	 */
26
	public int getStartLine();
27
28
	/**
29
	 * Returns the last line number of this macro instruction in the macro script that it belongs to.
30
	 * 
31
	 * @return The last line
32
	 */
33
	public int getStopLine();
34
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/util/VerificationHookClassLoader.java (+104 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * $Id: VerificationHookClassLoader.java,v 1.2 2006/07/14 23:17:02 amehregani Exp $
8
 * 
9
 * Contributors:
10
 *     IBM Corporation - initial API and implementation
11
 *******************************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.util;
13
14
import java.net.URL;
15
import java.net.URLClassLoader;
16
import java.util.Vector;
17
18
import org.eclipse.core.runtime.Platform;
19
import org.eclipse.osgi.util.NLS;
20
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
21
22
/**
23
 * A custom class loader that is used to resolve a class that the verificaiton hook is in along
24
 * with any other classes that are imported by the verification class.
25
 * 
26
 * @author Ali Mehregani
27
 */
28
public class VerificationHookClassLoader extends URLClassLoader
29
{
30
	/* The plugins that the verification plugin requires */
31
	private Vector reqPluginNames;
32
	
33
	public VerificationHookClassLoader (URL[] urls, ClassLoader parent, Vector requiredPluginNames)
34
	{
35
		super (urls, parent);		
36
		reqPluginNames = requiredPluginNames;
37
	}
38
	
39
   
40
	/**
41
	 * Invoked when a class can't be resolved by the upper level class loaders associated with
42
	 * this class.
43
	 */
44
	protected Class findClass(final String name) 
45
	 throws ClassNotFoundException 			 
46
    {  	
47
		
48
    	/* Try and walk through the required plugins of the plugin
49
    	 * containing the test suite */
50
    	try
51
    	{			
52
    		Class classFile = loadFromReqPlugins(name, 0);
53
    		if (classFile != null)
54
    			return classFile;
55
    	}
56
    	catch (Throwable t)
57
    	{
58
    		/* Doesn't need to be handled */
59
    	}
60
    	
61
		
62
		try
63
		{
64
			Class classFile = super.findClass(name);
65
			if (classFile != null)
66
				return classFile;
67
		}
68
		catch (Throwable t)
69
		{
70
			/* Doesn't need to be handled */
71
		}
72
		
73
	    		    	
74
    	
75
    	throw new ClassNotFoundException (NLS.bind(AutoGUIMessages.AUTO_GUI_ERROR_VER_CLASS_NOT_FS, name));
76
    }
77
78
79
	/**
80
	 * Attempt to load the class from the required plugins.
81
	 * 
82
	 * @param name
83
	 * @param inx
84
	 * @return
85
	 */
86
	private Class loadFromReqPlugins(String name, int inx)
87
	{
88
		try
89
		{
90
			if (reqPluginNames == null || inx >= reqPluginNames.size())
91
				return null;
92
			
93
			Class classFile = Platform.getBundle(((String)reqPluginNames.get(inx))).loadClass(name);				
94
			if (classFile != null)
95
				return classFile;
96
		}
97
		catch (Throwable t)
98
		{
99
			/* Handled by next statement */
100
		}
101
		
102
		return loadFromReqPlugins(name, inx + 1);
103
	}
104
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/uiobject/resolver/delegate/AdaptiveUIObjectResolverDelegate.java (+650 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2005, 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * $Id: AdaptiveUIObjectResolverDelegate.java,v 1.6 2007/04/26 20:03:22 paules Exp $
8
 * 
9
 * Contributors:
10
 *     IBM Corporation - initial API and implementation
11
 *******************************************************************************/
12
package org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate;
13
14
import java.io.IOException;
15
import java.io.InputStream;
16
import java.lang.reflect.Method;
17
import java.net.URL;
18
import java.util.Hashtable;
19
import java.util.Vector;
20
21
import org.eclipse.core.runtime.CoreException;
22
import org.eclipse.hyades.test.common.util.XMLUtil;
23
import org.eclipse.jface.dialogs.MessageDialog;
24
import org.eclipse.swt.widgets.Widget;
25
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIMessages;
26
import org.eclipse.tptp.test.auto.gui.internal.AutoGUIUtil;
27
import org.eclipse.tptp.test.auto.gui.internal.GuiPlugin;
28
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroManager;
29
import org.eclipse.tptp.test.auto.gui.internal.macro.ModeConstants;
30
import org.eclipse.tptp.test.auto.gui.internal.macroobject.MacroObject;
31
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObject;
32
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
33
import org.eclipse.tptp.test.auto.gui.internal.uiobject.UIObject;
34
import org.eclipse.tptp.test.auto.gui.internal.uiobject.WeightedPropertyUIObjectIdentifier;
35
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.UIObjectResolver;
36
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.deresolvingsupport.IUIObjectDeprecatedDeresolvingFacade;
37
import org.eclipse.tptp.test.auto.gui.internal.uiobject.resolver.delegate.deresolvingsupport.UIObjectDeprecatedDeresolvingSupport;
38
import org.osgi.framework.Bundle;
39
import org.w3c.dom.Element;
40
import org.w3c.dom.NodeList;
41
42
/**
43
 * The following widget resolver attempts to resolve widgets using a static XML
44
 * file stored under the auto-gui folder under this plugin.
45
 * 
46
 * @since 4.1
47
 * @author Ali Mehregani
48
 */
49
public class AdaptiveUIObjectResolverDelegate implements
50
		IUIObjectResolverDelegate, IUIObjectDeprecatedDeresolvingFacade {
51
52
	/**
53
	 * The id of this resolver -- must be in sync with the id registered with
54
	 * the widgetResolver extension.
55
	 */
56
	private static final String ID = "org.eclipse.tptp.test.auto.gui.adaptive";
57
58
	/** The assumed file name relative to this plugin */
59
	public final static String WIDGET_REG_FILE = "auto-gui/widgetReg.xml";
60
61
	/** The widget registerations */
62
	private IWidgetRegistration widgetReg;
63
64
	public AdaptiveUIObjectResolverDelegate() {
65
		widgetReg = new WidgetRegistration(this, WIDGET_REG_FILE);
66
	}
67
68
	public IUIObjectIdentifier resolve(Object context, IUIObject object)
69
			throws CoreException {
70
		if (object.getObject() != null)
71
			return null;
72
73
		widgetReg.load();
74
		IUIObjectIdentifier widgetId = widgetReg
75
				.getWidgetId(object.getWidget());
76
		return widgetId;
77
	}
78
79
	public IUIObject deresolve(Object context,
80
			IUIObjectIdentifier uiObjectIdentifier) throws CoreException {
81
		return UIObjectDeprecatedDeresolvingSupport.deresolve(context,
82
				uiObjectIdentifier);
83
	}
84
85
	/**
86
	 * Clients have the option of overwriting this in order to be able to locate
87
	 * the widget them self in the registeration entries that exist.
88
	 */
89
	public WidgetRegValue findWidget(Hashtable registerations, Widget widget) {
90
		return null;
91
	}
92
93
	public class WidgetRegistration implements IWidgetRegistration {
94
95
		/* The file name */
96
		private String fileName;
97
98
		/* The last size of the file when it was properly read */
99
		private long lastModifiedDate;
100
101
		/*
102
		 * The file size (stored in case there was an error last time reading
103
		 * the file
104
		 */
105
		private long lastModifiedDateDetected;
106
107
		/* Indicates if there was an error in parsing the file */
108
		private boolean errorOccurred;
109
110
		/*
111
		 * The data structures holding the registered widgets. Key = class name;
112
		 * Value = WidgetRegValue
113
		 */
114
		private Hashtable regWidgets;
115
116
		/* The global match threshold */
117
		private float globalMatchThreshold;
118
119
		/* The class name used for the default entry */
120
		public static final String DEFAULT_ENTYR = "0_DEFAULT_ENTRY";
121
122
		/* The adaptive widget resolver used as the driver for resolving widgets */
123
		private AdaptiveUIObjectResolverDelegate adaptiveWidgetResolver;
124
125
		public WidgetRegistration(
126
				AdaptiveUIObjectResolverDelegate adaptiveWidgetResolver,
127
				String fileName) {
128
			this.fileName = fileName;
129
			this.lastModifiedDate = 0;
130
			this.lastModifiedDateDetected = 0;
131
			this.errorOccurred = false;
132
			this.regWidgets = new Hashtable();
133
			this.adaptiveWidgetResolver = adaptiveWidgetResolver;
134
		}
135
136
		public void load() {
137
			InputStream regXMLInputStream = null;
138
			try {
139
140
				Bundle guiBundle = GuiPlugin.getDefault().getBundle();
141
				long currentModifiedDate = guiBundle.getLastModified();// added
142
				// for
143
				// defect
144
				// 169733
145
				// Liz
146
				// Dancy
147
148
				/*
149
				 * Checking the file size doesn't guarantee to us that the file
150
				 * hasn't changed. This is the best we can do. Replace this with
151
				 * last modified date if API is available.
152
				 */
153
				if (currentModifiedDate > 0
154
						&& (currentModifiedDate == lastModifiedDate || (errorOccurred && lastModifiedDateDetected == currentModifiedDate)))
155
					return;
156
157
				URL regFileURL = GuiPlugin.getDefault().getBundle().getEntry(
158
						fileName);
159
				lastModifiedDateDetected = currentModifiedDate;
160
161
				/* Parse the XML file */
162
				regXMLInputStream = regFileURL.openStream();
163
				Element rootElement = XMLUtil.loadDom(regXMLInputStream,
164
						"widgetResolverRule");
165
				if (rootElement == null) {
166
					lastModifiedDate = 0;
167
					errorOccurred = true;
168
169
					/* Display an error message if we are recording */
170
					if (MacroManager.getInstance().getGlobalState() == ModeConstants.RECORDING_MODE) {
171
						AutoGUIUtil.showMessage(
172
								AutoGUIMessages.AUTO_GUI_ERROR_WID_RESOLVER_T,
173
								AutoGUIMessages.AUTO_GUI_ERROR_WID_RESOLVER,
174
								MessageDialog.WARNING);
175
					}
176
					return;
177
				}
178
				this.regWidgets.clear();
179
				parseRegFile(rootElement);
180
				lastModifiedDate = currentModifiedDate;
181
			} catch (Throwable t) {
182
				/* Set the file size to zero to invalidate this widget resolver */
183
				lastModifiedDate = 0;
184
				errorOccurred = true;
185
186
				/* Display an error message if we are recording */
187
				if (MacroManager.getInstance().getGlobalState() == ModeConstants.RECORDING_MODE) {
188
					AutoGUIUtil.showMessage(
189
							AutoGUIMessages.AUTO_GUI_ERROR_WID_RESOLVER_T,
190
							AutoGUIMessages.AUTO_GUI_ERROR_WID_RESOLVER,
191
							MessageDialog.WARNING);
192
				}
193
			} finally {
194
				if (regXMLInputStream != null) {
195
					try {
196
						regXMLInputStream.close();
197
					} catch (IOException e) {
198
						/* Ignore the error */
199
					}
200
				}
201
			}
202
203
		}
204
205
		public float getGlobalThreshold() {
206
			return globalMatchThreshold;
207
		}
208
209
		/**
210
		 * parse the registation file that has already been loaded
211
		 */
212
		private void parseRegFile(Element rootElement) {
213
			if (rootElement == null)
214
				return;
215
216
			NodeList classList = XMLUtil
217
					.getChildrenByName(rootElement, "class");
218
			parseClassElements(classList);
219
			globalMatchThreshold = Float.parseFloat(XMLUtil.getValue(
220
					rootElement, "globalMatchThreshold"));
221
			NodeList defaultList = XMLUtil.getChildrenByName(rootElement,
222
					"default");
223
			parseDefaultElements(defaultList);
224
		}
225
226
		private void parseDefaultElements(NodeList defaultList) {
227
			if (defaultList == null || defaultList.getLength() < 1)
228
				return;
229
230
			/* We only expect one default element */
231
			if (defaultList.item(0) instanceof Element) {
232
				Element defaultElement = (Element) defaultList.item(0);
233
				NodeList methodList = XMLUtil.getChildrenByName(defaultElement,
234
						"method");
235
				WidgetRegValue widgetReg = new WidgetRegValue();
236
237
				parseMethod(methodList, widgetReg);
238
				if (widgetReg != null)
239
					regWidgets.put(DEFAULT_ENTYR, widgetReg);
240
241
			}
242
		}
243
244
		/**
245
		 * Parse the class elements
246
		 */
247
		private void parseClassElements(NodeList classList) {
248
			if (classList == null || classList.getLength() <= 0)
249
				return;
250
251
			for (int i = 0; i < classList.getLength(); i++) {
252
				if (classList.item(i) instanceof Element) {
253
254
					Element classElement = (Element) classList.item(i);
255
					String className = XMLUtil.getValue(classElement, "name");
256
					NodeList methodList = XMLUtil.getChildrenByName(
257
							classElement, "method");
258
					WidgetRegValue widgetReg = new WidgetRegValue();
259
					String matchThreshold = XMLUtil.getValue(classElement,
260
							"matchThreshold");
261
					if (matchThreshold != null)
262
						widgetReg.setClassMatchThreshold(Float
263
								.parseFloat(matchThreshold));
264
265
					parseMethod(methodList, widgetReg);
266
					if (widgetReg != null)
267
						regWidgets.put(className, widgetReg);
268
269
				}
270
			}
271
		}
272
273
		/**
274
		 * Parse the method element and return a widget registration entry
275
		 * 
276
		 * @param methodList
277
		 *            The method list
278
		 * @param widgetReg
279
		 *            the widget registration entry that will be augmented
280
		 * @return A widget registeration entry
281
		 */
282
		private void parseMethod(NodeList methodList, WidgetRegValue widgetReg) {
283
			if (methodList == null || methodList.getLength() <= 0)
284
				return;
285
286
			for (int i = 0; i < methodList.getLength(); i++) {
287
				if (methodList.item(i) instanceof Element) {
288
					Element methodElement = (Element) methodList.item(i);
289
					String methodName = XMLUtil.getValue(methodElement, "name");
290
					float weight = Float.parseFloat(XMLUtil.getValue(
291
							methodElement, "weight"));
292
					PropertyValue propertyVal = new PropertyValue();
293
					propertyVal.setWeight(weight);
294
295
					NodeList argumentList = XMLUtil.getChildrenByName(
296
							methodElement, "argument");
297
					if (argumentList != null)
298
						parseArguments(argumentList, propertyVal);
299
300
					widgetReg.addProperty(methodName, propertyVal);
301
				}
302
			}
303
		}
304
305
		/**
306
		 * Parse the arguments
307
		 * 
308
		 * @param argumentList
309
		 *            The arugment list
310
		 * @param propertyVal
311
		 *            The property value entry that will be augmented to.
312
		 */
313
		private void parseArguments(NodeList argumentList,
314
				PropertyValue propertyVal) {
315
			if (argumentList == null || argumentList.getLength() <= 0)
316
				return;
317
318
			Vector arguments = new Vector();
319
			for (int i = 0; i < argumentList.getLength(); i++) {
320
				if (argumentList.item(i) instanceof Element) {
321
					Element argumentElement = (Element) argumentList.item(i);
322
					String argumentValue = XMLUtil.getValue(argumentElement,
323
							"value");
324
					arguments.add(argumentValue);
325
				}
326
			}
327
328
			propertyVal.setArguments(arguments);
329
		}
330
331
		public IUIObjectIdentifier getWidgetId(Widget widget) {
332
			/*
333
			 * Use this resolver if we were able to successfully resolve parse
334
			 * the XML file
335
			 */
336
			if (lastModifiedDate > 0) {
337
				/*
338
				 * First attempt the widget itself. If that fails, then try its
339
				 * data attribute
340
				 */
341
				Object data = widget;
342
343
				WidgetRegValue widgetValue = (WidgetRegValue) regWidgets
344
						.get(data.getClass().getName());
345
				if (widgetValue == null && widget.getData() != null) {
346
					data = widget.getData();
347
					widgetValue = (WidgetRegValue) regWidgets.get(data
348
							.getClass().getName());
349
350
					/*
351
					 * If that fails, then walk throught the class heirarchy
352
					 * (the interafaces and superclasses
353
					 */
354
					if (widgetValue == null) {
355
						widgetValue = walkThroughClassHeirarchy(data.getClass());
356
357
					}
358
				}
359
360
				/*
361
				 * As a final resolution, try and call the driver class to
362
				 * resolve the widget
363
				 */
364
				if (widgetValue == null)
365
					widgetValue = adaptiveWidgetResolver.findWidget(regWidgets,
366
							widget);
367
368
				Vector propertyWeightPair = new Vector(5);
369
370
				boolean specificValidEntry = false;
371
				boolean defaultValidEntry = false;
372
373
				float threshold = 0;
374
				if (widgetValue != null) {
375
					threshold = widgetValue.getClassMatchThreshold();
376
					if (threshold == 0)
377
						threshold = globalMatchThreshold;
378
379
					/* Specific properties associated with this type */
380
					specificValidEntry = appendProperties(data,
381
							propertyWeightPair, widgetValue);
382
				}
383
384
				/* Default properties */
385
				Vector defaultEntries = new Vector();
386
				defaultValidEntry = appendProperties(widget, defaultEntries,
387
						(WidgetRegValue) regWidgets.get(DEFAULT_ENTYR), true);
388
				if (defaultValidEntry)
389
					propertyWeightPair.addAll(propertyWeightPair);
390
391
				/*
392
				 * Return null if we weren't able to get any of the widgets
393
				 * properties
394
				 */
395
				if (propertyWeightPair.size() <= 0)
396
					return null;
397
398
				if (specificValidEntry || defaultValidEntry) {
399
					WeightedPropertyUIObjectIdentifier adaptiveWidgetId = new WeightedPropertyUIObjectIdentifier(
400
							propertyWeightPair.toArray(), threshold, ID);
401
					return adaptiveWidgetId;
402
				}
403
				return null;
404
			}
405
406
			return null;
407
		}
408
409
		private WidgetRegValue walkThroughClassHeirarchy(Class widgetClass) {
410
			WidgetRegValue widgetValue = null;
411
412
			widgetValue = (WidgetRegValue) regWidgets
413
					.get(widgetClass.getName());
414
			if (widgetValue != null)
415
				return widgetValue;
416
417
			Class[] interfaces = widgetClass.getInterfaces();
418
419
			/* Try the interfaces first */
420
			for (int i = 0; i < interfaces.length; i++) {
421
				widgetValue = (WidgetRegValue) regWidgets.get(interfaces[i]
422
						.getName());
423
				widgetValue = (widgetValue == null ? walkThroughClassHeirarchy(interfaces[i])
424
						: widgetValue);
425
				if (widgetValue != null)
426
					return widgetValue;
427
			}
428
429
			/* We failed with the interfaces, now try the super class */
430
			Class extendedClass = widgetClass.getSuperclass();
431
			if (extendedClass != null)
432
				widgetValue = walkThroughClassHeirarchy(extendedClass);
433
434
			return widgetValue;
435
		}
436
437
		private boolean appendProperties(Object data,
438
				Vector propertyWeightPair, WidgetRegValue widgetValue) {
439
			return appendProperties(data, propertyWeightPair, widgetValue,
440
					false);
441
		}
442
443
		private boolean appendProperties(Object data,
444
				Vector propertyWeightPair, WidgetRegValue widgetValue,
445
				boolean isDefault) {
446
			boolean validEntry = false;
447
			if (widgetValue == null)
448
				return false;
449
450
			Vector properties = widgetValue.getProperties();
451
			for (int i = 0, propertySize = properties.size(); i < propertySize; i++) {
452
				String property = (String) properties.get(i);
453
				PropertyValue propertyValue = widgetValue
454
						.getPropertyValue(property);
455
				String retValue = invokeProperty(data, property, propertyValue);
456
457
				if ((retValue == null || retValue.length() <= 0) && isDefault)
458
					retValue = invokeProperty(((Widget) data).getData(),
459
							property, propertyValue);
460
461
				/* Don't add it if the return value is null or of zero length */
462
				if (retValue == null || retValue.length() <= 0)
463
					retValue = "null"; /*
464
										 * Set the value to the literal string
465
										 * 'null'
466
										 */
467
				else
468
					validEntry = true;
469
470
				propertyWeightPair.add(new Object[] { retValue,
471
						String.valueOf(propertyValue.getWeight()) });
472
			}
473
			return validEntry;
474
		}
475
476
		/**
477
		 * Invoke the appropriate method to get the property value
478
		 * 
479
		 * @param data
480
		 *            The data corresponding to the widget or the data attribute
481
		 *            of the widget
482
		 * @param theMethod
483
		 *            The method corresponding to the property value
484
		 * @param propertyValue
485
		 *            The property information container
486
		 * 
487
		 * @return The returned value of the method corresponding to the
488
		 *         argument
489
		 */
490
		private String invokeProperty(Object data, String theMethod,
491
				PropertyValue propertyValue) {
492
			try {
493
				if (data == null) {
494
					return null;
495
				}
496
497
				Class theClass = data.getClass();
498
				int paramCount = 0;
499
				Vector args = propertyValue.getArguments();
500
				if (args != null && args.size() > 0)
501
					paramCount = args.size();
502
503
				/* We only support method with string parameters */
504
				Class[] params = new Class[paramCount];
505
				for (int i = 0; i < params.length; i++)
506
					params[i] = String.class;
507
508
				Method method = theClass.getMethod(theMethod, params);
509
510
				Object[] methodArgs = null;
511
				if (paramCount > 0)
512
					methodArgs = propertyValue.getArguments().toArray();
513
514
				Object retValue = method.invoke(data, methodArgs);
515
				if (retValue != null) {
516
					return retValue.toString();
517
				}
518
				return null;
519
			} catch (Throwable t) {
520
				/* Return null if in case we can retrieve the property value */
521
				return null;
522
			}
523
524
		}
525
526
		public WidgetRegValue getDefaultWidgetReg() {
527
			if (regWidgets == null)
528
				return null;
529
			return (WidgetRegValue) regWidgets.get(DEFAULT_ENTYR);
530
		}
531
532
	}
533
534
	/**
535
	 * Can be used to provide any alternative implementation of how the widget
536
	 * registration file is loaded and queried.
537
	 * 
538
	 * @author Ali Mehregani
539
	 */
540
	public interface IWidgetRegistration {
541
542
		/**
543
		 * Used to load the necessary file and store the data in a datastructure
544
		 * that will later be used to query the registrations.
545
		 */
546
		public void load();
547
548
		/**
549
		 * Retrieve the widget id from the registrations
550
		 * 
551
		 * @param widget
552
		 *            The widget in question
553
		 * @return The persistent identifier for the widget
554
		 */
555
		public IUIObjectIdentifier getWidgetId(Widget widget);
556
	}
557
558
	/**
559
	 * A container class for the registeration value of a widget
560
	 * 
561
	 * @author Ali Mehregani
562
	 */
563
	private class WidgetRegValue {
564
565
		/* Key = method names, value = propertyValue */
566
		private Hashtable properties;
567
568
		/* Class match treshold */
569
		private float classMatchThreshold;
570
571
		/*
572
		 * This vector is used to preserve the ordering of the properties
573
		 * inserted in the hashtable
574
		 */
575
		private Vector hashKeys;
576
577
		public WidgetRegValue() {
578
			properties = new Hashtable();
579
			classMatchThreshold = 0;
580
			hashKeys = new Vector();
581
		}
582
583
		public Vector getProperties() {
584
			return hashKeys;
585
		}
586
587
		public PropertyValue getPropertyValue(String propertyValue) {
588
			return (PropertyValue) properties.get(propertyValue);
589
		}
590
591
		public PropertyValue getPropertyValue(int inx) {
592
			if (inx >= hashKeys.size())
593
				return null;
594
			return (PropertyValue) properties.get(hashKeys.get(inx));
595
		}
596
597
		public void addProperty(String methodName, PropertyValue propertyValue) {
598
			hashKeys.add(methodName);
599
			properties.put(methodName, propertyValue);
600
		}
601
602
		public float getClassMatchThreshold() {
603
			return classMatchThreshold;
604
		}
605
606
		public void setClassMatchThreshold(float classMatchThreshold) {
607
			this.classMatchThreshold = classMatchThreshold;
608
		}
609
610
	}
611
612
	/**
613
	 * Container class for property values
614
	 * 
615
	 * @author Ali Mehregani
616
	 */
617
	private class PropertyValue {
618
619
		private Vector arguments;
620
		private float weight;
621
622
		public Vector getArguments() {
623
			return arguments;
624
		}
625
626
		public void setArguments(Vector arguments) {
627
			this.arguments = arguments;
628
		}
629
630
		public float getWeight() {
631
			return weight;
632
		}
633
634
		public void setWeight(float weight) {
635
			this.weight = weight;
636
		}
637
	}
638
639
	public boolean foundWidget(Widget widget, IUIObjectIdentifier widgetId) {
640
		try {
641
			IUIObjectIdentifier id = UIObjectResolver.resolve(new MacroObject(new UIObject(
642
					widget)).getContext(), new UIObject(widget));
643
			return id == null ? false : id == null ? false : id.getWidgetId()
644
					.equals(widgetId.getWidgetId());
645
		} catch (CoreException e) {
646
			e.printStackTrace();
647
		}
648
		return false;
649
	}
650
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macroobject/MacroObject.java (+216 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.macroobject;
13
14
import org.eclipse.jface.action.ContributionManager;
15
import org.eclipse.jface.action.IMenuManager;
16
import org.eclipse.jface.action.MenuManager;
17
import org.eclipse.jface.wizard.IWizardPage;
18
import org.eclipse.jface.wizard.WizardDialog;
19
import org.eclipse.swt.custom.CTabItem;
20
import org.eclipse.swt.widgets.Button;
21
import org.eclipse.swt.widgets.Control;
22
import org.eclipse.swt.widgets.Decorations;
23
import org.eclipse.swt.widgets.Menu;
24
import org.eclipse.swt.widgets.MenuItem;
25
import org.eclipse.swt.widgets.Shell;
26
import org.eclipse.swt.widgets.TabItem;
27
import org.eclipse.swt.widgets.ToolItem;
28
import org.eclipse.swt.widgets.Widget;
29
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroUtil;
30
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObject;
31
import org.eclipse.ui.IEditorPart;
32
import org.eclipse.ui.IViewPart;
33
import org.eclipse.ui.IWorkbenchPage;
34
import org.eclipse.ui.IWorkbenchPart;
35
import org.eclipse.ui.IWorkbenchWindow;
36
37
/**
38
 * 
39
 * @author Alexander Nyssen
40
 * 
41
 */
42
public class MacroObject implements IMacroObject {
43
44
	private Object context;
45
	private IUIObject uiObject;
46
47
	/**
48
	 * Constructor is used by MacroObjectResolver to instantiate a new
49
	 * MacroObject during deresolving of an IMacroObjectIdentifier
50
	 * 
51
	 * @param context
52
	 * @param uiObject
53
	 */
54
	public MacroObject(Object context, IUIObject uiObject) {
55
		this.uiObject = uiObject;
56
		this.context = context;
57
	}
58
59
	/**
60
	 * Constructor is used by clients when constructing a new MacroObject to
61
	 * pass it to the MacroObjectResolver to retrieve an IMacroObjectIdentifier.
62
	 * The context of the MacroObject is automatically detected based on the
63
	 * IUIObject passed in.
64
	 * 
65
	 * 
66
	 * @param uiObject
67
	 */
68
	public MacroObject(IUIObject uiObject) {
69
		this.uiObject = uiObject;
70
		this.context = retrieveContext(uiObject);
71
	}
72
73
	private Object retrieveContext(IUIObject uiObject) {
74
		Widget widget = uiObject.getWidget();
75
		if (widget instanceof MenuItem) {
76
			MenuItem menuItem = (MenuItem) widget;
77
			IViewPart view = null;
78
			if (MacroUtil.onMenubar(menuItem)) {
79
				// return the menu containing the item
80
				return menuItem.getParent().getShell().getMenuBar();
81
			} else if ((view = MacroUtil.onWorkbenchPartToolbar(menuItem)) != null) {
82
				// return the menu located on the action bar of the view
83
				// Note: formerly, the ToolBarManager was returned here,
84
				// however, this
85
				// was never used during resolving -> instead the MenuManager of
86
				// the action bar was used to find the menu.
87
				IMenuManager menuManager = view.getViewSite().getActionBars()
88
						.getMenuManager();
89
				if (menuManager != null && menuManager instanceof MenuManager) {
90
					Menu menu = ((MenuManager) menuManager).getMenu();
91
					if (menu == null) {
92
						// try to create menu
93
						((MenuManager) menuManager)
94
								.createMenuBar((Decorations) view.getSite()
95
										.getShell());
96
					}
97
					return menu;
98
				} else {
99
					return null;
100
				}
101
			} else {
102
				// popup menu item
103
				return widget.getDisplay().getFocusControl();
104
			}
105
		} else if (widget instanceof ToolItem) {
106
			ToolItem toolItem = (ToolItem) widget;
107
			ContributionManager contributionManager = null;
108
			if ((contributionManager = MacroUtil.onToolbar(toolItem)) != null) {
109
				// global toolbar
110
				return contributionManager;
111
			} else {
112
				// local toolbar
113
				return toolItem.getParent();
114
			}
115
		} else if (widget instanceof TabItem) {
116
			// ANy: Added to allow proper resolving of TabItems
117
			return ((TabItem) widget).getParent();
118
		} else if (widget instanceof CTabItem) {
119
			// ANy: Added to allow proper resolving of CTabItems
120
			return ((CTabItem) widget).getParent();
121
		}
122
		// else if (widget instanceof Shell) {
123
		// return ((Shell)widget).getData();
124
		// }
125
		else if (widget instanceof Control) {
126
			return retrieveControlContext(uiObject);
127
		}
128
		// ANy: it seems that Menus are actually never used as macro objects,
129
		// as the deresolver only has capability to deresolve menu items and not
130
		// menus,
131
		// so we will ignore this case here as well (the MacroObjectResolver
132
		// throws a CoreException if called with a MacroObject denoting a menu)
133
134
		// else if (widget instanceof Menu) {
135
		// return null;
136
		// }
137
		return null;
138
	}
139
140
	/**
141
	 * @param uiObject
142
	 */
143
	private Object retrieveControlContext(IUIObject uiObject) {
144
		if (uiObject.getWidget() instanceof Control) {
145
			Control control = (Control) uiObject.getWidget();
146
			Shell shell = control.getShell();
147
			Object data = shell.getData();
148
			if (data instanceof WizardDialog) {
149
				// in wizard
150
				WizardDialog wd = (WizardDialog) data;
151
				IWizardPage page = wd.getCurrentPage();
152
				if (page == null)
153
					return null;
154
				// check for wizard buttons
155
				if (control instanceof Button
156
						&& MacroUtil.onWizardDialog(wd, (Button) control)) {
157
					return wd;
158
				}
159
				// wizard page related
160
				else {
161
					return page;
162
				}
163
			} else if (data instanceof IWorkbenchWindow) {
164
				IWorkbenchWindow window = (IWorkbenchWindow) data;
165
				IWorkbenchPage page = window.getActivePage();
166
167
				/**
168
				 * Ali M.: Under some situations, the part that is returned by
169
				 * the 'getActivePart' method is the old active part. Although
170
				 * the control object is coming from the newly active part, the
171
				 * part that is retrieved below will be from the old active
172
				 * part. This will cause MacroUtil.getControlIdentifier to
173
				 * return null when attempting to retrieve the widget id in the
174
				 * wrong context. One situation that this fails under is when: -
175
				 * Macro recorder start while the test suite editor is active -
176
				 * A hook is inserted - The package view is focused (not
177
				 * activated and focused but just focused)
178
				 * 
179
				 * To resolve this issue, I have registered a part listener when
180
				 * the client starts recording. When there is a new active part
181
				 * detected, an event is created and fired to the usual onEvent
182
				 * handler in MacroManager. See MacroManager.hookPartListener.
183
				 */
184
				IWorkbenchPart part = page.getActivePart();
185
				if (part instanceof IViewPart || part instanceof IEditorPart) {
186
					return part;
187
				} else {
188
					return null;
189
				}
190
			} else {
191
				// an arbitrary control on a shell
192
				return shell;
193
			}
194
		}
195
		return null;
196
	}
197
198
	/**
199
	 * {@inheritDoc}
200
	 * 
201
	 * @see org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObject#getUIObject()
202
	 */
203
	public IUIObject getUIObject() {
204
		return uiObject;
205
	}
206
207
	/**
208
	 * {@inheritDoc}
209
	 * 
210
	 * @see org.eclipse.tptp.test.auto.gui.internal.macroobject.IMacroObject#getContext()
211
	 */
212
	public Object getContext() {
213
		return context;
214
	}
215
216
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macro/EventConstants.java (+28 lines)
Added Link Here
1
/**********************************************************************
2
 * Copyright (c) {2008} Alexander Nyssen and others.
3
 * All rights reserved. This content is made available under 
4
 * the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html        
7
 * $Id$
8
 *
9
 * Contributors:
10
 * Alexander Nyssen - Initial contribution
11
 **********************************************************************/ 
12
package org.eclipse.tptp.test.auto.gui.internal.macro;
13
14
15
/**
16
 * @author Alexander Nyssen
17
 */
18
public interface EventConstants {
19
20
	/* Custom event types */
21
	/* Indicates that a workbnech part has been closed */
22
	public static final int EVENT_TYPE__WORKBENCH_PART_CLOSED = -1;
23
	
24
	/* Custom event details */
25
	public static final int EVENT_DETAIL__POSITION_BASED_EVENT = Integer.MIN_VALUE;
26
	
27
	public static final int EVENT_DETAIL__VERIFICATION_HOOK_INSERTION_EVENT = Integer.MIN_VALUE + 1;
28
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/util/XMLDefaultHandler.java (+166 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2003, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.util;
12
13
import java.util.Hashtable;
14
import java.util.Stack;
15
16
import javax.xml.parsers.DocumentBuilderFactory;
17
import javax.xml.parsers.ParserConfigurationException;
18
19
import org.w3c.dom.Element;
20
import org.w3c.dom.Node;
21
import org.w3c.dom.Text;
22
import org.xml.sax.Attributes;
23
import org.xml.sax.Locator;
24
import org.xml.sax.helpers.DefaultHandler;
25
26
public class XMLDefaultHandler extends DefaultHandler
27
{
28
29
	private org.w3c.dom.Document fDocument;
30
31
	private Locator fLocator;
32
33
	private Hashtable fLineTable;
34
35
	private Element fRootElement;
36
37
	private Stack fElementStack = new Stack();
38
	
39
	/* Indicates whether a CDATA section is reached */
40
	private boolean cdataStarted;
41
42
	public XMLDefaultHandler()
43
	{
44
		fLineTable = new Hashtable();
45
	}
46
47
	public void startElement(String uri, String localName, String qName, Attributes attributes)
48
	{
49
		Element element = fDocument.createElement(qName);
50
		for (int i = 0; i < attributes.getLength(); i++)
51
		{
52
			element.setAttribute(attributes.getQName(i), attributes.getValue(i));
53
		}
54
55
		Integer lineNumber = new Integer(fLocator.getLineNumber());
56
		Integer[] range = new Integer[] { lineNumber, new Integer(-1) };
57
		fLineTable.put(element, range);
58
		if (fRootElement == null)
59
			fRootElement = element;
60
		else
61
			((Element) fElementStack.peek()).appendChild(element);
62
		fElementStack.push(element);
63
	}
64
65
	public void endElement(String uri, String localName, String qName)
66
	{
67
		Integer[] range = (Integer[]) fLineTable.get(fElementStack.pop());
68
		range[1] = new Integer(fLocator.getLineNumber());
69
	}
70
71
	/*
72
	 * (non-Javadoc)
73
	 * 
74
	 * @see org.xml.sax.helpers.DefaultHandler#setDocumentLocator(org.xml.sax.Locator)
75
	 */
76
	public void setDocumentLocator(Locator locator)
77
	{
78
		fLocator = locator;
79
	}
80
81
	/*
82
	 * (non-Javadoc)
83
	 * 
84
	 * @see org.xml.sax.helpers.DefaultHandler#startDocument()
85
	 */
86
	public void startDocument()
87
	{
88
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
89
		try
90
		{
91
			fDocument = factory.newDocumentBuilder().newDocument();
92
		}
93
		catch (ParserConfigurationException e)
94
		{
95
		}
96
	}
97
98
	/*
99
	 * (non-Javadoc)
100
	 * 
101
	 * @see org.xml.sax.helpers.DefaultHandler#endDocument()
102
	 */
103
	public void endDocument()
104
	{
105
		fDocument.appendChild(fRootElement);
106
	}
107
108
	/*
109
	 * (non-Javadoc)
110
	 * 
111
	 * @see org.xml.sax.helpers.DefaultHandler#processingInstruction(java.lang.String,
112
	 *      java.lang.String)
113
	 */
114
	public void processingInstruction(String target, String data)
115
	{
116
		fDocument.appendChild(fDocument.createProcessingInstruction(target, data));
117
	}
118
119
	/*
120
	 * (non-Javadoc)
121
	 * 
122
	 * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int)
123
	 */
124
	public void characters(char[] characters, int start, int length)
125
	{
126
		StringBuffer buff = new StringBuffer();
127
		for (int i = 0; i < length; i++)
128
		{
129
			buff.append(characters[start + i]);
130
		}
131
132
		String buffValue = buff.toString();	
133
		boolean isBufferJustWhiteSpace = buffValue.trim().equals("");
134
		boolean isBufferEmpty = buffValue.length() <= 0;
135
		
136
		if ((cdataStarted && isBufferEmpty) || (!cdataStarted && isBufferJustWhiteSpace))
137
		{
138
			cdataStarted = false;
139
			return;
140
		}
141
				
142
		Text text = fDocument.createTextNode(buffValue);
143
		cdataStarted = true;
144
		if (fRootElement == null)
145
			fDocument.appendChild(text);
146
		else
147
			((Element) fElementStack.peek()).appendChild(text);
148
	}
149
	
150
	public Node getDocumentElement()
151
	{
152
		fDocument.getDocumentElement().normalize();
153
		return fDocument.getDocumentElement();
154
	}
155
156
	public org.w3c.dom.Document getDocument()
157
	{
158
		fDocument.getDocumentElement().normalize();
159
		return fDocument;
160
	}
161
162
	public Hashtable getLineTable()
163
	{
164
		return fLineTable;
165
	}
166
}
(-)src/org/eclipse/tptp/test/auto/gui/internal/macroobject/MacroObjectIdentifier.java (+150 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.tptp.test.auto.gui.internal.macroobject;
12
13
import org.eclipse.core.runtime.Path;
14
import org.eclipse.tptp.test.auto.gui.internal.macro.MacroConstants;
15
import org.eclipse.tptp.test.auto.gui.internal.uiobject.IUIObjectIdentifier;
16
import org.eclipse.tptp.test.auto.gui.internal.uiobject.PrimitiveUIObjectIdentifier;
17
18
/**
19
 * Used as an identifier for Macro objects.
20
 * 
21
 * @author Alexander Nyssen
22
 */
23
public class MacroObjectIdentifier implements IMacroObjectIdentifier {
24
25
	/** The context id */
26
	private String contextId;
27
28
	/** The ui object id */
29
	private IUIObjectIdentifier uiObjectIdentifier;
30
31
	/**
32
	 * Constructor
33
	 * 
34
	 * @param contextId
35
	 *            The context id
36
	 * @param uiObjectId
37
	 *            The widget id
38
	 */
39
	public MacroObjectIdentifier(String contextId,
40
			IUIObjectIdentifier uiObjectIdentifier) {
41
		this.contextId = contextId;
42
		this.uiObjectIdentifier = uiObjectIdentifier;
43
	}
44
45
	/**
46
	 * An object in question is equalled to this object iff the object is of the
47
	 * same type and the context and the widget ids are the same.
48
	 * 
49
	 * @param object
50
	 *            The object in question
51
	 * 
52
	 * @return A boolean indicating whether object is equalled to this object or
53
	 *         not.
54
	 */
55
	public boolean equals(Object object) {
56
		if (object == null)
57
			return false;
58
		if (object == this)
59
			return true;
60
		if (object instanceof MacroObjectIdentifier) {
61
			MacroObjectIdentifier wid = (MacroObjectIdentifier) object;
62
			return wid.contextId.equals(contextId)
63
					&& uiObjectIdentifier.getWidgetId().equals(
64
							wid.getObjectIdentifier().getWidgetId());
65
		}
66
		return false;
67
	}
68
69
	/**
70
	 * Returns the context id of this identifier
71
	 * 
72
	 * @return The context id
73
	 */
74
	public String getContextIdentifier() {
75
		return contextId.toString();
76
	}
77
78
	public IUIObjectIdentifier getObjectIdentifier() {
79
		return uiObjectIdentifier;
80
	}
81
82
	public static IMacroObjectIdentifier deserializeMacroObjectIdentifier(
83
			String macroObjectIdentifierString) {
84
85
		// 1) retrieve the context, object and resolver id
86
		// first retrieve the resolver id
87
		String resolverId = null;
88
		if (macroObjectIdentifierString
89
				.indexOf(MacroConstants.RESOLVER_ID_SUFFIX_SEPARATOR) >= 0) {
90
			resolverId = macroObjectIdentifierString
91
					.substring(macroObjectIdentifierString
92
							.lastIndexOf(MacroConstants.RESOLVER_ID_SUFFIX_SEPARATOR) + 3);
93
			macroObjectIdentifierString = macroObjectIdentifierString
94
					.substring(
95
							0,
96
							macroObjectIdentifierString
97
									.lastIndexOf(MacroConstants.RESOLVER_ID_SUFFIX_SEPARATOR));
98
		}
99
100
		// now the object id separator
101
		String objectId = null;
102
		if (macroObjectIdentifierString
103
				.indexOf(MacroConstants.OBJECT_ID_SUFFIX_SEPARATOR) >= 0) {
104
			objectId = macroObjectIdentifierString
105
					.substring(macroObjectIdentifierString
106
							.lastIndexOf(MacroConstants.OBJECT_ID_SUFFIX_SEPARATOR) + 3);
107
			macroObjectIdentifierString = macroObjectIdentifierString
108
					.substring(
109
							0,
110
							macroObjectIdentifierString
111
									.lastIndexOf(MacroConstants.OBJECT_ID_SUFFIX_SEPARATOR));
112
		}
113
114
		// now the widget id
115
		String widgetId = macroObjectIdentifierString
116
				.substring(macroObjectIdentifierString
117
						.lastIndexOf(MacroConstants.WIDGET_ID_SUFFIX_SEPARATOR) + 3);
118
		macroObjectIdentifierString = macroObjectIdentifierString
119
				.substring(0, macroObjectIdentifierString
120
						.lastIndexOf(MacroConstants.WIDGET_ID_SUFFIX_SEPARATOR));
121
122
		// now the context id
123
		String contextId = new Path(macroObjectIdentifierString).removeTrailingSeparator().toString();
124
125
		// 2) construct a new identifier and return it
126
		IMacroObjectIdentifier macroObjectIdentifier = new MacroObjectIdentifier(
127
				contextId,
128
				new PrimitiveUIObjectIdentifier(widgetId, objectId, resolverId));
129
		return macroObjectIdentifier;
130
	}
131
132
	public static String serializeMacroObjectIdentifier(
133
			IMacroObjectIdentifier macroObjectIdentifier) {
134
		return macroObjectIdentifier.getContextIdentifier()
135
				// concat widet id
136
				+ MacroConstants.WIDGET_ID_SUFFIX_SEPARATOR
137
				+ macroObjectIdentifier.getObjectIdentifier().getWidgetId()
138
				// concat object id
139
				+ (macroObjectIdentifier.getObjectIdentifier().getObjectId() != null ? MacroConstants.OBJECT_ID_SUFFIX_SEPARATOR
140
						+ macroObjectIdentifier.getObjectIdentifier()
141
								.getObjectId()
142
						: "")
143
				// concat resolver id
144
				+ (macroObjectIdentifier.getObjectIdentifier().getResolverId() != null ? MacroConstants.RESOLVER_ID_SUFFIX_SEPARATOR
145
						+ macroObjectIdentifier.getObjectIdentifier()
146
								.getResolverId()
147
						: "");
148
	}
149
150
}

Return to bug 133099