From 65b9194baf6bbceb4a3325b5d74adbe9e3bf4278 Mon Sep 17 00:00:00 2001 From: Paul Richardson Date: Fri, 7 Jun 2013 17:55:11 +0100 Subject: [PATCH] TEIIDDES-1739: Refactors the DDL importer * Separates out the ddl importer into specialised node sub-importers * Node Importers keys against the parser id returned from modeshape * spi plugin provides the node importer registry and extension point --- .../org.teiid.designer.feature/feature.xml | 7 + .../compare/selector/ModelSelector.java | 3 +- .../META-INF/MANIFEST.MF | 3 +- .../build.properties | 3 +- .../plugin.xml | 28 + .../designer/ddl/importer/DdlImporter.java | 1103 ++--------------- .../ddl/importer/DdlImporterI18n.java | 39 +- .../ddl/importer/DdlImporterPlugin.java | 11 + .../designer/ddl/importer/i18n.properties | 2 + .../ddl/importer/node/AbstractImporter.java | 85 ++ .../ddl/importer/node/DerbyImporter.java | 113 ++ .../ddl/importer/node/MySQLImporter.java | 40 + .../ddl/importer/node/OracleImporter.java | 101 ++ .../ddl/importer/node/PostgresImporter.java | 39 + .../ddl/importer/node/StandardImporter.java | 520 ++++++++ .../ddl/importer/node/TeiidDdlImporter.java | 553 +++++++++ plugins/org.teiid.designer.ddl.spi/.classpath | 7 + plugins/org.teiid.designer.ddl.spi/.project | 28 + .../META-INF/MANIFEST.MF | 20 + .../build.properties | 7 + .../plugin.properties | 9 + plugins/org.teiid.designer.ddl.spi/plugin.xml | 5 + plugins/org.teiid.designer.ddl.spi/pom.xml | 28 + .../schema/ddlNodeImporter.exsd | 123 ++ .../teiid/designer/ddl/DdlImporterModel.java | 361 ++++++ .../teiid/designer/ddl/DdlNodeImporter.java | 34 + .../ddl/registry/DdlNodeImporterRegistry.java | 51 + plugins/pom.xml | 1 + 28 files changed, 2273 insertions(+), 1051 deletions(-) create mode 100644 plugins/org.teiid.designer.ddl.importer/plugin.xml create mode 100644 plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/AbstractImporter.java create mode 100644 plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/DerbyImporter.java create mode 100644 plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/MySQLImporter.java create mode 100644 plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/OracleImporter.java create mode 100644 plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/PostgresImporter.java create mode 100644 plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/StandardImporter.java create mode 100644 plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/TeiidDdlImporter.java create mode 100644 plugins/org.teiid.designer.ddl.spi/.classpath create mode 100644 plugins/org.teiid.designer.ddl.spi/.project create mode 100644 plugins/org.teiid.designer.ddl.spi/META-INF/MANIFEST.MF create mode 100644 plugins/org.teiid.designer.ddl.spi/build.properties create mode 100644 plugins/org.teiid.designer.ddl.spi/plugin.properties create mode 100644 plugins/org.teiid.designer.ddl.spi/plugin.xml create mode 100644 plugins/org.teiid.designer.ddl.spi/pom.xml create mode 100644 plugins/org.teiid.designer.ddl.spi/schema/ddlNodeImporter.exsd create mode 100644 plugins/org.teiid.designer.ddl.spi/src/org/teiid/designer/ddl/DdlImporterModel.java create mode 100644 plugins/org.teiid.designer.ddl.spi/src/org/teiid/designer/ddl/DdlNodeImporter.java create mode 100644 plugins/org.teiid.designer.ddl.spi/src/org/teiid/designer/ddl/registry/DdlNodeImporterRegistry.java diff --git a/features/org.teiid.designer.feature/feature.xml b/features/org.teiid.designer.feature/feature.xml index cda5c27375..f510ae91fb 100644 --- a/features/org.teiid.designer.feature/feature.xml +++ b/features/org.teiid.designer.feature/feature.xml @@ -611,4 +611,11 @@ version="0.0.0" unpack="false"/> + + diff --git a/plugins/org.teiid.designer.compare/src/org/teiid/designer/compare/selector/ModelSelector.java b/plugins/org.teiid.designer.compare/src/org/teiid/designer/compare/selector/ModelSelector.java index 708d5206ef..a631602912 100644 --- a/plugins/org.teiid.designer.compare/src/org/teiid/designer/compare/selector/ModelSelector.java +++ b/plugins/org.teiid.designer.compare/src/org/teiid/designer/compare/selector/ModelSelector.java @@ -9,6 +9,7 @@ import java.util.List; import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EObject; import org.teiid.core.designer.ModelerCoreException; import org.teiid.designer.core.util.ModelContents; import org.teiid.designer.core.workspace.ModelWorkspaceException; @@ -28,7 +29,7 @@ public interface ModelSelector { public void setLabel( String label ); - public List getRootObjects() throws ModelerCoreException; + public List getRootObjects() throws ModelerCoreException; public URI getUri(); diff --git a/plugins/org.teiid.designer.ddl.importer/META-INF/MANIFEST.MF b/plugins/org.teiid.designer.ddl.importer/META-INF/MANIFEST.MF index 95ea67ee7b..fa495fe2b2 100644 --- a/plugins/org.teiid.designer.ddl.importer/META-INF/MANIFEST.MF +++ b/plugins/org.teiid.designer.ddl.importer/META-INF/MANIFEST.MF @@ -14,7 +14,8 @@ Require-Bundle: org.teiid.designer.compare;bundle-version="[8.1.0,9.0.0)", org.eclipse.emf.ecore;bundle-version="[2.8.0,3.0.0)", org.eclipse.core.resources;bundle-version="[3.8.0,4.0.0)", org.eclipse.core.runtime;bundle-version="[3.8.0,4.0.0)", - org.teiid.designer.modeshape;bundle-version="[8.1.0,9.0.0)" + org.teiid.designer.modeshape;bundle-version="[8.1.0,9.0.0)", + org.teiid.designer.ddl.spi;bundle-version="[8.2.0,9.0.0)" Bundle-RequiredExecutionEnvironment: JavaSE-1.6 Bundle-ActivationPolicy: lazy Bundle-ClassPath: . diff --git a/plugins/org.teiid.designer.ddl.importer/build.properties b/plugins/org.teiid.designer.ddl.importer/build.properties index e9673b032a..47fc788200 100644 --- a/plugins/org.teiid.designer.ddl.importer/build.properties +++ b/plugins/org.teiid.designer.ddl.importer/build.properties @@ -4,4 +4,5 @@ bin.includes = META-INF/,\ .,\ OSGI-INF/,\ OSGI-INF/l10n/,\ - LEGAL.txt + LEGAL.txt,\ + plugin.xml diff --git a/plugins/org.teiid.designer.ddl.importer/plugin.xml b/plugins/org.teiid.designer.ddl.importer/plugin.xml new file mode 100644 index 0000000000..445433fd42 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.importer/plugin.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + diff --git a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/DdlImporter.java b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/DdlImporter.java index 57cd0dabdd..21f1716561 100644 --- a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/DdlImporter.java +++ b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/DdlImporter.java @@ -9,44 +9,23 @@ import java.io.File; import java.io.FileReader; -import java.io.IOException; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; import java.util.List; -import java.util.Map; -import java.util.Set; - import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; -import org.eclipse.emf.common.util.URI; -import org.eclipse.emf.ecore.EObject; -import org.modeshape.sequencer.ddl.DdlConstants; import org.modeshape.sequencer.ddl.DdlParsers; import org.modeshape.sequencer.ddl.StandardDdlLexicon; -import org.modeshape.sequencer.ddl.dialect.derby.DerbyDdlLexicon; -import org.modeshape.sequencer.ddl.dialect.mysql.MySqlDdlLexicon; -import org.modeshape.sequencer.ddl.dialect.oracle.OracleDdlLexicon; -import org.modeshape.sequencer.ddl.dialect.postgres.PostgresDdlLexicon; -import org.modeshape.sequencer.ddl.dialect.teiid.TeiidDdlConstants; -import org.modeshape.sequencer.ddl.dialect.teiid.TeiidDdlLexicon; import org.modeshape.sequencer.ddl.node.AstNode; import org.teiid.core.designer.CoreModelerPlugin; -import org.teiid.core.designer.I18n; -import org.teiid.core.designer.ModelerCoreException; import org.teiid.core.designer.exception.EmptyArgumentException; -import org.teiid.core.designer.util.CoreArgCheck; -import org.teiid.core.designer.util.CoreStringUtil; import org.teiid.core.designer.util.FileUtils; import org.teiid.core.designer.util.OperationUtil; import org.teiid.core.designer.util.OperationUtil.Unreliable; @@ -54,37 +33,15 @@ import org.teiid.designer.compare.DifferenceReport; import org.teiid.designer.compare.MergeProcessor; import org.teiid.designer.compare.ModelerComparePlugin; -import org.teiid.designer.compare.processor.DifferenceProcessorImpl; -import org.teiid.designer.compare.selector.ModelResourceSelector; -import org.teiid.designer.compare.selector.ModelSelector; -import org.teiid.designer.compare.selector.TransientModelSelector; import org.teiid.designer.core.ModelerCore; -import org.teiid.designer.core.validation.rules.StringNameValidator; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.core.workspace.ModelUtil; +import org.teiid.designer.ddl.DdlImporterModel; +import org.teiid.designer.ddl.DdlNodeImporter; +import org.teiid.designer.ddl.registry.DdlNodeImporterRegistry; import org.teiid.designer.metamodels.core.ModelAnnotation; import org.teiid.designer.metamodels.core.ModelType; -import org.teiid.designer.metamodels.relational.AccessPattern; -import org.teiid.designer.metamodels.relational.BaseTable; -import org.teiid.designer.metamodels.relational.Column; -import org.teiid.designer.metamodels.relational.ColumnSet; -import org.teiid.designer.metamodels.relational.DirectionKind; -import org.teiid.designer.metamodels.relational.ForeignKey; -import org.teiid.designer.metamodels.relational.Index; -import org.teiid.designer.metamodels.relational.NullableType; -import org.teiid.designer.metamodels.relational.PrimaryKey; -import org.teiid.designer.metamodels.relational.Procedure; -import org.teiid.designer.metamodels.relational.ProcedureParameter; -import org.teiid.designer.metamodels.relational.ProcedureResult; -import org.teiid.designer.metamodels.relational.ProcedureUpdateCount; -import org.teiid.designer.metamodels.relational.RelationalEntity; -import org.teiid.designer.metamodels.relational.RelationalFactory; import org.teiid.designer.metamodels.relational.RelationalPackage; -import org.teiid.designer.metamodels.relational.Schema; -import org.teiid.designer.metamodels.relational.SearchabilityType; -import org.teiid.designer.metamodels.relational.Table; -import org.teiid.designer.metamodels.relational.UniqueConstraint; -import org.teiid.designer.metamodels.relational.util.RelationalTypeMappingImpl; /** * DdlImporter parses the provided DDL and generates a model containing the parsed entities @@ -93,755 +50,24 @@ */ public class DdlImporter { - private static final RelationalFactory FACTORY = RelationalFactory.eINSTANCE; - private static final String STRING_TYPENAME = "string"; //$NON-NLS-1$ - - private final IProject[] projects; + private IProject[] projects; private IContainer modelFolder; private String ddlFileName; - private String modelName; private IFile modelFile; - private ModelType modelType; private DifferenceProcessor chgProcessor; private ModelResource model; - private boolean optToCreateModelEntitiesForUnsupportedDdl; - private boolean optToSetModelEntityDescription; - boolean isTeiidDdl = false; - - // hold on to DDL so that it can be set in the description - private Map descriptionMap = new HashMap(); - private Map teiidAnnotationMap = new HashMap(); + + private DdlImporterModel importerModel = new DdlImporterModel(); /** * DdlImporter contructor * @param projects the list of open workspace projects */ - public DdlImporter( final IProject[] projects ) { + public DdlImporter(IProject[] projects ) { this.projects = projects; } - /* - * Create a Model Entity, using the provided AstNode - * @param node the provided AstNode - * @param roots the current model roots - * @param schema the schema - * @param messages the list of messages generated during generation - */ - private void create( final AstNode node, - final List roots, - final Schema schema, - final List messages ) throws CoreException { - isTeiidDdl = false; - try { - // ----------------------------------------------------------------------- - // Handle Creation of Teiid Entities - // ----------------------------------------------------------------------- - if (node.hasMixin(TeiidDdlLexicon.CreateTable.TABLE_STATEMENT) - || node.hasMixin(TeiidDdlLexicon.CreateProcedure.PROCEDURE_STATEMENT) - || node.hasMixin(TeiidDdlLexicon.CreateProcedure.FUNCTION_STATEMENT) - || node.hasMixin(TeiidDdlLexicon.AlterOptions.TABLE_STATEMENT) - || node.hasMixin(TeiidDdlLexicon.AlterOptions.VIEW_STATEMENT) - || node.hasMixin(TeiidDdlLexicon.AlterOptions.PROCEDURE_STATEMENT) - || node.hasMixin(TeiidDdlLexicon.CreateTable.VIEW_STATEMENT)) { - - isTeiidDdl = true; - - createTeiidEntity(node,roots,messages); - - // ----------------------------------------------------------------------- - // All other Non-Teiid DDL - // ----------------------------------------------------------------------- - } else if (node.hasMixin(StandardDdlLexicon.TYPE_CREATE_TABLE_STATEMENT)) { - isTeiidDdl = false; - - final BaseTable table = initializeTable(FACTORY.createBaseTable(), node, roots); - for (final AstNode child : node) { - if (child.hasMixin(StandardDdlLexicon.TYPE_COLUMN_DEFINITION)) createColumn(child, table); - else if (child.hasMixin(StandardDdlLexicon.TYPE_TABLE_CONSTRAINT)) createKey(child, table, roots, messages); - } - } else if (node.hasMixin(StandardDdlLexicon.TYPE_CREATE_VIEW_STATEMENT)) { - isTeiidDdl = false; - if (modelType != ModelType.VIRTUAL_LITERAL && optToCreateModelEntitiesForUnsupportedDdl) initializeTable(FACTORY.createView(), - node, - roots); - } else if (node.hasMixin(OracleDdlLexicon.TYPE_CREATE_INDEX_STATEMENT) - || node.hasMixin(DerbyDdlLexicon.TYPE_CREATE_INDEX_STATEMENT) - || node.hasMixin(MySqlDdlLexicon.TYPE_CREATE_INDEX_STATEMENT) - || node.hasMixin(PostgresDdlLexicon.TYPE_CREATE_INDEX_STATEMENT)) { - isTeiidDdl = false; - final Index index = FACTORY.createIndex(); - final Info info = new Info(index, node, roots); - if (info.schema == null) roots.add(index); - else info.schema.getIndexes().add(index); - initialize(index, node, info.name); - Object prop = node.getProperty(OracleDdlLexicon.UNIQUE_INDEX); - if (prop == null) prop = node.getProperty(DerbyDdlLexicon.UNIQUE_INDEX); - if (prop != null) index.setUnique((Boolean)prop); - prop = node.getProperty(OracleDdlLexicon.TABLE_NAME); - if (prop == null) prop = node.getProperty(DerbyDdlLexicon.TABLE_NAME); - if (prop != null) { - try { - final Table table = find(Table.class, prop.toString(), node, null, roots); - for (final AstNode node1 : node) { - // Probably need to check for a simple column reference for Oracle - if (node1.hasMixin(DerbyDdlLexicon.TYPE_INDEX_COLUMN_REFERENCE)) try { - index.getColumns().add(find(Column.class, node1, table, roots)); - } catch (final EntityNotFoundException error) { - messages.add(error.getMessage()); - } - } - } catch (final EntityNotFoundException error) { - messages.add(error.getMessage()); - } - } - } else if (node.hasMixin(OracleDdlLexicon.TYPE_CREATE_PROCEDURE_STATEMENT) - || node.hasMixin(DerbyDdlLexicon.TYPE_CREATE_PROCEDURE_STATEMENT) - || node.hasMixin(MySqlDdlLexicon.TYPE_CREATE_PROCEDURE_STATEMENT)) try { - isTeiidDdl = false; - createProcedure(node, roots); - } catch (final EntityNotFoundException error) { - messages.add(error.getMessage()); - } - else if (node.hasMixin(OracleDdlLexicon.TYPE_CREATE_FUNCTION_STATEMENT) - || node.hasMixin(DerbyDdlLexicon.TYPE_CREATE_FUNCTION_STATEMENT) - || node.hasMixin(MySqlDdlLexicon.TYPE_CREATE_FUNCTION_STATEMENT) - || node.hasMixin(PostgresDdlLexicon.TYPE_CREATE_FUNCTION_STATEMENT)) try { - isTeiidDdl = false; - createProcedure(node, roots).setFunction(true); - } catch (final EntityNotFoundException error) { - messages.add(error.getMessage()); - } - else if (node.hasMixin(StandardDdlLexicon.TYPE_ALTER_TABLE_STATEMENT)) { - isTeiidDdl = false; - final BaseTable table = find(BaseTable.class, node, schema, roots); - for (final AstNode node1 : node) { - if (node1.hasMixin(StandardDdlLexicon.TYPE_ADD_TABLE_CONSTRAINT_DEFINITION)) createKey(node1, - table, - roots, - messages); - else if (node1.hasMixin(StandardDdlLexicon.TYPE_ADD_COLUMN_DEFINITION)) createColumn(node1, table); - } - } - } catch (final EntityNotFoundException error) { - messages.add(error.getMessage()); - } - } - - /** - * Creates Entity from Teiid DDL nodes - * @param node the provided AstNode - * @param roots the current model roots - * @param messages the generated messages - * @throws CoreException - * @throws EntityNotFoundException - */ - private void createTeiidEntity(AstNode node, List roots, List messages) throws CoreException,EntityNotFoundException { - // TODO need to handle SchemaElement (foreign or virtual) - DO we need to set model type to physical or virtual - - if (node.hasMixin(TeiidDdlLexicon.CreateTable.TABLE_STATEMENT) - || node.hasMixin(TeiidDdlLexicon.CreateTable.VIEW_STATEMENT) ) { - - final BaseTable table = initializeTable(FACTORY.createBaseTable(), node, roots); - - for (final AstNode child : node) { - // Table Elements - if (child.hasMixin(TeiidDdlLexicon.CreateTable.TABLE_ELEMENT)) { - createColumn(child, table); - // Contraints - } else if(child.hasMixin(TeiidDdlLexicon.Constraint.TABLE_ELEMENT) - || child.hasMixin(TeiidDdlLexicon.Constraint.FOREIGN_KEY_CONSTRAINT) - || child.hasMixin(TeiidDdlLexicon.Constraint.INDEX_CONSTRAINT)) { - - createTeiidConstraint(child,table,roots,messages); - // Statement Options - } else if(child.hasMixin(StandardDdlLexicon.TYPE_STATEMENT_OPTION)) { - handleTeiidTableOption(table,child); - } - } - } else if (node.hasMixin(TeiidDdlLexicon.CreateProcedure.PROCEDURE_STATEMENT) - || node.hasMixin(TeiidDdlLexicon.CreateProcedure.FUNCTION_STATEMENT)) { - createProcedure(node,roots); - - // Handle Alter Table - } else if ( node.hasMixin(TeiidDdlLexicon.AlterOptions.TABLE_STATEMENT) ) { - final BaseTable table = find(BaseTable.class, node, null, roots); - if(table!=null) { - for (final AstNode child : node) { - if (child.hasMixin(TeiidDdlLexicon.AlterOptions.OPTIONS_LIST)) { - List nodeList = child.getChildren(); - for(AstNode listItem: nodeList) { - if(listItem.hasMixin(StandardDdlLexicon.TYPE_STATEMENT_OPTION)) { - handleTeiidTableOption(table,listItem); - } - } - } - } - } - // Handle Alter View and Procedure - // TODO: could potentially be combined with alter table block above - } else if ( node.hasMixin(TeiidDdlLexicon.AlterOptions.VIEW_STATEMENT) - || node.hasMixin(TeiidDdlLexicon.AlterOptions.PROCEDURE_STATEMENT) ) { - } else { - throw new IllegalStateException(); - } - } - - /* - * Handle the OPTION keys that may be set on Tables for Teiid DDL - */ - private void handleTeiidTableOption(BaseTable table, AstNode node) { - boolean wasCommonOption = handleTeiidCommonOption(table,node); - if(wasCommonOption) return; - - // TODO: handle 'generic' statement options - String optionName = node.getName(); - Object optionValue = node.getProperty(StandardDdlLexicon.VALUE); - if(!CoreStringUtil.isEmpty(optionName)) { - String optionValueStr = (String)optionValue; - if(!CoreStringUtil.isEmpty(optionValueStr)) { - if(optionName.equalsIgnoreCase(TeiidDDLConstants.CARDINALITY)) { - table.setCardinality(Integer.parseInt(optionValueStr)); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.MATERIALIZED)) { - table.setMaterialized(isTrue(optionValueStr)); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.MATERIALIZED_TABLE)) { - //Table mattable = new Table(); - //mattable.setName(value); - //table.setMaterializedTable(mattable); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.UPDATABLE)) { - table.setSupportsUpdate(isTrue(optionValueStr)); - } - } - } - } - - /* - * Handle the OPTION keys that may be set on ProcedureParameters for Teiid DDL - * @param procParam the ProcedureParameter - * @param paramNode the procedure parameter AstNode - */ - private void handleTeiidProcParamOptions(ProcedureParameter procParam, AstNode paramNode) { - List children = paramNode.getChildren(); - for(AstNode child: children) { - if(child.hasMixin(StandardDdlLexicon.TYPE_STATEMENT_OPTION)) { - handleTeiidProcParamOption(procParam,child); - } - } - } - - /* - * Handle the OPTION keys that may be set on a ProcedureParameter for Teiid DDL - * @param procParam the ProcedureParameter - * @param procParamOptionNode a statementOption node for the procedure parameter - */ - private void handleTeiidProcParamOption(ProcedureParameter procParam, AstNode procParamOptionNode) { - boolean wasCommonOption = handleTeiidCommonOption(procParam,procParamOptionNode); - if(wasCommonOption) return; - } - - /* - * Handle the OPTION keys that may be set on Column for Teiid DDL - * @param column the Column - * @param columnNode the column AstNode - */ - private void handleTeiidColumnOptions(Column column, AstNode columnNode) { - List children = columnNode.getChildren(); - for(AstNode child: children) { - if(child.hasMixin(StandardDdlLexicon.TYPE_STATEMENT_OPTION)) { - handleTeiidColumnOption(column,child); - } - } - } - - /* - * Handle a statement OPTION key for Column for Teiid DDL - * @param column the Column - * @param columnOptionNode a statementOption node for a column - */ - private void handleTeiidColumnOption(Column column, AstNode columnOptionNode) { - boolean wasCommonOption = handleTeiidCommonOption(column,columnOptionNode); - if(wasCommonOption) return; - - String optionName = columnOptionNode.getName(); - Object optionValue = columnOptionNode.getProperty(StandardDdlLexicon.VALUE); - if(!CoreStringUtil.isEmpty(optionName)) { - String optionValueStr = (String)optionValue; - if(!CoreStringUtil.isEmpty(optionValueStr)) { - if(optionName.equalsIgnoreCase(TeiidDDLConstants.SELECTABLE)) { - column.setSelectable(isTrue(optionValueStr)); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.UPDATABLE)) { - column.setUpdateable(isTrue(optionValueStr)); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.CURRENCY)) { - column.setCurrency(isTrue(optionValueStr)); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.CASE_SENSITIVE)) { - column.setCaseSensitive(isTrue(optionValueStr)); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.SIGNED)) { - column.setSigned(isTrue(optionValueStr)); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.FIXED_LENGTH)) { - column.setFixedLength(isTrue(optionValueStr)); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.SEARCHABLE)) { - column.setSearchability(SearchabilityType.get(optionValueStr.toUpperCase())); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.MIN_VALUE)) { - column.setMinimumValue(optionValueStr); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.MAX_VALUE)) { - column.setMaximumValue(optionValueStr); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.NATIVE_TYPE)) { - column.setNativeType(optionValueStr); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.NULL_VALUE_COUNT)) { - column.setNullValueCount(Integer.parseInt(optionValueStr)); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.DISTINCT_VALUES)) { - //column.setDistinctValueCount(value); - } - } - } - } - - /* - * Handle a statementOption for a Procedure for Teiid DDL - * @param proc the Procedure - * @param procOptionNode a statementOption for a procedure - */ - private void handleTeiidProcedureOption(Procedure proc, AstNode procOptionNode) { - boolean wasCommonOption = handleTeiidCommonOption(proc,procOptionNode); - if(wasCommonOption) return; - - String optionName = procOptionNode.getName(); - Object optionValue = procOptionNode.getProperty(StandardDdlLexicon.VALUE); - if(!CoreStringUtil.isEmpty(optionName)) { - String optionValueStr = (String)optionValue; - if(!CoreStringUtil.isEmpty(optionValueStr)) { - if(optionName.equalsIgnoreCase(TeiidDDLConstants.UPDATECOUNT)) { - proc.setUpdateCount(getUpdateCount(optionValueStr)); - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.CATEGORY)) { - proc.setFunction(true); - } - } - } - } - - /* - * Get ProcedureUpdateCount object for the provided string value - * @param value the string value - * @return the ProcedureUpdateCount object corresponding to the provided string - */ - private ProcedureUpdateCount getUpdateCount(String value) { - if( ProcedureUpdateCount.AUTO_LITERAL.getName().equalsIgnoreCase(value) ) { - return ProcedureUpdateCount.AUTO_LITERAL; - } - if( ProcedureUpdateCount.ONE_LITERAL.getName().equalsIgnoreCase(value) ) { - return ProcedureUpdateCount.ONE_LITERAL; - } - if( ProcedureUpdateCount.MULTIPLE_LITERAL.getName().equalsIgnoreCase(value) ) { - return ProcedureUpdateCount.MULTIPLE_LITERAL; - } - if( ProcedureUpdateCount.ZERO_LITERAL.getName().equalsIgnoreCase(value) ) { - return ProcedureUpdateCount.ZERO_LITERAL; - } - - return ProcedureUpdateCount.AUTO_LITERAL; - } - - /* - * Gets boolean value for the provided text string - * @param text a text string - * @return 'true' if provided string is "true", otherwise 'false' - */ - private static boolean isTrue(final String text) { - return Boolean.valueOf(text); - } - - /* - * Creates constraints for Table for Teiid DDL - * @param contraintNode the AstNode for the constraint - * @param table the BaseTable object - * @param roots the current model roots - * @param message the list of messages - */ - private void createTeiidConstraint(final AstNode constraintNode, - final BaseTable table, - final List roots, - final List messages) throws CoreException { - - final String type = constraintNode.getProperty(TeiidDdlLexicon.Constraint.TYPE).toString(); - - boolean primaryKeyConstraint = false; - boolean uniqueConstraint = false; - boolean accessPatternConstraint = false; - boolean foreignKeyConstraint = false; - boolean indexConstraint = false; - RelationalEntity key = null; - - if (DdlConstants.PRIMARY_KEY.equals(type)) { - key = FACTORY.createPrimaryKey(); - initialize(key, constraintNode); - table.setPrimaryKey((PrimaryKey)key); - primaryKeyConstraint = true; - } else if (DdlConstants.INDEX.equals(type)) { - // TODO need to process teiidddl:expression property - key = FACTORY.createIndex(); - initialize(key, constraintNode); - roots.add(key); - indexConstraint = true; - } else if (DdlConstants.UNIQUE.equals(type)) { - key = FACTORY.createUniqueConstraint(); - initialize(key, constraintNode); - table.getUniqueConstraints().add(key); - uniqueConstraint = true; - } else if (TeiidDdlConstants.TeiidNonReservedWord.ACCESSPATTERN.toDdl().equals(type)) { - key = FACTORY.createAccessPattern(); - initialize(key, constraintNode); - table.getAccessPatterns().add(key); - accessPatternConstraint = true; - } else if (DdlConstants.FOREIGN_KEY.equals(type)) { - key = FACTORY.createForeignKey(); - initializeFK(table.getForeignKeys(), (ForeignKey)key, constraintNode); - table.getForeignKeys().add(key); - foreignKeyConstraint = true; - } else { - assert false : "Unexpected constraint type of '" + type + "'"; //$NON-NLS-1$ //$NON-NLS-2$ - } - - // process referenced columns multi-valued property - final Object temp = constraintNode.getProperty(TeiidDdlLexicon.Constraint.REFERENCES); - final List references = (List)temp; - - for (final AstNode ref : references) { - try { - if (primaryKeyConstraint) { - ((PrimaryKey)key).getColumns().add(find(Column.class, ref, table, roots)); - } else if (uniqueConstraint) { - ((UniqueConstraint)key).getColumns().add(find(Column.class, ref, table, roots)); - } else if (accessPatternConstraint) { - ((AccessPattern)key).getColumns().add(find(Column.class, ref, table, roots)); - } else if (foreignKeyConstraint) { - ((ForeignKey)key).getColumns().add(find(Column.class, ref, table, roots)); - } else if (indexConstraint) { - ((Index)key).getColumns().add(find(Column.class, ref, table, roots)); - }else { - assert false : "Unexpected constraint type of '" + type + "'"; //$NON-NLS-1$ //$NON-NLS-2$ - } - } catch (final EntityNotFoundException error) { - messages.add(error.getMessage()); - } - } - - // special processing for foreign key - if (foreignKeyConstraint) { - final ForeignKey foreignKey = (ForeignKey)key; - - // must have a table reference - final AstNode tableRefNode = (AstNode)constraintNode.getProperty(TeiidDdlLexicon.Constraint.TABLE_REFERENCE); - if(tableRefNode==null) { - messages.add(DdlImporterI18n.FK_TABLE_REF_NOT_FOUND_MSG+" '"+foreignKey.getName()+"'"); //$NON-NLS-1$ //$NON-NLS-2$ - return; - } - - try { - final BaseTable tableRef = find(BaseTable.class, tableRefNode, null, roots); - final PrimaryKey tableRefPrimaryKey = tableRef.getPrimaryKey(); - final List primaryKeyColumns = tableRef.getColumns(); - // check to see if foreign table columns are referenced - final Object tempRefColumns = constraintNode.getProperty(TeiidDdlLexicon.Constraint.TABLE_REFERENCE_REFERENCES); - - final List foreignTableColumnNodes = (tempRefColumns==null) ? Collections.emptyList() : (List)tempRefColumns; - int numPKColumns = primaryKeyColumns.size(); - int numFKColumns = foreignTableColumnNodes.size(); - - if( foreignTableColumnNodes.isEmpty() ) { - foreignKey.setUniqueKey(tableRefPrimaryKey); - } else if( numPKColumns == numFKColumns ) { - for(AstNode fTableColumn : foreignTableColumnNodes) { - find(Column.class, fTableColumn, tableRef, roots); - } - foreignKey.setUniqueKey(tableRefPrimaryKey); - // } else { - // for (final Object obj : foreignTable.getUniqueConstraints()) { - // final UniqueConstraint uniqueKey = (UniqueConstraint)obj; - // final List uniqueKeyColumns = uniqueKey.getColumns(); - // - // if (uniqueKeyColumns.containsAll(foreignColumns) && uniqueKeyColumns.size() == foreignColumns.size()) { - // key.setUniqueKey(uniqueKey); - // break; - // } - // } - } else { - foreignKey.setUniqueKey(tableRefPrimaryKey); - } - } catch (final EntityNotFoundException error) { - messages.add(error.getMessage()); - } - } - } - - /* - * Create Column from the provided AstNode within ColumnSet - * @param node the provided AstNode - * @param table the ColumnSet in which to create the column - */ - private void createColumn( final AstNode node, - final ColumnSet table) throws CoreException { - final Column col = FACTORY.createColumn(); - table.getColumns().add(col); - initialize(col, node); - - final String datatype = node.getProperty(StandardDdlLexicon.DATATYPE_NAME).toString(); - col.setNativeType(datatype); - - EObject type = null; - if(!isTeiidDdl) { - type = RelationalTypeMappingImpl.getInstance().getDatatype(datatype); - } else { - type = getTeiidDatatype(datatype); - } - col.setType(type); - - Object prop = node.getProperty(StandardDdlLexicon.DATATYPE_LENGTH); - // Datatype length - if (prop != null) { - col.setLength(Integer.parseInt(prop.toString())); - // If length is not provided for type 'string', use the default length specified in preferences... - } else { - String dtName = ModelerCore.getWorkspaceDatatypeManager().getName(type); - if(dtName!=null && dtName.equalsIgnoreCase(STRING_TYPENAME)) { - col.setLength(ModelerCore.getTransformationPreferences().getDefaultStringLength()); - } - } - prop = node.getProperty(StandardDdlLexicon.DATATYPE_PRECISION); - if (prop != null) col.setPrecision(Integer.parseInt(prop.toString())); - prop = node.getProperty(StandardDdlLexicon.DATATYPE_SCALE); - if (prop != null) col.setScale(Integer.parseInt(prop.toString())); - prop = node.getProperty(StandardDdlLexicon.NULLABLE); - if (prop != null) col.setNullable(prop.toString().equals("NULL") ? NullableType.NULLABLE_LITERAL : NullableType.NO_NULLS_LITERAL); //$NON-NLS-1$ - prop = node.getProperty(StandardDdlLexicon.DEFAULT_VALUE); - if (prop != null) col.setDefaultValue(prop.toString()); - - // Handle Teiid-specific properties and options - if(isTeiidDdl) { - prop = node.getProperty(TeiidDdlLexicon.CreateTable.AUTO_INCREMENT); - if(prop!=null) col.setAutoIncremented(isTrue(prop.toString())); - handleTeiidColumnOptions(col,node); - } - } - - /* - * Handles statementOption common to all relational entities for Teiid DDL - * @param entity the RelationalEntity - * @param node the statementOption AstNode - * @return 'true' if the provided OPTION was a 'common' option, 'false' if not. - */ - private boolean handleTeiidCommonOption(RelationalEntity entity, AstNode optionNode) { - boolean wasCommonOption = false; - - String optionName = optionNode.getName(); - Object optionValue = optionNode.getProperty(StandardDdlLexicon.VALUE); - if(!CoreStringUtil.isEmpty(optionName)) { - String optionValueStr = (String)optionValue; - if(!CoreStringUtil.isEmpty(optionValueStr)) { - if(optionName.equalsIgnoreCase(TeiidDDLConstants.ANNOTATION)) { - this.teiidAnnotationMap.put(entity, optionValueStr); - wasCommonOption = true; - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.UUID)) { - // entity.setUUID(); - wasCommonOption = true; - } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.NAMEINSOURCE)) { - entity.setNameInSource(optionValueStr); - wasCommonOption = true; - } - } - } - return wasCommonOption; - } - - /* - * Get the Datatype for Teiid DDL. First tries to match the datatype string with a teiid built-in type. - * If a built-in type is not found, then attempt to use the relational mapping to find a match. - * @param datatype the datatype string - * @param the matching EObject datatype - */ - private EObject getTeiidDatatype(String datatype) throws ModelerCoreException { - EObject resultType = null; - - // Look up matching Built-In type - Object[] builtInTypes = ModelerCore.getWorkspaceDatatypeManager().getAllDatatypes(); - String dtName = null; - for( int i=0; i roots, - final List messages ) throws CoreException { - final String type = node.getProperty(StandardDdlLexicon.CONSTRAINT_TYPE).toString(); - if (DdlConstants.PRIMARY_KEY.equals(type)) { - final PrimaryKey key = FACTORY.createPrimaryKey(); - table.setPrimaryKey(key); - initialize(key, node); - for (final AstNode node1 : node) { - if (node1.hasMixin(StandardDdlLexicon.TYPE_COLUMN_REFERENCE)) try { - Column column = find(Column.class, node1, table, roots); - - if( column.getNullable() == NullableType.NULLABLE_UNKNOWN_LITERAL || column.getNullable() == NullableType.NULLABLE_LITERAL ) { - column.setNullable(NullableType.NO_NULLS_LITERAL); - } - key.getColumns().add(column); - } catch (final EntityNotFoundException error) { - messages.add(error.getMessage()); - } - } - } else if (DdlConstants.FOREIGN_KEY.equals(type)) { - final ForeignKey key = FACTORY.createForeignKey(); - initializeFK(table.getForeignKeys(), key, node); - table.getForeignKeys().add(key); - BaseTable foreignTable = null; - final Set foreignColumns = new HashSet(); - for (final AstNode node1 : node) { - if (node1.hasMixin(StandardDdlLexicon.TYPE_COLUMN_REFERENCE)) try { - key.getColumns().add(find(Column.class, node1, table, roots)); - } catch (final EntityNotFoundException error) { - messages.add(error.getMessage()); - } - else if (node1.hasMixin(StandardDdlLexicon.TYPE_TABLE_REFERENCE)) try { - foreignTable = find(BaseTable.class, node1, null, roots); - } catch (final EntityNotFoundException error) { - messages.add(error.getMessage()); - } - else if (node1.hasMixin(StandardDdlLexicon.TYPE_FK_COLUMN_REFERENCE)) { - if (foreignTable != null) try { - foreignColumns.add(find(Column.class, node1, foreignTable, roots)); - } catch (final EntityNotFoundException error) { - messages.add(error.getMessage()); - } - } - } - if (foreignTable != null) { - final PrimaryKey primaryKey = foreignTable.getPrimaryKey(); - final List primaryKeyColumns = primaryKey.getColumns(); - if (foreignColumns.isEmpty()) key.setUniqueKey(primaryKey); - if (primaryKeyColumns.containsAll(foreignColumns) && primaryKeyColumns.size() == foreignColumns.size()) key.setUniqueKey(primaryKey); - else for (final Object obj : foreignTable.getUniqueConstraints()) { - final UniqueConstraint uniqueKey = (UniqueConstraint)obj; - final List uniqueKeyColumns = uniqueKey.getColumns(); - if (uniqueKeyColumns.containsAll(foreignColumns) && uniqueKeyColumns.size() == foreignColumns.size()) { - key.setUniqueKey(uniqueKey); - break; - } - } - } - } else if (DdlConstants.UNIQUE.equals(type)) { - final UniqueConstraint key = FACTORY.createUniqueConstraint(); - table.getUniqueConstraints().add(key); - initialize(key, node); - for (final AstNode node1 : node) { - if (node1.hasMixin(StandardDdlLexicon.TYPE_COLUMN_REFERENCE)) try { - Column column = find(Column.class, node1, table, roots); - - if( column.getNullable() == NullableType.NULLABLE_UNKNOWN_LITERAL || column.getNullable() == NullableType.NULLABLE_LITERAL ) { - column.setNullable(NullableType.NO_NULLS_LITERAL); - } - key.getColumns().add(column); - } catch (final EntityNotFoundException error) { - messages.add(error.getMessage()); - } - } - } - } - - private Procedure createProcedure( final AstNode procedureNode, - final List roots) throws EntityNotFoundException, CoreException { - final Procedure procedure = FACTORY.createProcedure(); - final Info info = new Info(procedure, procedureNode, roots); - if (info.schema == null) roots.add(procedure); - else info.schema.getProcedures().add(procedure); - initialize(procedure, procedureNode, info.name); - // TODO: determine how to handle Procedure StatementOption - // TODO: determine how to handle Procedure Statement - - if (procedureNode.getProperty(StandardDdlLexicon.DATATYPE_NAME) != null) { - final ProcedureResult result = FACTORY.createProcedureResult(); - procedure.setResult(result); - initialize(result, procedureNode); - } - for (final AstNode child : procedureNode) { - if (child.hasMixin(OracleDdlLexicon.TYPE_FUNCTION_PARAMETER) - || child.hasMixin(DerbyDdlLexicon.TYPE_FUNCTION_PARAMETER) - || child.hasMixin(TeiidDdlLexicon.CreateProcedure.PARAMETER)) { - final ProcedureParameter prm = FACTORY.createProcedureParameter(); - procedure.getParameters().add(prm); - initialize(prm, child); - final String datatype = child.getProperty(StandardDdlLexicon.DATATYPE_NAME).toString(); - prm.setNativeType(datatype); - - EObject type = null; - if(!isTeiidDdl) { - type = RelationalTypeMappingImpl.getInstance().getDatatype(datatype); - } else { - type = getTeiidDatatype(datatype); - } - prm.setType(type); - 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().equals("NULL") ? NullableType.NULLABLE_LITERAL : NullableType.NO_NULLS_LITERAL); //$NON-NLS-1$ - prop = child.getProperty(StandardDdlLexicon.DEFAULT_VALUE); - if (prop != null) prm.setDefaultValue(prop.toString()); - prop = child.getProperty(OracleDdlLexicon.IN_OUT_NO_COPY); - if (prop != null) { - final String direction = prop.toString(); - if ("IN".equals(direction)) prm.setDirection(DirectionKind.IN_LITERAL); //$NON-NLS-1$ - else if ("OUT".equals(direction) || "OUT NOCOPY".equals(direction)) prm.setDirection(DirectionKind.OUT_LITERAL); //$NON-NLS-1$ //$NON-NLS-2$ - else if ("IN OUT".equals(direction) || "IN OUT NOCOPY".equals(direction)) prm.setDirection(DirectionKind.INOUT_LITERAL); //$NON-NLS-1$ //$NON-NLS-2$ - } else { - prop = child.getProperty(TeiidDdlLexicon.CreateProcedure.PARAMETER_TYPE); - // TODO - Determine how to handle 'VARIADIC' - if(prop!=null) { - final String direction = prop.toString(); - if ("IN".equals(direction)) prm.setDirection(DirectionKind.IN_LITERAL); //$NON-NLS-1$ - else if ("OUT".equals(direction) ) prm.setDirection(DirectionKind.OUT_LITERAL); //$NON-NLS-1$ - else if ("INOUT".equals(direction) ) prm.setDirection(DirectionKind.INOUT_LITERAL); //$NON-NLS-1$ - } - } - handleTeiidProcParamOptions(prm,child); - // TODO: Determine how to handle teiidddl:result, ddl:defaultOption, ddl:statementOption - } else if(child.hasMixin(TeiidDdlLexicon.CreateProcedure.RESULT_COLUMNS)) { - // TODO: determine how to handle Table flag property - final ProcedureResult result = FACTORY.createProcedureResult(); - procedure.setResult(result); - initialize(result, procedureNode); - - for(AstNode resultCol: child) { - if(resultCol.hasMixin(TeiidDdlLexicon.CreateProcedure.RESULT_COLUMN)) { - createColumn(resultCol,result); - } - } - } else if(child.hasMixin(TeiidDdlLexicon.CreateProcedure.RESULT_DATA_TYPE)) { - final ProcedureResult result = FACTORY.createProcedureResult(); - procedure.setResult(result); - initialize(result, procedureNode); - createColumn(child,result); - } else if(child.hasMixin(StandardDdlLexicon.TYPE_STATEMENT_OPTION)) { - handleTeiidProcedureOption(procedure,child); - } - } - return procedure; - } - /** * @return ddlFileName */ @@ -849,45 +75,6 @@ public String ddlFileName() { return ddlFileName; } - private T find( final Class type, - final AstNode node, - final RelationalEntity parent, - final List roots ) throws EntityNotFoundException, CoreException { - return find(type, node.getName(), node, parent, roots); - } - - T find( final Class type, - final String name, - AstNode node, - final RelationalEntity parent, - final List roots ) throws EntityNotFoundException, CoreException { - for (final EObject obj : parent == null ? roots : parent.eContents()) { - if (type.isInstance(obj)) { - final T entity = (T)obj; - if (entity.getName().equalsIgnoreCase(name)) return entity; - } else if (parent == null && obj instanceof Schema) try { - return find(type, name, node, (Schema)obj, roots); - } catch (final EntityNotFoundException ignored) { - } - } - // Throw EntityNotFoundException - while (node.getProperty(StandardDdlLexicon.DDL_EXPRESSION) == null) { - node = node.getParent(); - } - String parentType = null; - if (parent == null) parentType = DdlImporterI18n.MODEL; - else for (final Class parentInterface : parent.getClass().getInterfaces()) { - if (RelationalEntity.class.isAssignableFrom(parentInterface)) parentType = parentInterface.getSimpleName(); - } - throw new EntityNotFoundException(I18n.format(DdlImporterI18n.ENTITY_NOT_FOUND_MSG, - type.getSimpleName(), - name, - parentType, - parent == null ? modelName : parent.getName(), - node.getProperty(StandardDdlLexicon.DDL_START_LINE_NUMBER).toString(), - node.getProperty(StandardDdlLexicon.DDL_START_COLUMN_NUMBER).toString())); - } - /** * @return The difference report for the {@link #importDdl(List, IProgressMonitor, int) imported} model */ @@ -895,7 +82,7 @@ public DifferenceReport getChangeReport() { return chgProcessor == null ? null : chgProcessor.getDifferenceReport(); } - private void handleStatus( final IStatus status ) { + private void handleStatus(IStatus status ) { if (!status.isOK()) { if (status.getException() != null) throw CoreModelerPlugin.toRuntimeException(status.getException()); throw new RuntimeException(status.getMessage()); @@ -907,10 +94,10 @@ private void handleStatus( final IStatus status ) { * @param monitor * @param totalWork */ - public void importDdl( final List messages, - final IProgressMonitor monitor, - final int totalWork ) { - if (chgProcessor != null) return; + public void importDdl(final List messages, final IProgressMonitor monitor, final int totalWork ) { + if (chgProcessor != null) + return; + OperationUtil.perform(new Unreliable() { private FileReader reader = null; @@ -932,31 +119,30 @@ public void tryToDo() throws Exception { }); } - void importDdl( final FileReader reader, - final List messages, - final IProgressMonitor monitor, - final int totalWork ) throws IOException, CoreException { + void importDdl(FileReader reader, List messages, IProgressMonitor monitor, int totalWork ) throws Exception { + + int workUnit = totalWork / 3; - final int workUnit = totalWork / 3; - // ------------------------------------------------------------------------------ // Parse the DDL from the file // ------------------------------------------------------------------------------ monitor.subTask(DdlImporterI18n.PARSING_DDL_MSG); // Read the file contents - final char[] buf = new char[FileUtils.DEFAULT_BUFFER_SIZE]; - final StringBuilder builder = new StringBuilder(); + char[] buf = new char[FileUtils.DEFAULT_BUFFER_SIZE]; + StringBuilder builder = new StringBuilder(); for (int charTot = reader.read(buf); charTot >= 0; charTot = reader.read(buf)) builder.append(buf, 0, charTot); Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); - final String ddlString = builder.toString(); - + // Parse the DDL - final DdlParsers parsers = new DdlParsers(); - final AstNode rootNode = parsers.parse(ddlString, ddlFileName); - if (monitor.isCanceled()) throw new OperationCanceledException(); + DdlParsers parsers = new DdlParsers(); + AstNode rootNode = parsers.parse(builder.toString(), ddlFileName); + String parserId = (String) rootNode.getProperty(StandardDdlLexicon.PARSER_ID); + + if (monitor.isCanceled()) + throw new OperationCanceledException(); monitor.worked(workUnit); - + // ------------------------------------------------------------------------------ // Set up DifferenceProcessor // - startingSelector -- existing model @@ -964,123 +150,30 @@ void importDdl( final FileReader reader, // ------------------------------------------------------------------------------ monitor.subTask(DdlImporterI18n.CREATING_MODEL_MSG); model = ModelerCore.create(modelFile); - final ModelResourceSelector startingSelector = new ModelResourceSelector(model); - final URI mdlUri = URI.createFileURI(model.getPath().toFile().getAbsolutePath()); - final ModelAnnotation mdlAnnotation = model.getModelAnnotation(); - - final TransientModelSelector endingSelector = new TransientModelSelector(mdlUri,mdlAnnotation); - - final DifferenceProcessor diffProcessor = createDifferenceProcessor(startingSelector,endingSelector); - final List roots = endingSelector.getRootObjects(); - for (final AstNode node : rootNode) { - if (node.hasMixin(StandardDdlLexicon.TYPE_CREATE_SCHEMA_STATEMENT)) { - final Schema schema = FACTORY.createSchema(); - roots.add(schema); - initialize(schema, node); - for (final AstNode node1 : node) { - create(node1, roots, schema, messages); - } - } else create(node, roots, null, messages); - } - if (monitor.isCanceled()) throw new OperationCanceledException(); + importerModel.setRelationalModel(model); + importerModel.setProgressMonitor(monitor); + importerModel.setProgressMessages(messages); + + DdlNodeImporter nodeImporter = DdlNodeImporterRegistry.getInstance().getRegistered(parserId.toUpperCase()); + if (nodeImporter == null) + throw new Exception(DdlImporterPlugin.i18n("noDDLImporterRegisteredMsg", parserId)); //$NON-NLS-1$ + + importerModel.setNodeImporter(nodeImporter); + nodeImporter.importNode(importerModel, rootNode); + if (monitor.isCanceled()) + throw new OperationCanceledException(); monitor.worked(workUnit); - - + // ------------------------------------------------------------------------------ // Execute generates the differenceReport // ------------------------------------------------------------------------------ monitor.subTask(DdlImporterI18n.CREATING_CHANGE_REPORT_MSG); - handleStatus(diffProcessor.execute(monitor)); - if (monitor.isCanceled()) throw new OperationCanceledException(); - monitor.worked(workUnit); - - chgProcessor = diffProcessor; - } - - /* - * Create DifferenceProcessor using starting and ending ModelSelector - * @param startingSelector the starting selector - * @param endingSelector the ending selector - * @return the difference processor - */ - private DifferenceProcessor createDifferenceProcessor( final ModelSelector startingSelector, - final ModelSelector endingSelector ) { - CoreArgCheck.isNotNull(startingSelector); - CoreArgCheck.isNotNull(endingSelector); - final DifferenceProcessor processor = new DifferenceProcessorImpl(startingSelector, endingSelector); - processor.addEObjectMatcherFactories(ModelerComparePlugin.createEObjectMatcherFactories()); - return processor; - } - - private void initialize( final RelationalEntity entity, - final AstNode node ) { - initialize(entity, node, node.getName()); - } - - private void initializeFK( final List currentFKs, - final ForeignKey key, - final AstNode node ) { - // Get Name from DDL node - String fkName = node.getName(); - // Make sure not to add duplicate FK names - String uniqueName = getUniqueFKName(currentFKs, fkName); - - initialize(key, node, uniqueName); - } - - /* - * Helper method for creating unique FK names - * @param currentFKs the List of ForeignKeys currently on the table - * @param newFKName the proposed name for the new FK - * @return the unique name - generated from the proposed name - */ - private String getUniqueFKName( List currentFKs, - String newFKName ) { - // If current list is empty, no need to check names - if (currentFKs == null || currentFKs.isEmpty()) return newFKName; - - // Use name validator for unique name generation - StringNameValidator nameValidator = new StringNameValidator(); + chgProcessor = importerModel.getDifferenceProcessor(); - // Add the current FK names to the validator - for (ForeignKey fk : currentFKs) { - nameValidator.addExistingName(fk.getName()); - } - - // Make the proposed name unique - return nameValidator.createValidUniqueName(newFKName); - } - - private void initialize( final RelationalEntity entity, - final AstNode node, - final String name ) { - entity.setName(name); - entity.setNameInSource(name); - - // descriptions must wait to be set until container and model type has been set - if (optToSetModelEntityDescription) { - final Object prop = node.getProperty(StandardDdlLexicon.DDL_EXPRESSION); - if (prop != null) { - this.descriptionMap.put(entity, prop.toString()); - } - } - } - - private T initializeTable( final T table, - final AstNode node, - final List roots ) throws EntityNotFoundException, CoreException { - final Info info = new Info(table, node, roots); - if (info.schema == null) roots.add(table); - else info.schema.getTables().add(table); - initialize(table, node, info.name); - return table; - } - - /** - * @return model - */ - public ModelResource model() { - return model; + handleStatus(chgProcessor.execute(monitor)); + if (monitor.isCanceled()) + throw new OperationCanceledException(); + monitor.worked(workUnit); } /** @@ -1101,51 +194,35 @@ public IContainer modelFolder() { * @return modelType */ public ModelType modelType() { - return modelType; + return importerModel.getModelType(); } /** * @param monitor * @param totalWork */ - public void save( final IProgressMonitor monitor, - final int totalWork ) { + public void save(IProgressMonitor monitor, int totalWork ) { monitor.subTask(DdlImporterI18n.SAVING_MODEL_MSG); try { if (!model.exists()) { - final ModelAnnotation modelAnnotation = model.getModelAnnotation(); + ModelAnnotation modelAnnotation = model.getModelAnnotation(); modelAnnotation.setPrimaryMetamodelUri(RelationalPackage.eNS_URI); - modelAnnotation.setModelType(modelType); + modelAnnotation.setModelType(importerModel.getModelType()); } - final MergeProcessor mergeProcessor = ModelerComparePlugin.createMergeProcessor(chgProcessor, + MergeProcessor mergeProcessor = ModelerComparePlugin.createMergeProcessor(chgProcessor, ModelerCore.getWorkspaceDatatypeManager().getAllDatatypes(), true); handleStatus(mergeProcessor.execute(monitor)); model.save(monitor, false); - // If Teiid DDL, use descriptionMap created from teiid annotations - boolean setDescriptions = false; - if(isTeiidDdl) { - for (Map.Entry entry : this.teiidAnnotationMap.entrySet()) { - ModelerCore.getModelEditor().setDescription(entry.getKey(), entry.getValue()); - setDescriptions = true; - } - } - - // If user chose to use DDL as description, now set those descriptions (model type and container *must* be already set) - if (optToSetModelEntityDescription) { - for (Map.Entry entry : this.descriptionMap.entrySet()) { - ModelerCore.getModelEditor().setDescription(entry.getKey(), entry.getValue()); - setDescriptions = true; - } - } - - if(setDescriptions) { + DdlNodeImporter nodeImporter = importerModel.getNodeImporter(); + if (nodeImporter != null) { + nodeImporter.importFinalize(); // save again model.save(monitor, false); } - } catch (final Exception error) { + } catch (Exception error) { throw CoreModelerPlugin.toRuntimeException(error); } monitor.worked(totalWork); @@ -1155,13 +232,13 @@ public void save( final IProgressMonitor monitor, /** * @param ddlFileName */ - public void setDdlFileName( String ddlFileName ) { + public void setDdlFileName(String ddlFileName ) { this.ddlFileName = null; chgProcessor = null; if (ddlFileName == null) throw new EmptyArgumentException("ddlFileName"); //$NON-NLS-1$ ddlFileName = ddlFileName.trim(); if (ddlFileName.isEmpty()) throw new EmptyArgumentException("ddlFileName"); //$NON-NLS-1$ - final File file = new File(ddlFileName); + File file = new File(ddlFileName); if (!file.exists() || file.isDirectory()) throw new IllegalArgumentException(DdlImporterI18n.DDL_FILE_NOT_FOUND_MSG); this.ddlFileName = ddlFileName; } @@ -1169,7 +246,7 @@ public void setDdlFileName( String ddlFileName ) { /** * @param modelFolder */ - public void setModelFolder( final IContainer modelFolder ) { + public void setModelFolder(IContainer modelFolder ) { this.modelFolder = modelFolder; chgProcessor = null; } @@ -1177,20 +254,20 @@ public void setModelFolder( final IContainer modelFolder ) { /** * @param modelFolderName */ - public void setModelFolder( String modelFolderName ) { + public void setModelFolder(String modelFolderName ) { modelFolder = null; chgProcessor = null; if (modelFolderName == null) throw new EmptyArgumentException("modelFolderName"); //$NON-NLS-1$ modelFolderName = modelFolderName.trim(); - final IPath modelFolderPath = Path.fromPortableString(modelFolderName).makeAbsolute(); + IPath modelFolderPath = Path.fromPortableString(modelFolderName).makeAbsolute(); if (modelFolderName.isEmpty() || modelFolderPath.segmentCount() == 0) throw new EmptyArgumentException("modelFolderName"); //$NON-NLS-1$ // Verify project is valid - final String projectName = modelFolderPath.segment(0); + String projectName = modelFolderPath.segment(0); IWorkspace workspace = ModelerCore.getWorkspace(); - final IWorkspaceRoot root = workspace.getRoot(); + IWorkspaceRoot root = workspace.getRoot(); if (root.findMember(projectName) != null) { boolean found = false; - for (final IProject project : projects) + for (IProject project : projects) if (projectName.equals(project.getName())) { found = true; break; @@ -1200,8 +277,8 @@ public void setModelFolder( String modelFolderName ) { // Verify folder is valid if (!workspace.validatePath(modelFolderPath.toString(), IResource.PROJECT | IResource.FOLDER).isOK()) throw new IllegalArgumentException( DdlImporterI18n.INVALID_MODEL_FOLDER_MSG); - final IResource resource = root.findMember(modelFolderPath); - // Verify final segment in folder is not a file + IResource resource = root.findMember(modelFolderPath); + // Verify segment in folder is not a file if (resource instanceof IFile) throw new IllegalArgumentException(DdlImporterI18n.MODEL_FOLDER_IS_FILE_MSG); if (resource == null) { if (modelFolderPath.segmentCount() == 1) modelFolder = root.getProject(projectName); @@ -1212,24 +289,24 @@ public void setModelFolder( String modelFolderName ) { /** * @param modelName */ - public void setModelName( String modelName ) { - this.modelName = null; + public void setModelName(String modelName ) { + importerModel.setModelName(null); modelFile = null; chgProcessor = null; if (modelName == null) throw new EmptyArgumentException("modelName"); //$NON-NLS-1$ modelName = modelName.trim(); if (modelName.isEmpty()) throw new EmptyArgumentException("modelName"); //$NON-NLS-1$ // Verify name is valid - final IWorkspace workspace = ModelerCore.getWorkspace(); + IWorkspace workspace = ModelerCore.getWorkspace(); if (!workspace.validateName(modelName, IResource.FILE).isOK()) throw new IllegalArgumentException( DdlImporterI18n.INVALID_MODEL_NAME_MSG); if (modelFolder != null) { - final IWorkspaceRoot root = workspace.getRoot(); + IWorkspaceRoot root = workspace.getRoot(); IPath modelPath = modelFolder.getFullPath().append(modelName); if (!modelName.endsWith(ModelerCore.MODEL_FILE_EXTENSION)) modelPath = modelPath.addFileExtension(ModelerCore.MODEL_FILE_EXTENSION.substring(1)); if (modelFolder.exists()) { // Verify name is not a folder - final IResource resource = root.findMember(modelPath); + IResource resource = root.findMember(modelPath); if (resource instanceof IContainer) throw new IllegalArgumentException(DdlImporterI18n.MODEL_NAME_IS_FOLDER_MSG); if (resource == null) modelFile = root.getFile(modelPath); else { @@ -1243,30 +320,30 @@ public void setModelName( String modelName ) { } } else modelFile = root.getFile(modelPath); } - this.modelName = new Path(modelName).removeFileExtension().lastSegment(); + importerModel.setModelName(new Path(modelName).removeFileExtension().lastSegment()); } /** * @param modelType Sets modelType to the specified value. */ - public void setModelType( final ModelType modelType ) { - this.modelType = modelType; + public void setModelType(ModelType modelType ) { + importerModel.setModelType(modelType); chgProcessor = null; } /** * @param optToCreateModelEntitiesForUnsupportedDdl */ - public void setOptToCreateModelEntitiesForUnsupportedDdl( final boolean optToCreateModelEntitiesForUnsupportedDdl ) { - this.optToCreateModelEntitiesForUnsupportedDdl = optToCreateModelEntitiesForUnsupportedDdl; + public void setOptToCreateModelEntitiesForUnsupportedDdl(boolean optToCreateModelEntitiesForUnsupportedDdl ) { + importerModel.setOptToCreateModelEntitiesForUnsupportedDdl(optToCreateModelEntitiesForUnsupportedDdl); chgProcessor = null; } /** * @param optToSetModelEntityDescription */ - public void setOptToSetModelEntityDescription( final boolean optToSetModelEntityDescription ) { - this.optToSetModelEntityDescription = optToSetModelEntityDescription; + public void setOptToSetModelEntityDescription(boolean optToSetModelEntityDescription ) { + importerModel.setOptToSetModelEntityDescription(optToSetModelEntityDescription); chgProcessor = null; } @@ -1276,36 +353,4 @@ public void setOptToSetModelEntityDescription( final boolean optToSetModelEntity public void undoImport() { chgProcessor = null; } - - private class EntityNotFoundException extends Exception { - - private static final long serialVersionUID = 1L; - - EntityNotFoundException( final String message ) { - super(message); - } - } - - private class Info { - - final Schema schema; - final String name; - - Info( final T entity, - final AstNode node, - final List roots ) throws EntityNotFoundException, CoreException { - final String name = node.getName(); - final int ndx = name.indexOf('.'); - if (ndx < 0) { - schema = null; - this.name = name; - } else if (isTeiidDdl) { - schema = null; - this.name = name.substring(ndx + 1); - } else { - schema = find(Schema.class, name.substring(0, ndx), node, null, roots); - this.name = name.substring(ndx + 1); - } - } - } } \ No newline at end of file diff --git a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/DdlImporterI18n.java b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/DdlImporterI18n.java index 383a108ebb..2a27c8ea45 100644 --- a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/DdlImporterI18n.java +++ b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/DdlImporterI18n.java @@ -9,23 +9,24 @@ import static org.teiid.designer.ddl.importer.DdlImporterPlugin.i18n; -class DdlImporterI18n { - static final String CREATING_CHANGE_REPORT_MSG = i18n("creatingChangeReportMsg"); //$NON-NLS-1$ - static final String CREATING_MODEL_MSG = i18n("creatingModelMsg"); //$NON-NLS-1$ - static final String DDL_FILE_NOT_FOUND_MSG = i18n("ddlFileNotFoundMsg"); //$NON-NLS-1$ - static final String ENTITY_NOT_FOUND_MSG = i18n("entityNotFoundMsg"); //$NON-NLS-1$ - static final String INVALID_MODEL_FOLDER_MSG = i18n("invalidModelFolderMsg"); //$NON-NLS-1$ - static final String INVALID_MODEL_NAME_MSG = i18n("invalidModelNameMsg"); //$NON-NLS-1$ - static final String MODEL = i18n("model"); //$NON-NLS-1$ - static final String MODEL_FOLDER_IN_NON_MODEL_PROJECT_MSG = i18n("modelFolderInNonModelProjectMsg"); //$NON-NLS-1$ - static final String MODEL_FOLDER_IS_FILE_MSG = i18n("modelFolderIsFileMsg"); //$NON-NLS-1$ - static final String MODEL_NAME_IS_FOLDER_MSG = i18n("modelNameIsFolderMsg"); //$NON-NLS-1$ - static final String MODEL_NAME_IS_NON_MODEL_FILE_MSG = i18n("modelNameIsNonModelFileMsg"); //$NON-NLS-1$ - static final String MODEL_NAME_IS_NON_RELATIONAL_MODEL_MSG = i18n("modelNameIsNonRelationalModelMsg"); //$NON-NLS-1$ - static final String PARSING_DDL_MSG = i18n("parsingDdlMsg"); //$NON-NLS-1$ - static final String SAVING_MODEL_MSG = i18n("savingModelMsg"); //$NON-NLS-1$ - static final String FK_TABLE_REF_NOT_FOUND_MSG = i18n("fkTableRefNotFoundMsg"); //$NON-NLS-1$ - - private DdlImporterI18n() { - } +/** + * i18n constants + */ +public interface DdlImporterI18n { + String CREATING_CHANGE_REPORT_MSG = i18n("creatingChangeReportMsg"); //$NON-NLS-1$ + String CREATING_MODEL_MSG = i18n("creatingModelMsg"); //$NON-NLS-1$ + String DDL_FILE_NOT_FOUND_MSG = i18n("ddlFileNotFoundMsg"); //$NON-NLS-1$ + String ENTITY_NOT_FOUND_MSG = i18n("entityNotFoundMsg"); //$NON-NLS-1$ + String INVALID_MODEL_FOLDER_MSG = i18n("invalidModelFolderMsg"); //$NON-NLS-1$ + String INVALID_MODEL_NAME_MSG = i18n("invalidModelNameMsg"); //$NON-NLS-1$ + String MODEL = i18n("model"); //$NON-NLS-1$ + String MODEL_FOLDER_IN_NON_MODEL_PROJECT_MSG = i18n("modelFolderInNonModelProjectMsg"); //$NON-NLS-1$ + String MODEL_FOLDER_IS_FILE_MSG = i18n("modelFolderIsFileMsg"); //$NON-NLS-1$ + String MODEL_NAME_IS_FOLDER_MSG = i18n("modelNameIsFolderMsg"); //$NON-NLS-1$ + String MODEL_NAME_IS_NON_MODEL_FILE_MSG = i18n("modelNameIsNonModelFileMsg"); //$NON-NLS-1$ + String MODEL_NAME_IS_NON_RELATIONAL_MODEL_MSG = i18n("modelNameIsNonRelationalModelMsg"); //$NON-NLS-1$ + String PARSING_DDL_MSG = i18n("parsingDdlMsg"); //$NON-NLS-1$ + String SAVING_MODEL_MSG = i18n("savingModelMsg"); //$NON-NLS-1$ + String FK_TABLE_REF_NOT_FOUND_MSG = i18n("fkTableRefNotFoundMsg"); //$NON-NLS-1$ + String FAILURE_IMPORT_MSG = i18n("importFailureMsg"); //$NON-NLS-1$ } diff --git a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/DdlImporterPlugin.java b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/DdlImporterPlugin.java index 71cb32ad9f..2e67f2dce7 100644 --- a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/DdlImporterPlugin.java +++ b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/DdlImporterPlugin.java @@ -41,6 +41,17 @@ static String i18n( final String key ) { return UTIL.getString(key); } + /** + * Not intended for use by any class other than {@link DdlImporterI18n}. + * + * @param key + * @param parameters + * @return The i18n template associated with the supplied key + */ + static String i18n( final String key, Object... parameters) { + return UTIL.getString(key, parameters); + } + /** * @return the singleton instance of this type */ diff --git a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/i18n.properties b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/i18n.properties index 16d78cbdb5..bd0c847fbd 100644 --- a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/i18n.properties +++ b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/i18n.properties @@ -13,3 +13,5 @@ modelNameIsNonRelationalModelMsg = The supplied model name refers to an existing parsingDdlMsg = Parsing DDL... savingModelMsg = Saving model... fkTableRefNotFoundMsg = Table reference not found for Foreign Key +importFailureMsg = Failed to import node +noDDLImporterRegisteredMsg = No ddl node importer registered for the {0} parser diff --git a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/AbstractImporter.java b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/AbstractImporter.java new file mode 100644 index 0000000000..f0275f200d --- /dev/null +++ b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/AbstractImporter.java @@ -0,0 +1,85 @@ +/* + * 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 org.modeshape.sequencer.ddl.node.AstNode; +import org.teiid.designer.ddl.DdlImporterModel; +import org.teiid.designer.ddl.DdlNodeImporter; +import org.teiid.designer.metamodels.relational.RelationalFactory; + +/** + * + */ +public abstract class AbstractImporter implements DdlNodeImporter { + + /** + * Entity Not Found Exception + */ + protected class EntityNotFoundException extends Exception { + + private static final long serialVersionUID = 1L; + + /** + * @param message + */ + public EntityNotFoundException(String message) { + super(message); + } + } + + private DdlImporterModel importerModel; + + /** + * @param importerModel + */ + protected void setImporterModel(DdlImporterModel importerModel) { + this.importerModel = importerModel; + } + + /** + * @return the importerModel + */ + protected DdlImporterModel getImporterModel() { + return this.importerModel; + } + + /** + * @return relational factory + */ + protected RelationalFactory getFactory() { + return importerModel.getFactory(); + } + + /** + * @param message + */ + protected void addProgressMessage(String message) { + importerModel.getProgressMessages().add(message); + } + + /** + * Gets boolean value for the provided text string + * + * @param text a text string + * @return 'true' if provided string is "true", otherwise 'false' + */ + protected boolean isTrue(String text) { + return Boolean.valueOf(text); + } + + /** + * Is given node of the given dialect + * + * @param node + * @param dialectType + * @return true if node has dialect + */ + protected boolean is(AstNode node, String dialectType) { + return node.hasMixin(dialectType); + } +} diff --git a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/DerbyImporter.java b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/DerbyImporter.java new file mode 100644 index 0000000000..ff6d6df0b5 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/DerbyImporter.java @@ -0,0 +1,113 @@ +/* + * 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.List; +import org.eclipse.emf.ecore.EObject; +import org.modeshape.sequencer.ddl.StandardDdlLexicon; +import org.modeshape.sequencer.ddl.dialect.derby.DerbyDdlLexicon; +import org.modeshape.sequencer.ddl.node.AstNode; +import org.teiid.designer.metamodels.relational.Column; +import org.teiid.designer.metamodels.relational.Index; +import org.teiid.designer.metamodels.relational.NullableType; +import org.teiid.designer.metamodels.relational.Procedure; +import org.teiid.designer.metamodels.relational.ProcedureParameter; +import org.teiid.designer.metamodels.relational.Schema; +import org.teiid.designer.metamodels.relational.Table; + +/** + * + */ +public class DerbyImporter extends StandardImporter { + + + @Override + protected Procedure createProcedure(AstNode procedureNode, List roots) throws Exception { + Procedure procedure = super.createProcedure(procedureNode, roots); + + for (AstNode child : procedureNode) { + if (! is(child, DerbyDdlLexicon.TYPE_FUNCTION_PARAMETER)) + continue; + + ProcedureParameter prm = getFactory().createProcedureParameter(); + procedure.getParameters().add(prm); + initialize(prm, child); + String datatype = child.getProperty(StandardDdlLexicon.DATATYPE_NAME).toString(); + prm.setNativeType(datatype); + + EObject type = getDataType(datatype); + prm.setType(type); + + 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().equals("NULL") ? NullableType.NULLABLE_LITERAL : NullableType.NO_NULLS_LITERAL); //$NON-NLS-1$ + + prop = child.getProperty(StandardDdlLexicon.DEFAULT_VALUE); + if (prop != null) + prm.setDefaultValue(prop.toString()); + } + + return procedure; + } + + @Override + protected void create(AstNode node, List roots, Schema schema) throws Exception { + if (is(node, DerbyDdlLexicon.TYPE_CREATE_INDEX_STATEMENT)) { + Index index = getFactory().createIndex(); + Info info = createInfo(node, roots); + if (info.getSchema() == null) + roots.add(index); + else + info.getSchema().getIndexes().add(index); + + initialize(index, node, info.getName()); + Object prop = node.getProperty(DerbyDdlLexicon.UNIQUE_INDEX); + if (prop != null) + index.setUnique((Boolean) prop); + + prop = node.getProperty(DerbyDdlLexicon.TABLE_NAME); + if (prop == null) + return; + + try { + Table table = find(Table.class, prop.toString(), node, null, roots); + for (AstNode node1 : node) { + // Probably need to check for a simple column reference for Oracle + if (node1.hasMixin(DerbyDdlLexicon.TYPE_INDEX_COLUMN_REFERENCE)) { + try { + index.getColumns().add(find(Column.class, node1, table, roots)); + } catch (EntityNotFoundException error) { + addProgressMessage(error.getMessage()); + } + } + } + } catch (EntityNotFoundException error) { + addProgressMessage(error.getMessage()); + } + } else if (is(node, DerbyDdlLexicon.TYPE_CREATE_PROCEDURE_STATEMENT)) { + createProcedure(node, roots); + } else if (is(node, DerbyDdlLexicon.TYPE_CREATE_FUNCTION_STATEMENT)) { + createProcedure(node, roots).setFunction(true); + } else { + super.create(node, roots, schema); + } + } + +} diff --git a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/MySQLImporter.java b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/MySQLImporter.java new file mode 100644 index 0000000000..33f70ae84e --- /dev/null +++ b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/MySQLImporter.java @@ -0,0 +1,40 @@ +/* + * 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.List; +import org.eclipse.emf.ecore.EObject; +import org.modeshape.sequencer.ddl.dialect.mysql.MySqlDdlLexicon; +import org.modeshape.sequencer.ddl.node.AstNode; +import org.teiid.designer.metamodels.relational.Index; +import org.teiid.designer.metamodels.relational.Schema; + +/** + * + */ +public class MySQLImporter extends StandardImporter { + + @Override + protected void create(AstNode node, List roots, Schema schema) throws Exception { + if (is(node, MySqlDdlLexicon.TYPE_CREATE_INDEX_STATEMENT)) { + Index index = getFactory().createIndex(); + Info info = createInfo(node, roots); + if (info.getSchema() == null) + roots.add(index); + else + info.getSchema().getIndexes().add(index); + + initialize(index, node, info.getName()); + } else if (is(node, MySqlDdlLexicon.TYPE_CREATE_PROCEDURE_STATEMENT)) { + createProcedure(node, roots); + } else if (is(node, MySqlDdlLexicon.TYPE_CREATE_FUNCTION_STATEMENT)) { + createProcedure(node, roots).setFunction(true); + } else + super.create(node, roots, schema); + } +} diff --git a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/OracleImporter.java b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/OracleImporter.java new file mode 100644 index 0000000000..b1883171c6 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/OracleImporter.java @@ -0,0 +1,101 @@ +/* + * 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.List; +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.DirectionKind; +import org.teiid.designer.metamodels.relational.Index; +import org.teiid.designer.metamodels.relational.NullableType; +import org.teiid.designer.metamodels.relational.Procedure; +import org.teiid.designer.metamodels.relational.ProcedureParameter; +import org.teiid.designer.metamodels.relational.Schema; + +/** + * + */ +public class OracleImporter extends StandardImporter { + + @Override + protected Procedure createProcedure(AstNode procedureNode, List roots) throws Exception { + Procedure procedure = super.createProcedure(procedureNode, roots); + + for (AstNode child : procedureNode) { + if (! is(child, OracleDdlLexicon.TYPE_FUNCTION_PARAMETER)) + continue; + + ProcedureParameter prm = getFactory().createProcedureParameter(); + procedure.getParameters().add(prm); + initialize(prm, child); + String datatype = child.getProperty(StandardDdlLexicon.DATATYPE_NAME).toString(); + prm.setNativeType(datatype); + + EObject type = getDataType(datatype); + prm.setType(type); + + 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().equals("NULL") ? NullableType.NULLABLE_LITERAL : NullableType.NO_NULLS_LITERAL); //$NON-NLS-1$ + + 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(); + if (DirectionKind.IN_LITERAL.getName().equals(direction)) + prm.setDirection(DirectionKind.IN_LITERAL); + else if (DirectionKind.OUT_LITERAL.getName().equals(direction) || "OUT NOCOPY".equals(direction)) //$NON-NLS-1$ + prm.setDirection(DirectionKind.OUT_LITERAL); + else if (DirectionKind.INOUT_LITERAL.getName().equals(direction) || "IN OUT NOCOPY".equals(direction)) //$NON-NLS-1$ + prm.setDirection(DirectionKind.INOUT_LITERAL); + } + } + + return procedure; + } + @Override + protected void create(AstNode node, List roots, Schema schema) throws Exception { + + if (is(node, OracleDdlLexicon.TYPE_CREATE_INDEX_STATEMENT)) { + Index index = getFactory().createIndex(); + Info info = createInfo(node, roots); + if (info.getSchema() == null) + roots.add(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); + } else if (is(node, OracleDdlLexicon.TYPE_CREATE_PROCEDURE_STATEMENT)) { + createProcedure(node, roots); + } else if (is(node, OracleDdlLexicon.TYPE_CREATE_FUNCTION_STATEMENT)) { + createProcedure(node, roots).setFunction(true); + } else + super.create(node, roots, schema); + } +} diff --git a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/PostgresImporter.java b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/PostgresImporter.java new file mode 100644 index 0000000000..f0507b0fa3 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/PostgresImporter.java @@ -0,0 +1,39 @@ +/* + * 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.List; +import org.eclipse.emf.ecore.EObject; +import org.modeshape.sequencer.ddl.dialect.postgres.PostgresDdlLexicon; +import org.modeshape.sequencer.ddl.node.AstNode; +import org.teiid.designer.metamodels.relational.Index; +import org.teiid.designer.metamodels.relational.Schema; + +/** + * + */ +public class PostgresImporter extends StandardImporter { + + @Override + protected void create(AstNode node, List roots, Schema schema) throws Exception { + if (is(node, PostgresDdlLexicon.TYPE_CREATE_INDEX_STATEMENT)) { + Index index = getFactory().createIndex(); + Info info = createInfo(node, roots); + if (info.getSchema() == null) + roots.add(index); + else + info.getSchema().getIndexes().add(index); + + initialize(index, node, info.getName()); + } + else if (is(node, PostgresDdlLexicon.TYPE_CREATE_FUNCTION_STATEMENT)) { + createProcedure(node, roots).setFunction(true); + } else + super.create(node, roots, schema); + } +} diff --git a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/StandardImporter.java b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/StandardImporter.java new file mode 100644 index 0000000000..b691778cbd --- /dev/null +++ b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/StandardImporter.java @@ -0,0 +1,520 @@ +/* + * 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.HashSet; +import java.util.List; +import java.util.Set; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.ecore.EObject; +import org.modeshape.sequencer.ddl.DdlConstants; +import org.modeshape.sequencer.ddl.StandardDdlLexicon; +import org.modeshape.sequencer.ddl.node.AstNode; +import org.teiid.core.designer.I18n; +import org.teiid.designer.core.ModelerCore; +import org.teiid.designer.core.validation.rules.StringNameValidator; +import org.teiid.designer.ddl.DdlImporterModel; +import org.teiid.designer.ddl.DdlImporterModel.EntityDescriptions; +import org.teiid.designer.ddl.DdlImporterModel.EntityDescriptions.DescriptionOperation; +import org.teiid.designer.ddl.importer.DdlImporterI18n; +import org.teiid.designer.metamodels.core.ModelType; +import org.teiid.designer.metamodels.relational.BaseTable; +import org.teiid.designer.metamodels.relational.Column; +import org.teiid.designer.metamodels.relational.ColumnSet; +import org.teiid.designer.metamodels.relational.ForeignKey; +import org.teiid.designer.metamodels.relational.NullableType; +import org.teiid.designer.metamodels.relational.PrimaryKey; +import org.teiid.designer.metamodels.relational.Procedure; +import org.teiid.designer.metamodels.relational.ProcedureResult; +import org.teiid.designer.metamodels.relational.RelationalEntity; +import org.teiid.designer.metamodels.relational.Schema; +import org.teiid.designer.metamodels.relational.Table; +import org.teiid.designer.metamodels.relational.UniqueConstraint; +import org.teiid.designer.metamodels.relational.util.RelationalTypeMappingImpl; + +/** + * Node importer for standard DDL + */ +public class StandardImporter extends AbstractImporter { + + class Info { + + protected Schema schema; + protected String name; + + public Info(AstNode node, List roots) throws Exception { + init(node, roots); + } + + protected void init(AstNode node, List roots) throws Exception { + String name = node.getName(); + int ndx = name.indexOf('.'); + if (ndx < 0) { + schema = null; + this.name = name; + } else { + schema = find(Schema.class, name.substring(0, ndx), node, null, roots); + this.name = name.substring(ndx + 1); + } + } + + /** + * @return the name + */ + public String getName() { + return this.name; + } + + /** + * @return the schema + */ + public Schema getSchema() { + return schema; + } + } + + private static final String STRING_TYPENAME = "string"; //$NON-NLS-1$ + + /** + * Create new info object + * + * @param node + * @param roots + * + * @return new info object + * + * @throws Exception + */ + protected Info createInfo(AstNode node, List roots) throws Exception { + return new Info(node, roots); + } + + /** + * @param type + * @param name + * @param node + * @param parent + * @param roots + * + * @return entity matching parameters + * + * @throws EntityNotFoundException + * @throws CoreException + */ + protected T find(Class type, String name, AstNode node, + RelationalEntity parent, List roots) throws EntityNotFoundException, CoreException { + for (EObject obj : parent == null ? roots : parent.eContents()) { + if (type.isInstance(obj)) { + T entity = (T)obj; + if (entity.getName().equalsIgnoreCase(name)) + return entity; + } else if (parent == null && obj instanceof Schema) { + try { + return find(type, name, node, (Schema)obj, roots); + } catch (EntityNotFoundException ignored) { + } + } + } + + while (node.getProperty(StandardDdlLexicon.DDL_EXPRESSION) == null) { + node = node.getParent(); + } + + String parentType = null; + if (parent == null) + parentType = DdlImporterI18n.MODEL; + else for (Class parentInterface : parent.getClass().getInterfaces()) { + if (RelationalEntity.class.isAssignableFrom(parentInterface)) + parentType = parentInterface.getSimpleName(); + } + + throw new EntityNotFoundException(I18n.format(DdlImporterI18n.ENTITY_NOT_FOUND_MSG, + type.getSimpleName(), + name, + parentType, + parent == null ? getImporterModel().getModelName() : parent.getName(), + node.getProperty(StandardDdlLexicon.DDL_START_LINE_NUMBER).toString(), + node.getProperty(StandardDdlLexicon.DDL_START_COLUMN_NUMBER).toString())); + } + + /** + * @param type + * @param node + * @param parent + * @param roots + * @return entity matching parameters + * + * @throws EntityNotFoundException + * @throws CoreException + */ + protected T find(Class type, AstNode node, RelationalEntity parent, + List roots) throws EntityNotFoundException, CoreException { + return find(type, node.getName(), node, parent, roots); + } + + /** + * + * @param entity + * @param node + * @param name + */ + protected void initialize(RelationalEntity entity, AstNode node, String name) { + entity.setName(name); + entity.setNameInSource(name); + + // descriptions must wait to be set until container and model type has been set + if (getImporterModel().optToSetModelEntityDescription()) { + Object prop = node.getProperty(StandardDdlLexicon.DDL_EXPRESSION); + if (prop != null) { + getImporterModel().addDescription(entity, prop.toString(), DescriptionOperation.PREPEND); + } + } + } + + + /** + * @param entity + * @param node + */ + protected void initialize(RelationalEntity entity, AstNode node) { + initialize(entity, node, node.getName()); + } + + /** + * Helper method for creating unique FK names + * @param currentFKs the List of ForeignKeys currently on the table + * @param newFKName the proposed name for the new FK + * @return the unique name - generated from the proposed name + */ + protected String getUniqueFKName(List currentFKs, String newFKName) { + // If current list is empty, no need to check names + if (currentFKs == null || currentFKs.isEmpty()) return newFKName; + + // Use name validator for unique name generation + StringNameValidator nameValidator = new StringNameValidator(); + + // Add the current FK names to the validator + for (ForeignKey fk : currentFKs) { + nameValidator.addExistingName(fk.getName()); + } + + // Make the proposed name unique + return nameValidator.createValidUniqueName(newFKName); + } + + /** + * @param currentFKs + * @param key + * @param node + */ + protected void initializeFK(List currentFKs, ForeignKey key, AstNode node) { + // Get Name from DDL node + String fkName = node.getName(); + // Make sure not to add duplicate FK names + String uniqueName = getUniqueFKName(currentFKs, fkName); + + initialize(key, node, uniqueName); + } + + /** + * @param table + * @param node + * @param roots + * + * @return initialised table + * + * @throws Exception + */ + protected T initializeTable(T table, AstNode node, List roots) throws Exception { + Info info = createInfo(node, roots); + if (info.getSchema() == null) + roots.add(table); + else + info.getSchema().getTables().add(table); + + initialize(table, node, info.getName()); + return table; + } + + /** + * Handle a statement OPTION key for Column for DDL + * + * @param column the Column + * @param columnOptionNode a statementOption node for a column + */ + protected void handleColumnOption(Column column, AstNode columnOptionNode) { + // Do nothing + } + + /** + * Handle the OPTION keys that may be set on Column for DDL + * + * @param column the Column + * @param columnNode the column AstNode + */ + protected void handleColumnOptions(Column column, AstNode columnNode) { + List children = columnNode.getChildren(); + for(AstNode child: children) { + if(is(child, StandardDdlLexicon.TYPE_STATEMENT_OPTION)) { + handleColumnOption(column,child); + } + } + } + + /** + * @param datatype + * + * @return {@link EObject} represented by the given data type id + * @throws Exception + */ + protected EObject getDataType(String datatype) throws Exception { + return RelationalTypeMappingImpl.getInstance().getDatatype(datatype); + } + + /** + * Create Column from the provided AstNode within ColumnSet + * @param node the provided AstNode + * @param table the ColumnSet in which to create the column + * @return the column + * + * @throws Exception + */ + protected Column createColumn(AstNode node, ColumnSet table) throws Exception { + Column col = getFactory().createColumn(); + table.getColumns().add(col); + initialize(col, node); + + String datatype = node.getProperty(StandardDdlLexicon.DATATYPE_NAME).toString(); + col.setNativeType(datatype); + + EObject type = getDataType(datatype); + col.setType(type); + + // Datatype length + Object prop = node.getProperty(StandardDdlLexicon.DATATYPE_LENGTH); + if (prop != null) { + col.setLength(Integer.parseInt(prop.toString())); + } else { + // Length is not provided for type 'string', use the default length specified in preferences... + String dtName = ModelerCore.getWorkspaceDatatypeManager().getName(type); + if(dtName != null && dtName.equalsIgnoreCase(STRING_TYPENAME)) { + col.setLength(ModelerCore.getTransformationPreferences().getDefaultStringLength()); + } + } + + prop = node.getProperty(StandardDdlLexicon.DATATYPE_PRECISION); + if (prop != null) + col.setPrecision(Integer.parseInt(prop.toString())); + + prop = node.getProperty(StandardDdlLexicon.DATATYPE_SCALE); + if (prop != null) + col.setScale(Integer.parseInt(prop.toString())); + + prop = node.getProperty(StandardDdlLexicon.NULLABLE); + if (prop != null) + col.setNullable(prop.toString().equals("NULL") ? NullableType.NULLABLE_LITERAL : NullableType.NO_NULLS_LITERAL); //$NON-NLS-1$ + + prop = node.getProperty(StandardDdlLexicon.DEFAULT_VALUE); + if (prop != null) + col.setDefaultValue(prop.toString()); + + return col; + } + + /** + * Create primary key + * + * @param node + * @param table + * @param roots + * + * @throws CoreException + */ + protected void createKey(AstNode node, BaseTable table, List roots) throws CoreException { + String type = node.getProperty(StandardDdlLexicon.CONSTRAINT_TYPE).toString(); + if (DdlConstants.PRIMARY_KEY.equals(type)) { + PrimaryKey key = getFactory().createPrimaryKey(); + table.setPrimaryKey(key); + initialize(key, node); + + for (AstNode node1 : node) { + if (is(node1, StandardDdlLexicon.TYPE_COLUMN_REFERENCE)) { + try { + Column column = find(Column.class, node1, table, roots); + + if (column.getNullable() == NullableType.NULLABLE_UNKNOWN_LITERAL + || column.getNullable() == NullableType.NULLABLE_LITERAL) { + column.setNullable(NullableType.NO_NULLS_LITERAL); + } + key.getColumns().add(column); + } catch (EntityNotFoundException error) { + addProgressMessage(error.getMessage()); + } + } + } + } else if (DdlConstants.FOREIGN_KEY.equals(type)) { + ForeignKey key = getFactory().createForeignKey(); + initializeFK(table.getForeignKeys(), key, node); + table.getForeignKeys().add(key); + BaseTable foreignTable = null; + Set foreignColumns = new HashSet(); + + for (AstNode node1 : node) { + try { + if (is(node1, StandardDdlLexicon.TYPE_COLUMN_REFERENCE)) + key.getColumns().add(find(Column.class, node1, table, roots)); + else if (is(node1, StandardDdlLexicon.TYPE_TABLE_REFERENCE)) + foreignTable = find(BaseTable.class, node1, null, roots); + else if (is(node1, StandardDdlLexicon.TYPE_FK_COLUMN_REFERENCE) && foreignTable != null) { + foreignColumns.add(find(Column.class, node1, foreignTable, roots)); + } + } catch (Exception error) { + addProgressMessage(error.getMessage()); + } + } + + if (foreignTable == null) + return; + + PrimaryKey primaryKey = foreignTable.getPrimaryKey(); + List primaryKeyColumns = primaryKey.getColumns(); + if (foreignColumns.isEmpty()) + key.setUniqueKey(primaryKey); + + if (primaryKeyColumns.containsAll(foreignColumns) && primaryKeyColumns.size() == foreignColumns.size()) + key.setUniqueKey(primaryKey); + else { + for (Object obj : foreignTable.getUniqueConstraints()) { + UniqueConstraint uniqueKey = (UniqueConstraint)obj; + List uniqueKeyColumns = uniqueKey.getColumns(); + if (uniqueKeyColumns.containsAll(foreignColumns) && uniqueKeyColumns.size() == foreignColumns.size()) { + key.setUniqueKey(uniqueKey); + break; + } + } + } + + } else if (DdlConstants.UNIQUE.equals(type)) { + UniqueConstraint key = getFactory().createUniqueConstraint(); + table.getUniqueConstraints().add(key); + initialize(key, node); + + for (AstNode node1 : node) { + if (! is(node1, StandardDdlLexicon.TYPE_COLUMN_REFERENCE)) + continue; + + try { + Column column = find(Column.class, node1, table, roots); + + if (column.getNullable() == NullableType.NULLABLE_UNKNOWN_LITERAL || column.getNullable() == NullableType.NULLABLE_LITERAL) { + column.setNullable(NullableType.NO_NULLS_LITERAL); + } + key.getColumns().add(column); + } catch (Exception error) { + addProgressMessage(error.getMessage()); + } + } + } + } + + /** + * Create a procedure + * + * @param procedureNode + * @param roots + * + * @return a procedure + * + * @throws Exception + */ + protected Procedure createProcedure( AstNode procedureNode, List roots) throws Exception { + Procedure procedure = getFactory().createProcedure(); + Info info = createInfo(procedureNode, roots); + if (info.getSchema() == null) + roots.add(procedure); + else + info.getSchema().getProcedures().add(procedure); + + initialize(procedure, procedureNode, info.getName()); + // TODO: determine how to handle Procedure StatementOption + // TODO: determine how to handle Procedure Statement + + if (procedureNode.getProperty(StandardDdlLexicon.DATATYPE_NAME) != null) { + ProcedureResult result = getFactory().createProcedureResult(); + procedure.setResult(result); + initialize(result, procedureNode); + } + + return procedure; + } + + /** + * Create a Model Entity, using the provided AstNode + * @param node the provided AstNode + * @param roots the current model roots + * @param schema the schema + * @throws Exception + */ + protected void create(AstNode node, List roots, Schema schema) throws Exception { + // ----------------------------------------------------------------------- + // Standard DDL + // ----------------------------------------------------------------------- + if (is(node, StandardDdlLexicon.TYPE_CREATE_TABLE_STATEMENT)) { + BaseTable table = initializeTable(getFactory().createBaseTable(), node, roots); + for (AstNode child : node) { + if (is(child, StandardDdlLexicon.TYPE_COLUMN_DEFINITION)) + createColumn(child, table); + else if (is(child, StandardDdlLexicon.TYPE_TABLE_CONSTRAINT)) + createKey(child, table, roots); + } + } else if (is(node, StandardDdlLexicon.TYPE_CREATE_VIEW_STATEMENT)) { + if (getImporterModel().getModelType() != ModelType.VIRTUAL_LITERAL + && getImporterModel().optToCreateModelEntitiesForUnsupportedDdl()) + + initializeTable(getFactory().createView(), node, roots); + + } else if (is(node, StandardDdlLexicon.TYPE_ALTER_TABLE_STATEMENT)) { + BaseTable table = find(BaseTable.class, node, schema, roots); + for (AstNode node1 : node) { + if (is(node1, StandardDdlLexicon.TYPE_ADD_TABLE_CONSTRAINT_DEFINITION)) + createKey(node1, table, roots); + else if (is(node1, StandardDdlLexicon.TYPE_ADD_COLUMN_DEFINITION)) + createColumn(node1, table); + } + } + } + + @Override + public void importNode(DdlImporterModel importerModel, AstNode rootNode) throws Exception { + // FIXME not sure I like this at the moment + setImporterModel(importerModel); + + List roots = importerModel.getEndingSelector().getRootObjects(); + + for (AstNode node : rootNode) { + if (is(node, StandardDdlLexicon.TYPE_CREATE_SCHEMA_STATEMENT)) { + Schema schema = importerModel.getFactory().createSchema(); + roots.add(schema); + initialize(schema, node); + for (AstNode node1 : node) { + create(node1, roots, schema); + } + } else create(node, roots, null); + } + } + + @Override + public void importFinalize() throws Exception { + // If user chose to use DDL as description, now set those descriptions (model type and container *must* be already set) + if (getImporterModel().optToSetModelEntityDescription()) { + for (EntityDescriptions pair : getImporterModel().getEntityDescriptions()) { + ModelerCore.getModelEditor().setDescription(pair.getEntity(), pair.getPreferredDescription()); + } + } + } +} diff --git a/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/TeiidDdlImporter.java b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/TeiidDdlImporter.java new file mode 100644 index 0000000000..cf9132c364 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.importer/src/org/teiid/designer/ddl/importer/node/TeiidDdlImporter.java @@ -0,0 +1,553 @@ +/* + * 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.Collections; +import java.util.List; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.emf.ecore.EObject; +import org.modeshape.sequencer.ddl.DdlConstants; +import org.modeshape.sequencer.ddl.StandardDdlLexicon; +import org.modeshape.sequencer.ddl.dialect.teiid.TeiidDdlConstants; +import org.modeshape.sequencer.ddl.dialect.teiid.TeiidDdlLexicon; +import org.modeshape.sequencer.ddl.node.AstNode; +import org.teiid.core.designer.util.CoreStringUtil; +import org.teiid.designer.core.ModelerCore; +import org.teiid.designer.ddl.DdlImporterModel.EntityDescriptions; +import org.teiid.designer.ddl.DdlImporterModel.EntityDescriptions.DescriptionOperation; +import org.teiid.designer.ddl.importer.DdlImporterI18n; +import org.teiid.designer.ddl.importer.TeiidDDLConstants; +import org.teiid.designer.metamodels.relational.AccessPattern; +import org.teiid.designer.metamodels.relational.BaseTable; +import org.teiid.designer.metamodels.relational.Column; +import org.teiid.designer.metamodels.relational.ColumnSet; +import org.teiid.designer.metamodels.relational.DirectionKind; +import org.teiid.designer.metamodels.relational.ForeignKey; +import org.teiid.designer.metamodels.relational.Index; +import org.teiid.designer.metamodels.relational.NullableType; +import org.teiid.designer.metamodels.relational.PrimaryKey; +import org.teiid.designer.metamodels.relational.Procedure; +import org.teiid.designer.metamodels.relational.ProcedureParameter; +import org.teiid.designer.metamodels.relational.ProcedureResult; +import org.teiid.designer.metamodels.relational.ProcedureUpdateCount; +import org.teiid.designer.metamodels.relational.RelationalEntity; +import org.teiid.designer.metamodels.relational.Schema; +import org.teiid.designer.metamodels.relational.SearchabilityType; +import org.teiid.designer.metamodels.relational.UniqueConstraint; + + +/** + * Teiid DDL node importer + */ +public class TeiidDdlImporter extends StandardImporter { + + private class TeiidInfo extends Info { + + /** + * @param node + * @param roots + * + * @throws Exception + */ + public TeiidInfo(AstNode node, List roots) throws Exception { + super(node, roots); + } + + @Override + protected void init(AstNode node, List roots) throws Exception { + String name = node.getName(); + int ndx = name.indexOf('.'); + if (ndx >= 0) { + this.schema = null; + this.name = name.substring(ndx + 1); + } else + super.init(node, roots); + } + } + + @Override + protected TeiidInfo createInfo(AstNode node, List roots) throws Exception { + return new TeiidInfo(node, roots); + } + + @Override + protected EObject getDataType(String datatype) throws Exception { + EObject resultType = null; + + /* + * Get the Datatype for Teiid DDL. + * First tries to match the datatype string with a teiid built-in type. + * If a built-in type is not found, then attempt to use the relational mapping to find a match. + */ + + // Look up matching Built-In type + EObject[] builtInTypes = ModelerCore.getWorkspaceDatatypeManager().getAllDatatypes(); + String dtName = null; + for (int i = 0; i < builtInTypes.length; i++) { + dtName = ModelerCore.getWorkspaceDatatypeManager().getName(builtInTypes[i]); + if (dtName != null && dtName.equalsIgnoreCase(datatype)) { + resultType = builtInTypes[i]; + break; + } + } + + // Built In type not found, try mapping from native to built-in + if(resultType == null) { + resultType = super.getDataType(datatype); + } + + return resultType; + } + + /** + * Creates constraints for Table for Teiid DDL + * @param constraintNode the AstNode for the constraint + * @param table the BaseTable object + * @param roots the current model roots + * + * @throws CoreException + */ + private void createConstraint(AstNode constraintNode, BaseTable table, List roots) throws CoreException { + + String type = constraintNode.getProperty(TeiidDdlLexicon.Constraint.TYPE).toString(); + boolean primaryKeyConstraint = false; + boolean uniqueConstraint = false; + boolean accessPatternConstraint = false; + boolean foreignKeyConstraint = false; + boolean indexConstraint = false; + RelationalEntity key = null; + + if (DdlConstants.PRIMARY_KEY.equals(type)) { + key = getFactory().createPrimaryKey(); + initialize(key, constraintNode); + table.setPrimaryKey((PrimaryKey)key); + primaryKeyConstraint = true; + } else if (DdlConstants.INDEX.equals(type)) { + // TODO need to process teiidddl:expression property + key = getFactory().createIndex(); + initialize(key, constraintNode); + roots.add(key); + indexConstraint = true; + } else if (DdlConstants.UNIQUE.equals(type)) { + key = getFactory().createUniqueConstraint(); + initialize(key, constraintNode); + table.getUniqueConstraints().add(key); + uniqueConstraint = true; + } else if (TeiidDdlConstants.TeiidNonReservedWord.ACCESSPATTERN.toDdl().equals(type)) { + key = getFactory().createAccessPattern(); + initialize(key, constraintNode); + table.getAccessPatterns().add(key); + accessPatternConstraint = true; + } else if (DdlConstants.FOREIGN_KEY.equals(type)) { + key = getFactory().createForeignKey(); + initializeFK(table.getForeignKeys(), (ForeignKey)key, constraintNode); + table.getForeignKeys().add(key); + foreignKeyConstraint = true; + } else { + assert false : "Unexpected constraint type of '" + type + "'"; //$NON-NLS-1$ //$NON-NLS-2$ + } + + // process referenced columns multi-valued property + Object temp = constraintNode.getProperty(TeiidDdlLexicon.Constraint.REFERENCES); + List references = (List)temp; + + for (AstNode ref : references) { + try { + if (primaryKeyConstraint) { + ((PrimaryKey)key).getColumns().add(find(Column.class, ref, table, roots)); + } else if (uniqueConstraint) { + ((UniqueConstraint)key).getColumns().add(find(Column.class, ref, table, roots)); + } else if (accessPatternConstraint) { + ((AccessPattern)key).getColumns().add(find(Column.class, ref, table, roots)); + } else if (foreignKeyConstraint) { + ((ForeignKey)key).getColumns().add(find(Column.class, ref, table, roots)); + } else if (indexConstraint) { + ((Index)key).getColumns().add(find(Column.class, ref, table, roots)); + }else { + assert false : "Unexpected constraint type of '" + type + "'"; //$NON-NLS-1$ //$NON-NLS-2$ + } + } catch (EntityNotFoundException error) { + addProgressMessage(error.getMessage()); + } + } + + // special processing for foreign key + if (foreignKeyConstraint) { + ForeignKey foreignKey = (ForeignKey)key; + + // must have a table reference + AstNode tableRefNode = (AstNode)constraintNode.getProperty(TeiidDdlLexicon.Constraint.TABLE_REFERENCE); + if(tableRefNode==null) { + addProgressMessage(DdlImporterI18n.FK_TABLE_REF_NOT_FOUND_MSG+" '"+foreignKey.getName()+"'"); //$NON-NLS-1$ //$NON-NLS-2$ + return; + } + + try { + BaseTable tableRef = find(BaseTable.class, tableRefNode, null, roots); + PrimaryKey tableRefPrimaryKey = tableRef.getPrimaryKey(); + List primaryKeyColumns = tableRef.getColumns(); + // check to see if foreign table columns are referenced + Object tempRefColumns = constraintNode.getProperty(TeiidDdlLexicon.Constraint.TABLE_REFERENCE_REFERENCES); + + List foreignTableColumnNodes = (tempRefColumns==null) ? Collections.emptyList() : (List)tempRefColumns; + int numPKColumns = primaryKeyColumns.size(); + int numFKColumns = foreignTableColumnNodes.size(); + + if( foreignTableColumnNodes.isEmpty() ) { + foreignKey.setUniqueKey(tableRefPrimaryKey); + } else if( numPKColumns == numFKColumns ) { + for(AstNode fTableColumn : foreignTableColumnNodes) { + find(Column.class, fTableColumn, tableRef, roots); + } + foreignKey.setUniqueKey(tableRefPrimaryKey); + } else { + foreignKey.setUniqueKey(tableRefPrimaryKey); + } + } catch (EntityNotFoundException error) { + addProgressMessage(error.getMessage()); + } + } + } + + /** + * Handles statementOption common to all relational entities for Teiid DDL + * @param entity the RelationalEntity + * @param optionNode the statementOption AstNode + * @return 'true' if the provided OPTION was a 'common' option, 'false' if not. + */ + private boolean handleCommonOption(RelationalEntity entity, AstNode optionNode) { + boolean wasCommonOption = false; + + String optionName = optionNode.getName(); + Object optionValue = optionNode.getProperty(StandardDdlLexicon.VALUE); + if(!CoreStringUtil.isEmpty(optionName)) { + String optionValueStr = (String)optionValue; + if(!CoreStringUtil.isEmpty(optionValueStr)) { + if(optionName.equalsIgnoreCase(TeiidDDLConstants.ANNOTATION)) { + getImporterModel().addDescription(entity, optionValueStr, DescriptionOperation.PREPEND); + wasCommonOption = true; + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.UUID)) { + // entity.setUUID(); + wasCommonOption = true; + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.NAMEINSOURCE)) { + entity.setNameInSource(optionValueStr); + wasCommonOption = true; + } + } + } + return wasCommonOption; + } + + /** + * Handle the OPTION keys that may be set on Tables for Teiid DDL + * @param table + * @param node + */ + private void handleTableOption(BaseTable table, AstNode node) { + boolean wasCommonOption = handleCommonOption(table,node); + if(wasCommonOption) return; + + // TODO: handle 'generic' statement options + String optionName = node.getName(); + Object optionValue = node.getProperty(StandardDdlLexicon.VALUE); + if(!CoreStringUtil.isEmpty(optionName)) { + String optionValueStr = (String)optionValue; + if(!CoreStringUtil.isEmpty(optionValueStr)) { + if(optionName.equalsIgnoreCase(TeiidDDLConstants.CARDINALITY)) { + table.setCardinality(Integer.parseInt(optionValueStr)); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.MATERIALIZED)) { + table.setMaterialized(isTrue(optionValueStr)); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.MATERIALIZED_TABLE)) { + //Table mattable = new Table(); + //mattable.setName(value); + //table.setMaterializedTable(mattable); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.UPDATABLE)) { + table.setSupportsUpdate(isTrue(optionValueStr)); + } + } + } + } + + /** + * Handle the OPTION keys that may be set on ProcedureParameters for Teiid DDL + * @param procParam the ProcedureParameter + * @param paramNode the procedure parameter AstNode + */ + private void handleProcParamOptions(ProcedureParameter procParam, AstNode paramNode) { + List children = paramNode.getChildren(); + for(AstNode child: children) { + if(is(child, StandardDdlLexicon.TYPE_STATEMENT_OPTION)) { + handleProcParamOption(procParam,child); + } + } + } + + /** + * Handle the OPTION keys that may be set on a ProcedureParameter for Teiid DDL + * @param procParam the ProcedureParameter + * @param procParamOptionNode a statementOption node for the procedure parameter + */ + private void handleProcParamOption(ProcedureParameter procParam, AstNode procParamOptionNode) { + boolean wasCommonOption = handleCommonOption(procParam,procParamOptionNode); + if(wasCommonOption) return; + } + + /** + * Get ProcedureUpdateCount object for the provided string value + * + * @param value the string value + * @return the ProcedureUpdateCount object corresponding to the provided string + */ + private ProcedureUpdateCount getUpdateCount(String value) { + if( ProcedureUpdateCount.AUTO_LITERAL.getName().equalsIgnoreCase(value) ) { + return ProcedureUpdateCount.AUTO_LITERAL; + } + if( ProcedureUpdateCount.ONE_LITERAL.getName().equalsIgnoreCase(value) ) { + return ProcedureUpdateCount.ONE_LITERAL; + } + if( ProcedureUpdateCount.MULTIPLE_LITERAL.getName().equalsIgnoreCase(value) ) { + return ProcedureUpdateCount.MULTIPLE_LITERAL; + } + if( ProcedureUpdateCount.ZERO_LITERAL.getName().equalsIgnoreCase(value) ) { + return ProcedureUpdateCount.ZERO_LITERAL; + } + + return ProcedureUpdateCount.AUTO_LITERAL; + } + + /** + * Handle a statementOption for a Procedure for Teiid DDL + * @param proc the Procedure + * @param procOptionNode a statementOption for a procedure + */ + private void handleProcedureOption(Procedure proc, AstNode procOptionNode) { + boolean wasCommonOption = handleCommonOption(proc,procOptionNode); + if(wasCommonOption) return; + + String optionName = procOptionNode.getName(); + Object optionValue = procOptionNode.getProperty(StandardDdlLexicon.VALUE); + if(!CoreStringUtil.isEmpty(optionName)) { + String optionValueStr = (String)optionValue; + if(!CoreStringUtil.isEmpty(optionValueStr)) { + if(optionName.equalsIgnoreCase(TeiidDDLConstants.UPDATECOUNT)) { + proc.setUpdateCount(getUpdateCount(optionValueStr)); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.CATEGORY)) { + proc.setFunction(true); + } + } + } + } + + @Override + protected void handleColumnOption(Column column, AstNode columnOptionNode) { + boolean wasCommonOption = handleCommonOption(column,columnOptionNode); + if(wasCommonOption) + return; + + String optionName = columnOptionNode.getName(); + Object optionValue = columnOptionNode.getProperty(StandardDdlLexicon.VALUE); + + if(CoreStringUtil.isEmpty(optionName)) + return; + + String optionValueStr = (String)optionValue; + if(CoreStringUtil.isEmpty(optionValueStr)) + return; + + if(optionName.equalsIgnoreCase(TeiidDDLConstants.SELECTABLE)) { + column.setSelectable(isTrue(optionValueStr)); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.UPDATABLE)) { + column.setUpdateable(isTrue(optionValueStr)); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.CURRENCY)) { + column.setCurrency(isTrue(optionValueStr)); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.CASE_SENSITIVE)) { + column.setCaseSensitive(isTrue(optionValueStr)); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.SIGNED)) { + column.setSigned(isTrue(optionValueStr)); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.FIXED_LENGTH)) { + column.setFixedLength(isTrue(optionValueStr)); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.SEARCHABLE)) { + column.setSearchability(SearchabilityType.get(optionValueStr.toUpperCase())); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.MIN_VALUE)) { + column.setMinimumValue(optionValueStr); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.MAX_VALUE)) { + column.setMaximumValue(optionValueStr); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.NATIVE_TYPE)) { + column.setNativeType(optionValueStr); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.NULL_VALUE_COUNT)) { + column.setNullValueCount(Integer.parseInt(optionValueStr)); + } else if(optionName.equalsIgnoreCase(TeiidDDLConstants.DISTINCT_VALUES)) { + //column.setDistinctValueCount(value); + } + } + + @Override + protected void handleColumnOptions(Column column, AstNode columnNode) { + List children = columnNode.getChildren(); + for(AstNode child: children) { + if(is(child, StandardDdlLexicon.TYPE_STATEMENT_OPTION)) { + handleColumnOption(column,child); + } + } + } + + @Override + protected Column createColumn(AstNode node, ColumnSet table) throws Exception { + Column column = super.createColumn(node, table); + + // Handle Teiid-specific properties and options + Object prop = node.getProperty(TeiidDdlLexicon.CreateTable.AUTO_INCREMENT); + if(prop != null) + column.setAutoIncremented(isTrue(prop.toString())); + + handleColumnOptions(column,node); + return column; + } + + @Override + protected Procedure createProcedure(AstNode procedureNode, List roots) throws Exception { + Procedure procedure = super.createProcedure(procedureNode, roots); + + for (AstNode child : procedureNode) { + if (is(child, TeiidDdlLexicon.CreateProcedure.PARAMETER)) { + ProcedureParameter prm = getFactory().createProcedureParameter(); + procedure.getParameters().add(prm); + initialize(prm, child); + String datatype = child.getProperty(StandardDdlLexicon.DATATYPE_NAME).toString(); + prm.setNativeType(datatype); + + EObject type = getDataType(datatype); + prm.setType(type); + + 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().equals("NULL") ? NullableType.NULLABLE_LITERAL : NullableType.NO_NULLS_LITERAL); //$NON-NLS-1$ + + prop = child.getProperty(StandardDdlLexicon.DEFAULT_VALUE); + if (prop != null) + prm.setDefaultValue(prop.toString()); + + prop = child.getProperty(TeiidDdlLexicon.CreateProcedure.PARAMETER_TYPE); + // TODO - Determine how to handle 'VARIADIC' + if(prop != null) { + String direction = prop.toString(); + if (DirectionKind.IN_LITERAL.getName().equals(direction)) + prm.setDirection(DirectionKind.IN_LITERAL); + else if (DirectionKind.OUT_LITERAL.getName().equals(direction) ) + prm.setDirection(DirectionKind.OUT_LITERAL); + else if (DirectionKind.INOUT_LITERAL.getName().equals(direction)) + prm.setDirection(DirectionKind.INOUT_LITERAL); + } + + handleProcParamOptions(prm,child); + + // TODO: Determine how to handle teiidddl:result, ddl:defaultOption, ddl:statementOption + } else if(is(child, TeiidDdlLexicon.CreateProcedure.RESULT_COLUMNS)) { + // TODO: determine how to handle Table flag property + ProcedureResult result = getFactory().createProcedureResult(); + procedure.setResult(result); + initialize(result, procedureNode); + + for(AstNode resultCol: child) { + if(resultCol.hasMixin(TeiidDdlLexicon.CreateProcedure.RESULT_COLUMN)) { + createColumn(resultCol,result); + } + } + } else if(is(child, TeiidDdlLexicon.CreateProcedure.RESULT_DATA_TYPE)) { + ProcedureResult result = getFactory().createProcedureResult(); + procedure.setResult(result); + initialize(result, procedureNode); + createColumn(child,result); + } else if(is(child, StandardDdlLexicon.TYPE_STATEMENT_OPTION)) { + handleProcedureOption(procedure,child); + } + } + + return procedure; + } + + @Override + protected void create(AstNode node, List roots, Schema schema) throws Exception { + + // ----------------------------------------------------------------------- + // Handle Creation of Teiid Entities + // ----------------------------------------------------------------------- + if (is(node, TeiidDdlLexicon.CreateTable.TABLE_STATEMENT) + || is(node, TeiidDdlLexicon.CreateTable.VIEW_STATEMENT)) { + + BaseTable table = initializeTable(getFactory().createBaseTable(), node, roots); + + for (AstNode child : node) { + // Table Elements + if (is(child, TeiidDdlLexicon.CreateTable.TABLE_ELEMENT)) { + createColumn(child, table); + // Contraints + } else if (is(child, TeiidDdlLexicon.Constraint.TABLE_ELEMENT) + || is(child, TeiidDdlLexicon.Constraint.FOREIGN_KEY_CONSTRAINT) + || is(child, TeiidDdlLexicon.Constraint.INDEX_CONSTRAINT)) { + + createConstraint(child, table, roots); + // Statement Options + } else if (is(child, StandardDdlLexicon.TYPE_STATEMENT_OPTION)) { + handleTableOption(table, child); + } + } + } else if (is(node, TeiidDdlLexicon.CreateProcedure.PROCEDURE_STATEMENT) + || is(node, TeiidDdlLexicon.CreateProcedure.FUNCTION_STATEMENT)) { + createProcedure(node, roots); + + // Handle Alter Table + } else if (is(node, TeiidDdlLexicon.AlterOptions.TABLE_STATEMENT)) { + BaseTable table = find(BaseTable.class, node, null, roots); + if (table != null) { + for (AstNode child : node) { + if (is(child, TeiidDdlLexicon.AlterOptions.OPTIONS_LIST)) { + List nodeList = child.getChildren(); + for (AstNode listItem : nodeList) { + if (listItem.hasMixin(StandardDdlLexicon.TYPE_STATEMENT_OPTION)) { + handleTableOption(table, listItem); + } + } + } + } + } + // Handle Alter View and Procedure + // TODO: could potentially be combined with alter table block above + } else if (is(node, TeiidDdlLexicon.AlterOptions.VIEW_STATEMENT) + || is(node, TeiidDdlLexicon.AlterOptions.PROCEDURE_STATEMENT)) { + } else { + // ----------------------------------------------------------------------- + // All other Non-Teiid DDL + // ----------------------------------------------------------------------- + super.create(node, roots, schema); + } + } + + @Override + public void importFinalize() throws Exception { + /* + * The descriptions are added from to the model's descriptions + * from the teiid annotations. + */ + for (EntityDescriptions pair : getImporterModel().getEntityDescriptions()) { + ModelerCore.getModelEditor().setDescription(pair.getEntity(), pair.getPreferredDescription()); + } + } +} diff --git a/plugins/org.teiid.designer.ddl.spi/.classpath b/plugins/org.teiid.designer.ddl.spi/.classpath new file mode 100644 index 0000000000..ad32c83a78 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.spi/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/plugins/org.teiid.designer.ddl.spi/.project b/plugins/org.teiid.designer.ddl.spi/.project new file mode 100644 index 0000000000..0b743b5c94 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.spi/.project @@ -0,0 +1,28 @@ + + + org.teiid.designer.ddl.spi + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/plugins/org.teiid.designer.ddl.spi/META-INF/MANIFEST.MF b/plugins/org.teiid.designer.ddl.spi/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..b08d175be1 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.spi/META-INF/MANIFEST.MF @@ -0,0 +1,20 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %pluginName +Bundle-SymbolicName: org.teiid.designer.ddl.spi;singleton:=true +Bundle-Version: 8.2.0.qualifier +Bundle-Vendor: %pluginProvider +Bundle-RequiredExecutionEnvironment: JavaSE-1.6 +Bundle-Localization: plugin +Export-Package: org.teiid.designer.ddl, + org.teiid.designer.ddl.registry +Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.9.0,4.0.0)", + org.eclipse.emf.ecore;bundle-version="2.9.0", + org.eclipse.emf.common;bundle-version="2.9.0", + org.teiid.core.designer, + org.teiid.designer.compare, + org.teiid.designer.core;bundle-version="[8.2.0,9.0.0)", + org.teiid.designer.metamodels.core, + org.teiid.designer.metamodels.relational, + org.teiid.designer.modeshape;bundle-version="[8.2.0,9.0.0)", + org.teiid.designer.spi;bundle-version="[8.2.0,9.0.0)";visibility:=reexport diff --git a/plugins/org.teiid.designer.ddl.spi/build.properties b/plugins/org.teiid.designer.ddl.spi/build.properties new file mode 100644 index 0000000000..d67426f33e --- /dev/null +++ b/plugins/org.teiid.designer.ddl.spi/build.properties @@ -0,0 +1,7 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + schema/,\ + plugin.properties diff --git a/plugins/org.teiid.designer.ddl.spi/plugin.properties b/plugins/org.teiid.designer.ddl.spi/plugin.properties new file mode 100644 index 0000000000..1b2a6a93a5 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.spi/plugin.properties @@ -0,0 +1,9 @@ +# 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. +pluginProvider = JBoss by Red Hat +pluginName = Teiid Designer DDL Service SPI + +ddl-node-importer-extension-point.name = DDL Node Importer \ No newline at end of file diff --git a/plugins/org.teiid.designer.ddl.spi/plugin.xml b/plugins/org.teiid.designer.ddl.spi/plugin.xml new file mode 100644 index 0000000000..ff0952e5a3 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.spi/plugin.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/plugins/org.teiid.designer.ddl.spi/pom.xml b/plugins/org.teiid.designer.ddl.spi/pom.xml new file mode 100644 index 0000000000..b790826e89 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.spi/pom.xml @@ -0,0 +1,28 @@ + + 4.0.0 + + org.jboss.tools.teiid + plugins + 0.0.4-SNAPSHOT + + org.jboss.tools + org.teiid.designer.ddl.spi + 8.2.0-SNAPSHOT + eclipse-plugin + + + + org.eclipse.tycho + tycho-compiler-plugin + ${tychoVersion} + + + 1.6 + 1.6 + + + + + diff --git a/plugins/org.teiid.designer.ddl.spi/schema/ddlNodeImporter.exsd b/plugins/org.teiid.designer.ddl.spi/schema/ddlNodeImporter.exsd new file mode 100644 index 0000000000..1fca7ca2b7 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.spi/schema/ddlNodeImporter.exsd @@ -0,0 +1,123 @@ + + + + + + + + + [Enter description of this extension point.] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Implementation of a ddl node importer + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + [Enter the first release in which this extension point appears.] + + + + + + + + + [Enter extension point usage example here.] + + + + + + + + + [Enter API information here.] + + + + + + + + + [Enter information about supplied implementation of this extension point.] + + + + + diff --git a/plugins/org.teiid.designer.ddl.spi/src/org/teiid/designer/ddl/DdlImporterModel.java b/plugins/org.teiid.designer.ddl.spi/src/org/teiid/designer/ddl/DdlImporterModel.java new file mode 100644 index 0000000000..6faf4ba117 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.spi/src/org/teiid/designer/ddl/DdlImporterModel.java @@ -0,0 +1,361 @@ +/* + * 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; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.emf.common.util.URI; +import org.teiid.core.designer.util.CoreArgCheck; +import org.teiid.designer.compare.DifferenceProcessor; +import org.teiid.designer.compare.ModelerComparePlugin; +import org.teiid.designer.compare.processor.DifferenceProcessorImpl; +import org.teiid.designer.compare.selector.ModelResourceSelector; +import org.teiid.designer.compare.selector.ModelSelector; +import org.teiid.designer.compare.selector.TransientModelSelector; +import org.teiid.designer.core.workspace.ModelResource; +import org.teiid.designer.ddl.DdlImporterModel.EntityDescriptions.DescriptionOperation; +import org.teiid.designer.metamodels.core.ModelAnnotation; +import org.teiid.designer.metamodels.core.ModelType; +import org.teiid.designer.metamodels.relational.RelationalEntity; +import org.teiid.designer.metamodels.relational.RelationalFactory; + +/** + * + */ +public class DdlImporterModel { + + /** + * A 1-1 mapping of an entity with a proposed description. + * Preferable to return a collection of these pair classes than + * expose a {@link Map}. + */ + public static class EntityDescriptions { + + /** + * Enum of operations used to add descriptions + */ + public static enum DescriptionOperation { + /** + * Insert at the beginning + */ + PREPEND, + + /** + * Insert at the end + */ + APPEND; + } + + private RelationalEntity entity; + + private List descriptions = new ArrayList(); + + /** + * @param entity + * @param description + */ + public EntityDescriptions(RelationalEntity entity, String description) { + CoreArgCheck.isNotNull(entity); + CoreArgCheck.isNotNull(description); + + this.entity = entity; + this.descriptions.add(description); + } + + /** + * @return the entity + */ + public RelationalEntity getEntity() { + return this.entity; + } + + /** + * @return the first description in the list, + * which is considered to have the highest priority + */ + public String getPreferredDescription() { + return this.descriptions.get(0); + } + + /** + * @return the complete description, + * which is the concatenation of all descriptions + */ + public String getCompleteDescription() { + StringBuilder builder = new StringBuilder(); + for (String description : descriptions) { + builder.append(description); + builder.append("\n"); //$NON-NLS-1$ + } + + return builder.toString(); + } + /** + * Add a description to the list of descriptions. + * + * Descriptions are in priority order with the preferred description + * being first in the list. Therefore, the first description is + * considered to be the preferred description. + *

+ * Use the given {@link DescriptionOperation} to determine whether + * to prepend or append the given description. + * + * @param description + * @param operation + */ + public void addDescription(String description, DescriptionOperation operation) { + if (DescriptionOperation.PREPEND.equals(operation)) + descriptions.add(0, description); + else + descriptions.add(description); + } + + @Override + public int hashCode() { + return entity.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null) return false; + if (getClass() != obj.getClass()) return false; + EntityDescriptions other = (EntityDescriptions)obj; + if (this.entity == null) { + if (other.entity != null) return false; + } else if (!this.entity.equals(other.entity)) return false; + return true; + } + } + + private final RelationalFactory factory = RelationalFactory.eINSTANCE; + + private ModelType modelType; + + private String modelName; + + private ModelResource model; + + private ModelResourceSelector startingSelector; + + private TransientModelSelector endingSelector; + + private DifferenceProcessor differenceProcessor; + + private IProgressMonitor monitor; + + private List messages; + + private boolean optToCreateModelEntitiesForUnsupportedDdl; + + private boolean optToSetModelEntityDescription; + + private Collection descriptionPairs = new ArrayList(); + + private DdlNodeImporter nodeImporter; + + /** + * @param model + */ + public void setRelationalModel(ModelResource model) { + this.model = model; + } + + /** + * @param modelType the modelType to set + */ + public void setModelType(ModelType modelType) { + this.modelType = modelType; + } + + /** + * @return the modelType + */ + public ModelType getModelType() { + return this.modelType; + } + + /** + * @param modelName the modelName to set + */ + public void setModelName(String modelName) { + this.modelName = modelName; + } + + /** + * @return the modelName + */ + public String getModelName() { + return this.modelName; + } + + /** + * @param monitor + */ + public void setProgressMonitor(IProgressMonitor monitor) { + this.monitor = monitor; + } + + /** + * Get the progress monitor + * + * @return {@link IProgressMonitor} + */ + public IProgressMonitor getProgressMonitor() { + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + + return monitor; + } + + /** + * @param messages + */ + public void setProgressMessages(List messages) { + this.messages = messages; + } + + /** + * Get the progress monitor + * + * @return {@link IProgressMonitor} + */ + public List getProgressMessages() { + if (messages == null) { + messages = new ArrayList(); + } + + return messages; + } + + /** + * Get the starting selector + * + * @return {@link ModelSelector} + */ + public ModelSelector getStartingSelector() { + CoreArgCheck.isNotNull(model); + + if (startingSelector == null) + startingSelector = new ModelResourceSelector(model); + + return startingSelector; + } + + /** + * Get the ending selector + * + * @return {@link ModelSelector} + * + * @throws Exception + */ + public ModelSelector getEndingSelector() throws Exception { + CoreArgCheck.isNotNull(model); + + if (endingSelector == null) { + final URI mdlUri = URI.createFileURI(model.getPath().toFile().getAbsolutePath()); + final ModelAnnotation mdlAnnotation = model.getModelAnnotation(); + endingSelector = new TransientModelSelector(mdlUri, mdlAnnotation); + } + + return endingSelector; + } + + /** + * Get the DifferenceProcessor + * + * @return the difference processor + * @throws Exception + */ + public DifferenceProcessor getDifferenceProcessor() throws Exception { + if (differenceProcessor == null) { + differenceProcessor = new DifferenceProcessorImpl(getStartingSelector(), getEndingSelector()); + differenceProcessor.addEObjectMatcherFactories(ModelerComparePlugin.createEObjectMatcherFactories()); + } + + return differenceProcessor; + } + + /** + * @return the factory + */ + public RelationalFactory getFactory() { + return factory; + } + + /** + * @return the optToCreateModelEntitiesForUnsupportedDdl + */ + public boolean optToCreateModelEntitiesForUnsupportedDdl() { + return optToCreateModelEntitiesForUnsupportedDdl; + } + + /** + * @param optToCreateModelEntitiesForUnsupportedDdl + */ + public void setOptToCreateModelEntitiesForUnsupportedDdl(boolean optToCreateModelEntitiesForUnsupportedDdl) { + this.optToCreateModelEntitiesForUnsupportedDdl = optToCreateModelEntitiesForUnsupportedDdl; + } + + /** + * @return the optToSetModelEntityDescription + */ + public boolean optToSetModelEntityDescription() { + return optToSetModelEntityDescription; + } + + /** + * @param optToSetModelEntityDescription + */ + public void setOptToSetModelEntityDescription(boolean optToSetModelEntityDescription) { + this.optToSetModelEntityDescription = optToSetModelEntityDescription; + } + + /** + * @param entity + * @param description + * @param operation + */ + public void addDescription(RelationalEntity entity, String description, DescriptionOperation operation) { + for (EntityDescriptions pair : descriptionPairs) { + if (pair.getEntity().equals(entity)) { + pair.addDescription(description, operation); + return; + } + } + + // Completely new entity description + descriptionPairs.add(new EntityDescriptions(entity, description)); + } + + /** + * @return the descriptionPairs + */ + public Collection getEntityDescriptions() { + return this.descriptionPairs; + } + + /** + * @param nodeImporter + */ + public void setNodeImporter(DdlNodeImporter nodeImporter) { + this.nodeImporter = nodeImporter; + } + + /** + * @return the nodeImporter + */ + public DdlNodeImporter getNodeImporter() { + return this.nodeImporter; + } +} diff --git a/plugins/org.teiid.designer.ddl.spi/src/org/teiid/designer/ddl/DdlNodeImporter.java b/plugins/org.teiid.designer.ddl.spi/src/org/teiid/designer/ddl/DdlNodeImporter.java new file mode 100644 index 0000000000..e7212080b1 --- /dev/null +++ b/plugins/org.teiid.designer.ddl.spi/src/org/teiid/designer/ddl/DdlNodeImporter.java @@ -0,0 +1,34 @@ +/* + * 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; + +import org.modeshape.sequencer.ddl.node.AstNode; + + +/** + * + */ +public interface DdlNodeImporter { + + /** + * Import the contents of the given {@link AstNode} + * + * @param importerModel + * @param rootNode + * @throws Exception + */ + void importNode(DdlImporterModel importerModel, AstNode rootNode) throws Exception; + + /** + * Perform any final processes upon completion of the import + * + * @throws Exception + */ + void importFinalize() throws Exception; + +} diff --git a/plugins/org.teiid.designer.ddl.spi/src/org/teiid/designer/ddl/registry/DdlNodeImporterRegistry.java b/plugins/org.teiid.designer.ddl.spi/src/org/teiid/designer/ddl/registry/DdlNodeImporterRegistry.java new file mode 100644 index 0000000000..e0311b511c --- /dev/null +++ b/plugins/org.teiid.designer.ddl.spi/src/org/teiid/designer/ddl/registry/DdlNodeImporterRegistry.java @@ -0,0 +1,51 @@ +/* + * 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.registry; + +import org.eclipse.core.runtime.IConfigurationElement; +import org.teiid.designer.ddl.DdlNodeImporter; +import org.teiid.designer.registry.AbstractExtensionRegistry; + +/** + * Registry for ddl node importer implementations + */ +public class DdlNodeImporterRegistry extends AbstractExtensionRegistry { + + private static final String EXT_POINT_ID = "org.teiid.designer.ddl.nodeImporter"; //$NON-NLS-1$ + + private static final String IMPORTER_ID = "importer"; //$NON-NLS-1$ + + private static final String DIALECT_ID = "dialect"; //$NON-NLS-1$ + + private static DdlNodeImporterRegistry registry; + + /** + * Get the singleton instance of this registry + * + * @return singleton {@link DdlNodeImporterRegistry} + * + * @throws Exception + */ + public static DdlNodeImporterRegistry getInstance() throws Exception { + if (registry == null) { + registry = new DdlNodeImporterRegistry(); + } + + return registry; + } + + private DdlNodeImporterRegistry() throws Exception { + super(EXT_POINT_ID, IMPORTER_ID); + } + + @Override + protected void register(IConfigurationElement configurationElement, DdlNodeImporter ddlImporter) { + String dialect = configurationElement.getAttribute(DIALECT_ID); + register(dialect.toUpperCase(), ddlImporter); + } +} diff --git a/plugins/pom.xml b/plugins/pom.xml index 6785c3fc9f..30e36bd73a 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -28,6 +28,7 @@ org.teiid.designer.datatools.ui org.teiid.designer.ddl org.teiid.designer.ddl.importer.ui + org.teiid.designer.ddl.spi org.teiid.designer.ddl.importer org.teiid.designer.diagram.ui org.teiid.designer.dqp