/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.translator.odata; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Properties; import org.junit.Test; import org.odata4j.edm.EdmAssociation; import org.odata4j.edm.EdmAssociationEnd; import org.odata4j.edm.EdmComplexType; import org.odata4j.edm.EdmEntitySet; import org.odata4j.edm.EdmEntityType; import org.odata4j.edm.EdmMultiplicity; import org.odata4j.edm.EdmNavigationProperty; import org.odata4j.edm.EdmProperty; import org.odata4j.edm.EdmReferentialConstraint; import org.odata4j.edm.EdmSimpleType; import org.odata4j.format.xml.EdmxFormatParser; import org.odata4j.stax2.util.StaxUtil; import org.teiid.core.util.ObjectConverterUtil; import org.teiid.core.util.UnitTestUtil; import org.teiid.metadata.BaseColumn.NullType; import org.teiid.metadata.Column; import org.teiid.metadata.ForeignKey; import org.teiid.metadata.KeyRecord; import org.teiid.metadata.KeyRecord.Type; import org.teiid.metadata.MetadataFactory; import org.teiid.metadata.Procedure; import org.teiid.metadata.Table; import org.teiid.query.function.FunctionTree; import org.teiid.query.function.UDFSource; import org.teiid.query.metadata.DDLStringVisitor; import org.teiid.query.metadata.MetadataValidator; import org.teiid.query.metadata.SystemMetadata; import org.teiid.query.metadata.TransformationMetadata; import org.teiid.query.parser.QueryParser; import org.teiid.query.unittest.RealMetadataFactory; import org.teiid.query.validator.ValidatorReport; @SuppressWarnings({"nls", "unused"}) public class TestODataMetadataProcessor { private ODataExecutionFactory translator; @Test public void testSchema() throws Exception { translator = new ODataExecutionFactory(); translator.start(); String csdl = ObjectConverterUtil.convertFileToString(UnitTestUtil.getTestDataFile("northwind.xml")); ODataMetadataProcessor processor = new ODataMetadataProcessor(); Properties props = new Properties(); props.setProperty("schemaNamespace", "ODataWeb.Northwind.Model"); props.setProperty("entityContainer", "NorthwindEntities"); MetadataFactory mf = new MetadataFactory("vdb", 1, "northwind", SystemMetadata.getInstance().getRuntimeTypeMap(), props, null); processor.getMetadata(mf, new EdmxFormatParser().parseMetadata(StaxUtil.newXMLEventReader(new InputStreamReader(new ByteArrayInputStream(csdl.getBytes()))))); TransformationMetadata metadata = RealMetadataFactory.createTransformationMetadata(mf.asMetadataStore(), "northwind", new FunctionTree("foo", new UDFSource(translator.getPushDownFunctions()))); ValidatorReport report = new MetadataValidator().validate(metadata.getVdbMetaData(), metadata.getMetadataStore()); if (report.hasItems()) { throw new RuntimeException(report.getFailureMessage()); } String ddl = DDLStringVisitor.getDDLString(mf.getSchema(), null, null); //System.out.println(ddl); MetadataFactory mf2 = new MetadataFactory("vdb", 1, "northwind", SystemMetadata.getInstance().getRuntimeTypeMap(), new Properties(), null); QueryParser.getQueryParser().parseDDL(mf2, ddl); Procedure p = mf.getSchema().getProcedure("executeVoid"); assertNotNull(p); assertEquals(1, p.getParameters().size()); } @Test public void testEnititySet() throws Exception { ODataMetadataProcessor processor = new ODataMetadataProcessor(); MetadataFactory mf = new MetadataFactory("vdb", 1, "northwind", SystemMetadata.getInstance().getRuntimeTypeMap(), new Properties(), null); ArrayList<EdmProperty.Builder> props = new ArrayList<EdmProperty.Builder>(); props.add(EdmProperty.newBuilder("name").setType(EdmSimpleType.STRING).setMaxLength(25)); props.add(EdmProperty.newBuilder("dob").setType(EdmSimpleType.DATETIME).setNullable(true)); props.add(EdmProperty.newBuilder("ssn").setType(EdmSimpleType.INT64).setNullable(false)); EdmEntityType.Builder entity = EdmEntityType.newBuilder().addProperties(props).addKeys("ssn"); EdmEntitySet es = EdmEntitySet.newBuilder().setName("Person").setEntityType(entity).build(); processor.addEntitySetAsTable(mf, es); assertNotNull(mf.getSchema().getTable("Person")); Table person = mf.getSchema().getTable("Person"); assertEquals(3, person.getColumns().size()); assertNotNull(person.getColumnByName("name")); assertNotNull(person.getColumnByName("dob")); assertNotNull(person.getColumnByName("ssn")); Column name = person.getColumnByName("name"); Column dob = person.getColumnByName("dob"); Column ssn = person.getColumnByName("ssn"); assertEquals("string", name.getDatatype().getRuntimeTypeName()); assertEquals("timestamp", dob.getDatatype().getRuntimeTypeName()); assertEquals("long", ssn.getDatatype().getRuntimeTypeName()); assertTrue(name.getNullType() == NullType.No_Nulls); assertTrue(dob.getNullType() == NullType.Nullable); assertTrue(ssn.getNullType() == NullType.No_Nulls); assertEquals(25, name.getLength()); assertNotNull(person.getPrimaryKey()); assertEquals(1, person.getPrimaryKey().getColumns().size()); assertEquals("ssn", person.getPrimaryKey().getColumns().get(0).getName()); assertTrue(person.getForeignKeys().isEmpty()); } @Test public void testEnititySetWithComplexType() throws Exception { ODataMetadataProcessor processor = new ODataMetadataProcessor(); MetadataFactory mf = new MetadataFactory("vdb", 1, "northwind", SystemMetadata.getInstance().getRuntimeTypeMap(), new Properties(), null); EdmEntitySet es = EdmEntitySet.newBuilder().setName("Person").setEntityType(buildPersonEntity(buildAddressEntity().build())).build(); processor.addEntitySetAsTable(mf, es); assertEquals(1, mf.getSchema().getTables().size()); assertNotNull(mf.getSchema().getTable("Person")); Table personTable = mf.getSchema().getTable("Person"); assertEquals(5, personTable.getColumns().size()); assertNotNull(personTable.getColumnByName("address_street")); } @Test public void testMultipleEnititySetWithSameComplexType() throws Exception { ODataMetadataProcessor processor = new ODataMetadataProcessor(); MetadataFactory mf = new MetadataFactory("vdb", 1, "northwind", SystemMetadata.getInstance().getRuntimeTypeMap(), new Properties(), null); EdmEntitySet es = EdmEntitySet.newBuilder().setName("Person").setEntityType(buildPersonEntity(buildAddressEntity().build())).build(); processor.addEntitySetAsTable(mf, es); es = EdmEntitySet.newBuilder().setName("Business").setEntityType(buildBusinessEntity(buildAddressEntity().build())).build(); processor.addEntitySetAsTable(mf, es); assertEquals(2, mf.getSchema().getTables().size()); assertNotNull(mf.getSchema().getTable("Person")); assertNotNull(mf.getSchema().getTable("Business")); Table personTable = mf.getSchema().getTable("Person"); assertEquals(5, personTable.getColumns().size()); Table businessTable = mf.getSchema().getTable("Business"); assertEquals(4, businessTable.getColumns().size()); assertNotNull(personTable.getColumnByName("address_street")); assertNotNull(businessTable.getColumnByName("address_street")); } @Test public void testOneToOneAssosiation() throws Exception { ODataMetadataProcessor processor = new ODataMetadataProcessor(); MetadataFactory mf = new MetadataFactory("vdb", 1, "northwind", SystemMetadata.getInstance().getRuntimeTypeMap(), new Properties(), null); EdmEntityType.Builder g1Entity = entityType("g1"); EdmEntityType.Builder g2Entity = entityType("g2"); EdmAssociationEnd.Builder aend1 = EdmAssociationEnd.newBuilder() .setRole("source").setType(g1Entity) .setMultiplicity(EdmMultiplicity.ONE); EdmAssociationEnd.Builder aend2 = EdmAssociationEnd.newBuilder() .setRole("target").setType(g2Entity) .setMultiplicity(EdmMultiplicity.ONE); EdmAssociation.Builder assocition = EdmAssociation.newBuilder() .setNamespace("namspace").setName("one_2_one") .setEnds(aend2, aend1); EdmNavigationProperty.Builder navigation = EdmNavigationProperty .newBuilder("g1").setFromTo(aend2, aend1).setFromToName("source", "target").setRelationship(assocition); g2Entity.addNavigationProperties(navigation); EdmEntitySet g1Set = EdmEntitySet.newBuilder().setName("G1").setEntityType(g1Entity).build(); processor.addEntitySetAsTable(mf, g1Set); EdmEntitySet g2Set = EdmEntitySet.newBuilder().setName("G2").setEntityType(g2Entity).build(); processor.addEntitySetAsTable(mf, g2Set); processor.addNavigationRelations(mf, "G2", g2Entity.build()); Table g1 = mf.getSchema().getTable("G1"); Table g2 = mf.getSchema().getTable("G2"); ForeignKey fk = g1.getForeignKeys().get(0); assertEquals("one_2_one", fk.getName()); assertNotNull(fk.getColumnByName("e1")); } @Test public void testAssosiationWithReferentialContriant() throws Exception { ODataMetadataProcessor processor = new ODataMetadataProcessor(); MetadataFactory mf = new MetadataFactory("vdb", 1, "northwind", SystemMetadata.getInstance().getRuntimeTypeMap(), new Properties(), null); EdmEntityType.Builder g1Entity = entityType("g1"); g1Entity.addProperties(EdmProperty.newBuilder("g2e2").setType(EdmSimpleType.STRING).setNullable(false)); EdmEntityType.Builder g2Entity = entityType("g2"); EdmAssociationEnd.Builder aend1 = EdmAssociationEnd.newBuilder() .setRole("source").setType(g1Entity) .setMultiplicity(EdmMultiplicity.ONE); EdmAssociationEnd.Builder aend2 = EdmAssociationEnd.newBuilder() .setRole("target").setType(g2Entity) .setMultiplicity(EdmMultiplicity.ONE); EdmReferentialConstraint.Builder refContraint = EdmReferentialConstraint .newBuilder().addPrincipalReferences("g2e2").setPrincipalRole("source") .addDependentReferences("e1").setDependentRole("target"); EdmAssociation.Builder assocition = EdmAssociation.newBuilder() .setNamespace("namspace").setName("one_2_one") .setEnds(aend2, aend1).setRefConstraint(refContraint); EdmNavigationProperty.Builder navigation = EdmNavigationProperty .newBuilder("g1").setFromTo(aend2, aend1).setFromToName("source","target").setRelationship(assocition); g2Entity.addNavigationProperties(navigation); EdmEntitySet g1Set = EdmEntitySet.newBuilder().setName("G1").setEntityType(g1Entity).build(); EdmEntitySet g2Set = EdmEntitySet.newBuilder().setName("G2").setEntityType(g2Entity).build(); Table t1 = processor.addEntitySetAsTable(mf, g1Set); Table t2 = processor.addEntitySetAsTable(mf, g2Set); KeyRecord record = new KeyRecord(Type.Unique); record.addColumn(t1.getColumnByName("g2e2")); t1.setUniqueKeys(Arrays.asList(record)); processor.addNavigationRelations(mf, "G2", g2Entity.build()); Table g1 = mf.getSchema().getTable("G1"); Table g2 = mf.getSchema().getTable("G2"); assertNotNull(g1); assertNotNull(g2); ForeignKey fk = g1.getForeignKeys().get(0); assertEquals("one_2_one", fk.getName()); assertNotNull(fk.getColumnByName("g2e2")); assertEquals("e1", fk.getReferenceColumns().get(0)); } @Test public void testManytoManyAssosiation() throws Exception { ODataMetadataProcessor processor = new ODataMetadataProcessor(); MetadataFactory mf = new MetadataFactory("vdb", 1, "northwind", SystemMetadata.getInstance().getRuntimeTypeMap(), new Properties(), null); EdmEntityType.Builder g1Entity = entityType("g1"); EdmEntityType.Builder g2Entity = entityType("g2"); EdmAssociationEnd.Builder aend1 = EdmAssociationEnd.newBuilder() .setRole("source").setType(g1Entity) .setMultiplicity(EdmMultiplicity.MANY); EdmAssociationEnd.Builder aend2 = EdmAssociationEnd.newBuilder() .setRole("target").setType(g2Entity) .setMultiplicity(EdmMultiplicity.MANY); EdmAssociation.Builder assocition = EdmAssociation.newBuilder() .setNamespace("namspace").setName("m_2_m") .setEnds(aend2, aend1); EdmNavigationProperty.Builder navigation = EdmNavigationProperty .newBuilder("g1").setFromTo(aend2, aend1).setFromToName("source", "target").setRelationship(assocition); g2Entity.addNavigationProperties(navigation); EdmEntitySet g1Set = EdmEntitySet.newBuilder().setName("G1").setEntityType(g1Entity).build(); EdmEntitySet g2Set = EdmEntitySet.newBuilder().setName("G2").setEntityType(g2Entity).build(); processor.addEntitySetAsTable(mf, g1Set); processor.addEntitySetAsTable(mf, g2Set); processor.addNavigationRelations(mf, "G2", g2Entity.build()); Table g1 = mf.getSchema().getTable("G1"); Table g2 = mf.getSchema().getTable("G2"); Table linkTable = mf.getSchema().getTable("m_2_m"); assertEquals(1, linkTable.getColumns().size()); assertEquals("e1", linkTable.getColumns().get(0).getName()); assertNotNull(linkTable); assertEquals("G2,G1", linkTable.getProperty(ODataMetadataProcessor.LINK_TABLES, false)); ForeignKey fk1 = linkTable.getForeignKeys().get(0); assertEquals("G2_FK", fk1.getName()); assertNotNull(fk1.getColumnByName("e1")); ForeignKey fk2 = linkTable.getForeignKeys().get(1); assertEquals("G1_FK", fk2.getName()); assertNotNull(fk2.getColumnByName("e1")); } @Test public void testManytoManyAssosiationWithReferntialConstraint() throws Exception { ODataMetadataProcessor processor = new ODataMetadataProcessor(); MetadataFactory mf = new MetadataFactory("vdb", 1, "northwind", SystemMetadata.getInstance().getRuntimeTypeMap(), new Properties(), null); EdmEntityType.Builder g1Entity = entityType("g1"); g1Entity.addProperties(EdmProperty.newBuilder("g2e2").setType(EdmSimpleType.STRING).setNullable(false)); EdmEntityType.Builder g2Entity = entityType("g2"); EdmAssociationEnd.Builder aend1 = EdmAssociationEnd.newBuilder() .setRole("source").setType(g1Entity) .setMultiplicity(EdmMultiplicity.MANY); EdmAssociationEnd.Builder aend2 = EdmAssociationEnd.newBuilder() .setRole("target").setType(g2Entity) .setMultiplicity(EdmMultiplicity.MANY); EdmReferentialConstraint.Builder refContraint = EdmReferentialConstraint .newBuilder().addPrincipalReferences("e1") .addDependentReferences("g2e2"); EdmAssociation.Builder assocition = EdmAssociation.newBuilder() .setNamespace("namspace").setName("m_2_m") .setEnds(aend2, aend1).setRefConstraint(refContraint); EdmNavigationProperty.Builder navigation = EdmNavigationProperty .newBuilder("g1").setFromTo(aend2, aend1).setFromToName("source", "target").setRelationship(assocition); g2Entity.addNavigationProperties(navigation); EdmEntitySet g1Set = EdmEntitySet.newBuilder().setName("G1").setEntityType(g1Entity).build(); EdmEntitySet g2Set = EdmEntitySet.newBuilder().setName("G2").setEntityType(g2Entity).build(); processor.addEntitySetAsTable(mf, g1Set); processor.addEntitySetAsTable(mf, g2Set); processor.addNavigationRelations(mf, "G2", g2Entity.build()); Table g1 = mf.getSchema().getTable("G1"); Table g2 = mf.getSchema().getTable("G2"); Table linkTable = mf.getSchema().getTable("m_2_m"); assertEquals(2, linkTable.getColumns().size()); assertEquals("e1", linkTable.getColumns().get(0).getName()); assertEquals("g2e2", linkTable.getColumns().get(1).getName()); assertNotNull(linkTable); assertEquals("G2,G1", linkTable.getProperty(ODataMetadataProcessor.LINK_TABLES, false)); ForeignKey fk = linkTable.getForeignKeys().get(0); assertEquals("G2_FK", fk.getName()); assertNotNull(fk.getColumnByName("e1")); ForeignKey fk2 = linkTable.getForeignKeys().get(1); assertEquals("G1_FK", fk2.getName()); assertNotNull(fk2.getColumnByName("g2e2")); } private EdmEntityType.Builder entityType(String name) { ArrayList<EdmProperty.Builder> props = new ArrayList<EdmProperty.Builder>(); props.add(EdmProperty.newBuilder("e1").setType(EdmSimpleType.INT32)); props.add(EdmProperty.newBuilder("e2").setType(EdmSimpleType.STRING).setNullable(false)); return EdmEntityType.newBuilder().addProperties(props).addKeys("e1").setName(name).setNamespace("namespace"); } private EdmEntityType.Builder buildBusinessEntity(EdmComplexType address) { ArrayList<EdmProperty.Builder> businessProperties = new ArrayList<EdmProperty.Builder>(); businessProperties.add(EdmProperty.newBuilder("name").setType(EdmSimpleType.STRING).setMaxLength(25)); businessProperties.add(EdmProperty.newBuilder("address").setType(address).setNullable(true)); return EdmEntityType.newBuilder().addProperties(businessProperties).addKeys("name"); } private EdmEntityType.Builder buildPersonEntity(EdmComplexType address) { ArrayList<EdmProperty.Builder> personProperties = new ArrayList<EdmProperty.Builder>(); personProperties.add(EdmProperty.newBuilder("name").setType(EdmSimpleType.STRING).setMaxLength(25)); personProperties.add(EdmProperty.newBuilder("ssn").setType(EdmSimpleType.INT64).setNullable(false)); personProperties.add(EdmProperty.newBuilder("address").setType(address).setNullable(true)); return EdmEntityType.newBuilder().addProperties(personProperties).addKeys("ssn"); } private EdmComplexType.Builder buildAddressEntity() { ArrayList<EdmProperty.Builder> addressProperties = new ArrayList<EdmProperty.Builder>(); addressProperties.add(EdmProperty.newBuilder("street").setType(EdmSimpleType.STRING)); addressProperties.add(EdmProperty.newBuilder("city").setType(EdmSimpleType.STRING)); addressProperties.add(EdmProperty.newBuilder("state").setType(EdmSimpleType.STRING)); return EdmComplexType.newBuilder().setName("Address") .setNamespace("namespace").addProperties(addressProperties); } @Test public void testKeyMaytches() { Column c1 = new Column(); c1.setName("one"); Column c2 = new Column(); c2.setName("two"); KeyRecord record = new KeyRecord(Type.Primary); record.addColumn(c1); record.addColumn(c2); ODataMetadataProcessor p = new ODataMetadataProcessor(); assertTrue(p.keyMatches(Arrays.asList("one", "one"), record)); assertTrue(p.keyMatches(Arrays.asList("two", "one"), record)); } }