/** * * 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 test.sdo21.tests.general; import commonj.sdo.*; import commonj.sdo.helper.*; import org.junit.After; import static org.junit.Assert.*; import org.junit.Before; import org.junit.Test; import test.sdo21.framework.CTSTestCase; import test.sdo21.tests.util.XMLEqualityChecker; import java.io.*; import java.math.BigDecimal; import java.net.URL; /** * Tests various concepts against the XMLHelper, including ... * * @see 2.1 spec section 3.11 */ public class XMLHelperTest extends CTSTestCase { private static final String CUSTOMER1_XML = "/customer1.xml"; private static final String CUSTOMER2_XML = "/customer2.xml"; private static final String MIXED_XML = "/mixed2.xml"; private static final String MIXEDOPEN_XML = "/mixedopen.xml"; /** * Verify how the XMLHelper handles serialization of a DataObject which includes a ChangeSummary.
* Checks are made before and after an {@link ChangeSummary#undoChanges()} call * @see 2.1 spec section 3.3.5 * @see XMLHelper#save(DataObject, String, String) */ @Test public void testChangeSummary() throws Exception { final String TEST_MODEL = "/simpleWithChangeSummary.xsd"; final String TEST_NAMESPACE = "http://www.example.com/simpleCS"; final String TEST_DATA_BEFORE_UNDO = "/simpleWithChangeSummary.xml"; final String TEST_DATA_AFTER_UNDO = "/simpleWithChangeSummaryUndone.xml"; // Populate the meta data for the test (Stock Quote) model URL url = getClass().getResource(TEST_MODEL); InputStream inputStream = url.openStream(); getScope().getXSDHelper().define(inputStream, url.toString()); inputStream.close(); Type quoteType = getScope().getTypeHelper().getType(TEST_NAMESPACE, "RootQuote"); DataObject quote = getScope().getDataFactory().create(quoteType); ChangeSummary cs = quote.getChangeSummary(); ChangeSummary csp = (ChangeSummary)quote.get("changes"); assertSame("The ChangeSummary Property should be returned by getChangeSummary.", cs, csp); quote.setString("symbol", "fbnt"); quote.setString("companyName", "FlyByNightTechnology"); quote.setBigDecimal("price", new BigDecimal("1000.0")); DataObject child = quote.createDataObject("quotes"); child.setBigDecimal("price", new BigDecimal("1500.0")); child = quote.createDataObject("quotes"); child.setBigDecimal("price", new BigDecimal("2000.0")); child = child.createDataObject("quotes"); child.setBigDecimal("price", new BigDecimal("2000.99")); child = quote.createDataObject("quotes"); child.setBigDecimal("price", new BigDecimal("2500.0")); // Begin logging changes // cs.beginLogging(); // Modify the data graph in various ways // quote.setString("symbol", "FBNT"); quote.setBigDecimal("price", new BigDecimal("999.0")); quote.setDouble("volume", 1000); child = quote.createDataObject("quotes"); child.setBigDecimal("price", new BigDecimal("3000.0")); child = quote.createDataObject("quotes"); child.setBigDecimal("price", new BigDecimal("4000.0")); quote.getDataObject("quotes[2]").delete(); // Stop logging changes and serialize the resulting data graph cs.endLogging(); ByteArrayOutputStream baos = new ByteArrayOutputStream(); getScope().getXMLHelper().save(quote, TEST_NAMESPACE, "stockQuote", baos); try { XMLEqualityChecker.compareXmlFiles( new ByteArrayInputStream(baos.toByteArray()), getClass().getResource(TEST_DATA_BEFORE_UNDO) ); } catch (Exception e) { fail("XMLHelper did not accurately reflect the ChangeSummary: " + e.getMessage()); } // Undo all changes and then serialize the resulting data graph again cs.undoChanges(); baos = new ByteArrayOutputStream(); getScope().getXMLHelper().save(quote, TEST_NAMESPACE, "stockQuote", baos); try { XMLEqualityChecker.compareXmlFiles( new ByteArrayInputStream(baos.toByteArray()), getClass().getResource(TEST_DATA_AFTER_UNDO) ); } catch (Exception e) { fail( "XMLHelper did not accurately reflect the ChangeSummary after undoChanges(): " + e.getMessage() ); } } /** * Verify how the XMLHelper handles open content.
* Ensures that the open content is serialized properly. * Uses global properties from the XSD, and open content properties * defined by the dynamic API.
* TODO -- is this primarily a TypeHelper test? Consider moving. * * @see 2.1 spec section 3.6.6 * @see 2.1 spec section 3.8.3 */ @Test public void testDefineOpenContentProperty() throws IOException { final String TEST_MODEL = "/open.xsd"; final String TEST_NAMESPACE = "http://www.example.com/open"; final String TEST_DATA = "/openContentProperty.xml"; TypeHelper typeHelper; XSDHelper xsdHelper; XMLHelper xmlHelper; DataFactory dataFactory; typeHelper = getScope().getTypeHelper(); dataFactory = getScope().getDataFactory(); xsdHelper = getScope().getXSDHelper(); xmlHelper = getScope().getXMLHelper(); // Populate the meta data for the test (Stock Quote) model URL url = getClass().getResource(TEST_MODEL); InputStream inputStream = url.openStream(); xsdHelper.define(inputStream, url.toString()); inputStream.close(); Type quoteType = typeHelper.getType(TEST_NAMESPACE, "OpenQuote"); DataObject quote = dataFactory.create(quoteType); assertNotNull( quote ); quote.setString("symbol", "s1"); Property companyProperty = typeHelper.getOpenContentProperty(TEST_NAMESPACE, "company"); DataObject company = quote.createDataObject(companyProperty); company.setString("name", "FlyByNightTechnology"); Property priceProperty = typeHelper.getOpenContentProperty(TEST_NAMESPACE, "price"); quote.getList(priceProperty).add(new BigDecimal("1000.0")); // Define a new SDO open content property with simple type DataObject p = dataFactory.create("commonj.sdo", "Property"); p.set("type", typeHelper.getType("commonj.sdo", "Decimal")); p.set("name", "highPrice"); Property highPrice = typeHelper.defineOpenContentProperty(TEST_NAMESPACE, p); quote.setBigDecimal(highPrice, new BigDecimal("1100.0")); // Define a new SDO open content property with complex type DataObject mutualFundQuotePropertyDef = dataFactory.create("commonj.sdo", "Property"); mutualFundQuotePropertyDef.set("type", quoteType); mutualFundQuotePropertyDef.set("name", "mutualFundQuote"); mutualFundQuotePropertyDef.setBoolean("containment", true); Property mutualFundQuoteProperty = typeHelper.defineOpenContentProperty(TEST_NAMESPACE, mutualFundQuotePropertyDef); DataObject mutualFundQuote = quote.createDataObject(mutualFundQuoteProperty); mutualFundQuote.setString("symbol", "mutual-1"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); xmlHelper.save(quote, TEST_NAMESPACE, "openStockQuote", baos); try { XMLEqualityChecker.compareXmlFiles( new ByteArrayInputStream(baos.toByteArray()), getClass().getResource(TEST_DATA) ); } catch (Exception e) { fail("XMLHelper did not accurately reflect open content." + e.getMessage()); } // validate existing property condition Property duplicateProp = typeHelper.defineOpenContentProperty(TEST_NAMESPACE, p); assertTrue("The expected Property equality was not true", highPrice.equals(duplicateProp)); // validate error condition, where new property exists with different // type boolean errorCondition = false; try { p = dataFactory.create("commonj.sdo", "Property"); p.set("type", typeHelper.getType("commonj.sdo", "String")); p.set("name", "highPrice"); highPrice = typeHelper.defineOpenContentProperty(TEST_NAMESPACE, p); } catch (IllegalArgumentException ex) { errorCondition = true; } assertTrue("Should not be able to redefine a Property with a different Type.", errorCondition); } /** * Verify how the XMLHelper handles Types defined using the TypeHelper. Save * and load the Dataobject with the XMLHelper as an intermediate step.
* TODO this is a hybrid test that needs some refactoring. It implicitly tests * dynamic type creation, creation of dynamic types, xml round tripping and the * dataObject API without a great deal of structure. Some assertions are * irrelevant since the tests would throw NPEs before performing the * tests. Other assertions could be stronger than checking for non-null. See also * testDefineTypes for similar issues.
* @see SDO spec 2..1 section 3.8.4 * @see SDO spec 2..1 section 3.11.3 * @see TypeHelper#define(DataObject) * @see XMLHelper#save(DataObject, String, String, java.io.OutputStream) * @see XMLHelper#load(InputStream, String, Object) * */ @Test public void testDefineTypeRoundTrip() throws Exception { TypeHelper types = getScope().getTypeHelper(); DataFactory factory = getScope().getDataFactory(); XMLHelper xmlHelper = getScope().getXMLHelper(); Type intType = types.getType("commonj.sdo", "Int"); assertNotNull( intType ); Type stringType = types.getType("commonj.sdo", "String"); // create a new Type for Customers DataObject customerType = factory.create("commonj.sdo", "Type"); customerType.set("uri", "http://example.com/customer"); customerType.set("name", "Customer"); Property xmlElementProp = getScope().getXSDHelper().getGlobalProperty("commonj.sdo/xml", "xmlElement", false); // create a customer number property DataObject custNumProperty = customerType.createDataObject("property"); custNumProperty.set("name", "custNum"); custNumProperty.set("type", intType); custNumProperty.setBoolean(xmlElementProp, false); // create a first name property DataObject firstNameProperty = customerType.createDataObject("property"); firstNameProperty.set("name", "firstName"); firstNameProperty.set("type", stringType); firstNameProperty.setBoolean(xmlElementProp, false); // create a last name property DataObject lastNameProperty = customerType.createDataObject("property"); lastNameProperty.set("name", "lastName"); lastNameProperty.set("type", stringType); lastNameProperty.setBoolean(xmlElementProp, false); ByteArrayOutputStream baos = new ByteArrayOutputStream(); xmlHelper.save(customerType, "commonj.sdo", "type", baos); ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); XMLDocument xdoc = xmlHelper.load(bais); customerType = xdoc.getRootObject(); // now define the Customer type so that customers can be made types.define(customerType); DataObject customer1 = factory.create("http://example.com/customer", "Customer"); customer1.setInt("custNum", 1); customer1.set("firstName", "John"); customer1.set("lastName", "Adams"); DataObject customer2 = factory.create("http://example.com/customer", "Customer"); customer2.setInt("custNum", 2); customer2.set("firstName", "Jeremy"); customer2.set("lastName", "Pavick"); assertNotNull("Customer1 should not be null", customer1); Type type = customer1.getType(); assertNotNull("Customer1.custNum should not be null", type.getProperty("custNum")); assertNotNull("Customer1.firstName should not be null", type.getProperty("firstName")); assertNotNull("Customer1.lastName should not be null", type.getProperty("lastName")); assertEquals("Customer1.custNum should be intType", type.getProperty("custNum").getType(), intType); assertEquals("Customer1.firstName should be stringType", type.getProperty("firstName").getType(), stringType); assertEquals("Customer1.lastName should be stringType", type.getProperty("lastName").getType(), stringType); assertNotNull("Customer2 should not be null", customer2); type = customer2.getType(); assertNotNull("Customer1.custNum should not be null", type.getProperty("custNum")); assertNotNull("Customer1.custNum should not be null", type.getProperty("firstName")); assertNotNull("Customer1.custNum should not be null", type.getProperty("lastName")); assertEquals("Customer1.custNum should be intType", type.getProperty("custNum").getType(), intType); assertEquals("Customer1.firstName should be stringType", type.getProperty("firstName").getType(), stringType); assertEquals("Customer1.lastName should be stringType", type.getProperty("lastName").getType(), stringType); baos = new ByteArrayOutputStream(); xmlHelper.save(customer1, "http://example.com/customer", "Customer", baos); try { XMLEqualityChecker.compareXmlFiles( new ByteArrayInputStream(baos.toByteArray()), getClass().getResource(CUSTOMER1_XML) ); } catch (Exception e) { fail("XMLHelper did not accurately reflect customer1: " + e.getMessage()); } baos = new ByteArrayOutputStream(); xmlHelper.save(customer2, "http://example.com/customer", "Customer", baos); try { XMLEqualityChecker.compareXmlFiles( new ByteArrayInputStream(baos.toByteArray()), getClass().getResource(CUSTOMER2_XML) ); } catch (Exception e) { fail("XMLHelper did not accurately reflect customer2: " + e.getMessage()); } } /** * Verify how the XMLHelper handles Types defined using the TypeHelper. * TODO this is the same as {@link XMLHelperTest#testDefineTypeRoundTrip()} without * the round tripping of the metametadata. See the issues described in the doc for that method. * @see SDO spec 2..1 section 3.8.4 * @see TypeHelper#define(DataObject) */ @Test public void testDefineType() throws Exception { TypeHelper types = getScope().getTypeHelper(); DataFactory factory = getScope().getDataFactory(); XMLHelper xmlHelper = getScope().getXMLHelper(); Type intType = types.getType("commonj.sdo", "Int"); Type stringType = types.getType("commonj.sdo", "String"); // create a new Type for Customers DataObject customerType = factory.create("commonj.sdo", "Type"); customerType.set("uri", "http://example.com/customer"); customerType.set("name", "Customer"); Property xmlElementProp = getScope().getXSDHelper().getGlobalProperty("commonj.sdo/xml", "xmlElement", false); // create a customer number property DataObject custNumProperty = customerType.createDataObject("property"); custNumProperty.set("name", "custNum"); custNumProperty.set("type", intType); custNumProperty.setBoolean(xmlElementProp, false); // create a first name property DataObject firstNameProperty = customerType.createDataObject("property"); firstNameProperty.set("name", "firstName"); firstNameProperty.set("type", stringType); firstNameProperty.setBoolean(xmlElementProp, false); // create a last name property DataObject lastNameProperty = customerType.createDataObject("property"); lastNameProperty.set("name", "lastName"); lastNameProperty.set("type", stringType); lastNameProperty.setBoolean(xmlElementProp, false); // now define the Customer type so that customers can be made types.define(customerType); DataObject customer1 = factory.create("http://example.com/customer", "Customer"); customer1.setInt("custNum", 1); customer1.set("firstName", "John"); customer1.set("lastName", "Adams"); DataObject customer2 = factory.create("http://example.com/customer", "Customer"); customer2.setInt("custNum", 2); customer2.set("firstName", "Jeremy"); customer2.set("lastName", "Pavick"); assertNotNull("Customer1 should not be null", customer1); Type type = customer1.getType(); assertNotNull("Customer1.custNum should not be null", type.getProperty("custNum")); assertNotNull("Customer1.firstName should not be null", type.getProperty("firstName")); assertNotNull("Customer1.lastName should not be null", type.getProperty("lastName")); assertEquals("Customer1.custNum should be intType", type.getProperty("custNum").getType(), intType); assertEquals("Customer1.firstName should be stringType", type.getProperty("firstName").getType(), stringType); assertEquals("Customer1.lastName should be stringType", type.getProperty("lastName").getType(), stringType); assertNotNull("Customer2 should not be null", customer2); type = customer2.getType(); assertNotNull("Customer1.custNum should not be null", type.getProperty("custNum")); assertNotNull("Customer1.custNum should not be null", type.getProperty("firstName")); assertNotNull("Customer1.custNum should not be null", type.getProperty("lastName")); assertEquals("Customer1.custNum should be intType", type.getProperty("custNum").getType(), intType); assertEquals("Customer1.firstName should be stringType", type.getProperty("firstName").getType(), stringType); assertEquals("Customer1.lastName should be stringType", type.getProperty("lastName").getType(), stringType); ByteArrayOutputStream baos = new ByteArrayOutputStream(); xmlHelper.save(customer1, "http://example.com/customer", "Customer", baos); try { XMLEqualityChecker.compareXmlFiles( new ByteArrayInputStream(baos.toByteArray()), getClass().getResource(CUSTOMER1_XML) ); } catch (Exception e) { fail("XMLHelper did not accurately reflect customer1: " + e.getMessage()); } baos = new ByteArrayOutputStream(); xmlHelper.save(customer2, "http://example.com/customer", "Customer", baos); try { XMLEqualityChecker.compareXmlFiles( new ByteArrayInputStream(baos.toByteArray()), getClass().getResource(CUSTOMER2_XML) ); } catch (Exception e) { fail("XMLHelper did not accurately reflect customer2: " + e.getMessage()); } } /** * Verify how the XMLHelper handles defined Sequence types. * @see SDO spec 2..1 section 3.1.8 * @see DataObject#getSequence() * @see Sequence#addText(String) * @see Sequence#add(Property, Object) */ @Test public void testDefineSequencedType() throws Exception { TypeHelper types = getScope().getTypeHelper(); DataFactory factory = getScope().getDataFactory(); XMLHelper xmlHelper = getScope().getXMLHelper(); Type stringType = types.getType("commonj.sdo", "String"); Type decimalType = types.getType("commonj.sdo", "Decimal"); // Define a new mixed type - MixedQuote DataObject mixedQuoteType = factory.create("commonj.sdo", "Type"); mixedQuoteType.set("uri", "http://www.example.com/mixed"); mixedQuoteType.set("name", "MixedQuote"); mixedQuoteType.set("sequenced", Boolean.TRUE); DataObject symbolProperty = mixedQuoteType.createDataObject("property"); symbolProperty.set("name", "symbol"); symbolProperty.set("type", stringType); DataObject companyNameProperty = mixedQuoteType.createDataObject("property"); companyNameProperty.set("name", "companyName"); companyNameProperty.set("type", stringType); DataObject priceProperty = mixedQuoteType.createDataObject("property"); priceProperty.set("name", "price"); priceProperty.set("type", decimalType); DataObject quotesProperty = mixedQuoteType.createDataObject("property"); quotesProperty.set("name", "quotes"); quotesProperty.set("type", mixedQuoteType); quotesProperty.set("many", Boolean.TRUE); quotesProperty.set("containment", Boolean.TRUE); types.define(mixedQuoteType); DataObject quote = factory.create("http://www.example.com/mixed", "MixedQuote"); assertTrue("Quote type should be Sequenced", quote.getType().isSequenced()); Sequence sequence = quote.getSequence(); sequence.addText("\n "); quote.setString("symbol", "fbnt"); sequence.addText("\n "); quote.setString("companyName", "FlyByNightTechnology"); sequence.addText("\n some text\n "); DataObject child = quote.createDataObject("quotes"); child.setBigDecimal("price", new BigDecimal("2000.0")); sequence.addText("\n more text\n "); // quote.setBigDecimal("price", new BigDecimal("1000.0")); sequence.add("price", new BigDecimal("1000.0")); sequence.addText("\n"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); xmlHelper.save(quote, "http://www.example.com/mixed", "mixedStockQuote", baos); try { XMLEqualityChecker.compareXmlFiles( new ByteArrayInputStream(baos.toByteArray()), getClass().getResource(MIXED_XML) ); } catch (Exception e) { fail("XMLHelper did not accurately reflect quote: " + e.getMessage()); } } /** * Verify how the XMLHelper handles Types which are Sequenced and Open. * @see SDO spec 2..1 section 3.1.8 * @see DataObject#getSequence() * @see Sequence#addText(String) * @see Sequence#add(Property, Object) * @see TypeHelper#defineOpenContentProperty(String, DataObject) * @see TypeHelper#getOpenContentProperty(String, String) */ @Test public void testDefineSequencedOpenType() throws Exception { TypeHelper types = getScope().getTypeHelper(); DataFactory factory = getScope().getDataFactory(); XMLHelper xmlHelper = getScope().getXMLHelper(); Type stringType = types.getType("commonj.sdo", "String"); Type decimalType = types.getType("commonj.sdo", "Decimal"); // Define a new mixed type - MixedQuote DataObject mixedQuoteType = factory.create("commonj.sdo", "Type"); mixedQuoteType.set("uri", "http://www.example.com/mixed"); mixedQuoteType.set("name", "MixedOpenQuote"); mixedQuoteType.set("sequenced", Boolean.TRUE); mixedQuoteType.set("open", Boolean.TRUE); // DataObject symbolProperty = // mixedQuoteType.createDataObject("property"); // symbolProperty.set("name", "symbol"); // symbolProperty.set("type", stringType); DataObject companyNameProperty = mixedQuoteType.createDataObject("property"); companyNameProperty.set("name", "companyName"); companyNameProperty.set("type", stringType); DataObject priceProperty = mixedQuoteType.createDataObject("property"); priceProperty.set("name", "price"); priceProperty.set("type", decimalType); DataObject quotesProperty = mixedQuoteType.createDataObject("property"); quotesProperty.set("name", "quotes"); quotesProperty.set("type", mixedQuoteType); quotesProperty.set("many", Boolean.TRUE); quotesProperty.set("containment", Boolean.TRUE); types.define(mixedQuoteType); // Define a global property DataObject symbolProperty = factory.create("commonj.sdo", "Property"); symbolProperty.set("name", "symbol"); symbolProperty.set("type", stringType); symbolProperty.set("containment", Boolean.TRUE); types.defineOpenContentProperty("http://www.example.com/open", symbolProperty); DataObject quote = factory.create("http://www.example.com/mixed", "MixedOpenQuote"); assertTrue("Quote type should be Sequenced.", quote.getType().isSequenced()); Sequence sequence = quote.getSequence(); sequence.addText("\n "); Property definedSymbolProperty = types.getOpenContentProperty("http://www.example.com/open", "symbol"); quote.setString(definedSymbolProperty, "fbnt"); sequence.addText("\n "); quote.setString("companyName", "FlyByNightTechnology"); sequence.addText("\n some text\n "); DataObject child = quote.createDataObject("quotes"); child.setBigDecimal("price", new BigDecimal("2000.0")); sequence.addText("\n more text\n "); // quote.setBigDecimal("price", new BigDecimal("1000.0")); sequence.add("price", new BigDecimal("1000.0")); sequence.addText("\n"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); xmlHelper.save(quote, "http://www.example.com/mixed", "mixedOpenStockQuote", baos); FileOutputStream fos = new FileOutputStream("XMLTCOutput"); xmlHelper.save(quote, "http://www.example.com/mixed", "mixedOpenStockQuote", fos); try { XMLEqualityChecker.compareXmlFiles( new ByteArrayInputStream(baos.toByteArray()), getClass().getResource(MIXEDOPEN_XML) ); } catch (Exception e) { fail("XMLHelper did not accurately reflect quote: " + e.getMessage()); } } @Before public void setUp() throws Exception { super.setUp(); } @After public void tearDown() throws Exception { super.tearDown(); } }