You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by en...@apache.org on 2021/08/03 00:05:01 UTC

[sling-org-apache-sling-scripting-sightly-runtime] branch master updated: SLING-10678 enhance ObjectModel#resolveProperty to handle target that is (#8)

This is an automated email from the ASF dual-hosted git repository.

enorman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-runtime.git


The following commit(s) were added to refs/heads/master by this push:
     new 4535795  SLING-10678 enhance ObjectModel#resolveProperty to handle target that is (#8)
4535795 is described below

commit 4535795ec08d4e7110e8731b01b51d30e6ffd9e8
Author: Eric Norman <er...@gmail.com>
AuthorDate: Mon Aug 2 17:04:54 2021 -0700

    SLING-10678 enhance ObjectModel#resolveProperty to handle target that is (#8)
    
    an enum class
---
 pom.xml                                            | 35 +++++++++++++
 .../scripting/sightly/render/ObjectModel.java      | 57 +++++++++++++++++++++-
 .../scripting/sightly/render/ObjectModelTest.java  | 44 +++++++++++++++++
 .../sightly/render/testobjects/TestEnum2.java      | 36 ++++++++++++++
 4 files changed, 170 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index fa76f2f..4041e31 100644
--- a/pom.xml
+++ b/pom.xml
@@ -89,6 +89,41 @@
                 </configuration>
             </plugin>
         </plugins>
+        <pluginManagement>
+            <plugins>
+                <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+                <plugin>
+                    <groupId>org.eclipse.m2e</groupId>
+                    <artifactId>lifecycle-mapping</artifactId>
+                    <version>1.0.0</version>
+                    <configuration>
+                        <lifecycleMappingMetadata>
+                            <pluginExecutions>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>
+                                            com.github.spotbugs
+                                        </groupId>
+                                        <artifactId>
+                                            spotbugs-maven-plugin
+                                        </artifactId>
+                                        <versionRange>
+                                            [3.1.11,)
+                                        </versionRange>
+                                        <goals>
+                                            <goal>check</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore></ignore>
+                                    </action>
+                                </pluginExecution>
+                            </pluginExecutions>
+                        </lifecycleMappingMetadata>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
     </build>
 
     <profiles>
diff --git a/src/main/java/org/apache/sling/scripting/sightly/render/ObjectModel.java b/src/main/java/org/apache/sling/scripting/sightly/render/ObjectModel.java
index ea13772..07523c0 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/render/ObjectModel.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/render/ObjectModel.java
@@ -122,6 +122,9 @@ public final class ObjectModel {
                     resolved = ((Map) target).get(property);
                 }
                 if (resolved == null) {
+                    resolved = getEnumValue(target, propertyName);
+                }
+                if (resolved == null) {
                     resolved = getField(target, propertyName);
                 }
                 if (resolved == null) {
@@ -360,6 +363,18 @@ public final class ObjectModel {
         if (object == null) {
             return null;
         }
+
+        // special handing for enum object
+        if (object instanceof Class && ((Class<?>)object).isEnum()) {
+            Class<?> cls = (Class<?>)object;
+            if (index >= 0 && index < cls.getEnumConstants().length) {
+                //find the enum constant whose ordinal matches the requested index
+                return cls.getEnumConstants()[index];
+            } else {
+                return null;
+            }
+        }
+
         Class<?> cls = object.getClass();
         if (cls.isArray() && index >= 0 && index < Array.getLength(object)) {
             return Array.get(object, index);
@@ -382,7 +397,15 @@ public final class ObjectModel {
         if (object == null || StringUtils.isEmpty(fieldName)) {
             return null;
         }
-        Class<?> cls = object.getClass();
+
+        Class<?> cls;
+        // special handing for enum object
+        if (object instanceof Class && ((Class<?>)object).isEnum()) {
+            cls = (Class<?>)object; 
+        } else {
+            cls = object.getClass();
+        }
+
         if (cls.isArray() && "length".equals(fieldName)) {
             return Array.getLength(object);
         }
@@ -411,7 +434,13 @@ public final class ObjectModel {
         if (object == null || StringUtils.isEmpty(methodName)) {
             return null;
         }
-        Class<?> cls = object.getClass();
+        Class<?> cls;
+        // special handing for enum object
+        if (object instanceof Class && ((Class<?>)object).isEnum()) {
+            cls = (Class<?>)object; 
+        } else {
+            cls = object.getClass();
+        }
         Method method = findBeanMethod(cls, methodName);
         if (method != null) {
             try {
@@ -425,6 +454,30 @@ public final class ObjectModel {
     }
 
     /**
+     * Given an {@code object}, this method will return the value of the enum value identified by {@code valueName}.
+     *
+     * @param object    the target object
+     * @param valueName the name of the enum value
+     * @return the value of the enum or {@code null} if the enum was not found
+     */
+    public static Object getEnumValue(Object object, String valueName) {
+        if (object == null || StringUtils.isEmpty(valueName)) {
+            return null;
+        }
+        if (object instanceof Class && ((Class<?>)object).isEnum()) {
+            try {
+                @SuppressWarnings({ "unchecked", "rawtypes" })
+                Enum<?> value = Enum.valueOf((Class<Enum>)object, valueName);
+                return value;
+            } catch (IllegalArgumentException e) {
+                // not a valid enum value?
+                return null;
+            }
+        }
+        return null;
+    }
+
+    /**
      * Given a bean class and a base method name, this method will try to find a public method without parameters that is named:
      * <ol>
      *      <li>{@code baseName}</li>
diff --git a/src/test/java/org/apache/sling/scripting/sightly/render/ObjectModelTest.java b/src/test/java/org/apache/sling/scripting/sightly/render/ObjectModelTest.java
index 1ddc7b1..e24eb07 100644
--- a/src/test/java/org/apache/sling/scripting/sightly/render/ObjectModelTest.java
+++ b/src/test/java/org/apache/sling/scripting/sightly/render/ObjectModelTest.java
@@ -33,11 +33,13 @@ import java.util.Vector;
 
 import org.apache.sling.scripting.sightly.render.testobjects.Person;
 import org.apache.sling.scripting.sightly.render.testobjects.TestEnum;
+import org.apache.sling.scripting.sightly.render.testobjects.TestEnum2;
 import org.apache.sling.scripting.sightly.render.testobjects.internal.AdultFactory;
 import org.hamcrest.MatcherAssert;
 import org.hamcrest.Matchers;
 import org.junit.Test;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -238,6 +240,35 @@ public class ObjectModelTest {
 
     }
 
+    /**
+     * Verify that values of an enumeration can be resolved
+     * by their name
+     */
+    @Test
+    public void testResolvePropertyFromEnum() {
+        assertEquals(TestEnum2.ONE, ObjectModel.resolveProperty(TestEnum2.class, "ONE"));
+        assertEquals(TestEnum2.TWO, ObjectModel.resolveProperty(TestEnum2.class, "TWO"));
+        assertNull(ObjectModel.resolveProperty(TestEnum.class, "INVALID"));
+
+        assertEquals("Expected to be able to access public static final constants.",
+                TestEnum2.STR_CONSTANT,
+                ObjectModel.resolveProperty(TestEnum2.class, "STR_CONSTANT"));
+    }
+
+    /**
+     * Verify that values of an static method of an enumeration can be invoked
+     */
+    @Test
+    public void testResolveMethodFromEnum() {
+        Object value = ObjectModel.resolveProperty(TestEnum2.class, "values");
+        assertNotNull(value);
+        assertTrue(value.getClass().isArray());
+        assertEquals(TestEnum2.class, value.getClass().getComponentType());
+        assertArrayEquals(TestEnum2.values(), (TestEnum2[])value);
+
+        assertEquals("value from static method", ObjectModel.resolveProperty(TestEnum2.class, "someStaticMethod1"));
+    }
+
     @Test
     public void testGetIndex() {
         assertNull(ObjectModel.getIndex(null, 0));
@@ -257,6 +288,19 @@ public class ObjectModelTest {
         assertNull(ObjectModel.getIndex(stringMap, 2));
     }
 
+    /**
+     * Verify that values of an enumeration can be resolved
+     * by their ordinal value
+     */
+    @Test
+    public void testGetIndexFromEnum() {
+        assertEquals(TestEnum2.ONE, ObjectModel.getIndex(TestEnum2.class, 0));
+        Object two = ObjectModel.getIndex(TestEnum2.class, 1);
+        assertEquals(TestEnum2.TWO, two);
+        assertEquals(TestEnum2.TWO.ordinal(), ((Enum<?>)two).ordinal());
+        assertNull(ObjectModel.getIndex(TestEnum.class, 100));
+    }
+
     @Test
     public void testClassBasedMethodsForNulls() {
         assertNull(ObjectModel.getField(null, null));
diff --git a/src/test/java/org/apache/sling/scripting/sightly/render/testobjects/TestEnum2.java b/src/test/java/org/apache/sling/scripting/sightly/render/testobjects/TestEnum2.java
new file mode 100644
index 0000000..c0a4a41
--- /dev/null
+++ b/src/test/java/org/apache/sling/scripting/sightly/render/testobjects/TestEnum2.java
@@ -0,0 +1,36 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements.  See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership.  The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License.  You may obtain a copy of the License at
+ ~
+ ~   http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied.  See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
+package org.apache.sling.scripting.sightly.render.testobjects;
+
+/**
+ * Used for testing/verifying the lookup
+ * of the enum values and field constants for a 
+ * "use" object that is an enum class
+ */
+public enum TestEnum2 {
+    ONE,
+    TWO,
+    THREE;
+    
+    public static final String STR_CONSTANT = "constant1";
+
+    public static String someStaticMethod1() {
+        return "value from static method";
+    }
+}
\ No newline at end of file