/*
* 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));
}
}