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 mb...@apache.org on 2017/05/31 21:20:07 UTC

svn commit: r1797113 - in /db/jdo/trunk/tck/src: conf/query.conf java/org/apache/jdo/tck/query/api/SampleQueries.java testdata/org/apache/jdo/tck/pc/company/companyForSampleQueriesTest.xml

Author: mbo
Date: Wed May 31 21:20:07 2017
New Revision: 1797113

URL: http://svn.apache.org/viewvc?rev=1797113&view=rev
Log:
JDO-761: Add TCK test running sample queries from the spec

Added:
    db/jdo/trunk/tck/src/java/org/apache/jdo/tck/query/api/SampleQueries.java
    db/jdo/trunk/tck/src/testdata/org/apache/jdo/tck/pc/company/companyForSampleQueriesTest.xml
Modified:
    db/jdo/trunk/tck/src/conf/query.conf

Modified: db/jdo/trunk/tck/src/conf/query.conf
URL: http://svn.apache.org/viewvc/db/jdo/trunk/tck/src/conf/query.conf?rev=1797113&r1=1797112&r2=1797113&view=diff
==============================================================================
--- db/jdo/trunk/tck/src/conf/query.conf (original)
+++ db/jdo/trunk/tck/src/conf/query.conf Wed May 31 21:20:07 2017
@@ -52,6 +52,7 @@ org.apache.jdo.tck.query.api.NewQueryWit
 org.apache.jdo.tck.query.api.NewQueryWithSpecifiedLanguageAndQuery \
 org.apache.jdo.tck.query.api.NewQuerySingleString \
 org.apache.jdo.tck.query.api.QueryExtentions \
+org.apache.jdo.tck.query.api.SampleQueries \
 org.apache.jdo.tck.query.api.SaveAsNamedQuery \
 org.apache.jdo.tck.query.api.SetCandidateCollection \
 org.apache.jdo.tck.query.api.SetCandidateExtent \

Added: db/jdo/trunk/tck/src/java/org/apache/jdo/tck/query/api/SampleQueries.java
URL: http://svn.apache.org/viewvc/db/jdo/trunk/tck/src/java/org/apache/jdo/tck/query/api/SampleQueries.java?rev=1797113&view=auto
==============================================================================
--- db/jdo/trunk/tck/src/java/org/apache/jdo/tck/query/api/SampleQueries.java (added)
+++ db/jdo/trunk/tck/src/java/org/apache/jdo/tck/query/api/SampleQueries.java Wed May 31 21:20:07 2017
@@ -0,0 +1,1370 @@
+package org.apache.jdo.tck.query.api;
+
+import org.apache.jdo.tck.JDO_Test;
+import org.apache.jdo.tck.pc.company.CompanyModelReader;
+import org.apache.jdo.tck.pc.company.Department;
+import org.apache.jdo.tck.pc.company.Employee;
+import org.apache.jdo.tck.pc.company.FullTimeEmployee;
+import org.apache.jdo.tck.pc.company.Person;
+import org.apache.jdo.tck.query.QueryTest;
+import org.apache.jdo.tck.util.BatchTestRunner;
+import org.apache.jdo.tck.util.EqualityHelper;
+
+import javax.jdo.Query;
+import javax.jdo.Transaction;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *<B>Title:</B> SampleQueries
+ *<BR>
+ *<B>Keywords:</B> query
+ *<BR>
+ *<B>Assertion IDs:</B> 
+ *<BR>
+ *<B>Assertion Description: </B>
+ * This test class runs the example queries from the JDO specification.
+ */
+public class SampleQueries extends QueryTest {
+
+    /** */
+    private static final String ASSERTION_FAILED = "Assertion (SampleQueries) failed: ";
+
+    /** */
+    private static final String SAMPLE_QUERIES_TEST_COMPANY_TESTDATA =
+            "org/apache/jdo/tck/pc/company/companyForSampleQueriesTest.xml";
+
+    /**
+     * 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(SampleQueries.class);
+    }
+
+    /**
+     * Basic query.
+     *
+     * This query selects all Employee instances from the candidate collection where
+     * the salary is greater than the constant 30000.
+     * Note that the float value for salary is unwrapped for the comparison with the
+     * literal int value, which is promoted to float using numeric promotion.
+     * If the value for the salary field in a candidate instance isnull, then it cannot
+     * be unwrapped for the comparison, and the candidate instance is rejected.
+     */
+    public void testQuery01a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select where salary > 30000";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "salary > 30000");
+            List<FullTimeEmployee> emps = (List<FullTimeEmployee>)q.execute();
+            List<FullTimeEmployee> expected =
+                    getTransientCompanyModelInstancesAsList(new String[] {"emp1", "emp2", "emp5"});
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, emps, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Basic query.
+     *
+     * This query selects all Employee instances from the candidate collection where
+     * the salary is greater than the constant 30000.
+     * Note that the float value for salary is unwrapped for the comparison with the
+     * literal int value, which is promoted to float using numeric promotion.
+     * If the value for the salary field in a candidate instance isnull, then it cannot
+     * be unwrapped for the comparison, and the candidate instance is rejected.
+     */
+    public void testQuery01b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select where salary > 30000";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "salary > 30000");
+            List<FullTimeEmployee> emps = q.executeList();
+            List<FullTimeEmployee> expected =
+                    getTransientCompanyModelInstancesAsList(new String[] {"emp1", "emp2", "emp5"});
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, emps, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Basic query with ordering.
+     *
+     * This query selects all Employee instances from the candidate collection where the salary
+     * is greater than the constant 30000, and returns a Collection ordered based on employee salary.
+     */
+    public void testQuery02a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select where salary > 30000 order by salary ascending";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "salary > 30000");
+            q.setOrdering ("salary ascending");
+            List<FullTimeEmployee> emps = (List<FullTimeEmployee>)q.execute();
+            List<FullTimeEmployee> expected =
+                    getTransientCompanyModelInstancesAsList(new String[] {"emp1", "emp5", "emp2"});
+            checkQueryResultWithOrder(ASSERTION_FAILED, singleStringQuery, emps, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Basic query with ordering.
+     *
+     * This query selects all Employee instances from the candidate collection where the salary
+     * is greater than the constant 30000, and returns a Collection ordered based on employee salary.
+     */
+    public void testQuery02b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select where salary > 30000 order by salary ascending";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "salary > 30000");
+            q.setOrdering ("salary ascending");
+            List<FullTimeEmployee> emps = q.executeList();
+            List<FullTimeEmployee> expected =
+                    getTransientCompanyModelInstancesAsList(new String[] {"emp1", "emp5", "emp2"});
+            checkQueryResultWithOrder(ASSERTION_FAILED, singleStringQuery, emps, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Parameter passing.
+     *
+     * This query selects all Employee instances from the candidate collection where the salary
+     * is greater than the value passed as a parameter and the name starts with the value passed
+     * as a second parameter.
+     * If the value for the salary field in a candidate instance is null, then it cannot be
+     * unwrapped for the comparison, and the candidate instance is rejected.
+     */
+    public void testQuery03a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select where salary > :sal && firstname.startsWith(:begin)";
+            Query<FullTimeEmployee> q =
+                    pm.newQuery(FullTimeEmployee.class,"salary > sal && firstname.startsWith(begin)");
+            q.declareParameters("Double sal, String begin");
+            List<FullTimeEmployee> emps = (List<FullTimeEmployee>)q.execute(30000., "M");
+            List<FullTimeEmployee> expected = getTransientCompanyModelInstancesAsList(new String[] {"emp1"});
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, emps, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Parameter passing.
+     *
+     * This query selects all Employee instances from the candidate collection where the salary
+     * is greater than the value passed as a parameter and the name starts with the value passed
+     * as a second parameter.
+     * If the value for the salary field in a candidate instance is null, then it cannot be
+     * unwrapped for the comparison, and the candidate instance is rejected.
+     */
+    public void testQuery03b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select where salary > :sal && firstname.startsWith(:begin)";
+            Query<FullTimeEmployee> q =
+                    pm.newQuery(FullTimeEmployee.class,"salary > sal && firstname.startsWith(begin)");
+            q.declareParameters("Double sal, String begin");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("sal", 30000.);
+            paramValues.put("begin", "M");
+            q.setNamedParameters(paramValues);
+            List<FullTimeEmployee> emps = q.executeList();
+            List<FullTimeEmployee> expected = getTransientCompanyModelInstancesAsList(new String[] {"emp1"});
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, emps, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Navigation through single-valued field.
+     *
+     * This query selects all Employee instances from the candidate collection where the value
+     * of the name field in the Department instance associated with the Employee instance
+     * is equal to the value passed as a parameter.
+     * If the value for the dept field in a candidate instance is null, then it cannot be
+     * navigated for the comparison, and the candidate instance is rejected.
+     */
+    public void testQuery04a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select where department.name == :dep";
+            Query<Employee> q = pm.newQuery(Employee.class, "department.name == dep");
+            q.declareParameters("String dep");
+            List<Employee> emps = (List<Employee>)q.execute ("R&D");
+            List<Employee> expected = getTransientCompanyModelInstancesAsList(new String[] {"emp1", "emp2", "emp3"});
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, emps, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Navigation through single-valued field.
+     *
+     * This query selects all Employee instances from the candidate collection where the value
+     * of the name field in the Department instance associated with the Employee instance
+     * is equal to the value passed as a parameter.
+     * If the value for the dept field in a candidate instance is null, then it cannot be
+     * navigated for the comparison, and the candidate instance is rejected.
+     */
+    public void testQuery04b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select where department.name == :dep";
+            Query<Employee> q = pm.newQuery (Employee.class, "department.name == dep");
+            q.declareParameters ("String dep");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("dep", "R&D");
+            q.setNamedParameters(paramValues);
+            List<Employee> emps = q.executeList();
+            List<Employee> expected = getTransientCompanyModelInstancesAsList(new String[] {"emp1", "emp2", "emp3"});
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, emps, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Navigation through multi-valued field.
+     *
+     * This query selects all Department instances from the candidate collection where
+     * the collection of Employee instances contains at least one Employee instance
+     * having a salary greater than the value passed as a parameter.
+     */
+    public void testQuery05a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select where employees.contains(e) && e.weeklyhours > :hours";
+            String filter = "employees.contains (emp) && emp.weeklyhours > hours";
+            Query<Department> q = pm.newQuery(Department.class, filter);
+            q.declareVariables("Employee emp");
+            q.declareParameters("double hours");
+            List<Department> deps = (List<Department>)q.execute (30.);
+            List expected = getTransientCompanyModelInstancesAsList(new String[] {"dept1"});
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, deps, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Navigation through multi-valued field.
+     *
+     * This query selects all Department instances from the candidate collection where
+     * the collection of Employee instances contains at least one Employee instance
+     * having a salary greater than the value passed as a parameter.
+     */
+    public void testQuery05b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select where employees.contains(e) && e.weeklyhours > :hours";
+            String filter = "employees.contains (emp) && emp.weeklyhours > hours";
+            Query<Department> q = pm.newQuery(Department.class, filter);
+            q.declareVariables("Employee emp");
+            q.declareParameters("double hours");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("hours", 30.);
+            q.setNamedParameters(paramValues);
+            List<Department> deps = q.executeList();
+            List<Department> expected = getTransientCompanyModelInstancesAsList(new String[] {"dept1"});
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, deps, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Membership in a collection.
+     *
+     * This query selects all Department instances where the name field is contained in
+     * a parameter collection, which in this example consists of three department names.
+     */
+    public void testQuery06a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select where :depts.contains(name)";
+            String filter = "depts.contains(name)";
+            Query<Department> q = pm.newQuery(Department.class, filter);
+            q.declareParameters("java.util.Collection depts");
+            List<String> depts = Arrays.asList("R&D", "Sales", "Marketing");
+            List<Department> deps = (List<Department>)q.execute(depts);
+            List<Department> expected =
+                    getTransientCompanyModelInstancesAsList(new String[] {"dept1", "dept2", "dept3"});
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, deps, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Membership in a collection.
+     *
+     * This query selects all Department instances where the name field is contained in
+     * a parameter collection, which in this example consists of three department names.
+     */
+    public void testQuery06b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select where :depts.contains(name)";
+            String filter = "depts.contains(name)";
+            Query<Department> q = pm.newQuery(Department.class, filter);
+            q.declareParameters("java.util.Collection depts");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("depts", Arrays.asList("R&D", "Sales", "Marketing"));
+            q.setNamedParameters(paramValues);
+            List<Department> deps = q.executeList();
+            List<Department> expected =
+                    getTransientCompanyModelInstancesAsList(new String[] {"dept1", "dept2", "dept3"});
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, deps, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+    
+    /**
+     * Projection of a Single Field.
+     *
+     * This query selects names of all Employees who work in the parameter department.
+     */
+    public void testQuery07a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select firstname where department.name == :deptName";
+            Query<Employee> q = pm.newQuery(Employee.class, "department.name == deptName");
+            q.setResult("firstname");
+            q.declareParameters("String deptName");
+            List<String> names = (List<String>)q.execute("R&D");
+            List<String> expected = Arrays.asList("Joe", "Craig", "Michael");
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, names, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Projection of a Single Field.
+     *
+     * This query selects names of all Employees who work in the parameter department.
+     */
+    public void testQuery07b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select firstname where department.name == :deptName";
+            Query<Employee> q = pm.newQuery(Employee.class, "department.name == deptName");
+            q.setResult("firstname");
+            q.declareParameters("String deptName");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("deptName", "R&D");
+            q.setNamedParameters(paramValues);
+            List<String> names = q.executeResultList(String.class);
+            List<String> expected = Arrays.asList("Joe", "Craig", "Michael");
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, names, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Projection of Multiple Fields and Expressions.
+     *
+     * This query selects names, salaries, and bosses of Employees who work in the parameter department.
+     */
+    public void testQuery08a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select firstname, salary, manager as reportsTo " +
+                    "into org.apache.jdo.tck.query.api.SampleQueries$Info where department.name == :deptName";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "department.name == deptName");
+            q.setResult("firstname, salary, manager as reportsTo");
+            q.setResultClass(Info.class);
+            q.declareParameters("String deptName");
+            List<Info> infos = (List<Info>) q.execute("R&D");
+            
+            Info info1 = new Info();
+            info1.firstname = "Michael";
+            info1.salary = 40000.;
+            info1.reportsTo = (Employee)getTransientCompanyModelInstance("emp2");
+            Info info2 = new Info();
+            info2.firstname = "Craig";
+            info2.salary = 50000.;
+            info2.reportsTo = null;
+            List expected = Arrays.asList(info1, info2);
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, infos, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Projection of Multiple Fields and Expressions.
+     *
+     * This query selects names, salaries, and bosses of Employees who work in the parameter department.
+     */
+    public void testQuery08b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select firstname, salary, manager as reportsTo " +
+                            "into org.apache.jdo.tck.query.api.SampleQueries$Info where department.name == :deptName";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "department.name == deptName");
+            q.setResult("firstname, salary, manager as reportsTo");
+            q.setResultClass(Info.class);
+            q.declareParameters("String deptName");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("deptName", "R&D");
+            q.setNamedParameters(paramValues);
+            List<Info> infos = q.executeResultList(Info.class);
+
+            Info info1 = new Info();
+            info1.firstname = "Michael";
+            info1.salary = 40000.;
+            info1.reportsTo = (Employee)getTransientCompanyModelInstance("emp2");
+            Info info2 = new Info();
+            info2.firstname = "Craig";
+            info2.salary = 50000.;
+            info2.reportsTo = null;
+            List expected = Arrays.asList(info1, info2);
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, infos, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+    
+    /**
+     * Projection of Multiple Fields and Expressions into a Constructed instance.
+     *
+     * This query selects names, salaries, and bosses of Employees who work in the parameter department,
+     * and uses the constructor for the result class.
+     */
+    public void testQuery09a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select new org.apache.jdo.tck.query.api.SampleQueries$Info (firstname, salary, manager) " +
+                    "where department.name == :deptName";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "department.name == deptName");
+            q.setResult("new org.apache.jdo.tck.query.api.SampleQueries$Info(firstname, salary, manager)");
+            q.declareParameters("String deptName");
+            List<Info> infos = (List<Info>)q.execute("R&D");
+
+            List<Info> expected = Arrays.asList(
+                    new Info("Michael", 40000., (Employee)getTransientCompanyModelInstance("emp2")),
+                    new Info("Craig", 50000., null)
+            );
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, infos, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Projection of Multiple Fields and Expressions into a Constructed instance.
+     *
+     * This query selects names, salaries, and bosses of Employees who work in the parameter department,
+     * and uses the constructor for the result class.
+     */
+    public void testQuery09b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select new org.apache.jdo.tck.query.api.SampleQueries$Info (firstname, salary, manager) " +
+                            "where department.name == :deptName";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "department.name == deptName");
+            q.setResult("new org.apache.jdo.tck.query.api.SampleQueries$Info(firstname, salary, manager)");
+            q.declareParameters("String deptName");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("deptName", "R&D");
+            q.setNamedParameters(paramValues);
+            List<Info> infos = q.executeResultList(Info.class);
+
+            List<Info> expected = Arrays.asList(
+                    new Info("Michael", 40000., (Employee)getTransientCompanyModelInstance("emp2")),
+                    new Info("Craig", 50000., null)
+            );
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, infos, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Aggregation of a single Field.
+     *
+     * This query averages the salaries of Employees who work in the parameter department
+     * and returns a single value.
+     */
+    public void testQuery10a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select avg(salary) where department.name == :deptName";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "department.name == deptName");
+            q.setResult("avg(salary)");
+            q.declareParameters("String deptName");
+            Double avgSalary = (Double) q.execute("R&D");
+
+            Double expected = 45000.;
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, avgSalary, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Aggregation of a single Field.
+     *
+     * This query averages the salaries of Employees who work in the parameter department
+     * and returns a single value.
+     */
+    public void testQuery10b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select avg(salary) where department.name == :deptName";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "department.name == deptName");
+            q.setResult("avg(salary)");
+            q.declareParameters("String deptName");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("deptName", "R&D");
+            q.setNamedParameters(paramValues);
+            Double avgSalary = q.executeResultUnique(Double.class);
+
+            Double expected = 45000.;
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, avgSalary, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Aggregation of Multiple Fields and Expressions.
+     *
+     * This query averages and sums the salaries of Employees who work in the parameter department.
+     */
+    public void testQuery11a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select avg(salary), sum(salary) where department.name == :deptName";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "department.name == deptName");
+            q.setResult("avg(salary), sum(salary)");
+            q.declareParameters("String deptName");
+            Object[] avgSum = (Object[]) q.execute("R&D");
+
+            Double[] expected = new Double[] {45000., 90000.};
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, avgSum, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Aggregation of Multiple Fields and Expressions.
+     *
+     * This query averages and sums the salaries of Employees who work in the parameter department.
+     */
+    public void testQuery11b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select avg(salary), sum(salary) where department.name == :deptName";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "department.name == deptName");
+            q.setResult("avg(salary), sum(salary)");
+            q.declareParameters("String deptName");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("deptName", "R&D");
+            q.setNamedParameters(paramValues);
+            Object[] avgSum = (Object[])q.executeResultUnique();
+
+            Double[] expected = new Double[] {45000., 90000.};
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, avgSum, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Aggregation of Multiple fields with Grouping.
+     *
+     * This query averages and sums the salaries of Employees who work in all departments having
+     * more than one employee and aggregates by department name.
+     */
+    public void testQuery12a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select avg(salary), sum(salary), department.name " +
+                    "from org.apache.jdo.tck.pc.company.FullTimeEmployee " +
+                    "where department.name == :deptName " +
+                    "group by department.name having count(department.name)";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class);
+            q.setResult("avg(salary), sum(salary), department.name");
+            q.setGrouping("department.name having count(department.name) > 1");
+            List<Object[]> results = (List<Object[]>)q.execute();
+            if (results.size() != 1) {
+                fail(ASSERTION_FAILED,
+                        "Query result has size " + results.size() + ", expected query result of size 1");
+            }
+            Object[] row = results.get(0);
+            Object[] expectedRow = new Object[]{45000., 90000., "R&D"};
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, row, expectedRow);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Aggregation of Multiple fields with Grouping.
+     *
+     * This query averages and sums the salaries of Employees who work in all departments having
+     * more than one employee and aggregates by department name.
+     */
+    public void testQuery12b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select avg(salary), sum(salary), department.name " +
+                            "from org.apache.jdo.tck.pc.company.FullTimeEmployee " +
+                            "where department.name == :deptName " +
+                            "group by department.name having count(department.name)";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class);
+            q.setResult("avg(salary), sum(salary), department.name");
+            q.setGrouping("department.name having count(department.name) > 1");
+            List<Object[]> results = q.executeResultList(Object[].class);
+            if (results.size() != 1) {
+                fail(ASSERTION_FAILED,
+                        "Query result has size " + results.size() + ", expected query result of size 1");
+            }
+            Object[] row = results.get(0);
+            Object[] expectedRow = new Object[]{45000., 90000., "R&D"};
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, row, expectedRow);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Selection of a Single Instance.
+     *
+     * This query returns a single instance of Employee.
+     */
+    public void testQuery13a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select unique this where firstname == :empName";
+            Query<Employee> q = pm.newQuery(Employee.class, "firstname == empName");
+            q.setUnique(true);
+            q.declareParameters ("String empName");
+            Employee emp = (Employee)q.execute("Michael");
+            Employee expectedEmp = (Employee)getTransientCompanyModelInstance("emp1");
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, emp, expectedEmp);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Selection of a Single Instance.
+     *
+     * This query returns a single instance of Employee.
+     */
+    public void testQuery13b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select unique this where firstname == :empName";
+            Query<Employee> q = pm.newQuery (Employee.class, "firstname == empName");
+            q.setUnique(true);
+            q.declareParameters ("String empName");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("empName", "Michael");
+            q.setNamedParameters(paramValues);
+            Employee emp = q.executeUnique();
+            Employee expectedEmp = (Employee)getTransientCompanyModelInstance("emp1");
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, emp, expectedEmp);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Selection of a Single Field.
+     * 
+     * This query returns a single field of a single Employee.
+     */
+    public void testQuery14a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select unique new Double(salary) where firstname == :empName";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "firstname == empName");
+            q.setResult("salary");
+            q.setResultClass(Double.class);
+            q.setUnique(true);
+            q.declareParameters("String empName");
+            Double salary = (Double) q.execute ("Michael");
+            Double expectedSalary = 40000.;
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, salary, expectedSalary);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Selection of a Single Field.
+     *
+     * This query returns a single field of a single Employee.
+     */
+    public void testQuery14b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select unique new Double(salary) where firstname == :empName";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "firstname == empName");
+            q.setResult("salary");
+            q.setResultClass(Double.class);
+            q.declareParameters("String empName");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("empName", "Michael");
+            q.setNamedParameters(paramValues);
+            Double salary = q.executeResultUnique(Double.class);
+            Double expectedSalary = 40000.;
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, salary, expectedSalary);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+    
+    /**
+     * Projection of "this" to User-defined Result Class with Matching Field.
+     *
+     * This query selects instances of Employee who make more than the parameter salary and
+     * stores the result in a user-defined class. Since the default is "distinct this as FullTimeEmployee",
+     * the field must be named FullTimeEmployee and be of type FullTimeEmployee.
+     */
+    public void testQuery15a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select into org.apache.jdo.tck.query.api.SampleQueries$EmpWrapper where salary > sal";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "salary > sal");
+            // ToDo: the following line should no be necessary
+            // org.datanucleus.exceptions.NucleusUserException:
+            // Query needs to return objects of type "org.apache.jdo.tck.query.api.SampleQueries$EmpWrapper"
+            // but it was impossible to set the field "birthdate" type "java.util.Date". The field should
+            // have either a public set/put method, or be public.
+            //q.setResult("distinct this as FullTimeEmployee");
+            q.setResultClass(EmpWrapper.class);
+
+            q.declareParameters("Double sal");
+            List<EmpWrapper> infos = (List<EmpWrapper>)q.execute(30000.);
+
+            EmpWrapper wrapper1 = new EmpWrapper();
+            wrapper1.FullTimeEmployee = (FullTimeEmployee)getTransientCompanyModelInstance("emp1");
+            EmpWrapper wrapper2 = new EmpWrapper();
+            wrapper2.FullTimeEmployee = (FullTimeEmployee)getTransientCompanyModelInstance("emp2");
+            EmpWrapper wrapper3 = new EmpWrapper();
+            wrapper3.FullTimeEmployee = (FullTimeEmployee)getTransientCompanyModelInstance("emp5");
+            List<EmpWrapper> expected = Arrays.asList(wrapper1, wrapper2, wrapper3);
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, infos, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Projection of "this" to User-defined Result Class with Matching Field.
+     *
+     * This query selects instances of Employee who make more than the parameter salary and
+     * stores the result in a user-defined class. Since the default is "distinct this as FullTimeEmployee",
+     * the field must be named FullTimeEmployee and be of type FullTimeEmployee.
+     */
+    public void testQuery15b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select into org.apache.jdo.tck.query.api.SampleQueries$EmpWrapper where salary > sal";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "salary > sal");
+            // ToDo: the following line should no be necessary
+            // org.datanucleus.exceptions.NucleusUserException:
+            // Query needs to return objects of type "org.apache.jdo.tck.query.api.SampleQueries$EmpWrapper"
+            // but it was impossible to set the field "birthdate" type "java.util.Date". The field should
+            // have either a public set/put method, or be public.
+            //q.setResult("distinct this as FullTimeEmployee");
+            q.setResultClass(EmpWrapper.class);
+
+            q.declareParameters ("Double sal");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("sal", 30000.);
+            q.setNamedParameters(paramValues);
+            List<EmpWrapper> infos = q.executeResultList(EmpWrapper.class);
+
+            EmpWrapper wrapper1 = new EmpWrapper();
+            wrapper1.FullTimeEmployee = (FullTimeEmployee)getTransientCompanyModelInstance("emp1");
+            EmpWrapper wrapper2 = new EmpWrapper();
+            wrapper2.FullTimeEmployee = (FullTimeEmployee)getTransientCompanyModelInstance("emp2");
+            EmpWrapper wrapper3 = new EmpWrapper();
+            wrapper3.FullTimeEmployee = (FullTimeEmployee)getTransientCompanyModelInstance("emp5");
+            List<EmpWrapper> expected = Arrays.asList(wrapper1, wrapper2, wrapper3);
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, infos, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+    
+    /**
+     * Projection of "this" to User-defined Result Class with Matching Method
+     *
+     * This query selects instances of FullTimeEmployee who make more than the parameter salary and
+     * stores the result in a user-defined class.
+     */
+    public void testQuery16a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select into org.apache.jdo.tck.query.api.SampleQueries$EmpInfo where salary > sal";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "salary > sal");
+            // ToDo: the following line should no be necessary
+            // org.datanucleus.exceptions.NucleusUserException:
+            // Query needs to return objects of type "org.apache.jdo.tck.query.api.SampleQueries$EmpInfo"
+            // but it was impossible to set the field "birthdate" type "java.util.Date". The field should
+            // have either a public set/put method, or be public.
+            //q.setResult("distinct this as FullTimeEmployee");
+            q.setResultClass(EmpInfo.class);
+
+            q.declareParameters("Double sal");
+            List<EmpInfo> infos = (List<EmpInfo>)q.execute(30000.);
+
+            EmpInfo info1 = new EmpInfo();
+            info1.setFullTimeEmployee((FullTimeEmployee)getTransientCompanyModelInstance("emp1"));
+            EmpInfo info2 = new EmpInfo();
+            info2.setFullTimeEmployee((FullTimeEmployee)getTransientCompanyModelInstance("emp2"));
+            EmpInfo info3 = new EmpInfo();
+            info3.setFullTimeEmployee((FullTimeEmployee)getTransientCompanyModelInstance("emp5"));
+            List<EmpInfo> expected = Arrays.asList(info1, info2, info3);
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, infos, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Projection of "this" to User-defined Result Class with Matching Method
+     *
+     * This query selects instances of FullTimeEmployee who make more than the parameter salary and
+     * stores the result in a user-defined class.
+     */
+    public void testQuery16b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select into org.apache.jdo.tck.query.api.SampleQueries$EmpInfo where salary > sal";
+            Query<FullTimeEmployee> q = pm.newQuery(FullTimeEmployee.class, "salary > sal");
+            // ToDo: the following line should no be necessary
+            // org.datanucleus.exceptions.NucleusUserException:
+            // Query needs to return objects of type "org.apache.jdo.tck.query.api.SampleQueries$EmpInfo"
+            // but it was impossible to set the field "birthdate" type "java.util.Date". The field should
+            // have either a public set/put method, or be public.
+            //q.setResult("distinct this as FullTimeEmployee");
+            q.setResultClass(EmpInfo.class);
+
+            q.declareParameters("Double sal");
+            Map<String, Object> paramValues = new HashMap<>();
+            paramValues.put("sal", 30000.);
+            q.setNamedParameters(paramValues);
+            List<EmpInfo> infos = q.executeResultList(EmpInfo.class);
+
+            EmpInfo info1 = new EmpInfo();
+            info1.setFullTimeEmployee((FullTimeEmployee)getTransientCompanyModelInstance("emp1"));
+            EmpInfo info2 = new EmpInfo();
+            info2.setFullTimeEmployee((FullTimeEmployee)getTransientCompanyModelInstance("emp2"));
+            EmpInfo info3 = new EmpInfo();
+            info3.setFullTimeEmployee((FullTimeEmployee)getTransientCompanyModelInstance("emp5"));
+            List<EmpInfo> expected = Arrays.asList(info1, info2, info3);
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, infos, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Projection of variables.
+     *
+     * This query returns the names of all Employees of all "Research" departments.
+     */
+    public void testQuery17a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select e.firstname where name.startsWith('R&D') " +
+                    "&& employees.contains((org.apache.jdo.tck.pc.company.Employee) e)";
+            Query<Department> q = pm.newQuery(Department.class);
+            q.declareVariables("org.apache.jdo.tck.pc.company.Employee e");
+            q.setFilter("name.startsWith('R&D') && employees.contains(e)");
+            q.setResult("e.firstname");
+            List<String> names = (List<String>) q.execute();
+            List<String> expected = Arrays.asList("Michael", "Craig", "Joe");
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, names, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Projection of variables.
+     *
+     * This query returns the names of all Employees of all "Research" departments.
+     */
+    public void testQuery17b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery = "select e.firstname where name.startsWith('R&D') " +
+                    "&& employees.contains((org.apache.jdo.tck.pc.company.Employee) e)";
+            Query<Department> q = pm.newQuery(Department.class);
+            q.declareVariables("org.apache.jdo.tck.pc.company.Employee e");
+            q.setFilter("name.startsWith('R&D') && employees.contains(e)");
+            q.setResult("e.firstname");
+            List<String> names = q.executeResultList(String.class);
+            List<String> expected = Arrays.asList("Michael", "Craig", "Joe");
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, names, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+    
+    /**
+     * Non-correlated subquery
+     * 
+     * This query returns names of employees who work more than the average of all employees.
+     */
+    public void testQuery18a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select firstname from org.apache.jdo.tck.pc.company.Employee " +
+                    "where this.weeklyhours > " +
+                    " (select avg(e.weeklyhours) from org.apache.jdo.tck.pc.company.Employee e)";
+            Query<Employee> subq = pm.newQuery(Employee.class);
+            subq.setResult("avg(weeklyhours)");
+            Query<Employee> q = pm.newQuery(Employee.class);
+            q.setFilter("this.weeklyhours > average_hours");
+            q.setResult("this.firstname");
+            q.addSubquery(subq, "double average_hours", null);
+            List<String> names = (List<String>)q.execute();
+            List<String> expected = Arrays.asList("Michael", "Craig");
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, names, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Non-correlated subquery
+     *
+     * This query returns names of employees who work more than the average of all employees.
+     */
+    public void testQuery18b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select firstname from org.apache.jdo.tck.pc.company.Employee " +
+                            "where this.weeklyhours > " +
+                            " (select avg(e.weeklyhours) from org.apache.jdo.tck.pc.company.Employee e)";
+            Query<Employee> subq = pm.newQuery(Employee.class);
+            subq.setResult("avg(weeklyhours)");
+            Query<Employee> q = pm.newQuery(Employee.class);
+            q.setFilter("this.weeklyhours > average_hours");
+            q.setResult("this.firstname");
+            q.addSubquery(subq, "double average_hours", null);
+            List<String> names = q.executeResultList(String.class);
+            List<String> expected = Arrays.asList("Michael", "Craig");
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, names, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+    
+    /**
+     * Correlated subquery.
+     * 
+     * This query returns names of employees who work more than the average of employees
+     * in the same department having the same manager. The candidate collection of the
+     * subquery is the collection of employees in the department of the candidate employee
+     * and the parameter passed to the subquery is the manager of the candidate employee.
+     */
+    public void testQuery19a() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select firstname from org.apache.jdo.tck.pc.company.Employee " +
+                    "where this.weeklyhours > " +
+                    "(select AVG(e.weeklyhours) from this.department.employees e " +
+                    " where e.manager == this.manager)";
+            Query<Employee> subq = pm.newQuery(Employee.class);
+            subq.setFilter("this.manager == :manager");
+            subq.setResult("avg(weeklyhours)");
+            Query<Employee> q = pm.newQuery(Employee.class);
+            q.setFilter("this.weeklyhours > average_hours");
+            q.setResult("firstname");
+            q.addSubquery(subq, "double average_hours","this.department.employees",
+                    "this.manager");
+            List<String> names = (List<String>)q.execute();
+            List<String> expected = Arrays.asList("Michael");
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, names, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Correlated subquery.
+     *
+     * This query returns names of employees who work more than the average of employees
+     * in the same department having the same manager. The candidate collection of the
+     * subquery is the collection of employees in the department of the candidate employee
+     * and the parameter passed to the subquery is the manager of the candidate employee.
+     */
+    public void testQuery19b() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            String singleStringQuery =
+                    "select firstname from org.apache.jdo.tck.pc.company.Employee " +
+                            "where this.weeklyhours > " +
+                            "(select AVG(e.weeklyhours) from this.department.employees e " +
+                            " where e.manager == this.manager)";
+            Query<Employee> subq = pm.newQuery(Employee.class);
+            subq.setFilter("this.manager == :manager");
+            subq.setResult("avg(weeklyhours)");
+            Query<Employee> q = pm.newQuery(Employee.class);
+            q.setFilter("this.weeklyhours > average_hours");
+            q.setResult("firstname");
+            q.addSubquery(subq, "double average_hours","this.department.employees",
+                    "this.manager");
+            List<String> names = q.executeResultList(String.class);
+            List<String> expected = Arrays.asList("Michael");
+            checkQueryResultWithoutOrder(ASSERTION_FAILED, singleStringQuery, names, expected);
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    /**
+     * Deleting Multiple Instances.
+     * 
+     * This query deletes all Employees who make more than the parameter salary.
+     */
+    public void testQuery20() {
+        Transaction tx = pm.currentTransaction();
+        try {
+            tx.begin();
+            Query<FullTimeEmployee> empQuery = pm.newQuery (FullTimeEmployee.class, "personid == 5");
+            empQuery.setUnique(true);
+            FullTimeEmployee emp5 = empQuery.executeUnique();
+            Object emp5Oid = pm.getObjectId(emp5);
+            Query q = pm.newQuery (FullTimeEmployee.class, "salary > sal");
+            q.declareParameters ("Double sal");
+            q.deletePersistentAll(30000.);
+            tx.commit();
+
+            tx.begin();
+            Query allQuery = pm.newQuery(FullTimeEmployee.class);
+            List<FullTimeEmployee> allFTE = allQuery.executeList();
+            if (!allFTE.isEmpty()) {
+                fail(ASSERTION_FAILED, "All FullTimeEmployee instances should have been deleted," +
+                " there are still " + allFTE.size() + " instances left.");
+            }
+            tx.commit();
+        } finally {
+            if (tx.isActive()) {
+                tx.rollback();
+            }
+        }
+    }
+
+    public static class Info {
+        public String firstname;
+        public Double salary;
+        public Person reportsTo;
+        public Info () {}
+        public Info (String firstname, Double salary, Person reportsTo) {
+            this.firstname = firstname;
+            this.salary = salary;
+            this.reportsTo = reportsTo;
+        }
+        public boolean equals(Object obj) {
+            if (!(obj instanceof Info)) {
+                return false;
+            }
+            Info other = (Info)obj;
+            if (!EqualityHelper.equals(firstname, other.firstname)) {
+                return false;
+            }
+            if (!EqualityHelper.equals(salary, other.salary)) {
+                return false;
+            }
+            if (!EqualityHelper.equals(reportsTo, other.reportsTo)) {
+                return false;
+            }
+            return true;
+        }
+        public int hashCode () {
+            int hashCode = 0;
+            hashCode += firstname == null ? 0 : firstname.hashCode();
+            hashCode += salary == null ? 0 : salary.hashCode();
+            hashCode += reportsTo == null ? 0 : reportsTo.hashCode();
+            return hashCode;
+        }
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("Info(");
+            builder.append("firstname:").append(firstname);
+            builder.append(", salary:").append(salary);
+            builder.append(", reportsTo:").append(reportsTo == null ? "null" : reportsTo.getFirstname());
+            builder.append(")");
+            return builder.toString();
+        }
+    }
+
+    public static class EmpWrapper {
+        public FullTimeEmployee FullTimeEmployee;
+        public EmpWrapper () {}
+        // Need constructor to prevent
+        // java.lang.NullPointerException
+        // at org.datanucleus.query.QueryUtils.createResultObjectUsingDefaultConstructorAndSetters(QueryUtils.java:293)
+        public EmpWrapper (FullTimeEmployee FullTimeEmployee) {
+            this.FullTimeEmployee = FullTimeEmployee;
+        }
+        public boolean equals(Object obj) {
+            if (!(obj instanceof EmpWrapper)) {
+                return false;
+            }
+            EmpWrapper other = (EmpWrapper)obj;
+            if (!EqualityHelper.equals(FullTimeEmployee, other.FullTimeEmployee)) {
+                return false;
+            }
+            return true;
+        }
+        public int hashCode () {
+            int hashCode = 0;
+            hashCode += FullTimeEmployee == null ? 0 : FullTimeEmployee.hashCode();
+            return hashCode;
+        }
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("EmpWrapper(");
+            builder.append("FullTimeEmployee:").append(FullTimeEmployee == null ? "null" : FullTimeEmployee.getFirstname());
+            builder.append(")");
+            return builder.toString();
+        }
+    }
+
+    public static class EmpInfo {
+        private FullTimeEmployee worker;
+        public EmpInfo () {}
+        // Need constructor to prevent
+        // java.lang.NullPointerException
+        // at org.datanucleus.query.QueryUtils.createResultObjectUsingDefaultConstructorAndSetters(QueryUtils.java:293)
+        public EmpInfo (FullTimeEmployee worker) {
+            this.worker = worker;
+        }
+        public FullTimeEmployee getWorker() {return worker;}
+        public void setFullTimeEmployee(FullTimeEmployee e) {
+            worker = e;
+        }
+        public boolean equals(Object obj) {
+            if (!(obj instanceof EmpInfo)) {
+                return false;
+            }
+            EmpInfo other = (EmpInfo)obj;
+            if (!EqualityHelper.equals(worker, other.worker)) {
+                return false;
+            }
+            return true;
+        }
+        public int hashCode () {
+            int hashCode = 0;
+            hashCode += worker == null ? 0 : worker.hashCode();
+            return hashCode;
+        }
+        public String toString() {
+            StringBuilder builder = new StringBuilder();
+            builder.append("EmpInfo(");
+            builder.append(", worker:").append(worker == null ? "null" : worker.getFirstname());
+            builder.append(")");
+            return builder.toString();
+        }
+    }
+    
+    /**
+     * @see JDO_Test#localSetUp()
+     */
+    protected void localSetUp() {
+        addTearDownClass(CompanyModelReader.getTearDownClasses());
+        loadAndPersistCompanyModel(getPM());
+    }
+
+    /**
+     * Returns the name of the company test data resource.
+     * @return name of the company test data resource.
+     */
+    protected String getCompanyTestDataResource() {
+        return SAMPLE_QUERIES_TEST_COMPANY_TESTDATA;
+    }
+}

Added: db/jdo/trunk/tck/src/testdata/org/apache/jdo/tck/pc/company/companyForSampleQueriesTest.xml
URL: http://svn.apache.org/viewvc/db/jdo/trunk/tck/src/testdata/org/apache/jdo/tck/pc/company/companyForSampleQueriesTest.xml?rev=1797113&view=auto
==============================================================================
--- db/jdo/trunk/tck/src/testdata/org/apache/jdo/tck/pc/company/companyForSampleQueriesTest.xml (added)
+++ db/jdo/trunk/tck/src/testdata/org/apache/jdo/tck/pc/company/companyForSampleQueriesTest.xml Wed May 31 21:20:07 2017
@@ -0,0 +1,453 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+
+<beans>
+    <description>Company instances for query testing</description>
+
+    <bean id="root" class="java.util.ArrayList">
+        <constructor-arg index="0">
+            <list>
+                <ref local="company1"/>
+                <ref local="dentalIns99"/>
+            </list>
+        </constructor-arg>
+    </bean>
+
+    <bean id="company1" factory-bean="companyFactory" factory-method="newCompany">
+        <constructor-arg index="0" type="long"><value>1</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Sun Microsystems, Inc.</value></constructor-arg>
+        <constructor-arg index="2" type="java.util.Date"><value>11/Apr/1952</value></constructor-arg>
+        <constructor-arg index="3" type="org.apache.jdo.tck.pc.company.IAddress"><ref local="addr1"/></constructor-arg>
+        <property name="departments">
+            <set>
+                <ref local="dept1"/>
+                <ref local="dept2"/>
+                <ref local="dept3"/>
+            </set>
+        </property>
+    </bean>
+
+    <bean id="room1" factory-bean="companyFactory" factory-method="newMeetingRoom">
+        <constructor-arg index="0" type="long"><value>1</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Comfy Room</value></constructor-arg>
+    </bean>
+    <bean id="room2" factory-bean="companyFactory" factory-method="newMeetingRoom">
+        <constructor-arg index="0" type="long"><value>2</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Large Discussion Room</value></constructor-arg>
+    </bean>
+    <bean id="room3" factory-bean="companyFactory" factory-method="newMeetingRoom">
+        <constructor-arg index="0" type="long"><value>3</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Conference Room</value></constructor-arg>
+    </bean>
+
+    <bean id="dept1" factory-bean="companyFactory" factory-method="newDepartment">
+        <constructor-arg index="0" type="long"><value>1</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String" ><value>R&amp;D</value></constructor-arg>
+        <property name="company"><ref bean="company1"/></property>
+        <property name="employees">
+            <set>
+                <ref local="emp1"/>
+                <ref local="emp2"/>
+                <ref local="emp3"/>
+            </set>
+        </property>
+        <property name="fundedEmps">
+            <set>
+                <ref local="emp2"/>
+                <ref local="emp3"/>
+            </set>
+        </property>
+        <property name="meetingRooms">
+            <list>
+                <ref local="room1"/>
+                <ref local="room2"/>
+                <ref local="room3"/>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="dept2" factory-bean="companyFactory" factory-method="newDepartment">
+        <constructor-arg index="0" type="long"><value>2</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String" ><value>Sales</value></constructor-arg>
+        <property name="company"><ref bean="company1"/></property>
+        <property name="employees">
+            <set>
+                <ref local="emp4"/>
+                <ref local="emp5"/>
+            </set>
+        </property>
+        <property name="fundedEmps">
+            <set>
+                <ref local="emp1"/>
+                <ref local="emp4"/>
+                <ref local="emp5"/>
+            </set>
+        </property>
+        <property name="meetingRooms">
+            <list>
+            </list>
+        </property>
+    </bean>
+
+       <bean id="dept3" factory-bean="companyFactory" factory-method="newDepartment">
+        <constructor-arg index="0" type="long"><value>3</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String" ><value>Marketing</value></constructor-arg>
+        <property name="company"><ref bean="company1"/></property>
+        <property name="employees">
+            <set>
+            </set>
+        </property>
+        <property name="fundedEmps">
+            <set>
+            </set>
+        </property>
+        <property name="meetingRooms">
+            <list>
+            </list>
+        </property>
+    </bean>
+
+    <bean id="emp1" factory-bean="companyFactory" factory-method="newFullTimeEmployee">
+        <constructor-arg index="0" type="long"><value>1</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Michael</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>Bouschn</value></constructor-arg>
+        <constructor-arg index="3" type="java.lang.String"><value></value></constructor-arg>
+        <constructor-arg index="4" type="java.util.Date"><value>10/Jun/1970</value></constructor-arg>
+        <constructor-arg index="5" type="org.apache.jdo.tck.pc.company.IAddress"><ref local="addr1"/></constructor-arg>
+        <constructor-arg index="6" type="java.util.Date"><value>1/Jan/1999</value></constructor-arg>
+        <constructor-arg index="7" type="double"><value>40000</value></constructor-arg>
+        <property name="weeklyhours"><value>40</value></property>
+        <property name="medicalInsurance"><ref bean="medicalIns1"/></property>
+        <property name="dentalInsurance"><ref bean="dentalIns1"/></property>
+        <property name="phoneNumbers">
+	        <map>
+                <entry key="home"><value>1111</value></entry>
+                <entry key="work"><value>123456-1</value></entry>
+            </map>
+	    </property>
+        <property name="department"><ref bean="dept1"/></property>
+        <property name="fundingDept"><ref bean="dept2"/></property>
+        <property name="manager"><ref bean="emp2"/></property>
+        <property name="mentor"><ref bean="emp2"/></property>
+        <property name="protege"><ref bean="emp5"/></property>
+        <property name="hradvisor"><ref bean="emp5"/></property>
+        <property name="reviewedProjects">
+            <set>
+                <ref local="proj3"/>
+            </set>
+        </property>
+        <property name="projects">
+            <set>
+                <ref local="proj1"/>
+            </set>
+        </property>
+    </bean>
+    <bean id="emp2" factory-bean="companyFactory" factory-method="newFullTimeEmployee">
+        <constructor-arg index="0" type="long"><value>2</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Craig</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>L.</value></constructor-arg>
+        <constructor-arg index="3" type="java.lang.String"><value>Russell</value></constructor-arg>
+        <constructor-arg index="4" type="java.util.Date"><value>22/Dec/1975</value></constructor-arg>
+        <constructor-arg index="5" type="org.apache.jdo.tck.pc.company.IAddress"><ref local="addr2"/></constructor-arg>
+        <constructor-arg index="6" type="java.util.Date"><value>1/Jul/2003</value></constructor-arg>
+        <constructor-arg index="7" type="double"><value>50000</value></constructor-arg>
+        <property name="weeklyhours"><value>40</value></property>
+        <property name="medicalInsurance"><ref bean="medicalIns2"/></property>
+        <property name="dentalInsurance"><ref bean="dentalIns2"/></property>
+        <property name="phoneNumbers">
+	        <map>
+                <entry key="home"><value>2222</value></entry>
+                <entry key="work"><value>123456-2</value></entry>
+            </map>
+	    </property>
+        <property name="department"><ref bean="dept1"/></property>
+        <property name="fundingDept"><ref bean="dept1"/></property>
+        <property name="mentor"><ref bean="emp3"/></property>
+        <property name="protege"><ref bean="emp1"/></property>
+        <property name="hradvisor"><ref bean="emp5"/></property>
+        <property name="projects">
+            <set>
+                <ref local="proj1"/>
+                <ref local="proj2"/>
+            </set>
+        </property>
+        <property name="team">
+            <set>
+                <ref local="emp1"/>
+                <ref local="emp3"/>
+                <ref local="emp4"/>
+                <ref local="emp5"/>
+            </set>
+        </property>
+    </bean>
+    <bean id="emp3" factory-bean="companyFactory" factory-method="newPartTimeEmployee">
+        <constructor-arg index="0" type="long"><value>3</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Joe</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>Doe</value></constructor-arg>
+        <constructor-arg index="3" type="java.lang.String"><value></value></constructor-arg>
+        <constructor-arg index="4" type="java.util.Date"><value>5/Sep/1972</value></constructor-arg>
+        <constructor-arg index="5" type="org.apache.jdo.tck.pc.company.IAddress"><ref local="addr3"/></constructor-arg>
+        <constructor-arg index="6" type="java.util.Date"><value>15/Aug/2002</value></constructor-arg>
+        <constructor-arg index="7" type="double"><value>15</value></constructor-arg>
+        <property name="weeklyhours"><value>19</value></property>
+        <property name="medicalInsurance"><ref bean="medicalIns3"/></property>
+        <property name="dentalInsurance"><ref bean="dentalIns3"/></property>
+        <property name="phoneNumbers">
+	        <map>
+                <entry key="home"><value>3333</value></entry>
+                <entry key="work"><value>123456-3</value></entry>
+            </map>
+	    </property>
+        <property name="department"><ref bean="dept1"/></property>
+        <property name="fundingDept"><ref bean="dept1"/></property>
+        <property name="manager"><ref bean="emp2"/></property>
+        <property name="mentor"><ref bean="emp4"/></property>
+        <property name="protege"><ref bean="emp2"/></property>
+        <property name="hradvisor"><ref bean="emp5"/></property>
+        <property name="projects">
+            <set>
+                <ref local="proj1"/>
+                <ref local="proj2"/>
+            </set>
+        </property>
+    </bean>
+    <bean id="emp4" factory-bean="companyFactory" factory-method="newPartTimeEmployee">
+        <constructor-arg index="0" type="long"><value>4</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Jane</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>Roe</value></constructor-arg>
+        <constructor-arg index="3" type="java.lang.String"><value></value></constructor-arg>
+        <constructor-arg index="4" type="java.util.Date"><value>6/Sep/1973</value></constructor-arg>
+        <constructor-arg index="5" type="org.apache.jdo.tck.pc.company.IAddress"><ref local="addr3"/></constructor-arg>
+        <constructor-arg index="6" type="java.util.Date"><value>15/Apr/2001</value></constructor-arg>
+        <constructor-arg index="7" type="double"><value>13</value></constructor-arg>
+        <property name="medicalInsurance"><ref bean="medicalIns4"/></property>
+        <property name="dentalInsurance"><ref bean="dentalIns4"/></property>
+        <property name="phoneNumbers">
+	        <map>
+                <entry key="home"><value>3343</value></entry>
+                <entry key="work"><value>124456-3</value></entry>
+            </map>
+	    </property>
+        <property name="department"><ref bean="dept2"/></property>
+        <property name="fundingDept"><ref bean="dept2"/></property>
+        <property name="manager"><ref bean="emp2"/></property>
+        <property name="mentor"><ref bean="emp5"/></property>
+        <property name="protege"><ref bean="emp3"/></property>
+        <property name="hradvisor"><ref bean="emp5"/></property>
+        <property name="projects">
+            <set>
+                <ref local="proj3"/>
+            </set>
+        </property>
+        <property name="reviewedProjects">
+            <set>
+                <ref local="proj2"/>
+            </set>
+        </property>
+    </bean>
+    <bean id="emp5" factory-bean="companyFactory" factory-method="newFullTimeEmployee">
+        <constructor-arg index="0" type="long"><value>5</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Tillmann</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>Zäschke</value></constructor-arg>
+        <constructor-arg index="3" type="java.lang.String"><value></value></constructor-arg>
+        <constructor-arg index="4" type="java.util.Date"><value>5/Jul/1979</value></constructor-arg>
+        <constructor-arg index="5" type="org.apache.jdo.tck.pc.company.IAddress"><ref local="addr3"/></constructor-arg>
+        <constructor-arg index="6" type="java.util.Date"><value>15/Aug/1999</value></constructor-arg>
+        <constructor-arg index="7" type="double"><value>45000</value></constructor-arg>
+        <property name="medicalInsurance"><ref bean="medicalIns5"/></property>
+        <property name="dentalInsurance"><ref bean="dentalIns5"/></property>
+        <property name="phoneNumbers">
+	        <map>
+                <entry key="home"><value>3363</value></entry>
+                <entry key="work"><value>126456-3</value></entry>
+            </map>
+	    </property>
+        <property name="department"><ref bean="dept2"/></property>
+        <property name="fundingDept"><ref bean="dept2"/></property>
+        <property name="manager"><ref bean="emp2"/></property>
+        <property name="mentor"><ref bean="emp1"/></property>
+        <property name="protege"><ref bean="emp4"/></property>
+        <property name="projects">
+            <set>
+                <ref local="proj3"/>
+            </set>
+        </property>
+        <property name="reviewedProjects">
+            <set>
+                <ref local="proj2"/>
+            </set>
+        </property>
+        <property name="hradvisees">
+            <set>
+                <ref local="emp1"/>
+                <ref local="emp2"/>
+                <ref local="emp3"/>
+                <ref local="emp4"/>
+            </set>
+        </property>
+    </bean>
+
+    <bean id="addr1" factory-bean="companyFactory" factory-method="newAddress">
+        <constructor-arg index="0" type="long"><value>1</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Unter den Linden 1</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>Berlin</value></constructor-arg>
+        <constructor-arg index="3" type="java.lang.String"><value>  </value></constructor-arg>
+        <constructor-arg index="4" type="java.lang.String"><value>12345</value></constructor-arg>
+        <constructor-arg index="5" type="java.lang.String"><value>Germany</value></constructor-arg>
+    </bean>
+    <bean id="addr2" factory-bean="companyFactory" factory-method="newAddress">
+        <constructor-arg index="0" type="long"><value>2</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Broadway 1</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>New York</value></constructor-arg>
+        <constructor-arg index="3" type="java.lang.String"><value>NY</value></constructor-arg>
+        <constructor-arg index="4" type="java.lang.String"><value>10000</value></constructor-arg>
+        <constructor-arg index="5" type="java.lang.String"><value>USA</value></constructor-arg>
+    </bean>
+    <bean id="addr3" factory-bean="companyFactory" factory-method="newAddress">
+        <constructor-arg index="0" type="long"><value>3</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Market St.</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>San Francisco</value></constructor-arg>
+        <constructor-arg index="3" type="java.lang.String"><value>CA</value></constructor-arg>
+        <constructor-arg index="4" type="java.lang.String"><value>94102</value></constructor-arg>
+        <constructor-arg index="5" type="java.lang.String"><value>USA</value></constructor-arg>
+    </bean>
+
+    <bean id="medicalIns1" factory-bean="companyFactory" factory-method="newMedicalInsurance">
+        <constructor-arg index="0" type="long"><value>1</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Carrier1</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>PPO</value></constructor-arg>
+        <property name="employee"><ref bean="emp1"/></property>
+    </bean>
+
+    <bean id="medicalIns2" factory-bean="companyFactory" factory-method="newMedicalInsurance">
+        <constructor-arg index="0" type="long"><value>2</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Carrier2</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>HMO</value></constructor-arg>
+        <property name="employee"><ref bean="emp2"/></property>
+    </bean>
+
+    <bean id="medicalIns3" factory-bean="companyFactory" factory-method="newMedicalInsurance">
+        <constructor-arg index="0" type="long"><value>3</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Carrier3</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>HMO</value></constructor-arg>
+        <property name="employee"><ref bean="emp3"/></property>
+    </bean>
+
+    <bean id="medicalIns4" factory-bean="companyFactory" factory-method="newMedicalInsurance">
+        <constructor-arg index="0" type="long"><value>4</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Carrier4</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>HMO</value></constructor-arg>
+        <property name="employee"><ref bean="emp4"/></property>
+    </bean>
+
+    <bean id="medicalIns5" factory-bean="companyFactory" factory-method="newMedicalInsurance">
+        <constructor-arg index="0" type="long"><value>5</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Carrier5</value></constructor-arg>
+        <constructor-arg index="2" type="java.lang.String"><value>HMO</value></constructor-arg>
+        <property name="employee"><ref bean="emp5"/></property>
+    </bean>
+
+    <bean id="dentalIns1" factory-bean="companyFactory" factory-method="newDentalInsurance">
+        <constructor-arg index="0" type="long"><value>11</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Carrier1</value></constructor-arg>
+        <constructor-arg index="2" type="java.math.BigDecimal"><value>99.995</value></constructor-arg>
+        <property name="employee"><ref bean="emp1"/></property>
+    </bean>
+
+    <bean id="dentalIns2" factory-bean="companyFactory" factory-method="newDentalInsurance">
+        <constructor-arg index="0" type="long"><value>12</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Carrier2</value></constructor-arg>
+        <constructor-arg index="2" type="java.math.BigDecimal"><value>99.996</value></constructor-arg>
+        <property name="employee"><ref bean="emp2"/></property>
+    </bean>
+
+    <bean id="dentalIns3" factory-bean="companyFactory" factory-method="newDentalInsurance">
+        <constructor-arg index="0" type="long"><value>13</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Carrier3</value></constructor-arg>
+        <constructor-arg index="2" type="java.math.BigDecimal"><value>99.997</value></constructor-arg>
+        <property name="employee"><ref bean="emp3"/></property>
+    </bean>
+
+    <bean id="dentalIns4" factory-bean="companyFactory" factory-method="newDentalInsurance">
+        <constructor-arg index="0" type="long"><value>14</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Carrier4</value></constructor-arg>
+        <constructor-arg index="2" type="java.math.BigDecimal"><value>99.998</value></constructor-arg>
+        <property name="employee"><ref bean="emp4"/></property>
+    </bean>
+
+    <bean id="dentalIns5" factory-bean="companyFactory" factory-method="newDentalInsurance">
+        <constructor-arg index="0" type="long"><value>15</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Carrier5</value></constructor-arg>
+        <constructor-arg index="2" type="java.math.BigDecimal"><value>99.999</value></constructor-arg>
+        <property name="employee"><ref bean="emp5"/></property>
+    </bean>
+
+    <bean id="dentalIns99" factory-bean="companyFactory" factory-method="newDentalInsurance">
+        <constructor-arg index="0" type="long"><value>99</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>Carrier99</value></constructor-arg>
+        <constructor-arg index="2" type="java.math.BigDecimal"><null/></constructor-arg>
+    </bean>
+
+    <bean id="proj1" factory-bean="companyFactory" factory-method="newProject">
+        <constructor-arg index="0" type="long"><value>1</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>orange</value></constructor-arg>
+        <constructor-arg index="2" type="java.math.BigDecimal"><value>2500000.99</value></constructor-arg>
+        <property name="members">
+            <set>
+                <ref local="emp1"/>
+                <ref local="emp2"/>
+                <ref local="emp3"/>
+            </set>
+        </property>
+    </bean>
+    <bean id="proj2" factory-bean="companyFactory" factory-method="newProject">
+        <constructor-arg index="0" type="long"><value>2</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>blue</value></constructor-arg>
+        <constructor-arg index="2" type="java.math.BigDecimal"><value>50000.00</value></constructor-arg>
+        <property name="reviewers">
+            <set>
+                <ref local="emp4"/>
+                <ref local="emp5"/>
+            </set>
+        </property>
+        <property name="members">
+            <set>
+                <ref local="emp2"/>
+                <ref local="emp3"/>
+            </set>
+        </property>
+    </bean>
+    <bean id="proj3" factory-bean="companyFactory" factory-method="newProject">
+        <constructor-arg index="0" type="long"><value>3</value></constructor-arg>
+        <constructor-arg index="1" type="java.lang.String"><value>green</value></constructor-arg>
+        <constructor-arg index="2" type="java.math.BigDecimal"><value>2000.99</value></constructor-arg>
+        <property name="reviewers">
+            <set>
+                <ref local="emp1"/>
+            </set>
+        </property>
+        <property name="members">
+            <set>
+                <ref local="emp4"/>
+                <ref local="emp5"/>
+            </set>
+        </property>
+    </bean>
+</beans>
+