/*
* 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.*;
import java.io.FileReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.core4j.Enumerable;
import org.junit.Test;
import org.odata4j.edm.*;
import org.odata4j.format.xml.EdmxFormatParser;
import org.odata4j.format.xml.EdmxFormatWriter;
import org.odata4j.stax2.util.StaxUtil;
import org.teiid.adminapi.Model.Type;
import org.teiid.adminapi.impl.ModelMetaData;
import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.PropertiesUtils;
import org.teiid.core.util.UnitTestUtil;
import org.teiid.metadata.Column;
import org.teiid.metadata.MetadataFactory;
import org.teiid.metadata.Procedure;
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.unittest.RealMetadataFactory;
import org.teiid.query.validator.ValidatorReport;
@SuppressWarnings("nls")
public class TestDataEntitySchemaBuilder {
@Test
public void testMetadata() throws Exception {
TransformationMetadata metadata = RealMetadataFactory.fromDDL(ObjectConverterUtil.convertFileToString(UnitTestUtil.getTestDataFile("northwind.ddl")), "northwind", "nw");
StringWriter sw = new StringWriter();
EdmDataServices eds = ODataEntitySchemaBuilder.buildMetadata(metadata.getMetadataStore());
EdmxFormatWriter.write(eds, sw);
//System.out.println(sw.toString());
EdmDataServices pds = new EdmxFormatParser().parseMetadata(StaxUtil.newXMLEventReader(new StringReader(sw.toString())));
assertEquals(eds.getSchemas().size(), pds.getSchemas().size());
for (int i = 0; i < eds.getSchemas().size(); i++) {
EdmSchema expected = eds.getSchemas().get(i);
EdmSchema actual = pds.getSchemas().get(i);
assertEdmSchema(expected, actual);
}
}
@Test
public void testArrayIterateMetadata() throws Exception {
TransformationMetadata metadata = RealMetadataFactory.fromDDL(ObjectConverterUtil.convertFileToString(UnitTestUtil.getTestDataFile("northwind.ddl")), "northwind", "nw");
StringWriter sw = new StringWriter();
EdmDataServices eds = ODataEntitySchemaBuilder.buildMetadata(metadata.getMetadataStore());
EdmxFormatWriter.write(eds, sw);
//System.out.println(sw.toString());
}
@Test
public void testMetadataWithSelfJoin() throws Exception {
TransformationMetadata metadata = RealMetadataFactory.fromDDL(ObjectConverterUtil.convertFileToString(UnitTestUtil.getTestDataFile("categories.ddl")), "northwind", "nw");
StringWriter sw = new StringWriter();
EdmDataServices eds = ODataEntitySchemaBuilder.buildMetadata(metadata.getMetadataStore());
EdmxFormatWriter.write(eds, sw);
String expectedXML = "<?xml version=\"1.0\" encoding=\"utf-8\"?><edmx:Edmx Version=\"1.0\" xmlns:edmx=\"http://schemas.microsoft.com/ado/2007/06/edmx\"><edmx:DataServices m:DataServiceVersion=\"2.0\" xmlns:m=\"http://schemas.microsoft.com/ado/2007/08/dataservices/metadata\"><Schema Namespace=\"nw\" xmlns=\"http://schemas.microsoft.com/ado/2008/09/edm\"><EntityType Name=\"Category\"><Key><PropertyRef Name=\"CategoryID\"></PropertyRef></Key><Property Name=\"CategoryID\" Type=\"Edm.Int32\" Nullable=\"false\"></Property><Property Name=\"Name\" Type=\"Edm.String\" Nullable=\"false\" MaxLength=\"25\" FixedLength=\"false\" Unicode=\"true\"></Property><Property Name=\"ParentCategoryID\" Type=\"Edm.Int32\" Nullable=\"false\"></Property><NavigationProperty Name=\"Category\" Relationship=\"nw.Category_FK_CATEGORY_ID\" FromRole=\"Category\" ToRole=\"Category\"></NavigationProperty></EntityType><Association Name=\"Category_FK_CATEGORY_ID\"><End Type=\"nw.Category\" Multiplicity=\"*\" Role=\"Category\"></End><End Type=\"nw.Category\" Multiplicity=\"0..1\" Role=\"Category\"></End><ReferentialConstraint><Principal Role=\"Category\"><PropertyRef Name=\"CategoryID\"></PropertyRef></Principal><Dependent Role=\"Category\"><PropertyRef Name=\"ParentCategoryID\"></PropertyRef></Dependent></ReferentialConstraint></Association><EntityContainer Name=\"nw\" m:IsDefaultEntityContainer=\"false\"><EntitySet Name=\"Category\" EntityType=\"nw.Category\"></EntitySet><AssociationSet Name=\"Category_FK_CATEGORY_ID\" Association=\"nw.Category_FK_CATEGORY_ID\"><End EntitySet=\"Category\" Role=\"Category\"></End><End EntitySet=\"Category\" Role=\"Category\"></End></AssociationSet></EntityContainer></Schema></edmx:DataServices></edmx:Edmx>\n";
EdmDataServices pds = new EdmxFormatParser().parseMetadata(StaxUtil.newXMLEventReader(new StringReader(expectedXML)));
assertEquals(eds.getSchemas().size(), pds.getSchemas().size());
for (int i = 0; i < eds.getSchemas().size(); i++) {
EdmSchema expected = eds.getSchemas().get(i);
EdmSchema actual = pds.getSchemas().get(i);
assertEdmSchema(expected, actual);
}
}
private void assertEdmSchema(EdmSchema expected, EdmSchema actual) {
assertEquals(expected.getEntityTypes().size(), actual.getEntityTypes().size());
assertEquals(expected.getEntityContainers().size(), actual.getEntityContainers().size());
assertEquals(expected.getAssociations().size(), actual.getAssociations().size());
for (int i = 0; i < expected.getEntityTypes().size(); i++) {
assertEntityType(expected.getEntityTypes().get(i), actual.getEntityTypes().get(i));
}
for (int i = 0; i < expected.getAssociations().size(); i++) {
assertEdmAssosiation(expected.getAssociations().get(i), actual.getAssociations().get(i));
}
for (int i = 0; i < expected.getEntityContainers().size(); i++) {
assertEntityContainer(expected.getEntityContainers().get(i), actual.getEntityContainers().get(i));
}
}
private void assertEntityType(EdmEntityType expected, EdmEntityType actual) {
assertEquals(expected.getName(), actual.getName());
assertEquals(expected.getNamespace(), actual.getNamespace());
assertArrayEquals(expected.getKeys().toArray(new String[expected.getKeys().size()]), actual.getKeys().toArray(new String[actual.getKeys().size()]));
List<EdmProperty> propertiesExpected = new ArrayList<EdmProperty>();
List<EdmProperty> propertiesActual = new ArrayList<EdmProperty>();
Iterator<EdmProperty> it = expected.getProperties().iterator();
while(it.hasNext()) {
propertiesExpected.add(it.next());
}
it = actual.getProperties().iterator();
while(it.hasNext()) {
propertiesActual.add(it.next());
}
assertEquals(propertiesExpected.size(), propertiesActual.size());
for (int i = 0; i < propertiesExpected.size(); i++) {
assertEdmProperty(propertiesExpected.get(i), propertiesActual.get(i));
}
List<EdmNavigationProperty> navExpected = new ArrayList<EdmNavigationProperty>();
List<EdmNavigationProperty> navActual = new ArrayList<EdmNavigationProperty>();
Iterator<EdmNavigationProperty> enpIt = expected.getDeclaredNavigationProperties().iterator();
while(enpIt.hasNext()) {
navExpected.add(enpIt.next());
}
enpIt = actual.getDeclaredNavigationProperties().iterator();
while(enpIt.hasNext()) {
navActual.add(enpIt.next());
}
assertEquals(navExpected.size(), navActual.size());
for (int i = 0; i < navExpected.size(); i++) {
assertEdmNavigationProperty(navExpected.get(i), navActual.get(i));
}
assertArrayEquals(expected.getKeys().toArray(), actual.getKeys().toArray());
}
private void assertEdmNavigationProperty(EdmNavigationProperty expected, EdmNavigationProperty actual) {
assertEquals(expected.getName(), actual.getName());
assertEdmAssosiation(expected.getRelationship(), actual.getRelationship());
assertEdmAssociationEnd(expected.getFromRole(), actual.getFromRole());
assertEdmAssociationEnd(expected.getToRole(), actual.getToRole());
}
private void assertEdmAssociationEnd(EdmAssociationEnd expected, EdmAssociationEnd actual) {
assertEquals(expected.getRole(), actual.getRole());
}
private void assertEdmAssosiation(EdmAssociation expected, EdmAssociation actual) {
assertEquals(expected.getNamespace(), actual.getNamespace());
assertEquals(expected.getName(), actual.getName());
assertEdmAssociationEnd(expected.getEnd1(), actual.getEnd1());
assertEdmAssociationEnd(expected.getEnd2(), actual.getEnd2());
// check referential integrity?
}
private void assertEdmProperty(EdmProperty expected, EdmProperty actual) {
assertEquals(expected.getName(), actual.getName());
assertEquals(expected.getType(), actual.getType());
}
private void assertEntityContainer(EdmEntityContainer expected, EdmEntityContainer actual) {
assertEquals(expected.getEntitySets().size(), actual.getEntitySets().size());
assertEquals(expected.getAssociationSets().size(), actual.getAssociationSets().size());
for (int i = 0; i < expected.getEntitySets().size(); i++) {
assertEnititySet(expected.getEntitySets().get(i), actual.getEntitySets().get(i));
}
for (int i = 0; i < expected.getAssociationSets().size(); i++) {
assertAssosiationSet(expected.getAssociationSets().get(i), actual.getAssociationSets().get(i));
}
}
private void assertAssosiationSet(EdmAssociationSet expected, EdmAssociationSet actual) {
assertEquals(expected.getName(), actual.getName());
assertEdmAssosiation(expected.getAssociation(), actual.getAssociation());
assertEdmAssociationSetEnd(expected.getEnd1(), actual.getEnd1());
assertEdmAssociationSetEnd(expected.getEnd1(), actual.getEnd1());
}
private void assertEdmAssociationSetEnd(EdmAssociationSetEnd expected, EdmAssociationSetEnd actual) {
assertEdmAssociationEnd(expected.getRole(), actual.getRole());
}
private void assertEnititySet(EdmEntitySet expected, EdmEntitySet actual) {
assertEquals(expected.getName(), actual.getName());
assertEntityType(expected.getType(), actual.getType());
}
@Test
public void testUnquieTreatedAsKey() {
// test that unique key is treated as key, when pk is absent.
}
@Test
public void testEdmPropertyPrimaryKey() throws Exception{
String ddl = "CREATE FOREIGN TABLE Sales (\n" +
" id integer PRIMARY KEY OPTIONS(NAMEINSOURCE 'myid'),\n" +
" name string(5));";
TransformationMetadata metadata = RealMetadataFactory.fromDDL(ddl, "sales", "sl");
EdmDataServices edm = ODataEntitySchemaBuilder.buildMetadata(metadata.getMetadataStore());
assertFalse("Primary key is nullable.", ((EdmProperty)edm.findEdmProperty("id")).isNullable());
assertTrue(((EdmProperty)edm.findEdmProperty("name")).isNullable());
}
@Test
public void testEntityTypeName() throws Exception{
String ddl = "CREATE FOREIGN TABLE BookingCollection (\n" +
" carrid bigdecimal NOT NULL,\n" +
" connid string(5) NOT NULL,\n" +
" bookid bigdecimal NOT NULL,\n" +
" LOCCURKEY string(5) NOT NULL,\n" +
" fldate timestamp NOT NULL,\n" +
" PRIMARY KEY(carrid, connid, fldate, bookid)\n" +
") OPTIONS (UPDATABLE TRUE, " +
" \"teiid_odata:EntityType\" 'RMTSAMPLEFLIGHT.Booking');";
TransformationMetadata metadata = RealMetadataFactory.fromDDL(ddl, "northwind", "nw");
EdmDataServices edm = ODataEntitySchemaBuilder.buildMetadata(metadata.getMetadataStore());
assertTrue(edm.findEdmEntitySet("nw.BookingCollection")!=null);
assertTrue(edm.findEdmEntityType("nw.RMTSAMPLEFLIGHT.Booking")!=null);
}
@Test
public void testEntityPropertyName() throws Exception{
String ddl = "CREATE FOREIGN TABLE BookingCollection (\n" +
" carrid bigdecimal NOT NULL OPTIONS(NAMEINSOURCE '\"carrageid\"'),\n" +
" connid string(5) NOT NULL OPTIONS(NAMEINSOURCE '\"connectionid\"'),\n" +
" PRIMARY KEY(carrid)\n" +
") OPTIONS (UPDATABLE TRUE, " +
" \"teiid_odata:EntityType\" 'RMTSAMPLEFLIGHT.Booking');";
TransformationMetadata metadata = RealMetadataFactory.fromDDL(ddl, "northwind", "nw");
EdmDataServices edm = ODataEntitySchemaBuilder.buildMetadata(metadata.getMetadataStore());
assertTrue(edm.findEdmEntitySet("nw.BookingCollection")!=null);
Enumerable<EdmProperty> properties = edm.getEdmEntitySet("nw.BookingCollection").getType().getProperties();
assertEquals(2, properties.count());
Iterator<EdmProperty> it = properties.iterator();
while(it.hasNext()) {
EdmProperty property = it.next();
if (!property.getName().equals("carrid") && !property.getName().equals("connid")) {
fail();
}
}
}
@Test
public void testEntityTypeName2() throws Exception{
TransformationMetadata metadata = getNorthwindMetadataFromODataXML();
EdmDataServices edm = ODataEntitySchemaBuilder.buildMetadata(metadata.getMetadataStore().getSchema("nw"));
assertTrue(edm.findEdmEntitySet("nw.Categories")!=null);
assertEquals("NorthwindModel.Category", edm.findEdmEntitySet("nw.Categories").getType().getName());
assertTrue(edm.findEdmEntityType("nw.NorthwindModel.Category")!=null);
assertTrue(edm.findEdmFunctionImport("nw.TopCustomers")!=null);
assertEquals("Collection(nw.NorthwindModel.Customer)", edm.findEdmFunctionImport("nw.TopCustomers").getReturnType().getFullyQualifiedTypeName());
assertTrue(edm.findEdmEntityType("nw.NorthwindModel.Category")!=null);
EdmComplexType complexType = edm.findEdmComplexType("nw.NorthwindModel.Address");
assertEquals("Address", complexType.getProperties().first().getName());
edm = new TeiidEdmMetadata("nw", edm);
assertTrue(edm.findEdmEntitySet("Categories")!=null);
assertEquals("NorthwindModel.Category", edm.findEdmEntitySet("Categories").getType().getName());
assertTrue(edm.findEdmEntityType("NorthwindModel.Category")!=null);
assertTrue(edm.findEdmFunctionImport("TopCustomers")!=null);
assertEquals("Collection(nw.NorthwindModel.Customer)", edm.findEdmFunctionImport("TopCustomers").getReturnType().getFullyQualifiedTypeName());
assertTrue(edm.findEdmEntityType("NorthwindModel.Category")!=null);
}
static TransformationMetadata getNorthwindMetadataFromODataXML() throws Exception {
ModelMetaData model = new ModelMetaData();
model.setName("nw");
model.setModelType(Type.PHYSICAL);
MetadataFactory mf = new MetadataFactory("northwind", 1, SystemMetadata.getInstance().getRuntimeTypeMap(), model);
EdmDataServices edm = new EdmxFormatParser().parseMetadata(StaxUtil.newXMLEventReader(new FileReader(UnitTestUtil.getTestDataFile("northwind.xml"))));
ODataMetadataProcessor metadataProcessor = new ODataMetadataProcessor();
PropertiesUtils.setBeanProperties(metadataProcessor, mf.getModelProperties(), "importer"); //$NON-NLS-1$
metadataProcessor.getMetadata(mf, edm);
String ddl = DDLStringVisitor.getDDLString(mf.getSchema(), null, null);
TransformationMetadata metadata = RealMetadataFactory.fromDDL(ddl, "northwind", "nw");
ValidatorReport report = new MetadataValidator().validate(metadata.getVdbMetaData(), metadata.getMetadataStore());
if (report.hasItems()) {
throw new RuntimeException(report.getFailureMessage());
}
return metadata;
}
@Test
public void testArrayType() throws Exception {
ModelMetaData model = new ModelMetaData();
model.setName("nw");
model.setModelType(Type.PHYSICAL);
MetadataFactory mf = new MetadataFactory("northwind", 1, SystemMetadata.getInstance().getRuntimeTypeMap(), model);
EdmDataServices edm = new EdmxFormatParser().parseMetadata(StaxUtil.newXMLEventReader(new FileReader(UnitTestUtil.getTestDataFile("arraytest.xml"))));
ODataMetadataProcessor metadataProcessor = new ODataMetadataProcessor();
PropertiesUtils.setBeanProperties(metadataProcessor, mf.getModelProperties(), "importer"); //$NON-NLS-1$
metadataProcessor.getMetadata(mf, edm);
Column c = mf.getSchema().getTable("G2").getColumnByName("e3");
assertEquals("integer[]", c.getRuntimeType());
Procedure p = mf.getSchema().getProcedure("ARRAYITERATE");
assertEquals("varbinary[]", p.getParameters().get(0).getRuntimeType());
assertEquals("varbinary", p.getResultSet().getColumns().get(0).getRuntimeType());
//String ddl = DDLStringVisitor.getDDLString(mf.getSchema(), null, null);
//System.out.println(ddl);
}
}