/*
* 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.odata4;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.apache.olingo.client.api.edm.xml.XMLMetadata;
import org.apache.olingo.commons.api.edm.provider.*;
import org.teiid.logging.LogConstants;
import org.teiid.logging.LogManager;
import org.teiid.metadata.*;
import org.teiid.metadata.BaseColumn.NullType;
import org.teiid.metadata.Column.SearchType;
import org.teiid.olingo.common.ODataTypeManager;
import org.teiid.translator.MetadataProcessor;
import org.teiid.translator.TranslatorException;
import org.teiid.translator.TranslatorProperty;
import org.teiid.translator.TranslatorProperty.PropertyType;
import org.teiid.translator.TypeFacility;
import org.teiid.translator.WSConnection;
public class ODataMetadataProcessor implements MetadataProcessor<WSConnection> {
private static final String EDM_GEOMETRY = "Edm.Geometry"; //$NON-NLS-1$
public enum ODataType {
COMPLEX,
NAVIGATION,
ENTITY,
ENTITY_COLLECTION,
ACTION,
FUNCTION,
COMPLEX_COLLECTION,
NAVIGATION_COLLECTION
};
// local planning properties
private static final String PARENT_TABLE = "PARENT_TABLE"; //$NON-NLS-1$
private static final String CONSTRAINT_PROPERTY = "CONSTRAINT_PROPERTY"; //$NON-NLS-1$
private static final String CONSTRAINT_REF_PROPERTY = "CONSTRAINT_REF_PROPERTY"; //$NON-NLS-1$
private static final String FK_NAME = "FK_NAME"; //$NON-NLS-1$
private static final String NAME_SEPARATOR = "_"; //$NON-NLS-1$
@ExtensionMetadataProperty(applicable = { Table.class, Procedure.class },
datatype = String.class,
display = "Name in OData Schema",
description = "Name in OData Schema",
required = true)
public static final String NAME_IN_SCHEMA = MetadataFactory.ODATA_URI+"NameInSchema"; //$NON-NLS-1$
@ExtensionMetadataProperty(applicable = { Table.class, Procedure.class },
datatype = String.class,
display = "OData Type",
description = "Type of OData Schema Item",
allowed = "COMPLEX, NAVIGATION, ENTITY, ENTITY_COLLECTION, ACTION, FUNCTION, COMPLEX_COLLECTION, NAVIGATION_COLLECTION",
required=true)
public static final String ODATA_TYPE = MetadataFactory.ODATA_URI+"Type"; //$NON-NLS-1$
@ExtensionMetadataProperty(applicable=Table.class,
datatype=String.class,
display="Merge Into Table",
description="Declare the name of table that this table needs to be merged into.")
public static final String MERGE = MetadataFactory.ODATA_URI+"MERGE"; //$NON-NLS-1$
@ExtensionMetadataProperty(applicable=Column.class,
datatype=String.class,
display="Pseudo Column",
description="Pseudo column for join purposes")
public static final String PSEUDO = MetadataFactory.ODATA_URI+"PSEUDO"; //$NON-NLS-1$
private String schemaNamespace;
private ODataExecutionFactory ef;
void setExecutionfactory(ODataExecutionFactory ef) {
this.ef = ef;
}
public void process(MetadataFactory mf, WSConnection conn)
throws TranslatorException {
XMLMetadata serviceMetadata = getSchema(conn);
getMetadata(mf, serviceMetadata);
}
protected XMLMetadata getSchema(WSConnection conn) throws TranslatorException {
if (this.ef != null) {
return this.ef.getSchema(conn);
}
return null;
}
void getMetadata(MetadataFactory mf, XMLMetadata metadata)
throws TranslatorException {
CsdlSchema csdlSchema = getDefaultSchema(metadata);
CsdlEntityContainer container = csdlSchema.getEntityContainer();
// add entity sets as tables
for (CsdlEntitySet entitySet : container.getEntitySets()) {
addTable(mf, entitySet.getName(), entitySet.getType(), ODataType.ENTITY_COLLECTION, metadata);
}
// add singletons sets as tables
for (CsdlSingleton singleton : container.getSingletons()) {
addTable(mf, singleton.getName(), singleton.getType(), ODataType.ENTITY_COLLECTION, metadata);
}
// build relationships among tables
for (CsdlEntitySet entitySet : container.getEntitySets()) {
addNavigationProperties(mf, entitySet.getName(), entitySet,
metadata);
}
for (CsdlSingleton singleton : container.getSingletons()) {
addNavigationProperties(mf, singleton.getName(), singleton,
metadata);
}
// add PK colums for complex-types
for (Table table : mf.getSchema().getTables().values()) {
String parentTable = table.getProperty(PARENT_TABLE, false);
if (parentTable != null) {
addPrimaryKeyToComplexTables(mf, table, mf.getSchema().getTable(parentTable));
}
}
// build relations between tables
for (Table table : mf.getSchema().getTables().values()) {
String parentTable = table.getProperty(PARENT_TABLE, false);
if (parentTable != null) {
table.setProperty(PARENT_TABLE, null);
addForeignKey(mf, table, mf.getSchema().getTable(parentTable));
}
}
// add functions
for (CsdlFunctionImport function : container.getFunctionImports()) {
addFunctionImportAsProcedure(mf, function, ODataType.FUNCTION, metadata);
}
// add actions
for (CsdlActionImport action : container.getActionImports()) {
addActionImportAsProcedure(mf, action, ODataType.ACTION, metadata);
}
}
private CsdlSchema getDefaultSchema(XMLMetadata metadata) throws TranslatorException {
CsdlSchema csdlSchema = null;
if (this.schemaNamespace != null) {
csdlSchema = metadata.getSchema(this.schemaNamespace);
}
else {
if (!metadata.getSchemas().isEmpty()) {
csdlSchema = metadata.getSchemas().get(0);
}
}
if(csdlSchema == null) {
throw new TranslatorException(ODataPlugin.Util.gs(ODataPlugin.Event.TEIID17019));
}
return csdlSchema;
}
private Table buildTable(MetadataFactory mf, String name) {
Table table = mf.addTable(name);
table.setSupportsUpdate(true);
return table;
}
private boolean isSimple(String type) {
return type.startsWith("Edm");
}
private boolean isEnum(XMLMetadata metadata, String type)
throws TranslatorException {
return getEnumType(metadata, type) != null;
}
private boolean isComplexType(XMLMetadata metadata, String type)
throws TranslatorException {
return getComplexType(metadata, type) != null;
}
private boolean isEntityType(XMLMetadata metadata, String type) throws TranslatorException {
return getEntityType(metadata, type) != null;
}
private Table addTable(MetadataFactory mf, String tableName,
String entityType, ODataType odataType, XMLMetadata metadata)
throws TranslatorException {
Table table = buildTable(mf, tableName);
table.setProperty(ODATA_TYPE, odataType.name());
table.setProperty(NAME_IN_SCHEMA, entityType);
CsdlEntityType type = getEntityType(metadata, entityType);
addEntityTypeProperties(mf, metadata, table, type);
return table;
}
private void addEntityTypeProperties(MetadataFactory mf,
XMLMetadata metadata, Table table, CsdlEntityType entityType)
throws TranslatorException {
// add columns; add complex types as child tables with 1-1 or 1-many
// relation
for (CsdlProperty property : entityType.getProperties()) {
addProperty(mf, metadata, table, property);
}
// add properties from base type; if any to flatten the model
String baseType = entityType.getBaseType();
while (baseType != null) {
CsdlEntityType baseEntityType = getEntityType(metadata, baseType);
for (CsdlProperty property : baseEntityType.getProperties()) {
addProperty(mf, metadata, table, property);
}
baseType = baseEntityType.getBaseType();
}
// add PK
addPrimaryKey(mf, table, entityType.getKey()); //$NON-NLS-1$
}
private void addProperty(MetadataFactory mf, XMLMetadata metadata,
Table table, CsdlProperty property) throws TranslatorException {
if (isSimple(property.getType()) || isEnum(metadata, property.getType())) {
addPropertyAsColumn(mf, table, property);
}
else {
CsdlComplexType childType = (CsdlComplexType)getComplexType(metadata, property.getType());
addComplexPropertyAsTable(mf, property, childType, metadata, table);
}
}
static String getPseudo(Column column) {
return column.getProperty(ODataMetadataProcessor.PSEUDO, false);
}
static String getMerge(Table table) {
return table.getProperty(ODataMetadataProcessor.MERGE, false);
}
static boolean isComplexType(Table table) {
ODataType type = ODataType.valueOf(table.getProperty(ODataMetadataProcessor.ODATA_TYPE, false));
return type == ODataType.COMPLEX || type == ODataType.COMPLEX_COLLECTION;
}
static boolean isNavigationType(Table table) {
ODataType type = ODataType.valueOf(table.getProperty(ODataMetadataProcessor.ODATA_TYPE, false));
return type == ODataType.NAVIGATION || type == ODataType.NAVIGATION_COLLECTION;
}
static boolean isCollection(Table table) {
ODataType type = ODataType.valueOf(table.getProperty(ODataMetadataProcessor.ODATA_TYPE, false));
return type == ODataType.ENTITY_COLLECTION
|| type == ODataType.COMPLEX_COLLECTION
|| type == ODataType.NAVIGATION_COLLECTION;
}
static boolean isEntitySet(Table table) {
ODataType type = ODataType.valueOf(table.getProperty(ODataMetadataProcessor.ODATA_TYPE, false));
return type == ODataType.ENTITY_COLLECTION;
}
static String getNativeType(Column column) {
String nativeType = column.getNativeType();
if (nativeType == null) {
nativeType = "Edm.String";
}
return nativeType;
}
private void addComplexPropertyAsTable(MetadataFactory mf, CsdlProperty parentProperty,
CsdlComplexType complexType, XMLMetadata metadata, Table parentTable)
throws TranslatorException {
String tableName = parentTable.getName()+NAME_SEPARATOR+parentProperty.getName();
Table childTable = buildTable(mf, tableName);
childTable.setProperty(NAME_IN_SCHEMA, parentProperty.getType()); // complex type
childTable.setProperty(ODATA_TYPE,
parentProperty.isCollection() ?
ODataType.COMPLEX_COLLECTION.name() : ODataType.COMPLEX.name()); // complex type
childTable.setProperty(PARENT_TABLE, parentTable.getName());
childTable.setProperty(MERGE, parentTable.getFullName());
if (isComplexType(parentTable)) {
childTable.setNameInSource(parentTable.getNameInSource()+"/"+parentProperty.getName());
} else {
childTable.setNameInSource(parentProperty.getName());
}
for (CsdlProperty property:complexType.getProperties()) {
addProperty(mf, metadata, childTable, property);
}
// add properties from base type; if any to flatten the model
String baseType = complexType.getBaseType();
while(baseType != null) {
CsdlComplexType baseComplexType = getComplexType(metadata, baseType);
for (CsdlProperty property:baseComplexType.getProperties()) {
addProperty(mf, metadata, childTable, property);
}
baseType = baseComplexType.getBaseType();
}
}
void addPrimaryKey(MetadataFactory mf, Table table,
List<CsdlPropertyRef> keys) throws TranslatorException {
List<String> pkNames = new ArrayList<String>();
for (CsdlPropertyRef ref : keys) {
pkNames.add(ref.getName());
if (ref.getAlias() != null) {
throw new TranslatorException(ODataPlugin.Util.gs(ODataPlugin.Event.TEIID17018,
table.getName(),ref.getName()));
}
}
mf.addPrimaryKey("PK", pkNames, table);
}
private CsdlNavigationPropertyBinding getNavigationPropertyBinding(CsdlBindingTarget entitySet, String name) {
List<CsdlNavigationPropertyBinding> bindings = entitySet.getNavigationPropertyBindings();
for (CsdlNavigationPropertyBinding binding:bindings) {
String path = binding.getPath();
int index = path.lastIndexOf('/');
if (index != -1) {
path = path.substring(index+1);
}
if (path.equals(name)) {
return binding;
}
}
return null;
}
private CsdlEntityType getEntityType(XMLMetadata metadata, String name) throws TranslatorException {
if(name == null) {
return null;
}
if (name.contains(".")) {
int idx = name.lastIndexOf('.');
CsdlSchema schema = metadata.getSchema(name.substring(0, idx));
if (schema == null) {
throw new TranslatorException(ODataPlugin.Util.gs(ODataPlugin.Event.TEIID17021, name));
}
return schema.getEntityType(name.substring(idx+1));
}
return getDefaultSchema(metadata).getEntityType(name);
}
private List<CsdlFunction> getFunctions(XMLMetadata metadata, String name) throws TranslatorException {
if (name.contains(".")) {
int idx = name.lastIndexOf('.');
CsdlSchema schema = metadata.getSchema(name.substring(0, idx));
if (schema == null) {
throw new TranslatorException(ODataPlugin.Util.gs(ODataPlugin.Event.TEIID17021, name));
}
return schema.getFunctions(name.substring(idx+1));
}
return getDefaultSchema(metadata).getFunctions(name);
}
private List<CsdlAction> getActions (XMLMetadata metadata, String name) throws TranslatorException {
if (name.contains(".")) {
int idx = name.lastIndexOf('.');
CsdlSchema schema = metadata.getSchema(name.substring(0, idx));
if (schema == null) {
throw new TranslatorException(ODataPlugin.Util.gs(ODataPlugin.Event.TEIID17021, name));
}
return schema.getActions(name.substring(idx+1));
}
return getDefaultSchema(metadata).getActions(name);
}
private CsdlComplexType getComplexType(XMLMetadata metadata, String name) throws TranslatorException {
if (name.contains(".")) {
int idx = name.lastIndexOf('.');
CsdlSchema schema = metadata.getSchema(name.substring(0, idx));
if (schema == null) {
throw new TranslatorException(ODataPlugin.Util.gs(ODataPlugin.Event.TEIID17021, name));
}
return schema.getComplexType(name.substring(idx+1));
}
return getDefaultSchema(metadata).getComplexType(name);
}
private CsdlEnumType getEnumType(XMLMetadata metadata, String name) throws TranslatorException {
if (name.contains(".")) {
int idx = name.lastIndexOf('.');
CsdlSchema schema = metadata.getSchema(name.substring(0, idx));
if (schema == null) {
throw new TranslatorException(ODataPlugin.Util.gs(ODataPlugin.Event.TEIID17021, name));
}
return schema.getEnumType(name.substring(idx+1));
}
return getDefaultSchema(metadata).getEnumType(name);
}
void addNavigationProperties(MetadataFactory mf, String tableName,
CsdlBindingTarget entitySet, XMLMetadata metadata)
throws TranslatorException {
Table fromTable = mf.getSchema().getTable(tableName);
CsdlEntityType fromEntityType = getEntityType(metadata,entitySet.getType());
Table toTable = null;
for (CsdlNavigationProperty property : fromEntityType.getNavigationProperties()) {
CsdlNavigationPropertyBinding binding = getNavigationPropertyBinding(
entitySet, property.getName());
if (binding != null) {
String target = binding.getTarget();
int index = target.lastIndexOf('/');
if (index != -1) {
target = target.substring(index+1);
}
toTable = mf.getSchema().getTable(target);
if(index != -1) {
toTable.setNameInSource(binding.getTarget());
}
} else {
// this means there is no EntitySet defined for this EntityType,
// or even if it is defined the set of rows are specific to this EntitySet
StringBuilder name = new StringBuilder()
.append(fromTable.getName()).append(NAME_SEPARATOR)
.append(property.getName());
toTable = addTable(mf, name.toString(), property.getType(),
property.isCollection()?ODataType.NAVIGATION_COLLECTION:ODataType.NAVIGATION,
metadata);
toTable.setNameInSource(property.getName());
}
// support for self-joins
if (same(fromTable, toTable)) {
StringBuilder name = new StringBuilder()
.append(fromTable.getName()).append(NAME_SEPARATOR)
.append(property.getName());
toTable = addTable(mf, name.toString(), toTable.getProperty(NAME_IN_SCHEMA, false),
property.isCollection()?ODataType.NAVIGATION_COLLECTION:ODataType.NAVIGATION,
metadata);
toTable.setNameInSource(property.getName());
}
toTable.setProperty(PARENT_TABLE, fromTable.getName());
toTable.setProperty(MERGE, fromTable.getFullName());
toTable.setProperty(FK_NAME, property.getName());
int i = 0;
for (CsdlReferentialConstraint constraint : property.getReferentialConstraints()) {
toTable.setProperty(CONSTRAINT_PROPERTY + i, constraint.getReferencedProperty());
toTable.setProperty(CONSTRAINT_REF_PROPERTY + i, constraint.getProperty());
i++;
}
}
}
private KeyRecord getPK(MetadataFactory mf, Table table) throws TranslatorException {
KeyRecord record = table.getPrimaryKey();
if (record == null) {
String parentTable = table.getProperty(PARENT_TABLE, false);
if (parentTable == null) {
throw new TranslatorException(ODataPlugin.Util.gs(ODataPlugin.Event.TEIID17024,
table.getName()));
}
return getPK(mf, mf.getSchema().getTable(parentTable));
}
return record;
}
private void addPrimaryKeyToComplexTables(MetadataFactory mf, Table childTable, Table parentTable)
throws TranslatorException {
KeyRecord record = null;
if (isComplexType(childTable)) {
// these are complex type based tables.
record = getPK(mf, parentTable);
} else {
// this is entity types now.
record = parentTable.getPrimaryKey();
}
if (record == null) {
throw new TranslatorException(ODataPlugin.Util.gs(ODataPlugin.Event.TEIID17025,
parentTable.getName()));
}
int i = 0;
List<String> columnNames = new ArrayList<String>();
for (Column column:record.getColumns()) {
String targetColumnName = isCollection(childTable) ?
parentTable.getName() + "_" + column.getName() : column.getName();
if (isNavigationType(childTable)) {
Column c = mf.getSchema().getTable(childTable.getName()).getColumnByName(targetColumnName);
if (c == null) {
c = addColumn(mf, childTable, column, targetColumnName);
c.setProperty(PSEUDO, column.getName());
} else {
targetColumnName = column.getName();
}
} else {
Column c = mf.getSchema().getTable(childTable.getName()).getColumnByName(column.getName());
if (c == null) {
c = addColumn(mf, childTable, column, targetColumnName);
c.setProperty(PSEUDO, column.getName());
} else {
targetColumnName = column.getName();
}
}
columnNames.add(targetColumnName);
// if there are no constraints are available then, define some implicit ones
if (childTable.getProperty(CONSTRAINT_PROPERTY + i, false) == null) {
childTable.setProperty(CONSTRAINT_PROPERTY + i, targetColumnName);
childTable.setProperty(CONSTRAINT_REF_PROPERTY + i, column.getName());
}
i++;
}
if (isComplexType(childTable)) {
mf.addPrimaryKey("PK0", columnNames, childTable);
}
}
private void addForeignKey(MetadataFactory mf, Table childTable, Table parentTable)
throws TranslatorException {
String fkName = childTable.getProperty(FK_NAME, false);
childTable.setProperty(FK_NAME, null);
if (fkName == null) {
fkName = "FK0";
}
int i = 0;
ArrayList<String> keyColumns = new ArrayList<String>();
ArrayList<String> refColumns = new ArrayList<String>();
while(true) {
if (childTable.getProperty(CONSTRAINT_PROPERTY + i, false) == null) {
break;
}
keyColumns.add(childTable.getProperty(CONSTRAINT_PROPERTY + i, false));
refColumns.add(childTable.getProperty(CONSTRAINT_REF_PROPERTY + i, false));
childTable.setProperty(CONSTRAINT_PROPERTY + i, null);
childTable.setProperty(CONSTRAINT_REF_PROPERTY + i, null);
i++;
}
mf.addForiegnKey(fkName, keyColumns, refColumns, parentTable.getName(), childTable); //$NON-NLS-1$
}
boolean same(Table x, Table y) {
return (x.getFullName().equalsIgnoreCase(y.getFullName()));
}
boolean keyMatches(List<String> names, KeyRecord record) {
if (names.size() != record.getColumns().size()) {
return false;
}
Set<String> keyNames = new TreeSet<String>(
String.CASE_INSENSITIVE_ORDER);
for (Column c : record.getColumns()) {
keyNames.add(c.getName());
}
for (int i = 0; i < names.size(); i++) {
if (!keyNames.contains(names.get(i))) {
return false;
}
}
return true;
}
private Column addPropertyAsColumn(MetadataFactory mf, Table table,
CsdlProperty property) {
Column c = buildColumn(mf, table, property);
c.setNullType(property.isNullable() ? NullType.Nullable
: NullType.No_Nulls);
if (property.getMaxLength() != null) {
c.setLength(property.getMaxLength());
}
if (property.getPrecision() != null) {
c.setPrecision(property.getPrecision());
}
if (property.getScale() != null) {
c.setScale(property.getScale());
}
if (property.getDefaultValue() != null) {
c.setDefaultValue(property.getDefaultValue());
}
if (property.getMimeType() != null) {
c.setProperty("MIME-TYPE", property.getMimeType());
}
if (property.getSrid() != null) {
c.setProperty(BaseColumn.SPATIAL_SRID, property.getSrid().toString());
}
if (!property.getType().equals("Edm.String")) {
if (property.isCollection()) {
c.setNativeType("Collection("+property.getType()+")");
} else {
c.setNativeType(property.getType());
}
}
if (property.getType().equals("Edm.String") && property.isCollection()) {
c.setNativeType("Collection("+property.getType()+")");
}
return c;
}
private Column addColumn(MetadataFactory mf, Table table, Column property, String newName) {
Column c = mf.addColumn(newName, property.getRuntimeType(),table);
c.setUpdatable(true);
c.setNullType(property.getNullType());
c.setLength(property.getLength());
c.setPrecision(property.getPrecision());
c.setScale(property.getScale());
c.setDefaultValue(property.getDefaultValue());
c.setProperty("MIME-TYPE", c.getProperty("MIME-TYPE", false));
c.setProperty(BaseColumn.SPATIAL_SRID, property.getProperty(BaseColumn.SPATIAL_SRID, false));
c.setProperty("NATIVE_TYPE", property.getProperty("NATIVE_TYPE", false));
return c;
}
private ProcedureParameter addParameterAsColumn(MetadataFactory mf,
Procedure procedure, CsdlParameter parameter) {
ProcedureParameter p = mf.addProcedureParameter(
parameter.getName(),
ODataTypeManager.teiidType(parameter.getType(),parameter.isCollection()),
ProcedureParameter.Type.In,
procedure);
p.setNullType(parameter.isNullable()?NullType.Nullable:NullType.No_Nulls);
if (parameter.getMaxLength() != null) {
p.setLength(parameter.getMaxLength());
}
if (parameter.getPrecision() != null) {
p.setPrecision(parameter.getPrecision());
}
if (parameter.getScale() != null) {
p.setScale(parameter.getScale());
}
if (parameter.getSrid() != null) {
p.setProperty(BaseColumn.SPATIAL_SRID, parameter.getSrid().toString());
}
return p;
}
private Column buildColumn(MetadataFactory mf, Table table, CsdlProperty property) {
String columnName = property.getName();
Column c = mf.addColumn(columnName, ODataTypeManager.teiidType(property.getType(),
property.isCollection()), table);
if (TypeFacility.RUNTIME_NAMES.GEOMETRY.equals(c.getDatatype().getName())) {
String type = property.getType();
if (type.startsWith(EDM_GEOMETRY) && type.length() > EDM_GEOMETRY.length()) {
c.setProperty(BaseColumn.SPATIAL_TYPE, type.substring(EDM_GEOMETRY.length()).toUpperCase());
}
}
if(property.isCollection()) {
c.setSearchType(SearchType.Unsearchable);
}
c.setUpdatable(true);
return c;
}
private void addParameter(MetadataFactory mf, XMLMetadata metadata,
Procedure procedure, CsdlParameter parameter) throws TranslatorException {
if (isSimple(parameter.getType())) {
addParameterAsColumn(mf, procedure, parameter);
}
else {
throw new TranslatorException(ODataPlugin.Util.gs(
ODataPlugin.Event.TEIID17022, parameter.getName()));
}
}
void addFunctionImportAsProcedure(MetadataFactory mf,
CsdlFunctionImport functionImport, ODataType odataType, XMLMetadata metadata)
throws TranslatorException {
List<CsdlFunction> functions = getFunctions(metadata,
functionImport.getFunction());
for (CsdlFunction function : functions) {
Procedure procedure = mf.addProcedure(function.getName());
addOperation(mf, metadata, odataType, function, procedure);
}
}
private void addProcedureTableReturn(MetadataFactory mf, XMLMetadata metadata, Procedure procedure,
CsdlComplexType type, String namePrefix) throws TranslatorException {
for (CsdlProperty property:type.getProperties()) {
if (isSimple(property.getType()) || isEnum(metadata, property.getType())) {
mf.addProcedureResultSetColumn(
namePrefix == null? property.getName():namePrefix+"_"+property.getName(),
ODataTypeManager.teiidType(property.getType(), property.isCollection()), procedure);
}
else if (isComplexType(metadata, property.getType())) {
CsdlComplexType childType = (CsdlComplexType)getComplexType(metadata, property.getType());
addProcedureTableReturn(mf, metadata, procedure, childType, property.getName());
}
else {
throw new TranslatorException(ODataPlugin.Util.gs(
ODataPlugin.Event.TEIID17023, procedure.getName()));
}
}
}
private void addProcedureTableReturn(MetadataFactory mf, XMLMetadata metadata, Procedure procedure,
CsdlEntityType type, String namePrefix) throws TranslatorException {
for (CsdlProperty property:type.getProperties()) {
if (isSimple(property.getType()) || isEnum(metadata, property.getType())) {
mf.addProcedureResultSetColumn(
namePrefix == null? property.getName():namePrefix+"_"+property.getName(),
ODataTypeManager.teiidType(property.getType(), property.isCollection()), procedure);
}
else if (isComplexType(metadata, property.getType())) {
CsdlComplexType childType = (CsdlComplexType)getComplexType(metadata, property.getType());
addProcedureTableReturn(mf, metadata, procedure, childType, property.getName());
}
else {
throw new TranslatorException(ODataPlugin.Util.gs(
ODataPlugin.Event.TEIID17023, procedure.getName()));
}
}
}
private void addActionImportAsProcedure(MetadataFactory mf, CsdlActionImport actionImport,
ODataType odataType, XMLMetadata metadata) throws TranslatorException {
List<CsdlAction> actions = getActions(metadata, actionImport.getAction());
for (CsdlAction action : actions) {
if (!hasComplexParameters(action.getParameters())) {
Procedure procedure = mf.addProcedure(action.getName());
addOperation(mf, metadata, odataType, action, procedure);
} else {
LogManager.logInfo(LogConstants.CTX_ODATA,
ODataPlugin.Util.gs(ODataPlugin.Event.TEIID17033, action.getName()));
}
}
}
private boolean hasComplexParameters(List<CsdlParameter> parameters) {
for (CsdlParameter parameter:parameters) {
if (!isSimple(parameter.getType())) {
return false;
}
}
return false;
}
private void addOperation(MetadataFactory mf, XMLMetadata metadata, ODataType odataType,
CsdlOperation function, Procedure procedure)
throws TranslatorException {
procedure.setProperty(ODATA_TYPE, odataType.name());
for (CsdlParameter parameter : function.getParameters()) {
addParameter(mf, metadata, procedure, parameter);
}
CsdlReturnType returnType = function.getReturnType();
if (returnType != null) {
if (isSimple(returnType.getType())) {
mf.addProcedureParameter("return", ODataTypeManager.teiidType(returnType.getType(),
returnType.isCollection()), ProcedureParameter.Type.ReturnValue, procedure);
}
else if (isComplexType(metadata, returnType.getType())) {
addProcedureTableReturn(mf, metadata, procedure,
getComplexType(metadata, returnType.getType()), null);
procedure.getResultSet().setProperty(ODATA_TYPE,
returnType.isCollection()?ODataType.COMPLEX_COLLECTION.name():ODataType.COMPLEX.name());
}
else if (isEntityType(metadata, returnType.getType())){
addProcedureTableReturn(mf, metadata, procedure,
getEntityType(metadata, returnType.getType()), null);
procedure.getResultSet().setProperty(ODATA_TYPE,
returnType.isCollection()?ODataType.ENTITY_COLLECTION.name():ODataType.ENTITY.name());
}
else {
throw new TranslatorException(ODataPlugin.Util.gs(
ODataPlugin.Event.TEIID17005, function.getName(),
returnType.getType()));
}
}
}
public void setSchemaNamespace(String namespace) {
this.schemaNamespace = namespace;
}
List<String> getColumnNames(List<Column> columns) {
ArrayList<String> names = new ArrayList<String>();
for (Column c : columns) {
names.add(c.getName());
}
return names;
}
@TranslatorProperty(display="Schema Namespace", category=PropertyType.IMPORT, description="Namespace of the schema to import")
public String getSchemaNamespace() {
return schemaNamespace;
}
}