/* * Copyright (c) 2010, SQL Power Group Inc. * * This file is part of SQL Power Library. * * SQL Power Library is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * SQL Power Library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package ca.sqlpower.sqlobject; import java.sql.Types; import java.util.ArrayList; import java.util.List; import ca.sqlpower.dao.SPPersisterListener; import ca.sqlpower.dao.SPSessionPersister; import ca.sqlpower.object.CountingSPListener; import ca.sqlpower.object.ObjectDependentException; import ca.sqlpower.object.SPChildEvent; import ca.sqlpower.object.SPChildEvent.EventType; import ca.sqlpower.object.SPObject; import ca.sqlpower.sqlobject.SQLTypePhysicalProperties.SQLTypeConstraint; import ca.sqlpower.sqlobject.SQLTypePhysicalPropertiesProvider.PropertyType; import ca.sqlpower.testutil.GenericNewValueMaker; import ca.sqlpower.testutil.NewValueMaker; /** * This particular test case is to ensure that {@link UserDefinedSQLType} * follows the following particular behaviour for its setters and getters: * <ul> * <li>Using a getter requires giving a platform name. This means the getter * will retrieve the requested property as setup for that particular platform.</li> * <li>A type may proxy requests to another type from which it 'inherits' * properties. This allows a type to inherit properties from another, (a domain * or User Defined Type), but make modifications on its own properties without * changing the properties of the types it inherits from</li> * <li>For getters, if a type does not have any properties defined for the * requested platform, or it does not have the requested property defined for * the requested platform, then it proxies the request to its upstream * UserDefinedDataType.</li> * <li>The setters for a UserDefinedSQLType will only edit the properties for * its instance. Unlike getters, it will not proxy requests to upstream data * types. This allows upstream data types to remain unedited.</li> * </ul> */ public class UserDefinedSQLTypeTest extends BaseSQLObjectTestCase { public UserDefinedSQLTypeTest(String name) throws Exception { super(name); } /** * The 'type proxy' that would typically be the instance that a SQLColumn * would use. */ private UserDefinedSQLType typeProxy; /** * A 'domain' type that acts as the upstream type for the type proxy. The * type proxy therefore inherits properties from it. */ private UserDefinedSQLType domain; /** * A user-defined type that acts as the upstream type for the domain. */ private UserDefinedSQLType udt; private SQLTypePhysicalProperties udtProperties; private SQLTypePhysicalProperties domainProperties; protected void setUp() throws Exception { super.setUp(); udt = new UserDefinedSQLType(); udtProperties = new SQLTypePhysicalProperties("Oracle"); udt.putPhysicalProperties("Oracle", udtProperties); udt.setType(Types.VARCHAR); domain = new UserDefinedSQLType(); domain.setUpstreamType(udt); domainProperties = new SQLTypePhysicalProperties("Oracle"); domain.putPhysicalProperties("Oracle", domainProperties); typeProxy = new UserDefinedSQLType(); typeProxy.setUpstreamType(domain); getRootObject().addChild(udt, 0); getRootObject().addChild(typeProxy, 0); getRootObject().addChild(domain, 0); } public void testGetScale() throws Exception { typeProxy.getDefaultPhysicalProperties().setScale(1); typeProxy.getDefaultPhysicalProperties().setScaleType(PropertyType.VARIABLE); udtProperties.setScale(2); udtProperties.setScaleType(PropertyType.VARIABLE); assertEquals(1, typeProxy.getScale("Oracle")); } public void testSetScale() throws Exception { final String platform = "Oracle"; typeProxy.setScale(platform, 3); typeProxy.setScaleType(platform, PropertyType.VARIABLE); assertEquals(3, typeProxy.getScale(platform)); } public void testGetPrecision() throws Exception { typeProxy.getDefaultPhysicalProperties().setPrecision(1); typeProxy.getDefaultPhysicalProperties().setPrecisionType(PropertyType.VARIABLE); udtProperties.setPrecision(2); udtProperties.setPrecisionType(PropertyType.VARIABLE); assertEquals(1, typeProxy.getPrecision("Oracle")); } public void testSetPrecision() throws Exception { final String platform = "Oracle"; typeProxy.setPrecision(platform, 3); typeProxy.setPrecisionType(platform, PropertyType.VARIABLE); assertEquals(3, typeProxy.getPrecision(platform)); } public void testGetEnumeration() throws Exception { SQLEnumeration proxyEnum = new SQLEnumeration("proxy"); typeProxy.getDefaultPhysicalProperties().addEnumeration(proxyEnum); SQLEnumeration udtEnum = new SQLEnumeration("udt"); udtProperties.addEnumeration(udtEnum); assertEquals(proxyEnum, typeProxy.getEnumerations("Oracle").get(0)); } public void testAddEnumeration() throws Exception { SQLEnumeration enumeration = new SQLEnumeration("enum"); typeProxy.addEnumeration("Oracle", enumeration); assertEquals(enumeration, typeProxy.getEnumerations("Oracle").get(0)); } public void testRemoveEnumeration() throws Exception { SQLEnumeration enumeration = new SQLEnumeration("enum"); typeProxy.addEnumeration("Oracle", enumeration); typeProxy.removeEnumeration("Oracle", enumeration); assertTrue(typeProxy.getEnumerations("Oracle").isEmpty()); } public void testGetDefaultValue() throws Exception { typeProxy.getDefaultPhysicalProperties().setDefaultValue("proxy"); udtProperties.setDefaultValue("udt"); assertEquals("proxy", typeProxy.getDefaultValue("Oracle")); } public void testSetDefaultValue() throws Exception { typeProxy.setDefaultValue("Oracle", "default"); assertEquals("default", typeProxy.getDefaultValue("Oracle")); } public void testGetConstraintType() throws Exception { typeProxy.getDefaultPhysicalProperties().setConstraintType(SQLTypeConstraint.CHECK); udtProperties.setConstraintType(SQLTypeConstraint.ENUM); assertEquals(SQLTypeConstraint.CHECK, typeProxy.getConstraintType("Oracle")); } public void testSetConstraintType() throws Exception { typeProxy.setConstraintType("Oracle", SQLTypeConstraint.CHECK); assertEquals(SQLTypeConstraint.CHECK, typeProxy.getConstraintType("Oracle")); } public void testGetCheckConstraints() throws Exception { SQLCheckConstraint constraint1 = new SQLCheckConstraint("testGetCheckConstraints - typeProxy", "Matches A1A 1A1"); SQLCheckConstraint constraint2 = new SQLCheckConstraint("testGetCheckConstraints - udtProperties", "Matches 12345"); typeProxy.getDefaultPhysicalProperties().addCheckConstraint(constraint1); udtProperties.addCheckConstraint(constraint2); assertEquals(1, typeProxy.getCheckConstraints("Oracle").size()); assertEquals(constraint1, typeProxy.getCheckConstraints("Oracle").get(0)); } public void testAddCheckConstraint() throws Exception { SQLCheckConstraint checkConstraint = new SQLCheckConstraint("testAddcheckConstraint", "Matches A1A 1A1"); typeProxy.addCheckConstraint("Oracle", checkConstraint); assertEquals(1, typeProxy.getCheckConstraints("Oracle").size()); assertEquals(checkConstraint, typeProxy.getCheckConstraints("Oracle").get(0)); } public void testRemoveCheckConstraint() throws Exception { SQLCheckConstraint checkConstraint = new SQLCheckConstraint("testRemoveCheckConstraint", "Matches A1A 1A1"); typeProxy.addCheckConstraint("Oracle", checkConstraint); typeProxy.removeCheckConstraint("Oracle", checkConstraint); assertTrue(typeProxy.getCheckConstraints("Oracle").isEmpty()); } public void testGetPrecisionType() throws Exception { typeProxy.getDefaultPhysicalProperties().setPrecisionType(PropertyType.CONSTANT); udtProperties.setPrecisionType(PropertyType.VARIABLE); assertEquals(PropertyType.CONSTANT, typeProxy.getPrecisionType("Oracle")); } public void testSetPrecisionType() throws Exception { typeProxy.setPrecisionType("Oracle", PropertyType.NOT_APPLICABLE); assertEquals(PropertyType.NOT_APPLICABLE, typeProxy.getPrecisionType("Oracle")); } /** * this test ensures that the new physical properties object replaces the * old when they have the same platform */ public void testSamePlatformOverwritesOld() throws Exception { UserDefinedSQLType obj = (UserDefinedSQLType) getSQLObjectUnderTest(); SQLTypePhysicalProperties props0 = new SQLTypePhysicalProperties("testPlatform"); SQLTypePhysicalProperties props1 = new SQLTypePhysicalProperties("testPlatform"); obj.putPhysicalProperties(props0.getPlatform(), props0); assertEquals(props0.getUUID(), obj.getPhysicalProperties(props0.getPlatform()).getUUID()); obj.putPhysicalProperties(props0.getPlatform(), props1); assertEquals(props1.getUUID(), obj.getPhysicalProperties(props0.getPlatform()).getUUID()); } @Override protected Class<? extends SPObject> getChildClassType() { return SQLTypePhysicalProperties.class; } @Override protected SQLObject getSQLObjectUnderTest() throws SQLObjectException { return typeProxy; } /** * Overriden because the superclass version does not account for the default * physical properties child, which must always exist and always be at index * 0. Inserting a child at 0 results in an exception being thrown. */ @Override public void testAllChildHandlingMethods() throws SQLObjectException, IllegalArgumentException, ObjectDependentException { if (!getSQLObjectUnderTest().allowsChildren()) return; getSQLObjectUnderTest().populate(); NewValueMaker newValueMaker = new GenericNewValueMaker(getRootObject()); Class<? extends SPObject> childType = getSQLObjectUnderTest().getAllowedChildTypes().get(0); int childCount = getSQLObjectUnderTest().getChildCount(); List<SPObject> children = new ArrayList<SPObject>(); children.addAll(getSQLObjectUnderTest().getChildren(childType)); SQLObject x = (SQLObject) newValueMaker.makeNewValue(childType, null, ""); getSQLObjectUnderTest().addChild(x); assertEquals(childCount + 1, getSQLObjectUnderTest().getChildCount()); assertEquals(x, getSQLObjectUnderTest().getChildren(childType).get( getSQLObjectUnderTest().getChildren(childType).size() - 1)); SQLObject y = (SQLObject) newValueMaker.makeNewValue(childType, null, ""); // Test addChild(SQLObject, int) getSQLObjectUnderTest().addChild(y, 1); assertEquals(y, getSQLObjectUnderTest().getChildren(y.getClass()).get(1)); assertEquals(x, getSQLObjectUnderTest().getChildren(childType).get( getSQLObjectUnderTest().getChildren(childType).size() - 1)); getSQLObjectUnderTest().removeChild(x); children.add(0, y); assertTrue(getSQLObjectUnderTest().getChildren(childType).containsAll(children)); getSQLObjectUnderTest().removeChild(y); assertEquals(childCount, getSQLObjectUnderTest().getChildCount()); } /** * Overriden because the superclass version does not account for the default * physical properties child, which must always exist and always be at index * 0. Inserting a child at 0 results in an exception being thrown. */ @Override public void testPreRemoveEventNoVeto() throws Exception { if (!getSQLObjectUnderTest().allowsChildren()) return; getSQLObjectUnderTest().populate(); Class<? extends SPObject> childType = getSQLObjectUnderTest().getAllowedChildTypes().get(0); NewValueMaker newValueMaker = new GenericNewValueMaker(getRootObject()); SQLObject x = (SQLObject) newValueMaker.makeNewValue(childType, null, ""); int childCount = getSQLObjectUnderTest().getChildCount(); getSQLObjectUnderTest().addChild(x); CountingSQLObjectPreEventListener l = new CountingSQLObjectPreEventListener(); getSQLObjectUnderTest().addSQLObjectPreEventListener(l); l.setVetoing(false); getSQLObjectUnderTest().removeChild(getSQLObjectUnderTest().getChild(1)); assertEquals("Event fired", 1, l.getPreRemoveCount()); assertEquals("Child removed", childCount, getSQLObjectUnderTest().getChildren().size()); } /** * Overriden because the superclass version does not account for the default * physical properties child, which must always exist and always be at index * 0. Inserting a child at 0 results in an exception being thrown. */ @Override public SPObject testSPPersisterAddsChild() throws Exception { NewValueMaker valueMaker = createNewValueMaker(getRootObject(), getPLIni()); SPObject spObject = getSPObjectUnderTest(); int oldChildCount = spObject.getChildren().size(); if (!spObject.allowsChildren()) return null; Class<? extends SPObject> childClassType = getChildClassType(); if (childClassType == null) return null; SPSessionPersister persister = new TestingSessionPersister("test", getSPObjectUnderTest(), getConverter()); persister.setWorkspaceContainer(getSPObjectUnderTest().getWorkspaceContainer()); SPPersisterListener listener = new SPPersisterListener(persister, getConverter()); SPObject newChild = (SPObject) valueMaker.makeNewValue(childClassType, null, "child"); newChild.setParent(spObject); listener.childAdded(new SPChildEvent(spObject, childClassType, newChild, 1, EventType.ADDED)); assertEquals(oldChildCount + 1, spObject.getChildren().size()); assertEquals(newChild, spObject.getChildren(childClassType).get(1)); newChild.removeSPListener(listener); //Find the actual child under the object under test as the persister will make a new, //different object to add not the newChild object. This lets the objects compare //equal by reference. for (SPObject existingChild : spObject.getChildren(childClassType)) { if (existingChild.getUUID().equals(newChild.getUUID())) { return existingChild; } } return null; } /** * Overriden because the superclass version does not account for the default * physical properties child, which must always exist and always be at index * 0. Inserting a child at 0 results in an exception being thrown. */ @Override public void testAddChildFiresEvents() throws Exception { SPObject o = getSPObjectUnderTest(); if (!o.allowsChildren()) return; Class<?> childClassType = getChildClassType(); if (childClassType == null) return; CountingSPListener listener = new CountingSPListener(); o.addSPListener(listener); NewValueMaker valueMaker = createNewValueMaker(getRootObject(), getPLIni()); SPObject newChild = (SPObject) valueMaker.makeNewValue(childClassType, null, "child"); o.addChild(newChild, 1); assertEquals(1, listener.getChildAddedCount()); } }