diff --git a/build/kits/jboss-as7/bin/scripts/teiid-domain-mode-install.cli b/build/kits/jboss-as7/bin/scripts/teiid-domain-mode-install.cli index ce3e01f65a..d8e02ebff6 100644 --- a/build/kits/jboss-as7/bin/scripts/teiid-domain-mode-install.cli +++ b/build/kits/jboss-as7/bin/scripts/teiid-domain-mode-install.cli @@ -68,6 +68,7 @@ connect /profile=ha/subsystem=teiid/translator=map-cache:add(module=org.jboss.teiid.translator.object) /profile=ha/subsystem=teiid/translator=google-spreadsheet:add(module=org.jboss.teiid.translator.google) /profile=ha/subsystem=teiid/translator=odata:add(module=org.jboss.teiid.translator.odata) +/profile=ha/subsystem=teiid/translator=sap-nw-gateway:add(module=org.jboss.teiid.translator.odata) /profile=ha/subsystem=teiid/translator=mongodb:add(module=org.jboss.teiid.translator.mongodb) /profile=ha/subsystem=teiid/translator=cassandra:add(module=org.jboss.teiid.translator.cassandra) diff --git a/build/kits/jboss-as7/bin/scripts/teiid-standalone-mode-install.cli b/build/kits/jboss-as7/bin/scripts/teiid-standalone-mode-install.cli index 2c3b1c43d2..4b228e162b 100644 --- a/build/kits/jboss-as7/bin/scripts/teiid-standalone-mode-install.cli +++ b/build/kits/jboss-as7/bin/scripts/teiid-standalone-mode-install.cli @@ -64,6 +64,7 @@ connect /subsystem=teiid/translator=map-cache:add(module=org.jboss.teiid.translator.object) /subsystem=teiid/translator=google-spreadsheet:add(module=org.jboss.teiid.translator.google) /subsystem=teiid/translator=odata:add(module=org.jboss.teiid.translator.odata) +/subsystem=teiid/translator=sap-nw-gateway:add(module=org.jboss.teiid.translator.odata) /subsystem=teiid/translator=mongodb:add(module=org.jboss.teiid.translator.mongodb) /subsystem=teiid/translator=cassandra:add(module=org.jboss.teiid.translator.cassandra) diff --git a/build/kits/jboss-as7/standalone/configuration/standalone-teiid.xml b/build/kits/jboss-as7/standalone/configuration/standalone-teiid.xml index 98a6e823fc..20619a5be2 100644 --- a/build/kits/jboss-as7/standalone/configuration/standalone-teiid.xml +++ b/build/kits/jboss-as7/standalone/configuration/standalone-teiid.xml @@ -357,6 +357,7 @@ + diff --git a/connectors/translator-odata/src/main/java/org/teiid/translator/odata/ODataExecutionFactory.java b/connectors/translator-odata/src/main/java/org/teiid/translator/odata/ODataExecutionFactory.java index a82b84e9cb..3201404075 100644 --- a/connectors/translator-odata/src/main/java/org/teiid/translator/odata/ODataExecutionFactory.java +++ b/connectors/translator-odata/src/main/java/org/teiid/translator/odata/ODataExecutionFactory.java @@ -75,11 +75,22 @@ public class ODataExecutionFactory extends ExecutionFactory functionModifiers = new TreeMap(String.CASE_INSENSITIVE_ORDER); private String databaseTimeZone; private TimeZone timeZone = DEFAULT_TIME_ZONE; + private boolean supportsOdataFilter; + private boolean supportsOdataOrderBy; + private boolean supportsOdataCount; + private boolean supportsOdataSkip; + private boolean supportsOdataTop; public ODataExecutionFactory() { setSourceRequiredForMetadata(true); setSupportsOrderBy(true); - + + setSupportsOdataCount(true); + setSupportsOdataFilter(true); + setSupportsOdataOrderBy(true); + setSupportsOdataSkip(true); + setSupportsOdataTop(true); + registerFunctionModifier(SourceSystemFunctions.CONVERT, new AliasModifier("cast")); //$NON-NLS-1$ registerFunctionModifier(SourceSystemFunctions.LOCATE, new AliasModifier("indexof")); //$NON-NLS-1$ registerFunctionModifier(SourceSystemFunctions.LCASE, new AliasModifier("tolower")); //$NON-NLS-1$ @@ -121,7 +132,7 @@ public void getMetadata(MetadataFactory metadataFactory, WSConnection conn) thro try { EdmDataServices eds = new EdmxFormatParser().parseMetadata(StaxUtil.newXMLEventReader(new InputStreamReader(out.getBinaryStream()))); - ODataMetadataProcessor metadataProcessor = new ODataMetadataProcessor(); + ODataMetadataProcessor metadataProcessor = getMetadataProcessor(); PropertiesUtils.setBeanProperties(metadataProcessor, metadataFactory.getModelProperties(), "importer"); //$NON-NLS-1$ metadataProcessor.getMetadata(metadataFactory, eds); } catch (SQLException e) { @@ -129,6 +140,9 @@ public void getMetadata(MetadataFactory metadataFactory, WSConnection conn) thro } } + protected ODataMetadataProcessor getMetadataProcessor() { + return new ODataMetadataProcessor(); + } @Override public ResultSetExecution createResultSetExecution(QueryExpression command, ExecutionContext executionContext, RuntimeMetadata metadata, WSConnection connection) throws TranslatorException { @@ -199,29 +213,74 @@ public List getDefaultSupportedFunctions(){ return Arrays.asList(new String[] { "+", "-", "*", "/" }); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ } + @TranslatorProperty(display="Supports $Filter", description="True, $filter is supported", advanced=true) + public boolean supportsOdataFilter() { + return supportsOdataFilter; + } + + public void setSupportsOdataFilter(boolean supports) { + this.supportsOdataFilter = supports; + } + + @TranslatorProperty(display="Supports $OrderBy", description="True, $orderby is supported", advanced=true) + public boolean supportsOdataOrderBy() { + return supportsOdataOrderBy; + } + + public void setSupportsOdataOrderBy(boolean supports) { + this.supportsOdataOrderBy = supports; + } + + @TranslatorProperty(display="Supports $count", description="True, $count is supported", advanced=true) + public boolean supportsOdataCount() { + return supportsOdataCount; + } + + public void setSupportsOdataCount(boolean supports) { + this.supportsOdataCount = supports; + } + + @TranslatorProperty(display="Supports $skip", description="True, $skip is supported", advanced=true) + public boolean supportsOdataSkip() { + return supportsOdataSkip; + } + + public void setSupportsOdataSkip(boolean supports) { + this.supportsOdataSkip = supports; + } + + @TranslatorProperty(display="Supports $top", description="True, $top is supported", advanced=true) + public boolean supportsOdataTop() { + return supportsOdataTop; + } + + public void setSupportsOdataTop(boolean supports) { + this.supportsOdataTop = supports; + } + @Override public boolean supportsCompareCriteriaEquals() { - return true; + return this.supportsOdataFilter; } @Override public boolean supportsCompareCriteriaOrdered() { - return true; + return supportsOdataFilter; } @Override public boolean supportsIsNullCriteria() { - return true; + return supportsOdataFilter; } @Override public boolean supportsOrCriteria() { - return true; + return supportsOdataFilter; } @Override public boolean supportsNotCriteria() { - return true; + return supportsOdataFilter; } @Override @@ -234,29 +293,35 @@ public boolean supportsQuantifiedCompareCriteriaAll() { return false; // TODO:FOR ALL } + @Override + @TranslatorProperty(display="Supports ORDER BY", description="True, if this connector supports ORDER BY", advanced=true) + public boolean supportsOrderBy() { + return supportsOdataOrderBy; + } + @Override public boolean supportsOrderByUnrelated() { - return true; + return this.supportsOdataOrderBy; } @Override public boolean supportsAggregatesCount() { - return true; + return supportsOdataCount; } @Override public boolean supportsAggregatesCountStar() { - return true; + return supportsOdataCount; } @Override public boolean supportsRowLimit() { - return true; + return supportsOdataTop; } @Override public boolean supportsRowOffset() { - return true; + return supportsOdataSkip; } @Override diff --git a/connectors/translator-odata/src/main/java/org/teiid/translator/odata/ODataMetadataProcessor.java b/connectors/translator-odata/src/main/java/org/teiid/translator/odata/ODataMetadataProcessor.java index c0602357a4..0b221ab4e6 100644 --- a/connectors/translator-odata/src/main/java/org/teiid/translator/odata/ODataMetadataProcessor.java +++ b/connectors/translator-odata/src/main/java/org/teiid/translator/odata/ODataMetadataProcessor.java @@ -63,7 +63,7 @@ public void getMetadata(MetadataFactory mf, EdmDataServices eds) throws Translat // add entity sets as tables for (EdmEntitySet entitySet:container.getEntitySets()) { - addEntitySetAsTable(mf, entitySet.getName(), entitySet.getType()); + addEntitySetAsTable(mf, entitySet); } // build relations ships among tables @@ -80,16 +80,20 @@ public void getMetadata(MetadataFactory mf, EdmDataServices eds) throws Translat } } - - Table addEntitySetAsTable(MetadataFactory mf, String name, EdmEntityType entity) throws TranslatorException { - Table table = mf.addTable(name); - table.setProperty(ENTITY_TYPE, entity.getFullyQualifiedTypeName()); + protected Table buildTable(MetadataFactory mf, EdmEntitySet entitySet) { + Table table = mf.addTable(entitySet.getName()); table.setSupportsUpdate(true); + return table; + } + + protected Table addEntitySetAsTable(MetadataFactory mf, EdmEntitySet entitySet) throws TranslatorException { + Table table = buildTable(mf, entitySet); + table.setProperty(ENTITY_TYPE, entitySet.getType().getFullyQualifiedTypeName()); // add columns - for (EdmProperty ep:entity.getProperties().toList()) { + for (EdmProperty ep:entitySet.getType().getProperties().toList()) { if (ep.getType().isSimple()) { - addPropertyAsColumn(mf, table, ep); + addPropertyAsColumn(mf, table, ep, entitySet); } else { // this is complex type, i.e treat them as embeddable in the same table add all columns. @@ -99,19 +103,19 @@ Table addEntitySetAsTable(MetadataFactory mf, String name, EdmEntityType entity) EdmComplexType embedded = (EdmComplexType)ep.getType(); for (EdmProperty property:embedded.getProperties().toList()) { if (property.getType().isSimple()) { - Column column = addPropertyAsColumn(mf, table, property, ep.getName()); + Column column = addPropertyAsColumn(mf, table, property, entitySet, ep.getName()); column.setProperty(COMPLEX_TYPE, embedded.getName()); // complex type column.setProperty(COLUMN_GROUP, ep.getName()); // name of parent column } else { - throw new TranslatorException(ODataPlugin.Util.gs(ODataPlugin.Event.TEIID17002, name, ep.getName())); + throw new TranslatorException(ODataPlugin.Util.gs(ODataPlugin.Event.TEIID17002, entitySet.getName(), ep.getName())); } } } } // add PK - mf.addPrimaryKey("PK", entity.getKeys(), table); //$NON-NLS-1$ + mf.addPrimaryKey("PK", entitySet.getType().getKeys(), table); //$NON-NLS-1$ return table; } @@ -299,17 +303,12 @@ private boolean matchesWithPkOrUnique(List names, Table table) { return false; } - private Column addPropertyAsColumn(MetadataFactory mf, Table table, EdmProperty ep) { - return addPropertyAsColumn(mf, table, ep, null); + private Column addPropertyAsColumn(MetadataFactory mf, Table table, EdmProperty ep, EdmEntitySet entitySet) { + return addPropertyAsColumn(mf, table, ep, entitySet, null); } - private Column addPropertyAsColumn(MetadataFactory mf, Table table, EdmProperty ep, String prefix) { - String columnName = ep.getName(); - if (prefix != null) { - columnName = prefix+"_"+columnName; //$NON-NLS-1$ - } - Column c = mf.addColumn(columnName, ODataTypeManager.teiidType(ep.getType().getFullyQualifiedTypeName()), table); - c.setNameInSource(ep.getName()); + private Column addPropertyAsColumn(MetadataFactory mf, Table table, EdmProperty ep, EdmEntitySet entitySet, String prefix) { + Column c = buildColumn(mf, table, ep, entitySet, prefix); if (ep.getFixedLength() != null) { c.setFixedLength(ep.getFixedLength()); } @@ -317,10 +316,21 @@ private Column addPropertyAsColumn(MetadataFactory mf, Table table, EdmProperty if (ep.getMaxLength() != null) { c.setLength(ep.getMaxLength()); } - c.setUpdatable(true); + return c; } + @SuppressWarnings("unused") + protected Column buildColumn(MetadataFactory mf, Table table, EdmProperty ep, EdmEntitySet entitySet, String prefix) { + String columnName = ep.getName(); + if (prefix != null) { + columnName = prefix+"_"+columnName; //$NON-NLS-1$ + } + Column c = mf.addColumn(columnName, ODataTypeManager.teiidType(ep.getType().getFullyQualifiedTypeName()), table); + c.setNameInSource(ep.getName()); + c.setUpdatable(true); + return c; + } void addFunctionImportAsProcedure(MetadataFactory mf, EdmFunctionImport function) throws TranslatorException { Procedure procedure = mf.addProcedure(function.getName()); diff --git a/connectors/translator-odata/src/main/java/org/teiid/translator/odata/sap/SAPMetadataProcessor.java b/connectors/translator-odata/src/main/java/org/teiid/translator/odata/sap/SAPMetadataProcessor.java new file mode 100644 index 0000000000..328d92eda8 --- /dev/null +++ b/connectors/translator-odata/src/main/java/org/teiid/translator/odata/sap/SAPMetadataProcessor.java @@ -0,0 +1,185 @@ +/* + * 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.sap; + +import java.util.HashMap; + +import org.odata4j.core.NamespacedAnnotation; +import org.odata4j.core.PrefixedNamespace; +import org.odata4j.edm.EdmEntitySet; +import org.odata4j.edm.EdmProperty; +import org.teiid.metadata.Column; +import org.teiid.metadata.Column.SearchType; +import org.teiid.metadata.KeyRecord; +import org.teiid.metadata.KeyRecord.Type; +import org.teiid.metadata.MetadataFactory; +import org.teiid.metadata.Table; +import org.teiid.translator.TranslatorException; +import org.teiid.translator.odata.ODataMetadataProcessor; +import org.teiid.translator.odata.ODataTypeManager; + +public class SAPMetadataProcessor extends ODataMetadataProcessor { + private static final String SAPURI = "http://www.sap.com/Protocols/SAPData"; //$NON-NLS-1$ + private HashMap accessPatterns = new HashMap(); + + @Override + protected Table buildTable(MetadataFactory mf, EdmEntitySet entitySet) { + boolean creatable = true; + boolean updatable = true; + boolean deletable = true; + boolean pageable = true; + boolean topable = true; + + Table t = mf.addTable(entitySet.getName()); + + Iterable annotations = entitySet.getAnnotations(); + for (NamespacedAnnotation annotation:annotations) { + PrefixedNamespace namespace = annotation.getNamespace(); + if (namespace.getUri().equals(SAPURI)) { + String name = annotation.getName(); + if (name.equalsIgnoreCase("label")) { //$NON-NLS-1$ + t.setAnnotation((String)annotation.getValue()); + } + else if (name.equalsIgnoreCase("creatable")) { //$NON-NLS-1$ + creatable = Boolean.parseBoolean((String)annotation.getValue()); + } + else if (name.equalsIgnoreCase("updatable")) { //$NON-NLS-1$ + updatable = Boolean.parseBoolean((String)annotation.getValue()); + } + else if (name.equalsIgnoreCase("pageable")) { //$NON-NLS-1$ + pageable = Boolean.parseBoolean((String)annotation.getValue()); + } + else if (name.equalsIgnoreCase("topable")) { //$NON-NLS-1$ + topable = Boolean.parseBoolean((String)annotation.getValue()); + } + else if (name.equalsIgnoreCase("deletable")) { //$NON-NLS-1$ + deletable = Boolean.parseBoolean((String)annotation.getValue()); + } + } + } + + t.setSupportsUpdate(creatable && updatable && deletable); + if (!topable || !pageable) { + // TODO: currently Teiid can not do this in fine grained manner; + // will be turned on by default; but user needs to turn off using the + // capabilities if any table does not support this feature + } + return t; + } + + String getProperty(EdmEntitySet entitySet, String key) { + Iterable annotations = entitySet.getAnnotations(); + for (NamespacedAnnotation annotation:annotations) { + PrefixedNamespace namespace = annotation.getNamespace(); + if (namespace.getUri().equals(SAPURI)) { + if (annotation.getName().equalsIgnoreCase(key)) { + return (String)annotation.getValue(); + } + } + } + return null; + } + + @Override + protected Column buildColumn(MetadataFactory mf, Table table, EdmProperty ep, EdmEntitySet entitySet, String prefix) { + boolean creatable = true; + boolean updatable = true; + boolean filterable = true; + boolean required_in_filter = false; + + String columnName = ep.getName(); + if (prefix != null) { + columnName = prefix+"_"+columnName; //$NON-NLS-1$ + } + Column c = mf.addColumn(columnName, ODataTypeManager.teiidType(ep.getType().getFullyQualifiedTypeName()), table); + c.setNameInSource(ep.getName()); + + Iterable annotations = ep.getAnnotations(); + for (NamespacedAnnotation annotation:annotations) { + PrefixedNamespace namespace = annotation.getNamespace(); + if (namespace.getUri().equals(SAPURI)) { + String name = annotation.getName(); + if (name.equalsIgnoreCase("label")) { //$NON-NLS-1$ + c.setAnnotation((String)annotation.getValue()); + } + else if (name.equalsIgnoreCase("creatable")) { //$NON-NLS-1$ + creatable = Boolean.parseBoolean((String)annotation.getValue()); + } + if (name.equalsIgnoreCase("visible")) { //$NON-NLS-1$ + c.setSelectable(Boolean.parseBoolean((String)annotation.getValue())); + } + if (name.equalsIgnoreCase("updatable")) { //$NON-NLS-1$ + updatable = Boolean.parseBoolean((String)annotation.getValue()); + } + if (name.equalsIgnoreCase("sortable")) { //$NON-NLS-1$ + if (!Boolean.parseBoolean((String)annotation.getValue())){ + c.setSearchType(SearchType.Unsearchable); + } + } + if (name.equalsIgnoreCase("filterable")) { //$NON-NLS-1$ + filterable = Boolean.parseBoolean((String)annotation.getValue()); + } + if (name.equalsIgnoreCase("required-in-filter")) { //$NON-NLS-1$ + required_in_filter = Boolean.parseBoolean((String)annotation.getValue()); + } + if (name.equalsIgnoreCase("filter-restriction")) { //$NON-NLS-1$ + //TODO: + } + } + } + + c.setUpdatable(creatable && updatable); + if (!filterable) { + c.setSearchType(SearchType.Unsearchable); + } + + if (required_in_filter) { + if (this.accessPatterns.get(table) == null) { + KeyRecord record = new KeyRecord(Type.AccessPattern); + record.addColumn(c); + this.accessPatterns.put(table, record); + } + else { + this.accessPatterns.get(table).addColumn(c); + } + } + + // entity set defined to as must have filter + boolean requiresFilter = Boolean.parseBoolean(getProperty(entitySet, "requires-filter")); //$NON-NLS-1$ + if (requiresFilter && filterable && !required_in_filter) { + KeyRecord record = new KeyRecord(Type.AccessPattern); + record.addColumn(c); + table.getAccessPatterns().add(record); + } + return c; + } + + @Override + protected Table addEntitySetAsTable(MetadataFactory mf, EdmEntitySet entitySet) throws TranslatorException { + Table table = super.addEntitySetAsTable(mf, entitySet); + KeyRecord accessPattern = this.accessPatterns.get(table); + if (accessPattern != null) { + table.getAccessPatterns().add(accessPattern); + } + return table; + } +} diff --git a/connectors/translator-odata/src/main/java/org/teiid/translator/odata/sap/SAPODataExecutionFactory.java b/connectors/translator-odata/src/main/java/org/teiid/translator/odata/sap/SAPODataExecutionFactory.java new file mode 100644 index 0000000000..7c314bb70a --- /dev/null +++ b/connectors/translator-odata/src/main/java/org/teiid/translator/odata/sap/SAPODataExecutionFactory.java @@ -0,0 +1,44 @@ +/* + * 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.sap; + +import org.teiid.translator.Translator; +import org.teiid.translator.odata.ODataExecutionFactory; +import org.teiid.translator.odata.ODataMetadataProcessor; + +@Translator(name="sap-nw-gateway", description="A translator for making OData data service calls to SAP Netweaver Gateway") +public class SAPODataExecutionFactory extends ODataExecutionFactory { + + public SAPODataExecutionFactory() { + super(); + setSupportsOdataCount(true); + setSupportsOdataFilter(true); + setSupportsOdataOrderBy(true); + setSupportsOdataSkip(true); + setSupportsOdataTop(true); + } + + @Override + protected ODataMetadataProcessor getMetadataProcessor() { + return new SAPMetadataProcessor(); + } +} diff --git a/connectors/translator-odata/src/main/resources/META-INF/services/org.teiid.translator.ExecutionFactory b/connectors/translator-odata/src/main/resources/META-INF/services/org.teiid.translator.ExecutionFactory index 3d7c768d3b..d5d8bd012b 100644 --- a/connectors/translator-odata/src/main/resources/META-INF/services/org.teiid.translator.ExecutionFactory +++ b/connectors/translator-odata/src/main/resources/META-INF/services/org.teiid.translator.ExecutionFactory @@ -1 +1,2 @@ -org.teiid.translator.odata.ODataExecutionFactory \ No newline at end of file +org.teiid.translator.odata.ODataExecutionFactory +org.teiid.translator.odata.sap.SAPODataExecutionFactory \ No newline at end of file diff --git a/connectors/translator-odata/src/test/java/org/teiid/translator/odata/TestODataMetadataProcessor.java b/connectors/translator-odata/src/test/java/org/teiid/translator/odata/TestODataMetadataProcessor.java index 7d8ed4338b..fd8c095c6b 100644 --- a/connectors/translator-odata/src/test/java/org/teiid/translator/odata/TestODataMetadataProcessor.java +++ b/connectors/translator-odata/src/test/java/org/teiid/translator/odata/TestODataMetadataProcessor.java @@ -32,15 +32,7 @@ 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.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.edm.*; import org.odata4j.format.xml.EdmxFormatParser; import org.odata4j.stax2.util.StaxUtil; import org.teiid.core.util.ObjectConverterUtil; @@ -102,8 +94,9 @@ public void testEnititySet() throws Exception { props.add(EdmProperty.newBuilder("dob").setType(EdmSimpleType.DATETIME).setNullable(true)); props.add(EdmProperty.newBuilder("ssn").setType(EdmSimpleType.INT64).setNullable(false)); - EdmEntityType entity = EdmEntityType.newBuilder().addProperties(props).addKeys("ssn").build(); - processor.addEntitySetAsTable(mf, "Person", entity); + 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")); @@ -141,7 +134,8 @@ public void testEnititySetWithComplexType() throws Exception { ODataMetadataProcessor processor = new ODataMetadataProcessor(); MetadataFactory mf = new MetadataFactory("vdb", 1, "northwind", SystemMetadata.getInstance().getRuntimeTypeMap(), new Properties(), null); - processor.addEntitySetAsTable(mf, "Person", buildPersonEntity(buildAddressEntity().build()).build()); + 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")); @@ -157,10 +151,13 @@ public void testEnititySetWithComplexType() throws Exception { public void testMultipleEnititySetWithSameComplexType() throws Exception { ODataMetadataProcessor processor = new ODataMetadataProcessor(); MetadataFactory mf = new MetadataFactory("vdb", 1, "northwind", SystemMetadata.getInstance().getRuntimeTypeMap(), new Properties(), null); - - processor.addEntitySetAsTable(mf, "Person", buildPersonEntity(buildAddressEntity().build()).build()); - processor.addEntitySetAsTable(mf, "Business", buildBusinessEntity(buildAddressEntity().build()).build()); - + + 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")); @@ -199,8 +196,12 @@ public void testOneToOneAssosiation() throws Exception { .newBuilder("g1").setFromTo(aend2, aend1).setFromToName("source", "target").setRelationship(assocition); g2Entity.addNavigationProperties(navigation); - processor.addEntitySetAsTable(mf, "G1", g1Entity.build()); - processor.addEntitySetAsTable(mf, "G2", g2Entity.build()); + 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"); @@ -242,8 +243,11 @@ public void testAssosiationWithReferentialContriant() throws Exception { g2Entity.addNavigationProperties(navigation); - Table t1 = processor.addEntitySetAsTable(mf, "G1", g1Entity.build()); - Table t2 = processor.addEntitySetAsTable(mf, "G2", g2Entity.build()); + 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")); @@ -288,8 +292,11 @@ public void testManytoManyAssosiation() throws Exception { .newBuilder("g1").setFromTo(aend2, aend1).setFromToName("source", "target").setRelationship(assocition); g2Entity.addNavigationProperties(navigation); - processor.addEntitySetAsTable(mf, "G1", g1Entity.build()); - processor.addEntitySetAsTable(mf, "G2", g2Entity.build()); + 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"); @@ -340,8 +347,11 @@ public void testManytoManyAssosiationWithReferntialConstraint() throws Exception .newBuilder("g1").setFromTo(aend2, aend1).setFromToName("source", "target").setRelationship(assocition); g2Entity.addNavigationProperties(navigation); - processor.addEntitySetAsTable(mf, "G1", g1Entity.build()); - processor.addEntitySetAsTable(mf, "G2", g2Entity.build()); + 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"); diff --git a/connectors/translator-odata/src/test/java/org/teiid/translator/odata/sap/TestSAPODataMetadataProcessor.java b/connectors/translator-odata/src/test/java/org/teiid/translator/odata/sap/TestSAPODataMetadataProcessor.java new file mode 100644 index 0000000000..c52de98e69 --- /dev/null +++ b/connectors/translator-odata/src/test/java/org/teiid/translator/odata/sap/TestSAPODataMetadataProcessor.java @@ -0,0 +1,97 @@ +/* + * 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.sap; + +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.Properties; + +import org.junit.Test; +import org.odata4j.format.xml.EdmxFormatParser; +import org.odata4j.stax2.util.StaxUtil; +import org.teiid.cdk.api.TranslationUtility; +import org.teiid.core.util.ObjectConverterUtil; +import org.teiid.core.util.UnitTestUtil; +import org.teiid.metadata.Column.SearchType; +import org.teiid.metadata.MetadataFactory; +import org.teiid.metadata.RuntimeMetadata; +import org.teiid.metadata.Table; +import org.teiid.query.function.FunctionTree; +import org.teiid.query.function.UDFSource; +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 TestSAPODataMetadataProcessor { + private SAPODataExecutionFactory translator; + + @Test + public void testSchema() throws Exception { + translator = new SAPODataExecutionFactory(); + translator.start(); + + String csdl = ObjectConverterUtil.convertFileToString(UnitTestUtil.getTestDataFile("sap-metadata.xml")); + SAPMetadataProcessor processor = new SAPMetadataProcessor(); + Properties props = new Properties(); + MetadataFactory mf = new MetadataFactory("vdb", 1, "flight", 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(), "flight", 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(null, 1, "flight", SystemMetadata.getInstance().getRuntimeTypeMap(), new Properties(), null); +// QueryParser.getQueryParser().parseDDL(mf2, ddl); + + TranslationUtility utility = new TranslationUtility(metadata); + RuntimeMetadata rm = utility.createRuntimeMetadata(); + + Table t = rm.getTable("flight", "SubscriptionCollection"); + assertNotNull(t); + + // check the label name + assertNotNull(t.getColumnByName("persistNotifications")); + assertTrue(!t.getColumnByName("ID").isUpdatable()); + assertEquals("Persist Notification", t.getColumnByName("persistNotifications").getAnnotation()); + // check filterable + assertEquals(SearchType.Unsearchable, t.getColumnByName("persistNotifications").getSearchType()); + // check sortable + assertEquals(SearchType.Unsearchable, t.getColumnByName("filter").getSearchType()); + // check visible + assertEquals(false, t.getColumnByName("filter").isSelectable()); + //check required-in-filter + assertEquals(1, t.getAccessPatterns().size()); + assertEquals(2, t.getAccessPatterns().get(0).getColumns().size()); + } +} diff --git a/connectors/translator-odata/src/test/resources/sap-metadata.xml b/connectors/translator-odata/src/test/resources/sap-metadata.xml new file mode 100644 index 0000000000..369ad2493a --- /dev/null +++ b/connectors/translator-odata/src/test/resources/sap-metadata.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file