You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by jo...@apache.org on 2016/06/03 01:44:39 UTC

deltaspike git commit: DELTASPIKE-1036 Support for returning optional when object should be a single result type.

Repository: deltaspike
Updated Branches:
  refs/heads/master 70299c16d -> b722b8f47


DELTASPIKE-1036 Support for returning optional when object should be a single result type.


Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/b722b8f4
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/b722b8f4
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/b722b8f4

Branch: refs/heads/master
Commit: b722b8f47114390359b110169630cf9045fbad45
Parents: 70299c1
Author: John D. Ament <jo...@apache.org>
Authored: Thu Jun 2 21:44:25 2016 -0400
Committer: John D. Ament <jo...@apache.org>
Committed: Thu Jun 2 21:44:25 2016 -0400

----------------------------------------------------------------------
 .../deltaspike/core/util/OptionalUtil.java      | 77 ++++++++++++++++++++
 .../deltaspike/core/util/OptionalUtilTest.java  | 65 +++++++++++++++++
 .../builder/result/QueryProcessorFactory.java   | 16 +++-
 .../impl/handler/CdiQueryInvocationContext.java | 15 +++-
 .../data/impl/meta/RepositoryMethod.java        |  7 ++
 .../deltaspike/data/impl/QueryResultTest.java   | 14 ++++
 .../data/test/service/SimpleRepository.java     |  3 +
 7 files changed, 193 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b722b8f4/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/OptionalUtil.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/OptionalUtil.java b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/OptionalUtil.java
new file mode 100644
index 0000000..9782bf7
--- /dev/null
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/OptionalUtil.java
@@ -0,0 +1,77 @@
+/*
+ * 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.deltaspike.core.util;
+
+import javax.enterprise.inject.Typed;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+@Typed()
+public abstract class OptionalUtil
+{
+    private static boolean optionalSupported = true;
+    private static Class<?> optionalClass;
+    private static Method optionalMethod;
+
+    static {
+        try
+        {
+            optionalClass = Class.forName("java.util.Optional");
+            optionalMethod = optionalClass.getMethod("ofNullable", Object.class);
+        }
+        catch (Exception e)
+        {
+            optionalSupported = false;
+            optionalClass = null;
+            optionalMethod = null;
+        }
+    }
+
+    public static boolean isOptionalSupported()
+    {
+        return optionalSupported;
+    }
+
+    public static boolean isOptionalReturned(Method method)
+    {
+        return optionalSupported && method.getReturnType().isAssignableFrom(optionalClass);
+    }
+
+    public static Object wrap(Object input)
+    {
+        if (!optionalSupported)
+        {
+            return input;
+        }
+        try
+        {
+            return optionalMethod.invoke(null, input);
+        }
+        catch (IllegalAccessException e)
+        {
+            e.printStackTrace();
+        }
+        catch (InvocationTargetException e)
+        {
+            e.printStackTrace();
+        }
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b722b8f4/deltaspike/core/api/src/test/java/org/apache/deltaspike/core/util/OptionalUtilTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/test/java/org/apache/deltaspike/core/util/OptionalUtilTest.java b/deltaspike/core/api/src/test/java/org/apache/deltaspike/core/util/OptionalUtilTest.java
new file mode 100644
index 0000000..7c76d9b
--- /dev/null
+++ b/deltaspike/core/api/src/test/java/org/apache/deltaspike/core/util/OptionalUtilTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.deltaspike.core.util;
+
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+public class OptionalUtilTest
+{
+    @Before
+    public void isEnabled()
+    {
+        Assume.assumeTrue(OptionalUtil.isOptionalSupported());
+    }
+
+    @Test
+    public void shouldIdentifyOptionalReturnType() throws Exception
+    {
+        Method empty = getOptionalClass().getMethod("empty");
+        Assert.assertTrue(OptionalUtil.isOptionalReturned(empty));
+    }
+
+    @Test
+    public void shouldReturnEmptyWhenGivenNull() throws Exception
+    {
+        Object wrapped = OptionalUtil.wrap(null);
+        Method isPresent = getOptionalClass().getMethod("isPresent");
+        Object invoke = isPresent.invoke(wrapped);
+        Assert.assertEquals(invoke, Boolean.FALSE);
+    }
+
+    @Test
+    public void shouldReturnNotEmptyWhenGivenNonnull() throws Exception
+    {
+        Object wrapped = OptionalUtil.wrap("String");
+        Method isPresent = getOptionalClass().getMethod("isPresent");
+        Object invoke = isPresent.invoke(wrapped);
+        Assert.assertEquals(invoke, Boolean.TRUE);
+    }
+
+    private static Class<?> getOptionalClass() throws ClassNotFoundException {
+        return Class.forName("java.util.Optional");
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b722b8f4/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java
index 10052f1..470cbfe 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/builder/result/QueryProcessorFactory.java
@@ -24,6 +24,7 @@ import java.util.List;
 import javax.persistence.NoResultException;
 import javax.persistence.Query;
 
+import org.apache.deltaspike.core.util.OptionalUtil;
 import org.apache.deltaspike.data.api.Modifying;
 import org.apache.deltaspike.data.api.QueryResult;
 import org.apache.deltaspike.data.api.SingleResultType;
@@ -112,6 +113,7 @@ public final class QueryProcessorFactory
         public Object executeQuery(Query query, CdiQueryInvocationContext context)
         {
             SingleResultType style = context.getSingleResultStyle();
+            Object result = null;
             switch (style)
             {
                 case JPA:
@@ -119,16 +121,24 @@ public final class QueryProcessorFactory
                 case OPTIONAL:
                     try
                     {
-                        return query.getSingleResult();
+                        result = query.getSingleResult();
                     }
                     catch (NoResultException e)
                     {
-                        return null;
                     }
+                    break;
                 default:
                     @SuppressWarnings("unchecked")
                     List<Object> queryResult = query.getResultList();
-                    return queryResult.size() > 0 ? queryResult.get(0) : null;
+                    result = queryResult.size() > 0 ? queryResult.get(0) : null;
+            }
+            if (context.isOptional())
+            {
+                return OptionalUtil.wrap(result);
+            }
+            else
+            {
+                return result;
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b722b8f4/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
index 9f032e5..1adee68 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/handler/CdiQueryInvocationContext.java
@@ -278,7 +278,15 @@ public class CdiQueryInvocationContext implements QueryInvocationContext
 
     public SingleResultType getSingleResultStyle()
     {
-        return repoMethod.getSingleResultStyle();
+        SingleResultType baseSingleResultType = repoMethod.getSingleResultStyle();
+        if (repoMethod.isOptional() && baseSingleResultType == SingleResultType.JPA)
+        {
+            return SingleResultType.OPTIONAL;
+        }
+        else
+        {
+            return baseSingleResultType;
+        }
     }
 
     public Object getProxy()
@@ -347,4 +355,9 @@ public class CdiQueryInvocationContext implements QueryInvocationContext
         }
         return false;
     }
+
+    public boolean isOptional()
+    {
+        return this.repoMethod.isOptional();
+    }
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b722b8f4/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
index 08cedd8..e349e56 100644
--- a/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
+++ b/deltaspike/modules/data/impl/src/main/java/org/apache/deltaspike/data/impl/meta/RepositoryMethod.java
@@ -32,6 +32,7 @@ import javax.persistence.LockModeType;
 import org.apache.deltaspike.core.api.provider.BeanManagerProvider;
 import org.apache.deltaspike.core.api.provider.BeanProvider;
 import org.apache.deltaspike.core.api.provider.DependentProvider;
+import org.apache.deltaspike.core.util.OptionalUtil;
 import org.apache.deltaspike.data.api.Modifying;
 import org.apache.deltaspike.data.api.Query;
 import org.apache.deltaspike.data.api.SingleResultType;
@@ -63,6 +64,7 @@ public class RepositoryMethod
     private final QueryRoot queryRoot;
     private final QueryProcessor queryProcessor;
     private final Class<? extends QueryInOutMapper<?>> mapper;
+    private final boolean isOptional;
 
     private volatile Boolean queryInOutMapperIsNormalScope;
 
@@ -75,6 +77,7 @@ public class RepositoryMethod
         this.queryRoot = initQueryRoot();
         this.queryProcessor = QueryProcessorFactory.newInstance(method, methodPrefix).build();
         this.mapper = extractMapper(method, repo);
+        this.isOptional = OptionalUtil.isOptionalReturned(this.method);
     }
 
     public boolean returns(Class<?> returnType)
@@ -247,4 +250,8 @@ public class RepositoryMethod
         return hasLockMode || method.isAnnotationPresent(Modifying.class);
     }
 
+    public boolean isOptional()
+    {
+        return this.isOptional;
+    }
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b722b8f4/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/QueryResultTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/QueryResultTest.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/QueryResultTest.java
index a42025a..b40b710 100644
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/QueryResultTest.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/impl/QueryResultTest.java
@@ -398,6 +398,20 @@ public class QueryResultTest extends TransactionalTestCase
         // no real check here, verifying query syntax passes.
         assertNotNull(result);
     }
+//    TODO Figure out a way to test this that doesn't require java 8
+//    @Test
+//    public void shouldFindbyIdOptional()
+//    {
+//        Simple simple = builder.createSimple("bob");
+//
+//        java.util.Optional<Simple> optional = repo.findById(simple.getId());
+//        assertTrue(optional.isPresent());
+//
+//        long nextId = simple.getId() + 1;
+//
+//        repo.findById(nextId);
+//        assertFalse(optional.isPresent());
+//    }
 
     @Before
     public void setup()

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/b722b8f4/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleRepository.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleRepository.java b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleRepository.java
index 977736d..7d2870f 100755
--- a/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleRepository.java
+++ b/deltaspike/modules/data/impl/src/test/java/org/apache/deltaspike/data/test/service/SimpleRepository.java
@@ -121,6 +121,9 @@ public abstract class SimpleRepository extends AbstractEntityRepository<Simple,
 
     public abstract void removeByNameAndEnabled(String name, Boolean aTrue);
 
+//    TODO Figure out a way to test this that doesn't require java 8
+//    public abstract java.util.Optional<Simple> findById(Long id);
+
     @Override
     protected abstract EntityManager entityManager();
 }