You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by lk...@apache.org on 2022/05/30 21:13:26 UTC
[netbeans] branch master updated: Added support for properties backed up by functional interfaces
This is an automated email from the ASF dual-hosted git repository.
lkishalmi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/master by this push:
new bfa926fee2 Added support for properties backed up by functional interfaces
bfa926fee2 is described below
commit bfa926fee2a7bf52574240c7981f15ba2cd57f29
Author: Laszlo Kishalmi <la...@gmail.com>
AuthorDate: Thu May 26 12:08:59 2022 -0700
Added support for properties backed up by functional interfaces
---
platform/openide.nodes/apichanges.xml | 24 ++++
.../src/org/openide/nodes/PropertySupport.java | 135 +++++++++++++++++++--
2 files changed, 147 insertions(+), 12 deletions(-)
diff --git a/platform/openide.nodes/apichanges.xml b/platform/openide.nodes/apichanges.xml
index 2c2fc5f6eb..300e1af5ec 100644
--- a/platform/openide.nodes/apichanges.xml
+++ b/platform/openide.nodes/apichanges.xml
@@ -25,6 +25,30 @@
<apidef name="nodes">Nodes API</apidef>
</apidefs>
<changes>
+ <change id="PropertySupport.FunctionalProperty">
+ <api name="nodes"/>
+ <summary>Adding static methods to PropertySupport to allow easy creation
+ of properties using functional interfaces.
+ </summary>
+ <version major="7" minor="62"/>
+ <date day="26" month="5" year="2022"/>
+ <author login="lkishalmi"/>
+ <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible"/>
+ <description>
+ <a href="@TOP@/org/openide/nodes/PropertySupport.html">PropertySupport</a>
+ received a bunch of static methods (<code>readWrite</code>, <code>readOnly</code>, and
+ <code>writeOnly</code> to allow easy property creation with <code>Supplier</code> and
+ <code>Provider</code> functional interfaces.
+ <pre>
+ Sheet.Set set = ...
+ SomeObject obj = getLookup().lookup(SomeObject.class);
+
+ set.put(PropertySupport.readWrite("name", String.class, obj::getName, obj::setName));
+ set.put(PropertySupport.readOnly("size", Long.class, obj::getSize));
+ </pre>
+ </description>
+ <class package="org.openide.nodes" name="DestroyableNodesFactory"/>
+ </change>
<change id="ChildFactory.DestroyableNodes">
<api name="nodes"/>
<summary>Adding ChildFactory.Detachable to allow ChildFactory implementations to
diff --git a/platform/openide.nodes/src/org/openide/nodes/PropertySupport.java b/platform/openide.nodes/src/org/openide/nodes/PropertySupport.java
index 3b5d42b526..a1b45fe7b2 100644
--- a/platform/openide.nodes/src/org/openide/nodes/PropertySupport.java
+++ b/platform/openide.nodes/src/org/openide/nodes/PropertySupport.java
@@ -26,13 +26,17 @@ import java.beans.PropertyEditor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle;
/** Support class for <code>Node.Property</code>.
-*
-* @author Jan Jancura, Jaroslav Tulach, Ian Formanek
-*/
+ *
+ * @param <T> the type of the represented property.
+ *
+ * @author Jan Jancura, Jaroslav Tulach, Ian Formanek
+ */
public abstract class PropertySupport<T> extends Node.Property<T> {
/** flag whether the property is readable */
private boolean canR;
@@ -62,6 +66,7 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
* Returns the value passed into constructor.
* @return <CODE>true</CODE> if the read of the value is supported
*/
+ @Override
public boolean canRead() {
return canR;
}
@@ -70,6 +75,7 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
* Returns the value passed into constructor.
* @return <CODE>true</CODE> if the read of the value is supported
*/
+ @Override
public boolean canWrite() {
return canW;
}
@@ -78,6 +84,7 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
* Like {@link Class#cast} but handles primitive types.
* See JDK #6456930.
*/
+ @SuppressWarnings("unchecked")
static <T> T cast(Class<T> c, Object o) {
if (c.isPrimitive()) {
// Could try to actually type-check it, but never mind.
@@ -87,6 +94,79 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
}
}
+ /**
+ * Fluent wrapper method for {@link #setDisplayName(java.lang.String)}.
+ *
+ * @param displayName the display name to set.
+ * @since 7.62
+ *
+ * @return this instance
+ */
+ public final PropertySupport<T> withDisplayName(String displayName) {
+ setDisplayName(displayName);
+ return this;
+ }
+
+ /**
+ * Fluent wrapper method for {@link #setShortDescription(java.lang.String)}.
+ *
+ * @param shortDescription short description
+ * @since 7.62
+ * @return this instance
+ */
+ public final PropertySupport<T> withShortDescription(String shortDescription) {
+ setShortDescription(shortDescription);
+ return this;
+ }
+
+ /**
+ * Creates a "virtual" property where getter and setter are backed by the
+ * provided {@link Supplier} and {@link Consumer} functional interfaces.
+ * @param <T> the type of the property
+ * @param name the name of the property
+ * @param valueType the type of the property
+ * @param supplier the getter functional interface, can be {@code null} for write-only properties.
+ * @param consumer the setter functional interface, can be {@code null} for read-only properties.
+ *
+ * @since 7.62
+ * @return a {@link PropertySupport} instance where getter and setter are
+ * backed by the provided functional interfaces.
+ */
+ public static <T> PropertySupport<T> readWrite(String name, Class<T> valueType, Supplier<T> supplier, Consumer<T> consumer) {
+ return new FunctionalProperty<>(name, valueType, supplier, consumer);
+ }
+
+ /**
+ * Creates a read-only "virtual" property where getter is backed by the
+ * provided {@link Supplier} functional interface.
+ * @param <T> the type of the property
+ * @param name the name of the property
+ * @param valueType the type of the property
+ * @param supplier the getter functional interface.
+ *
+ * @since 7.62
+ * @return a read-only {@link PropertySupport} instance where getter is
+ * backed by the provided functional interface.
+ */
+ public static <T> PropertySupport<T> readOnly(String name, Class<T> valueType, Supplier<T> supplier) {
+ return new FunctionalProperty<>(name, valueType, supplier, null);
+ }
+ /**
+ * Creates a write-only "virtual" property where setter is backed by the
+ * provided {@link Consumer} functional interface.
+ * @param <T> the type of the property
+ * @param name the name of the property
+ * @param valueType the type of the property
+ * @param consumer the setter functional interface.
+ *
+ * @since 7.62
+ * @return a write-only {@link PropertySupport} instance where setter is
+ * backed by the provided functional interface.
+ */
+ public static <T> PropertySupport<T> writeOnly(String name, Class<T> valueType, Consumer<T> consumer) {
+ return new FunctionalProperty<>(name, valueType, null, consumer);
+ }
+
/**
* Support for properties from Java Reflection.
* Since 7.19, the {@link FeatureDescriptor#getName} will be set automatically.
@@ -213,7 +293,7 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
}
// Finds the proper getter
- private static Method findGetter(Object instance, Class valueType, String property)
+ private static Method findGetter(Object instance, Class<?> valueType, String property)
throws NoSuchMethodException {
NoSuchMethodException nsme;
@@ -273,7 +353,7 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
}
} catch (IllegalArgumentException iae) {
//Provide a better message for debugging
- StringBuffer sb = new StringBuffer("Attempted to invoke method ");
+ StringBuilder sb = new StringBuilder("Attempted to invoke method ");
sb.append(getter.getName());
sb.append(" from class ");
sb.append(getter.getDeclaringClass().getName());
@@ -288,6 +368,7 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
/* Can write the value of the property.
* @return <CODE>true</CODE> if the read of the value is supported
*/
+ @Override
public boolean canWrite() {
return setter != null;
}
@@ -298,6 +379,7 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
* @exception IllegalArgumentException wrong argument
* @exception InvocationTargetException an exception during invocation
*/
+ @Override
public void setValue(T val)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
if (setter == null) {
@@ -322,14 +404,13 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
* @return the property editor or <CODE>null</CODE> if there should not be
* any editor.
*/
+ @Override
public PropertyEditor getPropertyEditor() {
if (propertyEditorClass != null) {
try {
- return propertyEditorClass.newInstance();
- } catch (InstantiationException ex) {
+ return propertyEditorClass.getDeclaredConstructor().newInstance();
+ } catch (ReflectiveOperationException | SecurityException | IllegalArgumentException ex) {
Exceptions.printStackTrace(ex);
- } catch (IllegalAccessException iex) {
- Exceptions.printStackTrace(iex);
}
}
@@ -360,6 +441,35 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
}
}
+ private static final class FunctionalProperty<T> extends PropertySupport<T> {
+ private final Supplier<T> supplier;
+ private final Consumer<T> consumer;
+
+ public FunctionalProperty(String name, Class<T> type, Supplier<T> supplier, Consumer<T> consumer) {
+ super(name, type, null, null, supplier != null, consumer != null);
+ this.supplier = supplier;
+ this.consumer = consumer;
+ }
+
+ @Override
+ public T getValue() throws IllegalAccessException {
+ if (supplier != null) {
+ return supplier.get();
+ } else {
+ throw new IllegalAccessException("Cannod read from WriteOnly property"); // NOI18N
+ }
+ }
+
+ @Override
+ public void setValue(T val) throws IllegalAccessException {
+ if (consumer != null) {
+ consumer.accept(val);
+ } else {
+ throw new IllegalAccessException("Cannot write to ReadOnly property"); // NOI18N
+ }
+ }
+ }
+
/** A simple read-only property.
* Subclasses should implement {@link #getValue}.
*/
@@ -424,9 +534,8 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
* @param node the node
*/
public Name(final Node node) {
- this(
- node, NbBundle.getBundle(PropertySupport.class).getString("CTL_StandardName"),
- NbBundle.getBundle(PropertySupport.class).getString("CTL_StandardHint")
+ this(node, NbBundle.getMessage(PropertySupport.class, "CTL_StandardName"),
+ NbBundle.getMessage(PropertySupport.class, "CTL_StandardHint")
);
}
@@ -443,6 +552,7 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
/* Getter for the value. Delegates to Node.getName().
* @return the name
*/
+ @Override
public String getValue() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
return node.getName();
}
@@ -450,6 +560,7 @@ public abstract class PropertySupport<T> extends Node.Property<T> {
/* Setter for the value. Delegates to Node.setName().
* @param val new name
*/
+ @Override
public void setValue(String val)
throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Object oldName = node.getName();
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists