/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.ddl.importer.node;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.modeshape.sequencer.ddl.StandardDdlLexicon;
import org.modeshape.sequencer.ddl.dialect.oracle.OracleDdlLexicon;
import org.modeshape.sequencer.ddl.node.AstNode;
import org.teiid.designer.metamodels.relational.util.RelationalTypeMapping;
import org.teiid.designer.relational.model.RelationalColumn;
import org.teiid.designer.relational.model.RelationalIndex;
import org.teiid.designer.relational.model.RelationalModel;
import org.teiid.designer.relational.model.RelationalParameter;
import org.teiid.designer.relational.model.RelationalProcedure;
import org.teiid.designer.relational.model.RelationalReference;
import org.teiid.designer.relational.model.RelationalSchema;
import org.teiid.designer.relational.model.RelationalTable;
/**
*
*/
public class OracleImporter extends StandardImporter {
private static final String VARCHAR2_TYPE_NAME = "VARCHAR2"; //$NON-NLS-1$
private static final String NVARCHAR2_TYPE_NAME = "NVARCHAR2"; //$NON-NLS-1$
private static final String NUMBER_TYPE_NAME = "NUMBER"; //$NON-NLS-1$
@Override
protected RelationalProcedure createProcedure(AstNode procedureNode, RelationalModel model) throws Exception {
RelationalProcedure procedure = super.createProcedure(procedureNode, model);
for (AstNode child : procedureNode) {
if (! is(child, OracleDdlLexicon.TYPE_FUNCTION_PARAMETER))
continue;
RelationalParameter prm = getFactory().createParameter();
procedure.getParameters().add(prm);
initialize(prm, child);
String datatype = child.getProperty(StandardDdlLexicon.DATATYPE_NAME).toString();
prm.setNativeType(datatype);
String teiidType = getTeiidDataTypeName(datatype);
prm.setDatatype(teiidType);
Object prop = child.getProperty(StandardDdlLexicon.DATATYPE_LENGTH);
if (prop != null)
prm.setLength(Integer.parseInt(prop.toString()));
prop = child.getProperty(StandardDdlLexicon.DATATYPE_PRECISION);
if (prop != null)
prm.setPrecision(Integer.parseInt(prop.toString()));
prop = child.getProperty(StandardDdlLexicon.DATATYPE_SCALE);
if (prop != null)
prm.setScale(Integer.parseInt(prop.toString()));
prop = child.getProperty(StandardDdlLexicon.NULLABLE);
if (prop != null)
prm.setNullable(prop.toString());
prop = child.getProperty(StandardDdlLexicon.DEFAULT_VALUE);
if (prop != null)
prm.setDefaultValue(prop.toString());
prop = child.getProperty(OracleDdlLexicon.IN_OUT_NO_COPY);
if (prop != null) {
String direction = prop.toString();
prm.setDirection(direction);
}
}
return procedure;
}
/**
* Create RelationalReference objects
* @param node the provided AstNode
* @param model the RelationalModel being created
* @param schema the schema
* @return the map of AstNodes which need to be deferred
* @throws Exception
*/
@Override
protected Map<AstNode,RelationalReference> createObject(AstNode node, RelationalModel model, RelationalSchema schema) throws Exception {
Map<AstNode,RelationalReference> deferredMap = new HashMap<AstNode,RelationalReference>();
if (is(node, OracleDdlLexicon.TYPE_CREATE_TABLE_INDEX_STATEMENT)) {
deferredMap.put(node, null);
} else if (is(node, OracleDdlLexicon.TYPE_CREATE_PROCEDURE_STATEMENT)) {
createProcedure(node, model);
} else if (is(node, OracleDdlLexicon.TYPE_CREATE_FUNCTION_STATEMENT)) {
createProcedure(node, model).setFunction(true);
} else {
return super.createObject(node, model, schema);
}
return deferredMap;
}
/**
* Create deferred objects using the supplied map
* @param deferredNodes the map of deferred AstNodes
* @param model the RelationalModel being created
* @throws Exception
*/
@Override
protected void createDeferredObjects(Map<AstNode,RelationalReference> deferredNodes, RelationalModel model) throws Exception {
Collection<RelationalReference> allRefs = model.getAllReferences();
// Make first pass to create the PKs
Set<AstNode> astNodes = deferredNodes.keySet();
for(AstNode node:astNodes) {
if (is(node, StandardDdlLexicon.TYPE_TABLE_CONSTRAINT)) {
RelationalTable table = (RelationalTable)deferredNodes.get(node);
createPrimaryKey(node, table, allRefs);
} else if (is(node, StandardDdlLexicon.TYPE_ALTER_TABLE_STATEMENT)) {
RelationalTable table = find(RelationalTable.class, node, null, allRefs);
for (AstNode node1 : node) {
if (is(node1, StandardDdlLexicon.TYPE_ADD_TABLE_CONSTRAINT_DEFINITION))
createPrimaryKey(node1, table, allRefs);
}
}
}
// Second pass create other constraints
for(AstNode node:astNodes) {
if (is(node, OracleDdlLexicon.TYPE_CREATE_TABLE_INDEX_STATEMENT)) {
RelationalIndex index = getFactory().createIndex();
Info info = createInfo(node, model);
if (info.getSchema() == null)
model.addChild(index);
else
info.getSchema().getIndexes().add(index);
initialize(index, node, info.getName());
Object prop = node.getProperty(OracleDdlLexicon.UNIQUE_INDEX);
if (prop != null) index.setUnique((Boolean)prop);
// Get Table referenced
String tableName = (String)node.getProperty(OracleDdlLexicon.TABLE_NAME);
RelationalTable table = find(RelationalTable.class, tableName, node, null, allRefs);
// Get columns referenced and add them to the index
if(table!=null) {
List<AstNode> childNodes = node.getChildren();
for(AstNode child : childNodes) {
if(is(child, StandardDdlLexicon.TYPE_COLUMN_REFERENCE)) {
try {
RelationalColumn col = find(RelationalColumn.class, child, table, allRefs);
if(col!=null) {
index.getColumns().add(col);
}
} catch (EntityNotFoundException error) {
addProgressMessage(error.getMessage());
}
}
}
}
} else if (is(node, StandardDdlLexicon.TYPE_TABLE_CONSTRAINT)) {
RelationalTable table = (RelationalTable)deferredNodes.get(node);
createConstraint(node, table, allRefs);
} else if (is(node, StandardDdlLexicon.TYPE_ALTER_TABLE_STATEMENT)) {
RelationalTable table = find(RelationalTable.class, node, null, allRefs);
for (AstNode node1 : node) {
if (is(node1, StandardDdlLexicon.TYPE_ADD_TABLE_CONSTRAINT_DEFINITION))
createConstraint(node1, table, allRefs);
else if (is(node1, StandardDdlLexicon.TYPE_ADD_COLUMN_DEFINITION))
createColumn(node1, table);
}
}
}
}
/**
* @param jdbcTypeName
*
* @return {@link EObject} represented by the given data type id
* @throws Exception
*/
@Override
protected String getTeiidDataTypeName(String jdbcTypeName) throws Exception {
String standardName = jdbcTypeName;
if (VARCHAR2_TYPE_NAME.equalsIgnoreCase(jdbcTypeName) || NVARCHAR2_TYPE_NAME.equalsIgnoreCase(jdbcTypeName)) {
standardName = RelationalTypeMapping.SQL_TYPE_NAMES.VARCHAR;
}
if (NUMBER_TYPE_NAME.equalsIgnoreCase(jdbcTypeName)) {
standardName = RelationalTypeMapping.SQL_TYPE_NAMES.NUMERIC;
}
return super.getTeiidDataTypeName(standardName);
}
}