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() {} - -}