Bug 574779: [ToolService] Enhance ToolCommandHandler for better data
access
Change-Id: Ied2238b50a24ee477fd05ee981e72666f91fe52d
diff --git a/jcommons/org.eclipse.statet.jcommons.util/META-INF/MANIFEST.MF b/jcommons/org.eclipse.statet.jcommons.util/META-INF/MANIFEST.MF
index 0a54b80..3f9a5a2 100644
--- a/jcommons/org.eclipse.statet.jcommons.util/META-INF/MANIFEST.MF
+++ b/jcommons/org.eclipse.statet.jcommons.util/META-INF/MANIFEST.MF
@@ -22,6 +22,5 @@
org.eclipse.statet.jcommons.status.util;version="4.5.0",
org.eclipse.statet.jcommons.string;version="4.5.0",
org.eclipse.statet.jcommons.ts.core;version="4.5.0",
- org.eclipse.statet.jcommons.ts.core.util;version="4.5.0",
org.eclipse.statet.jcommons.util;version="4.5.0"
Import-Package: org.apache.commons.logging;version="1.2.0";resolution:=optional
diff --git a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/lang/ObjectUtils.java b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/lang/ObjectUtils.java
index a2cf102..8b6b01f 100644
--- a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/lang/ObjectUtils.java
+++ b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/lang/ObjectUtils.java
@@ -304,10 +304,18 @@
@SuppressWarnings("null")
public static final Class<@Nullable Object> Nullable_Object_TYPE= Object.class;
+ public static final Class<@NonNull Object[]> NonNull_ObjectArray_TYPE= Object[].class;
+ @SuppressWarnings("null")
+ public static final Class<@Nullable Object[]> Nullable_ObjectArray_TYPE= Object[].class;
+
public static final Class<@NonNull String> NonNull_String_TYPE= String.class;
@SuppressWarnings("null")
public static final Class<@Nullable String> Nullable_String_TYPE= String.class;
+ public static final Class<@NonNull String[]> NonNull_StringArray_TYPE= String[].class;
+ @SuppressWarnings("null")
+ public static final Class<@Nullable String[]> Nullable_StringArray_TYPE= String[].class;
+
public static boolean isNull(final @Nullable Object object) {
return (object == null);
diff --git a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/BasicToolCommandData.java b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/BasicToolCommandData.java
new file mode 100644
index 0000000..cda6e8c
--- /dev/null
+++ b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/BasicToolCommandData.java
@@ -0,0 +1,121 @@
+/*=============================================================================#
+ # Copyright (c) 2021 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.jcommons.ts.core;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+
+@NonNullByDefault
+public class BasicToolCommandData implements ToolCommandData {
+
+
+ private final Map<String, ?> data;
+
+ private final Map<String, @Nullable Object> returnData= new HashMap<>();
+
+
+ public BasicToolCommandData(final Map<String, ?> data) {
+ this.data= data;
+ }
+
+ public BasicToolCommandData() {
+ this.data= Map.of();
+ }
+
+
+ @Override
+ public @Nullable Object getRawData(final String key) {
+ return this.data;
+ }
+
+ protected @Nullable Object getData(final String key) {
+ Object data= this.returnData.get(key);
+ if (data == null) {
+ data= getRawData(key);
+ }
+ return data;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <TData> @Nullable TData get(final String key, final Class<TData> type) {
+ final Object rawData= getData(key);
+ if (rawData != null) {
+ if (type.isInstance(rawData)) {
+ return (TData)rawData;
+ }
+ else {
+ final TData typedData= convert(rawData, type);
+ if (typedData == null) {
+ throw new IllegalArgumentException(String.format("Data entry '%1$s' is incompatible (%2$s).",
+ key, rawData.getClass().getName() ));
+ }
+ return typedData;
+ }
+ }
+ return null;
+ }
+
+
+ protected Map<String, @Nullable Object> getReturnData() {
+ return this.returnData;
+ }
+
+ public boolean hasReturnData() {
+ return !this.returnData.isEmpty();
+ }
+
+ @Override
+ public void setReturnData(final String key, final @Nullable Object value) {
+ this.returnData.put(key, value);
+ }
+
+ @Override
+ public void removeReturnData(final String key) {
+ this.returnData.remove(key);
+ }
+
+
+ @SuppressWarnings("unchecked")
+ public <TData> @Nullable TData convert(@Nullable Object data, final Class<TData> type) {
+ if (data != null && data.getClass().isArray()
+ && data.getClass().getComponentType().isAssignableFrom(type) ) {
+ final Object[] array= (Object[])data;
+ if (array.length == 1) {
+ data= array[0];
+ }
+ }
+ if (data == null || type.isInstance(data)) {
+ return (TData)data;
+ }
+ if (type == Integer.class) {
+ if (data instanceof Number) {
+ return (TData)Integer.valueOf(((Number)data).intValue());
+ }
+ }
+ if (type == Double.class ) {
+ if (data instanceof Number) {
+ return (TData)Double.valueOf(((Number)data).doubleValue());
+ }
+ }
+ return null;
+ }
+
+
+}
diff --git a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/ToolCommandData.java b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/ToolCommandData.java
new file mode 100644
index 0000000..1485cab
--- /dev/null
+++ b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/ToolCommandData.java
@@ -0,0 +1,155 @@
+/*=============================================================================#
+ # Copyright (c) 2021 Stephan Wahlbrink and others.
+ #
+ # This program and the accompanying materials are made available under the
+ # terms of the Eclipse Public License 2.0 which is available at
+ # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+ # which is available at https://www.apache.org/licenses/LICENSE-2.0.
+ #
+ # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+ #
+ # Contributors:
+ # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
+ #=============================================================================*/
+
+package org.eclipse.statet.jcommons.ts.core;
+
+import org.eclipse.statet.jcommons.lang.NonNull;
+import org.eclipse.statet.jcommons.lang.NonNullByDefault;
+import org.eclipse.statet.jcommons.lang.Nullable;
+
+
+/**
+ * The data for execution of tool commands by a {@link ToolCommandHandler}.
+ */
+@NonNullByDefault
+public interface ToolCommandData {
+
+
+ public static class IllegalDataException extends RuntimeException {
+
+ private static final long serialVersionUID= 1L;
+
+
+ public IllegalDataException(final String message) {
+ super(message);
+ }
+
+
+ }
+
+
+ /**
+ * Returns the raw data as provided by the tool, if available.
+ *
+ * @param key the key of the data entry.
+ * @return the data or {@code null} if not available.
+ */
+ public @Nullable Object getRawData(final String key);
+
+ /**
+ * Returns the data, if available.
+ *
+ * <p>If the {@link #getRawData(String) raw data} of the data entry is not available, the method
+ * returns {@code null}.
+ * If the raw data is available and not an instance of the requested type, the raw data is
+ * converted to the requested type. If the conversion fails, the method throws an exception.</p>
+ *
+ * @param key the key of the data entry
+ * @param type the type of the data
+ * @return the data or {@code null}
+ * @throws IllegalDataException if the data is incompatible to the required type
+ */
+ public <TData> @Nullable TData get(final String key, final Class<TData> type)
+ throws IllegalDataException;
+
+ /**
+ * Returns the data or the specified default data.
+ *
+ * <p>If the {@link #getRawData(String) raw data} of the data entry is not available, the method
+ * returns the specified default data.
+ * If the raw data is available and not an instance of the requested type, the raw data is
+ * converted to the requested type. If the conversion fails, the method throws an exception.</p>
+ *
+ * @param key the key of the data entry
+ * @param type the type of the data
+ * @param defaultData the data to return if the data entry is missing
+ * @return the data
+ * @throws IllegalDataException if the data is incompatible to the required type
+ */
+ public default <TData> TData get(final String key, final Class<TData> type,
+ final @NonNull TData defaultData)
+ throws IllegalDataException {
+ final var data= get(key, type);
+ if (data == null) {
+ return defaultData;
+ }
+ return data;
+ }
+
+ /**
+ * Returns the data.
+ *
+ * <p>If the {@link #getRawData(String) raw data} of the data entry is not available, the method
+ * throws an exception.
+ * If the raw data is available and not an instance of the requested type, the raw data is
+ * converted to the requested type. If the conversion fails, the method throws an exception.</p>
+ *
+ * @param key the key of the data entry
+ * @param type the type of the data
+ * @return the data
+ * @throws IllegalDataException if the data is missing or incompatible to the required type
+ */
+ public default <TData> TData getRequired(final String key, final Class<TData> type)
+ throws IllegalDataException {
+ final var data= get(key, type);
+ if (data == null) {
+ throw new IllegalDataException(String.format("Data entry '%1$s' is missing.",
+ key ));
+ }
+ return data;
+ }
+
+
+ public default @Nullable String getString(final String key)
+ throws IllegalDataException {
+ return get(key, String.class);
+ }
+
+ public default String getString(final String key, final String defaultData)
+ throws IllegalDataException {
+ return get(key, String.class, defaultData);
+ }
+
+ public default String getStringRequired(final String key)
+ throws IllegalDataException {
+ return getRequired(key, String.class);
+ }
+
+ public default boolean getBoolean(final String key, final boolean defaultData)
+ throws IllegalDataException {
+ return get(key, Boolean.class, defaultData);
+ }
+
+ public default boolean getBooleanRequired(final String key)
+ throws IllegalDataException {
+ return getRequired(key, Boolean.class);
+ }
+
+ public default int getInt(final String key, final int defaultData)
+ throws IllegalDataException {
+ return get(key, Integer.class, defaultData);
+ }
+
+ public default int getIntRequired(final String key)
+ throws IllegalDataException {
+ return getRequired(key, Integer.class);
+ }
+
+
+ public void setReturnData(final String key, @Nullable Object value);
+
+ public void removeReturnData(final String key);
+
+
+}
diff --git a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/ToolCommandHandler.java b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/ToolCommandHandler.java
index c461d8e..9aa7a54 100644
--- a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/ToolCommandHandler.java
+++ b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/ToolCommandHandler.java
@@ -14,8 +14,6 @@
package org.eclipse.statet.jcommons.ts.core;
-import java.util.Map;
-
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.status.ProgressMonitor;
import org.eclipse.statet.jcommons.status.Status;
@@ -39,13 +37,13 @@
* Executes the specified command
*
* @param id the ID of the command
- * @param service the tool service calling the action
- * @param data the action data for input (parameters) and output (return values)
+ * @param service the tool service calling the command
+ * @param data the command data for input (parameters) and output (return values)
* @param m the progress monitor
*
* @return the status
*/
- Status execute(final String id, final ToolService service, final Map<String, Object> data,
+ Status execute(final String id, final ToolService service, final ToolCommandData data,
final ProgressMonitor m) throws StatusException;
}
diff --git a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/util/ToolCommandHandlerUtils.java b/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/util/ToolCommandHandlerUtils.java
deleted file mode 100644
index 514bc85..0000000
--- a/jcommons/org.eclipse.statet.jcommons.util/src/org/eclipse/statet/jcommons/ts/core/util/ToolCommandHandlerUtils.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*=============================================================================#
- # Copyright (c) 2008, 2021 Stephan Wahlbrink and others.
- #
- # This program and the accompanying materials are made available under the
- # terms of the Eclipse Public License 2.0 which is available at
- # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
- # which is available at https://www.apache.org/licenses/LICENSE-2.0.
- #
- # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
- #
- # Contributors:
- # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
- #=============================================================================*/
-
-package org.eclipse.statet.jcommons.ts.core.util;
-
-import java.util.Map;
-
-
-/**
- * Utilities for implementations of {@link org.eclipse.statet.jcommons.ts.core.ToolCommandHandler}.
- */
-public class ToolCommandHandlerUtils {
-
-
- @SuppressWarnings("unchecked")
- public static <C> C getCheckedData(final Map<String, Object> data, final String name,
- final Class<C> clazz, final boolean required) {
- final Object obj= data.get(name);
- if (obj == null) {
- if (required) {
- throw new IllegalArgumentException("missing data entry: '" + name + '"');
- }
- return null;
- }
- if (!clazz.isInstance(obj)) {
- throw new IllegalArgumentException("incompatible data entry: '" + name + "' (" + obj.getClass().getName() + ")");
- }
- return (C) obj;
- }
-
- @SuppressWarnings("unchecked")
- public static <C> C getCheckedData(final Map<String, Object> data, final String name, final C defValue) {
- final Object obj= data.get(name);
- if (obj == null) {
- return defValue;
- }
- if (!defValue.getClass().isInstance(obj)) {
- throw new IllegalArgumentException("incompatible data entry: '" + name + "' (" + obj.getClass().getName() + ")");
- }
- return (C) obj;
- }
-
-
- private ToolCommandHandlerUtils() {}
-
-}