| /* |
| * 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.openjpa.persistence.models.company; |
| |
| import java.beans.*; |
| import java.io.*; |
| import java.util.*; |
| import javax.persistence.*; |
| import junit.framework.*; |
| import org.apache.openjpa.persistence.test.*; |
| |
| /** |
| * Generic test case that will be extended by a concrete company |
| * model subclass. |
| * |
| * @author Marc Prud'hommeaux |
| */ |
| public abstract class CompanyModelTest |
| extends SingleEMTestCase { |
| |
| private static Map<Class,Class> factoryClasses; |
| private Map<Class,Class> impls; |
| |
| public void setUp() { |
| // make a map of the implementations based on the class names in |
| // the current package of the test subclass |
| impls = new HashMap<Class,Class>(); |
| impls.put(IAddress.class, localClass("Address")); |
| impls.put(ICompany.class, localClass("Company")); |
| impls.put(ICustomer.class, localClass("Customer")); |
| impls.put(IPerson.class, localClass("Person")); |
| impls.put(IEmployee.class, localClass("Employee")); |
| impls.put(IFullTimeEmployee.class, localClass("FullTimeEmployee")); |
| impls.put(ILineItem.class, localClass("LineItem")); |
| impls.put(IProductOrder.class, localClass("ProductOrder")); |
| impls.put(IPartTimeEmployee.class, localClass("PartTimeEmployee")); |
| impls.put(IProduct.class, localClass("Product")); |
| |
| setUp(impls.values().toArray(new Class[impls.size()])); |
| checkModel(); |
| } |
| |
| private Class localClass(String name) { |
| String pkg = getClass().getPackage().getName(); |
| try { |
| return Class.forName(pkg + "." + name); |
| } catch (Exception e) { |
| throw new IllegalStateException(e); |
| } |
| } |
| |
| /** |
| * Runs through basic queries against all of the properties of all |
| * of the known persistent classes. We're just checking here to |
| * make sure the queries can be executed without problem. Queries |
| * should always return all known instances in the database. |
| */ |
| public void testBasicQueries() throws Exception { |
| for (Class c : impls.values()) { |
| for (PropertyDescriptor pd : |
| Introspector.getBeanInfo(c).getPropertyDescriptors()) { |
| |
| if (pd.getWriteMethod() == null) // ignore read-only |
| continue; |
| |
| Set<String> queries = new TreeSet<String>(); |
| getBasicQueries(queries, pd, "x."); |
| |
| StringBuilder str = new StringBuilder(); |
| |
| // execute the individual queries |
| for (String query : queries) { |
| find(c, "where " + query); |
| str.append(str.length() > 0 ? " or " : "").append(query); |
| } |
| |
| // now execute all the queries combined |
| find(c, "where " + str); |
| } |
| } |
| } |
| |
| void getBasicQueries(Set<String> queries, PropertyDescriptor pd, |
| String prefix) throws Exception { |
| |
| // max level of field traversal: 3 |
| // ### if (prefix.split("\\.").length > 3) |
| if (prefix.split("\\.").length > 2) |
| return; |
| |
| Class type = pd.getPropertyType(); |
| |
| String name = prefix + pd.getName(); |
| |
| if (!queries.add(name + " is not null")) |
| return; |
| |
| queries.add(name + " is null"); |
| |
| if (type.isAssignableFrom(Number.class) || type == int.class || |
| type == double.class || type == float.class || |
| type == long.class || type == short.class) { |
| queries.add(name + " = 0"); |
| queries.add(name + " <> 0"); |
| queries.add(name + " > 0"); |
| queries.add(name + " < 0"); |
| queries.add(name + " >= 0"); |
| queries.add(name + " <= 0"); |
| queries.add("sqrt(" + name + ") <> 0"); |
| queries.add("abs(" + name + ") <> 0"); |
| // queries.add("mod(" + name + ", 5) <> 0"); |
| } |
| |
| if (type.isAssignableFrom(Collection.class)) { |
| queries.add(name + " IS EMPTY"); |
| queries.add(name + " IS NOT EMPTY"); |
| queries.add("size(" + name + ") <> 0"); |
| } |
| |
| if (type.isAssignableFrom(String.class)) { |
| queries.add("lower(" + name + ") = 'x'"); |
| queries.add("upper(" + name + ") = 'x'"); |
| queries.add("concat(" + name + ", " + name + ") = 'x'"); |
| queries.add("substring(" + name + ", 1, 2) = 'x'"); |
| queries.add("length(" + name + ") > 0"); |
| queries.add("locate(" + name + ", 'x', 1) > 0"); |
| queries.add("trim(leading ' ' from " + name + ") = 'x'"); |
| } |
| |
| if (type.isAssignableFrom(Date.class)) { |
| queries.add(name + " <> CURRENT_TIMESTAMP"); |
| } |
| |
| // relation is an entity ... add all the relations |
| if (impls.containsKey(type) || impls.containsValue(type)) { |
| for (PropertyDescriptor desc : |
| Introspector.getBeanInfo(type).getPropertyDescriptors()) { |
| |
| if (desc.getWriteMethod() == null) // ignore read-only |
| continue; |
| |
| // prevent recursion |
| if (name.endsWith("." + desc.getName() + ".")) |
| continue; |
| |
| getBasicQueries(queries, desc, name + "."); |
| } |
| } |
| } |
| |
| void checkModel() { |
| try { |
| verifyModel(); |
| } catch (AssertionFailedError e) { |
| // clear all existing instances |
| clear(emf, impls.values().toArray(new Class[impls.size()])); |
| |
| // since the factory method needs to be static, we need to store |
| // the classes statically |
| factoryClasses = impls; |
| try { |
| final List<Exception> exceptions = new LinkedList<Exception>(); |
| XMLDecoder decoder = new XMLDecoder(CompanyModelTest.class. |
| getResourceAsStream("companies.xml")); |
| decoder.setExceptionListener(new ExceptionListener() { |
| public void exceptionThrown(Exception e) { |
| exceptions.add(e); |
| } |
| }); |
| Collection obs = (Collection) decoder.readObject(); |
| |
| if (exceptions.size() > 0) { |
| throw new IllegalStateException(exceptions.get(0)); |
| } |
| |
| assertNotNull(obs); |
| |
| persist(obs.toArray()); |
| } finally { |
| factoryClasses = null; |
| } |
| } |
| |
| verifyModel(); |
| } |
| |
| int queryCount(Class c, String query, Object... params) { |
| return find(c, query, params).size(); |
| } |
| |
| int queryCount(Class c) { |
| return find(c, null).size(); |
| } |
| |
| Class impl(Class c) { |
| return impls.get(c); |
| } |
| |
| void verifyModel() { |
| assertEquals(2, queryCount(impl(ICompany.class))); |
| assertEquals(11, queryCount(impl(IAddress.class))); |
| assertEquals(3, queryCount(impl(IProduct.class))); |
| assertEquals(2, queryCount(impl(IProductOrder.class))); |
| assertEquals(3, queryCount(impl(ILineItem.class))); |
| assertEquals(1, queryCount(impl(IPartTimeEmployee.class))); |
| assertEquals(3, queryCount(impl(IFullTimeEmployee.class))); |
| assertEquals(4, queryCount(impl(ICustomer.class))); |
| |
| assertEquals(3, queryCount(impl(IAddress.class), |
| "where x.state = 'CA'")); |
| |
| assertEquals(1, queryCount(impl(ICompany.class), |
| "where size(x.employees) = 4")); |
| assertEquals(1, queryCount(impl(ICompany.class), |
| "where size(x.employees) = 0")); |
| |
| assertEquals(2, queryCount(impl(ICustomer.class), |
| "where size(x.orders) = 1")); |
| |
| assertEquals(1, queryCount(impl(IProductOrder.class), |
| "where x.shippedDate is null")); |
| assertEquals(1, queryCount(impl(IProductOrder.class), |
| "where x.shippedDate is not null")); |
| |
| assertEquals(1, queryCount(impl(IEmployee.class), |
| "where x.manager is null")); |
| assertEquals(2, queryCount(impl(IEmployee.class), |
| "where x.manager.manager is null")); |
| assertEquals(1, queryCount(impl(IEmployee.class), |
| "where x.manager.manager.manager is null")); |
| |
| assertEquals(2, queryCount(impl(IPerson.class), |
| "where x.firstName like ?1 and x.lastName like ?1", "M%")); |
| assertEquals(1, queryCount(impl(IPerson.class), |
| "where x.homeAddress.state = 'CA'")); |
| } |
| |
| /** |
| * Factory method that is called from the serialized XML. |
| */ |
| public static Object create(Class intf) |
| throws InstantiationException, IllegalAccessException { |
| return factoryClasses.get(intf).newInstance(); |
| } |
| } |
| |