You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jdo-commits@db.apache.org by ti...@apache.org on 2017/01/06 20:05:47 UTC
svn commit: r1777710 - in /db/jdo/trunk/tck/src/java/org/apache/jdo/tck:
pc/query/OptionalSample.java
query/jdoql/methods/SupportedOptionalMethods.java
Author: tilmannz
Date: Fri Jan 6 20:05:47 2017
New Revision: 1777710
URL: http://svn.apache.org/viewvc?rev=1777710&view=rev
Log:
Patch for JDO-751 - Support for Java 8 Optional
Added:
db/jdo/trunk/tck/src/java/org/apache/jdo/tck/pc/query/OptionalSample.java (with props)
db/jdo/trunk/tck/src/java/org/apache/jdo/tck/query/jdoql/methods/SupportedOptionalMethods.java (with props)
Added: db/jdo/trunk/tck/src/java/org/apache/jdo/tck/pc/query/OptionalSample.java
URL: http://svn.apache.org/viewvc/db/jdo/trunk/tck/src/java/org/apache/jdo/tck/pc/query/OptionalSample.java?rev=1777710&view=auto
==============================================================================
--- db/jdo/trunk/tck/src/java/org/apache/jdo/tck/pc/query/OptionalSample.java (added)
+++ db/jdo/trunk/tck/src/java/org/apache/jdo/tck/pc/query/OptionalSample.java Fri Jan 6 20:05:47 2017
@@ -0,0 +1,128 @@
+/*
+ * 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.jdo.tck.pc.query;
+
+import java.util.Date;
+import java.util.Optional;
+
+public class OptionalSample {
+ long id;
+
+ Optional<OptionalSample> optionalPC;
+
+ Optional<Date> optionalDate;
+ Optional<Integer> optionalInteger;
+ Optional<String> optionalString;
+
+
+ public long getId() {
+ return id;
+ }
+
+ public void setId(long id) {
+ this.id = id;
+ }
+
+ public Optional<OptionalSample> getOptionalPC() {
+ return optionalPC;
+ }
+
+ public void setOptionalPC(Optional<OptionalSample> opt) {
+ this.optionalPC = opt;
+ }
+
+ public Optional<Date> getOptionalDate() {
+ return optionalDate;
+ }
+
+ public void setOptionalDate(Optional<Date> opt) {
+ this.optionalDate = opt;
+ }
+
+ public Optional<Integer> getOptionalInteger() {
+ return optionalInteger;
+ }
+
+ public void setOptionalInteger(Optional<Integer> opt) {
+ this.optionalInteger = opt;
+ }
+
+ public Optional<String> getOptionalString() {
+ return optionalString;
+ }
+
+ public void setOptionalString(Optional<String> opt) {
+ this.optionalString = opt;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((optionalPC == null) ? 0 : optionalPC.hashCode());
+ result = prime * result + ((optionalString == null) ? 0 : optionalString.hashCode());
+ result = prime * result + ((optionalInteger == null) ? 0 : optionalInteger.hashCode());
+ result = prime * result + ((optionalDate == null) ? 0 : optionalDate.hashCode());
+ result = prime * result + (int) (id ^ (id >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ OptionalSample other = (OptionalSample) obj;
+ if (id != other.id)
+ return false;
+
+ if (optionalPC == null) {
+ if (other.optionalPC != null)
+ return false;
+ } else if (!optionalPC.equals(other.optionalPC))
+ return false;
+
+ if (optionalDate == null) {
+ if (other.optionalDate != null)
+ return false;
+ } else if (!optionalDate.equals(other.optionalDate))
+ return false;
+
+ if (optionalInteger == null) {
+ if (other.optionalInteger != null)
+ return false;
+ } else if (!optionalInteger.equals(other.optionalInteger))
+ return false;
+
+ if (optionalString == null) {
+ if (other.optionalString != null)
+ return false;
+ } else if (!optionalString.equals(other.optionalString))
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "id=" + id + " " + super.toString();
+ }
+}
Propchange: db/jdo/trunk/tck/src/java/org/apache/jdo/tck/pc/query/OptionalSample.java
------------------------------------------------------------------------------
svn:executable = *
Added: db/jdo/trunk/tck/src/java/org/apache/jdo/tck/query/jdoql/methods/SupportedOptionalMethods.java
URL: http://svn.apache.org/viewvc/db/jdo/trunk/tck/src/java/org/apache/jdo/tck/query/jdoql/methods/SupportedOptionalMethods.java?rev=1777710&view=auto
==============================================================================
--- db/jdo/trunk/tck/src/java/org/apache/jdo/tck/query/jdoql/methods/SupportedOptionalMethods.java (added)
+++ db/jdo/trunk/tck/src/java/org/apache/jdo/tck/query/jdoql/methods/SupportedOptionalMethods.java Fri Jan 6 20:05:47 2017
@@ -0,0 +1,574 @@
+/*
+ * 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.jdo.tck.query.jdoql.methods;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Optional;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+import javax.jdo.Transaction;
+
+import org.apache.jdo.tck.JDO_Test;
+import org.apache.jdo.tck.pc.query.OptionalSample;
+import org.apache.jdo.tck.query.QueryElementHolder;
+import org.apache.jdo.tck.query.QueryTest;
+import org.apache.jdo.tck.util.BatchTestRunner;
+
+/**
+ *<B>Title:</B> Optional Fields.
+ *<BR>
+ *<B>Keywords:</B> query
+ *<BR>
+ *<B>Assertion ID:</B> A14.6.2-9
+ *<BR>
+ *<B>Assertion Description: </B>
+ *Queries on fields of type java.util.Optional .
+ */
+public class SupportedOptionalMethods extends QueryTest {
+
+ /** */
+ private static final String ASSERTION_FAILED =
+ "Assertion A14.6.2-9 (OptionalFields) failed: ";
+
+ private static final int PC_ID = 1;
+ private static final int PC_EMPTY_ID = 3;
+ private static final int PC_NULL_ID = 4;
+ private static final int REFERENCED_PC1_ID = 88;
+ private static final int REFERENCED_PC2_ID = 99;
+ private static final String STRING = "Hello JDO";
+ private static final Integer INTEGER = 2016;
+ private static final Date DATE = new Date(1000000000);
+ private Object oidReferencedPC1;
+ private Object oidReferencedPC2;
+ private Object oidPC;
+ private Object oidEmpty;
+ private Object oidNull;
+
+ /**
+ * The <code>main</code> is called when the class
+ * is directly executed from the command line.
+ * @param args The arguments passed to the program.
+ */
+ public static void main(String[] args) {
+ BatchTestRunner.run(SupportedOptionalMethods.class);
+ }
+
+ /** */
+ public void testQueriesWithPresence() {
+ //Matches 'optionalPC.isPresent() == true'
+ checkQuery("optionalPC != null", oidPC, oidReferencedPC1);
+
+ //matches !isPresent() but does NOT match Java 'optionalPC==null'
+ checkQuery("optionalPC == null", oidEmpty, oidNull, oidReferencedPC2);
+
+ //matches isPresent()
+ checkQuery("!(optionalPC == null)", oidReferencedPC1, oidPC);
+
+ //matches !isPresent()
+ checkQuery("!(optionalPC != null)", oidReferencedPC2, oidEmpty, oidNull);
+
+ checkQuery("optionalPC.get() != null", oidPC, oidReferencedPC1);
+ checkQuery("optionalPC.get() == null", oidEmpty, oidNull, oidReferencedPC2);
+ checkQuery("optionalPC.isPresent()", oidPC, oidReferencedPC1);
+ checkQuery("!optionalPC.isPresent()", oidReferencedPC2, oidEmpty, oidNull);
+
+ //querying non-PC 'Optional' fields
+ checkOptionalForPresence("optionalString");
+ checkOptionalForPresence("optionalDate");
+ checkOptionalForPresence("optionalInteger");
+ }
+
+ private void checkOptionalForPresence(String fieldName) {
+ checkQuery(fieldName + " != null", oidPC);
+ checkQuery(fieldName + " == null",
+ oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2);
+ checkQuery("!(" + fieldName + " == null)", oidPC);
+ checkQuery("!("+ fieldName + " != null)",
+ oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2);
+
+ checkQuery(fieldName + ".get() != null", oidPC);
+ checkQuery(fieldName + ".get() == null",
+ oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2);
+ checkQuery(fieldName + ".isPresent()", oidPC);
+ checkQuery("!"+ fieldName + ".isPresent()",
+ oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2);
+ }
+
+ public void testQueriesWithNavigation() {
+ checkQuery("optionalPC.id == " + REFERENCED_PC1_ID, oidPC);
+ checkQuery("optionalPC.id != " + REFERENCED_PC1_ID, oidReferencedPC1);
+ checkQuery("!(optionalPC.id == " + REFERENCED_PC1_ID + ")", oidReferencedPC1);
+ checkQuery("optionalPC.get().id == " + REFERENCED_PC1_ID, oidPC);
+ checkQuery("optionalPC.get().id != " + REFERENCED_PC1_ID, oidReferencedPC1);
+ checkQuery("!(optionalPC.get().id == " + REFERENCED_PC1_ID + ")", oidReferencedPC1);
+ checkQuery("optionalPC.optionalPC.isPresent()", oidPC);
+
+ //The following reflects the changed behavior in JDO 3.2 in the sense that
+ //all instances are returned where either 'optionalPC.optionalPC==null' (not present)
+ //or 'optionalPC==null' (the 'null' evaluates to 'null', which is followed until it is
+ //evaluated in the 'isPresent()'). In other words, the query also returns all
+ //objects that match '!(optionalPC.isPresent())'.
+ checkQuery("!(optionalPC.optionalPC.isPresent())",
+ oidReferencedPC1, oidReferencedPC2, oidEmpty, oidNull);
+
+ //A query where 'optionalPC!=null' and 'optionalPC.optionalPC==null;
+ //can be done as follows:
+ checkQuery("optionalPC.isPresent() && !(optionalPC.optionalPC.isPresent())",
+ oidReferencedPC1);
+
+ checkQuery("optionalPC.optionalPC.id == " + REFERENCED_PC2_ID, oidPC);
+ checkQuery("optionalPC.get().optionalPC.get().id == " + REFERENCED_PC2_ID, oidPC);
+
+ //test with && operator
+ checkQuery("!(optionalPC.isPresent() && optionalPC.id == " + REFERENCED_PC1_ID + ")",
+ oidReferencedPC1, oidReferencedPC2, oidEmpty, oidNull);
+ }
+
+ private void checkQuery(String filter, Object ... resultOids) {
+ QueryElementHolder qeh = new QueryElementHolder(
+ /*UNIQUE*/ null,
+ /*RESULT*/ null,
+ /*INTO*/ null,
+ /*FROM*/ OptionalSample.class,
+ /*EXCLUDE*/ null,
+ /*WHERE*/ filter,
+ /*VARIABLES*/ null,
+ /*PARAMETERS*/ null,
+ /*IMPORTS*/ null,
+ /*GROUP BY*/ null,
+ /*ORDER BY*/ null,
+ /*FROM*/ null,
+ /*TO*/ null);
+
+ ArrayList<Object> expectedResults = new ArrayList<>();
+ Transaction tx = pm.currentTransaction();
+ try {
+ tx.begin();
+ for (int i = 0; i < resultOids.length; i++) {
+ expectedResults.add(pm.getObjectById(resultOids[i]));
+ }
+ } finally {
+ if (tx.isActive()) {
+ tx.rollback();
+ }
+ }
+
+ executeAPIQuery(ASSERTION_FAILED, qeh, expectedResults);
+ executeSingleStringQuery(ASSERTION_FAILED, qeh, expectedResults);
+ }
+
+ /**
+ * This methods tests Optional fields and parameters.
+ */
+ public void testParameterOptional() {
+ OptionalSample osReferencedPC1 = getOptionalSampleById(oidReferencedPC1);
+ String paramDecl = "java.util.Optional op";
+ checkQuery("this.optionalPC == op", paramDecl,
+ new Object[]{Optional.of(osReferencedPC1)},
+ new Object[]{oidPC});
+ checkQuery("this.optionalDate == op", paramDecl,
+ new Object[]{Optional.of(DATE)},
+ new Object[]{oidPC});
+ checkQuery("this.optionalInteger == op", paramDecl,
+ new Object[]{Optional.of(INTEGER)},
+ new Object[]{oidPC});
+ checkQuery("this.optionalString == op", paramDecl,
+ new Object[]{Optional.of(STRING)},
+ new Object[]{oidPC});
+ }
+
+ /**
+ * This methods tests Optional fields and parameters with auto
+ * de-referencing.
+ */
+ public void testParameterOptionalAutoDeref() {
+ OptionalSample osReferencedPC1 = getOptionalSampleById(oidReferencedPC1);
+ checkQuery("this.optionalPC == op",
+ OptionalSample.class.getName() + " op",
+ new Object[]{osReferencedPC1}, new Object[]{oidPC});
+ checkQuery("this.optionalDate == op",
+ "java.util.Date op",
+ new Object[]{DATE}, new Object[]{oidPC});
+ checkQuery("this.optionalInteger == op",
+ "Integer op",
+ new Object[]{INTEGER}, new Object[]{oidPC});
+ checkQuery("this.optionalString == op",
+ "String op",
+ new Object[]{STRING}, new Object[]{oidPC});
+ }
+
+ private OptionalSample getOptionalSampleById(Object id) {
+ Transaction tx = pm.currentTransaction();
+ try {
+ tx.begin();
+ return (OptionalSample) pm.getObjectById(id);
+ } finally {
+ if (tx.isActive()) {
+ tx.rollback();
+ }
+ }
+ }
+
+ /**
+ * This methods tests that empty Optional fields and parameters matches with
+ * Optional.empty().
+ */
+ public void testParameterOptionalWithEmptyFields() {
+ String paramDecl = "java.util.Optional op";
+ Object[] params = new Object[]{Optional.empty()};
+ checkQuery("this.optionalPC == op", paramDecl, params,
+ new Object[]{oidEmpty, oidNull, oidReferencedPC2});
+ checkQuery("this.optionalDate == op", paramDecl, params,
+ new Object[]{oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
+ checkQuery("this.optionalInteger == op", paramDecl, params,
+ new Object[]{oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
+ checkQuery("this.optionalString == op", paramDecl, params,
+ new Object[]{oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
+ }
+
+ /**
+ * This methods tests that Optional fields and parameters matches with
+ * (Optional)null.
+ */
+ public void testParameterOptionalWithNull() {
+ String paramDecl = "java.util.Optional op";
+ Object[] params = new Object[]{null};
+ checkQuery("this.optionalPC == op", paramDecl, params,
+ new Object[]{oidEmpty, oidNull, oidReferencedPC2});
+ checkQuery("this.optionalDate == op", paramDecl, params,
+ new Object[]{oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
+ checkQuery("this.optionalInteger == op", paramDecl, params,
+ new Object[]{oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
+ checkQuery("this.optionalString == op", paramDecl, params,
+ new Object[]{oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
+ }
+
+ /**
+ * This methods tests that Optional fields and parameters matches with
+ * (Object)null.
+ */
+ public void testParameterOptionalNull() {
+ Object[] params = new Object[]{null};
+ checkQuery("this.optionalPC == op", OptionalSample.class.getName() + " op", params,
+ new Object[]{oidEmpty, oidNull, oidReferencedPC2});
+ checkQuery("this.optionalDate == op", "java.util.Date op", params,
+ new Object[]{oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
+ checkQuery("this.optionalInteger == op", "java.lang.Integer op", params,
+ new Object[]{oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
+ checkQuery("this.optionalString == op", "java.lang.String op", params,
+ new Object[]{oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
+
+ }
+
+ /**
+ * This methods tests that Optional fields can be accessed in subqueries.
+ */
+ public void testSubqueries() {
+ String queryStr1 =
+ "SELECT FROM " + OptionalSample.class.getName() + " WHERE " +
+ "(select max(a.id) from " + OptionalSample.class.getName() + " a " +
+ "where a.optionalPC.isPresent() ) == id";
+ Object[] expectedResult1 = new Object[]{oidReferencedPC1};
+ checkSingleStringQuery(queryStr1, expectedResult1);
+
+ String queryStr2 =
+ "SELECT FROM " + OptionalSample.class.getName() + " WHERE " +
+ "(select max(a.id) from " + OptionalSample.class.getName() + " a " +
+ "where a.optionalPC.get() != null) == id";
+ Object[] expectedResult2 = new Object[]{oidReferencedPC1};
+ checkSingleStringQuery(queryStr2, expectedResult2);
+ }
+
+ /**
+ * This methods tests that Optional fields can be accessed in subqueries.
+ */
+ public void testOptionalAggregation() {
+ String clsName = OptionalSample.class.getName();
+
+ String queryStr1 = "SELECT AVG(optionalInteger) FROM " + clsName;
+ Query<?> q1 = pm.newQuery(queryStr1);
+ executeJDOQuery(ASSERTION_FAILED, q1, queryStr1, false, null, (double)INTEGER, true);
+
+ String queryStr2 = "SELECT AVG(optionalInteger.get()) FROM " + clsName;
+ Query<?> q2 = pm.newQuery(queryStr2);
+ executeJDOQuery(ASSERTION_FAILED, q2, queryStr2, false, null, (double)INTEGER, true);
+
+ //return the object whose Integer is the same as the AVG of all
+ //objects that have the Integer present.
+ String queryStrSub1 = "SELECT FROM " + clsName + " WHERE " +
+ "(select avg(a.optionalInteger) from " + clsName + " a " +
+ "where a.optionalInteger.isPresent() ) == optionalInteger";
+ Object[] expectedResult1 = new Object[]{oidPC};
+ checkSingleStringQuery(queryStrSub1, expectedResult1);
+
+ String queryStrSub2 = "SELECT FROM " + clsName + " WHERE " +
+ "(select avg(a.optionalInteger.get()) from " + clsName + " a " +
+ "where a.optionalInteger.isPresent() ) == optionalInteger";
+ Object[] expectedResult2 = new Object[]{oidPC};
+ checkSingleStringQuery(queryStrSub2, expectedResult2);
+
+ //Find all where the average is the same as the integer value itself.
+ //This returns ALL objects!!!
+ String queryStrSub3 = "SELECT FROM " + clsName + " WHERE " +
+ "(select avg(a.optionalInteger) from " + clsName + " a " +
+ " ) == optionalInteger";
+ Object[] expectedResult3 = new Object[]{oidPC};
+ checkSingleStringQuery(queryStrSub3, expectedResult3);
+ }
+
+ private void checkSingleStringQuery(String singleStringJDOQL, Object ... resultOids) {
+ ArrayList<Object> expectedResults = new ArrayList<>();
+ Transaction tx = pm.currentTransaction();
+ try {
+ tx.begin();
+ for (int i = 0; i < resultOids.length; i++) {
+ expectedResults.add(pm.getObjectById(resultOids[i]));
+ }
+ } finally {
+ if (tx.isActive())
+ tx.rollback();
+ }
+
+ Query<?> singleStringQuery = pm.newQuery(singleStringJDOQL);
+ executeJDOQuery(ASSERTION_FAILED, singleStringQuery, singleStringJDOQL,
+ false, null, expectedResults, true);
+ }
+
+ private void checkQuery(String filter, String paramDecl, Object[] params, Object[] result) {
+ QueryElementHolder qeh = new QueryElementHolder(
+ /*UNIQUE*/ null,
+ /*RESULT*/ null,
+ /*INTO*/ null,
+ /*FROM*/ OptionalSample.class,
+ /*EXCLUDE*/ null,
+ /*WHERE*/ filter,
+ /*VARIABLES*/ null,
+ /*PARAMETERS*/ paramDecl,
+ /*IMPORTS*/ null,
+ /*GROUP BY*/ null,
+ /*ORDER BY*/ null,
+ /*FROM*/ null,
+ /*TO*/ null);
+
+ ArrayList<Object> expectedResults = new ArrayList<>();
+ PersistenceManager pm = getPM();
+ Transaction tx = pm.currentTransaction();
+ try {
+ tx.begin();
+ for (int i = 0; i < result.length; i++) {
+ Object o = result[i];
+ if (o instanceof String || o instanceof Date || o instanceof Integer) {
+ expectedResults.add(o);
+ } else {
+ expectedResults.add(pm.getObjectById(result[i]));
+ }
+ }
+ } finally {
+ if (tx.isActive()) {
+ tx.rollback();
+ }
+ }
+
+ executeAPIQuery(ASSERTION_FAILED, qeh, params, expectedResults);
+ executeSingleStringQuery(ASSERTION_FAILED, qeh, params, expectedResults);
+ }
+
+
+ /**
+ * Result class for queries on OptionalSample.
+ */
+ public static class ResultInfo {
+ public long id;
+ public String optionalString;
+ public ResultInfo() {};
+ public ResultInfo(long id, String optionalString) {
+ this.id = id;
+ this.optionalString = optionalString;
+ }
+ }
+
+
+ /**
+ * Test Optional.orElse() in the SELECT clause of JDOQL queries.
+ */
+ @SuppressWarnings("unchecked")
+ public void testOrElseInSELECT() {
+ Transaction tx = pm.currentTransaction();
+ try {
+ tx.begin();
+ Query<?> q = pm.newQuery("SELECT id, optionalString.orElse('NotPresent') FROM " +
+ OptionalSample.class.getName());
+ q.setResultClass(ResultInfo.class);
+ Collection<ResultInfo> c = (Collection<ResultInfo>) q.execute();
+ if (c.size() != 5) {
+ fail(ASSERTION_FAILED, "Wrong result count: " + c.size());
+ }
+ for (ResultInfo i: c) {
+ switch ((int)i.id) {
+ case PC_ID:
+ if (!STRING.equals(i.optionalString)) {
+ fail(ASSERTION_FAILED, "Wrong string value: " + i.optionalString);
+ }
+ break;
+ case PC_EMPTY_ID:
+ case PC_NULL_ID:
+ case REFERENCED_PC1_ID:
+ case REFERENCED_PC2_ID:
+ assertEquals("NotPresent", i.optionalString);
+ break;
+ default: fail(ASSERTION_FAILED, "Wrong object id: " + i.id);
+ }
+ }
+ } finally {
+ if (tx.isActive()) {
+ tx.rollback();
+ }
+ }
+ }
+
+
+ /**
+ * This test assert that null-references are converted to Optional.empty() when
+ * loaded from the database.
+ */
+ public void testPersistenceNotNull() {
+ OptionalSample osNotNull = getOptionalSampleById(oidNull);
+
+ Transaction tx = pm.currentTransaction();
+ try {
+ tx.begin();
+
+ if (osNotNull.getOptionalDate() == null) {
+ fail(ASSERTION_FAILED, "Date field was 'null'");
+ }
+ if (osNotNull.getOptionalInteger() == null) {
+ fail(ASSERTION_FAILED, "Integer field was 'null'");
+ }
+ if (osNotNull.getOptionalPC() == null) {
+ fail(ASSERTION_FAILED, "optionalPC field was 'null'");
+ }
+ if (osNotNull.getOptionalString() == null) {
+ fail(ASSERTION_FAILED, "String field was 'null'");
+ }
+
+ if (osNotNull.getOptionalDate().isPresent()) {
+ fail(ASSERTION_FAILED, "Date field was present");
+ }
+ if (osNotNull.getOptionalInteger().isPresent()) {
+ fail(ASSERTION_FAILED, "Integer field was present");
+ }
+ if (osNotNull.getOptionalPC().isPresent()) {
+ fail(ASSERTION_FAILED, "optionalPC field was present");
+ }
+ if (osNotNull.getOptionalString().isPresent()) {
+ fail(ASSERTION_FAILED, "String field was present");
+ }
+ } finally {
+ if (tx.isActive()) {
+ tx.rollback();
+ }
+ }
+ }
+
+
+ /**
+ * @see JDO_Test#localSetUp()
+ */
+ @Override
+ protected void localSetUp() {
+ addTearDownClass(OptionalSample.class);
+ insertOptionalSample(getPM());
+ }
+
+
+ private void insertOptionalSample(PersistenceManager pm) {
+ Transaction tx = pm.currentTransaction();
+ try {
+ tx.begin();
+
+ //Create two objects that are referenced by other objects, this allows
+ //testing of navigation in queries.
+ //The referencedPC1 will be referenced by 'osPC',
+ //The referencedPC2 will be referenced by referencedPC1.
+ OptionalSample referencedPC1 = new OptionalSample();
+ referencedPC1.setId(REFERENCED_PC1_ID);
+ pm.makePersistent(referencedPC1);
+ oidReferencedPC1 = pm.getObjectId(referencedPC1);
+
+ OptionalSample referencedPC2 = new OptionalSample();
+ referencedPC2.setId(REFERENCED_PC2_ID);
+ pm.makePersistent(referencedPC2);
+ oidReferencedPC2 = pm.getObjectId(referencedPC2);
+
+ referencedPC1.setOptionalPC(Optional.of(referencedPC2));
+
+ OptionalSample osPC = new OptionalSample();
+ osPC.setId(PC_ID);
+ osPC.setOptionalPC(Optional.of(referencedPC1));
+ osPC.setOptionalDate(Optional.of(DATE));
+ osPC.setOptionalInteger(Optional.of(INTEGER));
+ osPC.setOptionalString(Optional.of(STRING));
+ pm.makePersistent(osPC);
+ oidPC = pm.getObjectId(osPC);
+
+ //use empty optionals
+ OptionalSample osEmpty = new OptionalSample();
+ osEmpty.setId(PC_EMPTY_ID);
+ osEmpty.setOptionalPC(Optional.empty());
+ osEmpty.setOptionalDate(Optional.empty());
+ osEmpty.setOptionalInteger(Optional.empty());
+ osEmpty.setOptionalString(Optional.empty());
+ pm.makePersistent(osEmpty);
+ oidEmpty = pm.getObjectId(osEmpty);
+
+ //use null for optional fields
+ OptionalSample osNull = new OptionalSample();
+ osNull.setId(PC_NULL_ID);
+ osNull.setOptionalPC(null);
+ osNull.setOptionalDate(null);
+ osNull.setOptionalInteger(null);
+ osNull.setOptionalString(null);
+ pm.makePersistent(osNull);
+ oidNull = pm.getObjectId(osNull);
+
+ tx.commit();
+ } finally {
+ if (tx.isActive()) {
+ tx.rollback();
+ }
+ }
+ }
+
+ @Override
+ protected void localTearDown() {
+ //set all references to null to allow deletion of (otherwise) referenced objects
+ Transaction tx = getPM().currentTransaction();
+ tx.begin();
+ Query<OptionalSample> q = pm.newQuery(OptionalSample.class);
+ for (OptionalSample os: q.executeList()) {
+ os.setOptionalPC(Optional.empty());
+ }
+ tx.commit();
+
+ super.localTearDown();
+ }
+
+}
Propchange: db/jdo/trunk/tck/src/java/org/apache/jdo/tck/query/jdoql/methods/SupportedOptionalMethods.java
------------------------------------------------------------------------------
svn:executable = *