/*******************************************************************************
* Copyright (c) 2004, 2010 BREDEX GmbH.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* BREDEX GmbH - initial API and implementation and/or initial documentation
*******************************************************************************/
package org.eclipse.jubula.rc.swing.listener;
import java.awt.Component;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.swing.ComboBoxEditor;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.JTextPane;
import javax.swing.JTree;
import javax.swing.text.JTextComponent;
import javax.swing.tree.TreePath;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jubula.communication.internal.message.CAPRecordedMessage;
import org.eclipse.jubula.communication.internal.message.MessageCap;
import org.eclipse.jubula.communication.internal.message.MessageParam;
import org.eclipse.jubula.communication.internal.message.RecordActionMessage;
import org.eclipse.jubula.communication.internal.message.ShowObservInfoMessage;
import org.eclipse.jubula.rc.common.AUTServer;
import org.eclipse.jubula.rc.common.Constants;
import org.eclipse.jubula.rc.common.exception.NoIdentifierForComponentException;
import org.eclipse.jubula.rc.common.logger.AutServerLogger;
import org.eclipse.jubula.rc.common.util.MatchUtil;
import org.eclipse.jubula.toolkit.enums.ValueSets.InteractionMode;
import org.eclipse.jubula.tools.internal.constants.CharacterConstants;
import org.eclipse.jubula.tools.internal.constants.StringConstants;
import org.eclipse.jubula.tools.internal.exception.CommunicationException;
import org.eclipse.jubula.tools.internal.objects.IComponentIdentifier;
import org.eclipse.jubula.tools.internal.utils.StringParsing;
import org.eclipse.jubula.tools.internal.xml.businessmodell.Action;
import org.eclipse.jubula.tools.internal.xml.businessmodell.Param;
/**
* @author BREDEX GmbH
* @created 23.08.2004
*/
public class RecordActions {
/** the logger */
private static AutServerLogger log = new AutServerLogger(
RecordListener.class);
/** parent of component */
private Component m_parent;
/** set to true if Event is Selection */
private boolean m_isSelEvent;
/** row and column of Table */
private int[] m_tableRowColumn = {0, 0};
/** map to store contents of TextComponents */
private Map<Component, String> m_map = new HashMap<Component, String>();
/** map to store logical Names */
private Map<String, IComponentIdentifier> m_logNameMap =
new HashMap<String, IComponentIdentifier>();
/** map to store technical Names */
private Map<Component, String> m_techNameMap = new
HashMap<Component, String>();
/** mouse button for popups */
private int m_popupMouseBtn = MouseEvent.BUTTON3;
/** The RecordHelper */
private RecordHelper m_recordHelper = new RecordHelper();
/**
* default constructor
*/
public RecordActions() {
// do nothing
}
/**
* contents of TextComponents
* @return map
*/
public Map<Component, String> getTextCompContent() {
return m_map;
}
/**
* contents of TextComponents
* @param map The message data
*/
public void setTextCompContent(Map<Component, String> map) {
m_map = map;
}
/**
* stores contents of TextComponents
* @param source TextComponent
* @param content content to store
*/
public void addTextCompContent(Component source, String content) {
m_map.put(source, content);
}
/**
* @return parent of Component
*/
public Component getComponentParent() {
return m_parent;
}
/**
* set to true if event is selection, false otherwise
* @param isSelEvent boolean
*/
public void setSelectionState(boolean isSelEvent) {
m_isSelEvent = isSelEvent;
}
/**
* @return true if event is selection, false otherwise
*/
public boolean isSelectionEvent() {
return m_isSelEvent;
}
/**
* set parent of Component
* @param parent Component
*/
public void setComponentParent(Component parent) {
m_parent = parent;
}
/**
* @return row and column of Component
*/
public int[] getTableRowColumn() {
return m_tableRowColumn;
}
/**
* row and column of Component
* @param row int
* @param column int
*/
public void setTableRowColumn(int row, int column) {
m_tableRowColumn[0] = row;
m_tableRowColumn[1] = column;
}
/**
* popup mouse button
* @return map
*/
public int getPopupMouseButton() {
return m_popupMouseBtn;
}
/**
* set popup mouse button
* @param popupMouseBtn popup mouse button
*/
public void setPopupMouseButton(int popupMouseBtn) {
m_popupMouseBtn = popupMouseBtn;
}
/**
* select item
* @param jlst JList
* @param id IComponentIdentifier
* @param a Action
*/
protected void selectListValues(JList jlst, IComponentIdentifier id,
Action a) {
String[] entries = m_recordHelper.getRenderedListValues(jlst);
String entr = StringConstants.EMPTY;
for (int i = 0; i < entries.length; i++) {
String item = StringParsing.maskAndSingleQuoteText(
entries[i], StringParsing.LISTCOMBOMASK);
entr = entr.concat(item);
if (i < (entries.length - 1)) {
entr = entr.concat(","); //$NON-NLS-1$
}
}
List<String> lstValues = new LinkedList<String>();
lstValues.add(entr);
lstValues.add(Constants.REC_OPERATOR);
lstValues.add(Constants.REC_SEARCH_MODE);
lstValues.add(Constants.REC_EXT_SELECTION);
String logName = createLogicalName(jlst, id);
createCAP(a, id, lstValues, logName);
}
/**
* select node by textpath
* @param jtre JTree
* @param path TreePath
* @param id IComponentIdentifier
* @param clickcount int
* @param a Action
*/
protected void selectNode(JTree jtre, TreePath path,
IComponentIdentifier id, Action a, int clickcount) {
String nodepath = m_recordHelper.treepathToTextpath(jtre, path);
int count = clickcount;
if (count < 1) {
count = 1;
}
String clCount = String.valueOf(count);
List<String> treValues = new LinkedList<String>();
treValues.add(Constants.REC_SEARCH_MODE);
treValues.add("0"); //$NON-NLS-1$
treValues.add(nodepath);
treValues.add(Constants.REC_OPERATOR);
treValues.add(clCount);
treValues.add(String.valueOf(InteractionMode.primary.rcIntValue()));
treValues.add(Constants.REC_EXT_SELECTION);
String logName = createLogicalName(jtre, id);
createCAP(a, id, treValues, logName);
}
/**
* collapse or Expand Tree
* @param jtre JTree
* @param path Treepath
* @param id IComponentIdentifier
* @param collOrExp String
*/
protected void collExpTree(JTree jtre, TreePath path,
IComponentIdentifier id, String collOrExp) {
String nodepath = null;
nodepath = m_recordHelper.treepathToTextpath(jtre, path);
Action a = m_recordHelper.compSysToAction(id, collOrExp);
java.util.List<String> treValues = new LinkedList<String>();
treValues.add(Constants.REC_SEARCH_MODE);
treValues.add("0"); //$NON-NLS-1$
treValues.add(nodepath);
treValues.add(Constants.REC_OPERATOR);
String logName = createLogicalName(jtre, id);
createCAP(a, id, treValues, logName);
}
/**
* select tab
* @param jtpn JTabbedPane
* @param id IComponentIdentifier
* @param a Action
*/
protected void selectTab(JTabbedPane jtpn, IComponentIdentifier id,
Action a) {
List<String> tpnValues = new LinkedList<String>();
String tpnTitle = StringParsing.singleQuoteText(jtpn
.getTitleAt(jtpn.getSelectedIndex()));
tpnValues.add(tpnTitle);
tpnValues.add(Constants.REC_OPERATOR);
String logName = createLogicalName(jtpn, id);
createCAP(a, id, tpnValues, logName);
}
/**
* select value
* @param jcbx JComboBox
* @param id IComponentIdentifier
* @param a Action
*/
protected void selectCbxValue(JComboBox jcbx, IComponentIdentifier id,
Action a) {
String cbxText = StringParsing.singleQuoteText(m_recordHelper
.getRenderedComboText(jcbx));
if (cbxText.equals(StringConstants.EMPTY) || cbxText == null) {
cbxText = Constants.EMPTY_ITEM;
}
List<String> cbxValues = new LinkedList<String>();
cbxValues.add(cbxText);
cbxValues.add(Constants.REC_OPERATOR);
cbxValues.add(Constants.REC_SEARCH_MODE);
String logName = createLogicalName(jcbx, id);
createCAP(a, id, cbxValues, logName);
}
/**
* select cell
* @param jtbl JTable
* @param id IComponentIdentifier
* @param clickcount int
* @param a Action
* @param mouseButton the mouse button used
*/
protected void selectTableCell(JTable jtbl, IComponentIdentifier id,
int clickcount, Action a, int mouseButton) {
int row = jtbl.getSelectedRow();
int column = jtbl.getSelectedColumn();
int count = clickcount;
if (count < 1) {
count = 1;
}
String clCount = (new Integer(count)
.toString());
String rowStr = (new Integer(row + 1)).toString();
String columnStr = (new Integer(column + 1)).toString();
List<String> tblValues = new LinkedList<String>();
tblValues.add(rowStr);
tblValues.add(MatchUtil.EQUALS);
tblValues.add(columnStr);
tblValues.add(MatchUtil.EQUALS);
tblValues.add(clCount);
tblValues.add("50"); //$NON-NLS-1$
tblValues.add("percent"); //$NON-NLS-1$
tblValues.add("50"); //$NON-NLS-1$
tblValues.add("percent"); //$NON-NLS-1$
tblValues.add(Constants.REC_EXT_SELECTION);
tblValues.add(String.valueOf(mouseButton));
String logName = createLogicalName(jtbl, id);
createCAP(a, id, tblValues, logName);
}
/**
* select MenuItem
* @param mi JMenuItem
*/
protected void selectMenuItem(JMenuItem mi) {
Component comp = mi;
boolean isMenuBarItem = false;
String logName = null;
while (comp.getParent() != null) {
if (comp.getParent() instanceof JPopupMenu) {
JPopupMenu jpm = (JPopupMenu)comp.getParent();
comp = jpm.getInvoker();
} else {
comp = comp.getParent();
}
if (comp instanceof JMenuBar) {
isMenuBarItem = true;
break;
}
if (comp instanceof JComponent
&& !(comp instanceof JMenu)) {
break;
}
}
IComponentIdentifier id = null;
Action a = new Action();
if (comp instanceof JComponent) {
String pth = m_recordHelper.getPath(mi);
List<String> parValues = new LinkedList<String>();
parValues.add(pth);
parValues.add(Constants.REC_OPERATOR);
if (isMenuBarItem) {
id = m_recordHelper.getMenuCompID();
a = m_recordHelper.compSysToAction(id, "CompSystem.SelectMenuItem"); //$NON-NLS-1$
} else {
try {
id = ComponentHandler
.getIdentifier(comp);
a = m_recordHelper.compSysToAction(id, "CompSystem.PopupSelectByTextPathNew"); //$NON-NLS-1$
logName = createLogicalName(comp, id);
parValues.add((new Integer(m_popupMouseBtn)).toString());
} catch (NoIdentifierForComponentException
nifce) {
// no identifier for the component, log this as an error
log.error("no identifier for '" + comp); //$NON-NLS-1$
}
}
if (logName != null) {
createCAP(a, id, parValues, logName);
} else {
createCAP(a, id, parValues);
}
}
}
/**
* creates CAP for KeyCominations like ENTER, BACKSPACE, SHIFT+TAB etc
* @param id IComponentIdentifier
* @param ke KeyEvent
* @param keycode int
*/
protected void keyComboApp(IComponentIdentifier id,
KeyEvent ke, int keycode) {
Action a = new Action();
a = m_recordHelper.compSysToAction(id, "CompSystem.KeyStroke"); //$NON-NLS-1$
List<String> parameterValues = new LinkedList<String>();
String modifierKey = null;
if (ke.getModifiers() == 0) {
modifierKey = "none"; //$NON-NLS-1$
} else {
modifierKey = RecordHelper.getModifierName(ke.getModifiers());
if (modifierKey != null) {
modifierKey = modifierKey.toLowerCase().replace('+', ' ');
}
}
String baseKey = null;
baseKey = RecordHelper.getKeyName(keycode);
if (baseKey == null) {
baseKey = KeyEvent.getKeyText(keycode).toUpperCase();
}
if (baseKey != null && modifierKey != null) {
parameterValues.add(modifierKey);
parameterValues.add(baseKey);
createCAP(a, id, parameterValues);
}
}
/**
* creates CAP for Click on Graphics Component
* @param id IComponentIdentifier
* @param me MouseEvent
* @param source Component
*/
protected void clickGraphComp(IComponentIdentifier id, MouseEvent me,
Component source) {
if ((source instanceof JTable
|| source instanceof JList
|| source instanceof JTree
|| source instanceof JTabbedPane)) {
clickInComponent(id, me, source);
} else {
int clickcount = me.getClickCount();
if (clickcount < 1) {
clickcount = 1;
}
String clCount = (new Integer(clickcount)
.toString());
String mbutton = (new Integer(me.getButton())
.toString());
Action a = m_recordHelper.compSysToAction(id, "CompSystem.Click"); //$NON-NLS-1$
List<String> parValues = new LinkedList<String>();
parValues.add(clCount);
parValues.add(mbutton);
String logName = createLogicalName(source, id);
createCAP(a, id, parValues, logName);
}
}
/**
* creates CAP for Click in Component
* @param id IComponentIdentifier
* @param me MouseEvent
* @param source Component
*/
protected void clickInComponent(IComponentIdentifier id, MouseEvent me,
Component source) {
int clickcount = me.getClickCount();
if (clickcount < 1) {
clickcount = 1;
}
String clCount = (new Integer(clickcount)
.toString());
String mbutton = (new Integer(me.getButton())
.toString());
Action a = m_recordHelper.compSysToAction(id, "CompSystem.ClickDirect"); //$NON-NLS-1$
Rectangle bounds = me.getComponent().getBounds();
int percentX = (int)(me.getX() / bounds.getWidth() * 100);
String percentXString = new Integer(percentX).toString();
int percentY = (int)(me.getY() / bounds.getHeight() * 100);
String percentYString = new Integer(percentY).toString();
String units = Constants.REC_UNITS;
List<String> parValues = new LinkedList<String>();
parValues.add(clCount);
parValues.add(mbutton);
parValues.add(percentXString);
parValues.add(units);
parValues.add(percentYString);
parValues.add(units);
String logName = createLogicalName(source, id);
createCAP(a, id, parValues, logName);
}
/**
* creates CAP for Actions Replace Text
* @param source Component
*/
protected void replaceText(Component source) {
Component src = source;
Component parent = getComponentParent() != null
? getComponentParent() : src.getParent();
if (parent instanceof JComboBox) {
src = parent;
}
String text = null;
boolean isEditable = false;
boolean isCbxItem = false;
boolean isSupported = true;
if (src instanceof JTextComponent) {
JTextComponent jtf = (JTextComponent)src;
text = jtf.getText();
isEditable = jtf.isEditable();
if ((source instanceof JTextArea || source instanceof JTextPane
|| source instanceof JEditorPane)
&& (text.indexOf(CharacterConstants.LINEFEED) != -1
|| text.indexOf(CharacterConstants.RETURN) != -1)) {
isSupported = false;
sendInfoMessage(Constants.REC_MULTILINE_MSG);
}
if (parent instanceof JTable) {
JTable tbl = (JTable)parent;
replaceTableText(src, tbl, text);
return;
}
}
if (src instanceof JComboBox) {
JComboBox cbx = (JComboBox)src;
isEditable = cbx.isEditable();
if (isEditable) {
ComboBoxEditor cbxEditor = cbx.getEditor();
text = cbxEditor.getItem().toString();
String[] cbxItems = m_recordHelper.getRenderedComboItems(cbx);
for (int i = 0; i < cbxItems.length; i++) {
String item = cbxItems[i];
if (item.equals(text)) {
isCbxItem = true;
}
}
} else {
return;
}
}
if (text.length() > Constants.REC_MAX_STRING_LENGTH) {
ShowObservInfoMessage infoMsg =
new ShowObservInfoMessage(Constants.REC_MAX_STRING_MSG);
try {
AUTServer.getInstance().getServerCommunicator().send(infoMsg);
} catch (CommunicationException e) {
// no log available here
}
return;
}
if (m_map.get(source) != null
&& !(text.equals(m_map.get(source).toString()))
&& isSupported && isEditable && !isCbxItem) {
m_map.put(src, text);
IComponentIdentifier id = null;
try {
id = ComponentHandler.getIdentifier(src);
Action a = new Action();
a = m_recordHelper.compSysToAction(id, "CompSystem.InputText"); //$NON-NLS-1$
List<String> parameterValues = new LinkedList<String>();
text = StringParsing.singleQuoteText(text);
parameterValues.add(text);
String logName = createLogicalName(src, id);
createCAP(a, id, parameterValues, logName);
} catch (NoIdentifierForComponentException nifce) {
// no identifier for the component, log this as an error
log.error("no identifier for '" + src); //$NON-NLS-1$
}
}
}
/**
* creates CAP for Actions Replace Text (Specified by Cell) on Table
* @param src Component
* @param tbl JTable
* @param text String
*/
private void replaceTableText(Component src, JTable tbl, String text) {
String txt = StringParsing.singleQuoteText(text);
if (!(txt.equals(m_map.get(src).toString()))) {
IComponentIdentifier id = null;
try {
id = ComponentHandler.getIdentifier(tbl);
Action a = new Action();
a = m_recordHelper.compSysToAction(id, "CompSystem.ReplaceTextInTableCellNew"); //$NON-NLS-1$
//int row = tbl.getSelectedRow();
//int column = tbl.getSelectedColumn();
int row = getTableRowColumn()[0];
int column = getTableRowColumn()[1];
String rowStr = (new Integer(row + 1)).toString();
String columnStr = (new Integer(column + 1)).toString();
List<String> parameterValues = new LinkedList<String>();
if (txt.equals(StringConstants.EMPTY) || txt == null) {
txt = "''"; //$NON-NLS-1$
}
parameterValues.add(txt);
parameterValues.add(rowStr);
parameterValues.add(columnStr);
String logName = createLogicalName(tbl, id);
createCAP(a, id, parameterValues, logName);
m_map.put(src, txt);
} catch (NoIdentifierForComponentException nifce) {
// no identifier for the component, log this as an error
log.error("no identifier for '" + tbl); //$NON-NLS-1$
}
}
}
/**
* select item
* @param window Component
* @param id IComponentIdentifier
* @param a Action
*/
protected void waitForWindow(Component window, IComponentIdentifier id,
Action a) {
String title = null;
if (window instanceof JFrame) {
JFrame jf = (JFrame)window;
title = StringParsing.singleQuoteText(jf.getTitle());
}
if (window instanceof JDialog) {
JDialog jd = (JDialog)window;
title = StringParsing.singleQuoteText(jd.getTitle());
}
if (title != null && !(title.equals(StringConstants.EMPTY))) {
String operator = Constants.REC_OPERATOR;
String delay = new Integer(Constants.REC_WAIT_DELAY).toString();
String timeout = null;
long timestamp = AUTServer.getInstance().getObservTimestamp();
if (timestamp == 0) {
timeout = new Integer(Constants.REC_WAIT_TIMEOUT).toString();
} else {
long timeoutLong = (System.currentTimeMillis() - timestamp)
+ 10000;
double timeoutDouble = (
Math.ceil(timeoutLong / 5000.0)) * 5000.0;
int timeoutInt = (int)timeoutDouble;
timeout = new Integer(timeoutInt).toString();
}
java.util.List<String> winValues = new LinkedList<String>();
winValues.add(title);
winValues.add(operator);
winValues.add(timeout);
winValues.add(delay);
createCAP(a, id, winValues);
}
}
/**
* records and executes a cap
* @param a Action
* @param id IComponentIdentifier
* @param parValues List of values
*/
private void createCAP(Action a,
IComponentIdentifier id, List<String> parValues) {
String defaultName = "default"; //$NON-NLS-1$
createCAP(a, id, parValues, defaultName);
}
/**
* records and executes a cap
* @param a Action
* @param id IComponentIdentifier
* @param parValues List of values
* @param logName Logical Name
*/
private void createCAP(Action a,
IComponentIdentifier id, List<String> parValues, String logName) {
MessageCap messageCap = new MessageCap();
// setup Action in MessageCap
messageCap.setMethod(a.getMethod());
messageCap.setAction(a);
// setup ComponentIdentifier in MessageCap
messageCap.setCi(id);
// setup parameters in MessageCap
List<String> parameterValues = parValues;
List params = a.getParams();
for (int i = 0; i < params.size(); i++) {
Param param = (Param) params.get(i);
MessageParam messageParam = new MessageParam();
messageParam.setType(param.getType());
String emptyString = StringConstants.EMPTY;
String value =
emptyString.equals(parameterValues.get(i)) ? null
: parameterValues.get(i);
messageParam.setValue(value);
messageCap.addMessageParam(messageParam);
}
if (StringUtils.isEmpty(id.getComponentName())) {
messageCap.setLogicalName(logName);
messageCap.sethasDefaultMapping(true);
}
CAPRecordedMessage capRecMessage = new CAPRecordedMessage(messageCap);
try {
RecordActionMessage message =
new RecordActionMessage(capRecMessage);
AUTServer.getInstance().getServerCommunicator().send(message);
} catch (CommunicationException e) {
log.error(e.getLocalizedMessage(), e);
}
AUTServer.getInstance().setObservTimestamp(System.currentTimeMillis());
}
/**
* creates logical name for component
* @param c Component
* @param id IComponentIdentifier
* @return logical Name
*/
private String createLogicalName(Component c, IComponentIdentifier id) {
String logName = m_techNameMap.get(c);
if (logName == null) {
logName = m_recordHelper.generateLogicalName(c, id);
if (logName != null) {
IComponentIdentifier id2 =
m_logNameMap.get(logName);
if (m_logNameMap.containsKey(logName)) {
if (!(m_recordHelper.isCiEqual(id, id2))) {
Collection<String> col = m_techNameMap.values();
Iterator<String> it = col.iterator();
int counter = 0;
while (it.hasNext()) {
String name = it.next();
if (name.equals(logName)
|| name.equals(
logName + "_" + (counter + 1))) { //$NON-NLS-1$
counter++;
}
}
logName = logName + "_" + counter; //$NON-NLS-1$
}
}
m_logNameMap.put(logName, id);
m_techNameMap.put(c, logName);
}
}
return logName;
}
/**
* send info Message to Observation Console
* @param info String info Message
*/
private void sendInfoMessage(String info) {
ShowObservInfoMessage infoMsg =
new ShowObservInfoMessage(info);
try {
AUTServer.getInstance().getServerCommunicator().send(infoMsg);
} catch (CommunicationException e) {
// no log available here
}
}
}