This is an automated email from the ASF dual-hosted git repository.
mattcasters pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git
The following commit(s) were added to refs/heads/main by this push:
new 4b3492db47 Issue #6974 (Code hardening against data conversion errors)
(#7038)
4b3492db47 is described below
commit 4b3492db470ebf7238605bb0f16a66cc6a1faeda
Author: Matt Casters <[email protected]>
AuthorDate: Fri Apr 24 09:20:23 2026 +0200
Issue #6974 (Code hardening against data conversion errors) (#7038)
* Issue #6974 (Code hardening against data conversion errors)
* Issue #6974 (spotless)
* Issue #6974 (avoid confusion in OpenSearch index date formats)
---
.../org/apache/hop/execution/ExecutionData.java | 28 ++--
.../apache/hop/execution/ExecutionDataBuilder.java | 8 ++
.../neo4j/execution/NeoExecutionInfoLocation.java | 30 +++-
.../OpenSearchExecutionInfoLocation.java | 22 +--
.../execution/ExecutionPerspective.java | 4 +
.../execution/PipelineExecutionViewer.java | 129 ++++-------------
.../hop/ui/hopgui/shared/BaseExecutionViewer.java | 153 +--------------------
7 files changed, 96 insertions(+), 278 deletions(-)
diff --git a/engine/src/main/java/org/apache/hop/execution/ExecutionData.java
b/engine/src/main/java/org/apache/hop/execution/ExecutionData.java
index 962341ed9b..199ffe417a 100644
--- a/engine/src/main/java/org/apache/hop/execution/ExecutionData.java
+++ b/engine/src/main/java/org/apache/hop/execution/ExecutionData.java
@@ -85,23 +85,17 @@ public class ExecutionData {
@JsonDeserialize(using = ExecutionDataSetMetaDeserializer.class)
private Map<String, ExecutionDataSetMeta> setMetaData;
+ /**
+ * A map with the set key as entry key. The values in the map are a link
between the name of the
+ * value in the row and the (conversion) error given.
+ */
+ @JsonIgnore private Map<String, Map<String, String>> dataSetErrors;
+
public ExecutionData() {
this.collectionDate = new Date();
this.dataSets = Collections.synchronizedMap(new HashMap<>());
this.setMetaData = Collections.synchronizedMap(new HashMap<>());
- }
-
- public ExecutionData(
- Date collectionDate,
- String parentId,
- String ownerId,
- Map<String, RowBuffer> dataSets,
- Map<String, ExecutionDataSetMeta> setDescriptions) {
- this.collectionDate = collectionDate;
- this.parentId = parentId;
- this.ownerId = ownerId;
- this.dataSets = dataSets;
- this.setMetaData = setDescriptions;
+ this.dataSetErrors = Collections.synchronizedMap(new HashMap<>());
}
@Override
@@ -179,7 +173,7 @@ public class ExecutionData {
/**
* Encode the rows in binary compressed and encoded format fit for inclusion
in JSON
*
- * @return
+ * @return The rows in binary Gzip Base64 encoded string format
*/
@JsonInclude
public String getRowsBinaryGzipBase64Encoded() throws IOException,
HopFileException {
@@ -245,9 +239,9 @@ public class ExecutionData {
/**
* Convert the encoded rows of data back to a list of rows
*
- * @param encodedString
- * @throws IOException
- * @throws HopFileException
+ * @param encodedString The base64 encoded binary Gzip string
+ * @throws IOException In case there was an error with the encoding
+ * @throws HopFileException In case there was a data conversion issue
*/
public void setRowsBinaryGzipBase64Encoded(String encodedString)
throws IOException, HopFileException {
diff --git
a/engine/src/main/java/org/apache/hop/execution/ExecutionDataBuilder.java
b/engine/src/main/java/org/apache/hop/execution/ExecutionDataBuilder.java
index a00787fcdd..df79b1a0d6 100644
--- a/engine/src/main/java/org/apache/hop/execution/ExecutionDataBuilder.java
+++ b/engine/src/main/java/org/apache/hop/execution/ExecutionDataBuilder.java
@@ -60,11 +60,13 @@ public final class ExecutionDataBuilder {
private String ownerId;
private Map<String, RowBuffer> dataSets;
private Map<String, ExecutionDataSetMeta> setMetaData;
+ private Map<String, Map<String, String>> dataSetErrors;
private ExecutionDataBuilder() {
this.collectionDate = new Date();
this.dataSets = Collections.synchronizedMap(new HashMap<>());
this.setMetaData = Collections.synchronizedMap(new HashMap<>());
+ this.dataSetErrors = Collections.synchronizedMap(new HashMap<>());
}
public static ExecutionDataBuilder of() {
@@ -312,6 +314,11 @@ public final class ExecutionDataBuilder {
return this;
}
+ public ExecutionDataBuilder withDataSetErrors(Map<String, Map<String,
String>> dataSetErrors) {
+ this.dataSetErrors = dataSetErrors;
+ return this;
+ }
+
public ExecutionDataBuilder withFinished(boolean finished) {
this.finished = finished;
return this;
@@ -375,6 +382,7 @@ public final class ExecutionDataBuilder {
executionData.setOwnerId(ownerId);
executionData.setDataSets(dataSets);
executionData.setSetMetaData(setMetaData);
+ executionData.setDataSetErrors(dataSetErrors);
return executionData;
}
}
diff --git
a/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/execution/NeoExecutionInfoLocation.java
b/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/execution/NeoExecutionInfoLocation.java
index 3745b2c370..964d777cb7 100644
---
a/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/execution/NeoExecutionInfoLocation.java
+++
b/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/execution/NeoExecutionInfoLocation.java
@@ -1291,6 +1291,7 @@ public class NeoExecutionInfoLocation implements
IExecutionInfoLocation {
.withDelete("r", "rel"));
// Add the new rows
//
+ int nrErrors = 0;
for (int rowNr = 1; rowNr <= rowBuffer.getBuffer().size(); rowNr++) {
Object[] row = rowBuffer.getBuffer().get(rowNr - 1);
CypherCreateBuilder builder =
@@ -1308,7 +1309,20 @@ public class NeoExecutionInfoLocation implements
IExecutionInfoLocation {
rowNr));
for (int v = 0; v < rowMeta.size(); v++) {
IValueMeta valueMeta = rowMeta.getValueMeta(v);
- builder.withValue("field" + v, valueMeta.getNativeDataType(row[v]));
+ Object valueData = null;
+ try {
+ valueData = valueMeta.getNativeDataType(row[v]);
+ } catch (Exception e) {
+ if (nrErrors++ < 10) {
+ log.logError(
+ "Data conversion error (max 10) in field "
+ + valueMeta.getName()
+ + " of data set: "
+ + setMeta,
+ e);
+ }
+ }
+ builder.withValue("field" + v, valueData);
}
execute(transaction, builder);
@@ -1410,6 +1424,7 @@ public class NeoExecutionInfoLocation implements
IExecutionInfoLocation {
"n", DP_EXECUTION_TYPE, DP_OWNER_ID, DP_FINISHED,
DP_COLLECTION_DATE));
boolean foundData = false;
boolean allFinished = true;
+ Map<String, Map<String, String>> dataSetErrors = new HashMap<>();
while (result.hasNext()) {
org.neo4j.driver.Record dataRecord = result.next();
foundData = true;
@@ -1498,13 +1513,24 @@ public class NeoExecutionInfoLocation implements
IExecutionInfoLocation {
for (int v = 0; v < rowMeta.size(); v++) {
IValueMeta valueMeta = rowMeta.getValueMeta(v);
Value value = rowsRecord.get("n.field" + v);
- row[v] = extractHopValue(valueMeta, value);
+ try {
+ row[v] = extractHopValue(valueMeta, value);
+ } catch (Exception exception) {
+ // This is usually a data conversion error because the value
data type
+ // doesn't correspond to what is described in the metadata.
+ // We keep track of the
+ //
+ Map<String, String> errorsSet =
+ dataSetErrors.computeIfAbsent(setKey, f -> new
HashMap<>());
+ errorsSet.put(valueMeta.getName(),
Const.getSimpleStackTrace(exception));
+ }
}
rowBuffer.addRow(row);
}
// Store the row buffer
//
builder.addDataSet(setKey, rowBuffer);
+ builder.withDataSetErrors(dataSetErrors);
}
}
}
diff --git
a/plugins/tech/opensearch/src/main/java/org/apache/hop/execution/opensearch/OpenSearchExecutionInfoLocation.java
b/plugins/tech/opensearch/src/main/java/org/apache/hop/execution/opensearch/OpenSearchExecutionInfoLocation.java
index 1dd2467052..f23228fefe 100644
---
a/plugins/tech/opensearch/src/main/java/org/apache/hop/execution/opensearch/OpenSearchExecutionInfoLocation.java
+++
b/plugins/tech/opensearch/src/main/java/org/apache/hop/execution/opensearch/OpenSearchExecutionInfoLocation.java
@@ -66,6 +66,7 @@ import org.json.simple.parser.JSONParser;
public class OpenSearchExecutionInfoLocation extends
BaseCachingExecutionInfoLocation
implements IExecutionInfoLocation {
public static final Class<?> PKG = OpenSearchExecutionInfoLocation.class;
+ public static final String STRICT_DATE_OPTIONAL_TIME_FORMAT = "yyyy-MM-dd
HH:mm:ss.SSS";
@GuiWidgetElement(
id = "url",
@@ -489,15 +490,20 @@ public class OpenSearchExecutionInfoLocation extends
BaseCachingExecutionInfoLoc
// This array contains the results wrapped in its own structure.
//
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
+ SimpleDateFormat sdf = new
SimpleDateFormat(STRICT_DATE_OPTIONAL_TIME_FORMAT);
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
for (Object row : dataRows) {
JSONArray dataRow = (JSONArray) row;
String id = (String) dataRow.get(0);
- Long creationEpoch = (Long) dataRow.get(1);
- Date creationDate = new Date(creationEpoch);
- ids.add(new DatedId(id, creationDate));
+ Object timestamp = dataRow.get(1);
+ if (timestamp instanceof Long creationEpoch) {
+ Date creationDate = new Date(creationEpoch);
+ ids.add(new DatedId(id, creationDate));
+ } else if (timestamp instanceof String dtString) {
+ Date creationDate = (sdf).parse(dtString);
+ ids.add(new DatedId(id, creationDate));
+ }
}
} catch (Exception e) {
throw new HopException("Error finding execution ids from OpenSearch", e);
@@ -536,7 +542,7 @@ public class OpenSearchExecutionInfoLocation extends
BaseCachingExecutionInfoLoc
"properties": {
"id" : { "type": "text"},
"name": { "type": "text"},
- "creationDate": { "type": "date", "format":
"epoch_millis||yyyy/MM/dd HH:mm:ss.SSS||strict_date_optional_time" },
+ "creationDate": { "type": "date", "format":
"epoch_millis||yyyy-MM-dd HH:mm:ss.SSS||strict_date_optional_time" },
"summary": {
"type" : "nested",
"properties": {
@@ -559,9 +565,9 @@ public class OpenSearchExecutionInfoLocation extends
BaseCachingExecutionInfoLoc
"executionState": {
"type" : "nested",
"properties": {
- "executionStartDate": { "type": "date", "format":
"epoch_millis||yyyy/MM/dd HH:mm:ss.SSS||strict_date_optional_time" },
- "executionEndDate": { "type": "date", "format":
"epoch_millis||yyyy/MM/dd HH:mm:ss.SSS||strict_date_optional_time" },
- "updateTime": { "type": "date", "format":
"epoch_millis||yyyy/MM/dd HH:mm:ss.SSS||strict_date_optional_time" },
+ "executionStartDate": { "type": "date", "format":
"epoch_millis||yyyy-MM-dd HH:mm:ss.SSS||strict_date_optional_time" },
+ "executionEndDate": { "type": "date", "format":
"epoch_millis||yyyy-MM-dd HH:mm:ss.SSS||strict_date_optional_time" },
+ "updateTime": { "type": "date", "format":
"epoch_millis||yyyy-MM-dd HH:mm:ss.SSS||strict_date_optional_time" },
"statusDescription": { "type": "text" }
}
},
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/ExecutionPerspective.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/ExecutionPerspective.java
index d0661ef604..84df59e06e 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/ExecutionPerspective.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/ExecutionPerspective.java
@@ -478,6 +478,8 @@ public class ExecutionPerspective implements
IHopPerspective, TabClosable {
Node pipelineNode =
XmlHandler.loadXmlString(execution.getExecutorXml(),
PipelineMeta.XML_TAG);
PipelineMeta pipelineMeta = new PipelineMeta(pipelineNode,
provider);
+ pipelineMeta.setName(execution.getName());
+ pipelineMeta.setFilename(execution.getFilename());
PipelineExecutionViewer viewer =
new PipelineExecutionViewer(
tabFolder, hopGui, pipelineMeta, locationName, this,
execution, executionState);
@@ -489,6 +491,8 @@ public class ExecutionPerspective implements
IHopPerspective, TabClosable {
Node workflowNode =
XmlHandler.loadXmlString(execution.getExecutorXml(),
WorkflowMeta.XML_TAG);
WorkflowMeta workflowMeta = new WorkflowMeta(workflowNode,
provider, variables);
+ workflowMeta.setName(execution.getName());
+ workflowMeta.setFilename(execution.getFilename());
WorkflowExecutionViewer viewer =
new WorkflowExecutionViewer(
tabFolder, hopGui, workflowMeta, locationName, this,
execution, executionState);
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/PipelineExecutionViewer.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/PipelineExecutionViewer.java
index 612e9e84f7..85ce4531e8 100644
---
a/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/PipelineExecutionViewer.java
+++
b/ui/src/main/java/org/apache/hop/ui/hopgui/perspective/execution/PipelineExecutionViewer.java
@@ -29,6 +29,9 @@ import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.commons.lang3.StringUtils;
import org.apache.hop.core.Const;
import org.apache.hop.core.Props;
import org.apache.hop.core.RowMetaAndData;
@@ -113,6 +116,8 @@ import org.eclipse.swt.widgets.Text;
import org.w3c.dom.Node;
@GuiPlugin(name = "i18n::PipelineExecutionViewer.Name")
+@Getter
+@Setter
public class PipelineExecutionViewer extends BaseExecutionViewer
implements IExecutionViewer, PaintListener, MouseListener {
private static final Class<?> PKG = PipelineExecutionViewer.class;
@@ -556,6 +561,10 @@ public class PipelineExecutionViewer extends
BaseExecutionViewer
// Look up the key in the metadata...
//
ExecutionData data = loadSelectedTransformData();
+ if (data == null) {
+ return;
+ }
+ Map<String, Map<String, String>> dataSetErrors = data.getDataSetErrors();
for (ExecutionDataSetMeta setMeta : data.getSetMetaData().values()) {
if (setDescription.equals(setMeta.getDescription())) {
@@ -565,6 +574,9 @@ public class PipelineExecutionViewer extends
BaseExecutionViewer
if (rowBuffer != null) {
java.util.List<ColumnInfo> columns = new ArrayList<>();
IRowMeta rowMeta = rowBuffer.getRowMeta();
+ Map<String, String> valueErrorsMap =
+ dataSetErrors.computeIfAbsent(setMeta.getSetKey(), f -> new
HashMap<>());
+
// Add a column for every
for (IValueMeta valueMeta : rowMeta.getValueMetaList()) {
ColumnInfo columnInfo =
@@ -573,6 +585,15 @@ public class PipelineExecutionViewer extends
BaseExecutionViewer
columnInfo.setValueMeta(valueMeta);
columnInfo.setToolTip(valueMeta.toStringMeta());
columnInfo.setImage(GuiResource.getInstance().getImage(valueMeta));
+
+ // Add a tooltip concerning a data conversion error, if there
are any
+ //
+ String error = valueErrorsMap.get(valueMeta.getName());
+ if (StringUtils.isNotEmpty(error)) {
+ columnInfo.setToolTip(error);
+ columnInfo.setImage(GuiResource.getInstance().getImageError());
+ }
+
columns.add(columnInfo);
}
@@ -606,6 +627,9 @@ public class PipelineExecutionViewer extends
BaseExecutionViewer
}
}
dataView.optWidth(true);
+
+ // We found the data set we'd been looking for. We can break out
of the loop.
+ //
break;
}
}
@@ -707,12 +731,6 @@ public class PipelineExecutionViewer extends
BaseExecutionViewer
super.zoomFitToScreen();
}
- @Override
- protected Point getArea() {
- org.eclipse.swt.graphics.Rectangle rect = canvas.getClientArea();
- return new Point(rect.width, rect.height);
- }
-
public void drawPipelineImage(GC swtGc, int width, int height, float
magnificationFactor) {
IGc gc = new SwtGc(swtGc, width, height, iconSize);
@@ -1059,7 +1077,7 @@ public class PipelineExecutionViewer extends
BaseExecutionViewer
if (childExecutions.isEmpty()) {
break;
}
- Execution child = childExecutions.get(0);
+ Execution child = childExecutions.getFirst();
// Don't load logging text as that can be a lot of data.
// Lazily load that when the logging text comes into focus.
@@ -1092,7 +1110,7 @@ public class PipelineExecutionViewer extends
BaseExecutionViewer
}
Execution transformExecution;
if (executions.size() == 1) {
- transformExecution = executions.get(0);
+ transformExecution = executions.getFirst();
} else {
transformExecution = selectExecution(executions);
}
@@ -1109,7 +1127,7 @@ public class PipelineExecutionViewer extends
BaseExecutionViewer
}
Execution childExecution;
if (childExecutions.size() == 1) {
- childExecution = childExecutions.get(0);
+ childExecution = childExecutions.getFirst();
} else {
childExecution = selectExecution(childExecutions);
}
@@ -1278,97 +1296,4 @@ public class PipelineExecutionViewer extends
BaseExecutionViewer
// If we're still here, return the pipeline log channel ID
return getLogChannelId();
}
-
- /**
- * Gets pipelineMeta
- *
- * @return value of pipelineMeta
- */
- public PipelineMeta getPipelineMeta() {
- return pipelineMeta;
- }
-
- /**
- * Gets execution
- *
- * @return value of execution
- */
- @Override
- public Execution getExecution() {
- return execution;
- }
-
- /**
- * Gets selectedTransform
- *
- * @return value of selectedTransform
- */
- public TransformMeta getSelectedTransform() {
- return selectedTransform;
- }
-
- /**
- * Sets selectedTransform
- *
- * @param selectedTransform value of selectedTransform
- */
- public void setSelectedTransform(TransformMeta selectedTransform) {
- this.selectedTransform = selectedTransform;
- }
-
- /**
- * Gets locationName
- *
- * @return value of locationName
- */
- @Override
- public String getLocationName() {
- return locationName;
- }
-
- /**
- * Gets selectedTransformData
- *
- * @return value of selectedTransformData
- */
- public ExecutionData getSelectedTransformData() {
- return selectedTransformData;
- }
-
- /**
- * Sets selectedTransformData
- *
- * @param selectedTransformData value of selectedTransformData
- */
- public void setSelectedTransformData(ExecutionData selectedTransformData) {
- this.selectedTransformData = selectedTransformData;
- }
-
- /**
- * Gets dataList
- *
- * @return value of dataList
- */
- public org.eclipse.swt.widgets.List getDataList() {
- return dataList;
- }
-
- /**
- * Sets dataList
- *
- * @param dataList value of dataList
- */
- public void setDataList(org.eclipse.swt.widgets.List dataList) {
- this.dataList = dataList;
- }
-
- /**
- * Gets perspective
- *
- * @return value of perspective
- */
- @Override
- public ExecutionPerspective getPerspective() {
- return perspective;
- }
}
diff --git
a/ui/src/main/java/org/apache/hop/ui/hopgui/shared/BaseExecutionViewer.java
b/ui/src/main/java/org/apache/hop/ui/hopgui/shared/BaseExecutionViewer.java
index fca9a356c4..e71411e76f 100644
--- a/ui/src/main/java/org/apache/hop/ui/hopgui/shared/BaseExecutionViewer.java
+++ b/ui/src/main/java/org/apache/hop/ui/hopgui/shared/BaseExecutionViewer.java
@@ -25,6 +25,8 @@ import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import lombok.Getter;
+import lombok.Setter;
import org.apache.hop.core.Const;
import org.apache.hop.core.gui.AreaOwner;
import org.apache.hop.core.gui.DPoint;
@@ -59,6 +61,8 @@ import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Text;
+@Getter
+@Setter
public abstract class BaseExecutionViewer extends DragViewZoomBase
implements MouseListener, MouseMoveListener {
@@ -120,11 +124,6 @@ public abstract class BaseExecutionViewer extends
DragViewZoomBase
canvas.setFocus();
}
- @Override
- protected float calculateCorrectedMagnification() {
- return (float) (magnification * PropsUi.getInstance().getZoomFactor());
- }
-
public synchronized AreaOwner getVisibleAreaOwner(int x, int y) {
for (int i = areaOwners.size() - 1; i >= 0; i--) {
AreaOwner areaOwner = areaOwners.get(i);
@@ -213,15 +212,6 @@ public abstract class BaseExecutionViewer extends
DragViewZoomBase
// don't do anything for now
}
- /**
- * Gets toolBarWidgets
- *
- * @return value of toolBarWidgets
- */
- public GuiToolbarWidgets getToolBarWidgets() {
- return toolBarWidgets;
- }
-
protected void viewMetadata(Execution execution) {
try {
// Also inflate the metadata
@@ -313,139 +303,4 @@ public abstract class BaseExecutionViewer extends
DragViewZoomBase
}
public abstract String getActiveId();
-
- /**
- * Gets perspective
- *
- * @return value of perspective
- */
- public ExecutionPerspective getPerspective() {
- return perspective;
- }
-
- /**
- * Gets areaOwners
- *
- * @return value of areaOwners
- */
- public List<AreaOwner> getAreaOwners() {
- return areaOwners;
- }
-
- /**
- * Gets locationName
- *
- * @return value of locationName
- */
- public String getLocationName() {
- return locationName;
- }
-
- /**
- * Gets execution
- *
- * @return value of execution
- */
- public Execution getExecution() {
- return execution;
- }
-
- /**
- * Gets toolBar
- *
- * @return value of toolBar
- */
- public Control getToolBar() {
- return toolBar;
- }
-
- /**
- * Sets toolBar
- *
- * @param toolBar value of toolBar
- */
- public void setToolBar(Control toolBar) {
- this.toolBar = toolBar;
- }
-
- /**
- * Sets toolBarWidgets
- *
- * @param toolBarWidgets value of toolBarWidgets
- */
- public void setToolBarWidgets(GuiToolbarWidgets toolBarWidgets) {
- this.toolBarWidgets = toolBarWidgets;
- }
-
- /**
- * Gets sash
- *
- * @return value of sash
- */
- public SashForm getSash() {
- return sash;
- }
-
- /**
- * Sets sash
- *
- * @param sash value of sash
- */
- public void setSash(SashForm sash) {
- this.sash = sash;
- }
-
- /**
- * Gets tabFolder
- *
- * @return value of tabFolder
- */
- public CTabFolder getTabFolder() {
- return tabFolder;
- }
-
- /**
- * Sets tabFolder
- *
- * @param tabFolder value of tabFolder
- */
- public void setTabFolder(CTabFolder tabFolder) {
- this.tabFolder = tabFolder;
- }
-
- /**
- * Gets lastClick
- *
- * @return value of lastClick
- */
- public Point getLastClick() {
- return lastClick;
- }
-
- /**
- * Sets lastClick
- *
- * @param lastClick value of lastClick
- */
- public void setLastClick(Point lastClick) {
- this.lastClick = lastClick;
- }
-
- /**
- * Gets executionState
- *
- * @return value of executionState
- */
- public ExecutionState getExecutionState() {
- return executionState;
- }
-
- /**
- * Sets executionState
- *
- * @param executionState value of executionState
- */
- public void setExecutionState(ExecutionState executionState) {
- this.executionState = executionState;
- }
}