/*
* 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.lang.ref.WeakReference;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.jdom.Attribute;
import org.jdom.Document;
import org.jdom.Element;
import org.teiid.core.designer.ModelerCoreException;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.core.designer.util.ModelType.Type;
import org.teiid.designer.core.ModelEditor;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.metamodel.MetamodelDescriptor;
import org.teiid.designer.core.types.DatatypeManager;
import org.teiid.designer.core.util.ConcurrentModelVisitorProcessor;
import org.teiid.designer.core.util.ModelVisitor;
import org.teiid.designer.core.util.ModelVisitorProcessor;
import org.teiid.designer.metamodels.core.Annotation;
import org.teiid.designer.metamodels.core.ModelAnnotation;
import org.teiid.designer.metamodels.core.ModelType;
import org.teiid.designer.metamodels.relational.BaseTable;
import org.teiid.designer.metamodels.relational.Catalog;
import org.teiid.designer.metamodels.relational.Column;
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.RelationalEntity;
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.UniqueKey;
/**
* IntermediateFormat
*
* @since 8.0
*/
public class IntermediateFormat {
public static final String FALSE_VALUE = DdlPlugin.Util.getString("IntermediateFormat.falseValue"); //$NON-NLS-1$
public static final String TRUE_VALUE = DdlPlugin.Util.getString("IntermediateFormat.trueValue"); //$NON-NLS-1$
public static final String DATE_FORMAT = DdlPlugin.Util.getString("IntermediateFormat.DateFormat"); //$NON-NLS-1$
public static final String TIME_FORMAT = DdlPlugin.Util.getString("IntermediateFormat.TimeFormat"); //$NON-NLS-1$
private static final DateFormat DATE_FORMATTER;
private static final DateFormat TIME_FORMATTER;
static {
TIME_FORMATTER = new SimpleDateFormat(TIME_FORMAT);
TIME_FORMATTER.setLenient(false);
DATE_FORMATTER = new SimpleDateFormat(DATE_FORMAT);
DATE_FORMATTER.setLenient(false);
}
public static class Xml {
public static class Comment {
public static final String TAG = "comment"; //$NON-NLS-1$
}
public static class DDL {
public static final String TAG = "ddl"; //$NON-NLS-1$
}
public static class Model {
public static final String TAG = "model"; //$NON-NLS-1$
public static class Attributes {
public static final String NAME = "name"; //$NON-NLS-1$
public static final String UUID = "uuid"; //$NON-NLS-1$
public static final String GENERATE_INFO_COMMENTS = "generateInfoComments"; //$NON-NLS-1$
public static final String GENERATE_TABLE_COMMENTS = "generateTableComments"; //$NON-NLS-1$
public static final String GENERATE_COLUMN_COMMENTS = "generateColumnComments"; //$NON-NLS-1$
public static final String GENERATE_DROPS = "generateDrops"; //$NON-NLS-1$
public static final String EXPORT_TOOL = "exportTool"; //$NON-NLS-1$
public static final String EXPORT_VERSION = "exportToolVersion"; //$NON-NLS-1$
public static final String EXPORT_DATE = "exportDate"; //$NON-NLS-1$
public static final String EXPORT_TIME = "exportTime"; //$NON-NLS-1$
public static final String MODEL_FILENAME = "modelFilename"; //$NON-NLS-1$
public static final String MODEL_TYPE = "modelType"; //$NON-NLS-1$
public static final String METAMODEL = "metaModel"; //$NON-NLS-1$
public static final String METAMODEL_URL = "metaModelURL"; //$NON-NLS-1$
}
}
public static class Schema {
public static final String TAG = "schema"; //$NON-NLS-1$
public static class Attributes {
public static final String NAME = "name"; //$NON-NLS-1$
public static final String UUID = "uuid"; //$NON-NLS-1$
public static final String PATH_IN_MODEL = "pathInModel"; //$NON-NLS-1$
}
}
public static class Table {
public static final String TAG = "table"; //$NON-NLS-1$
public static class Attributes {
public static final String NAME = "name"; //$NON-NLS-1$
public static final String UUID = "uuid"; //$NON-NLS-1$
public static final String DESCRIPTION = "description"; //$NON-NLS-1$
public static final String PATH_IN_MODEL = "pathInModel"; //$NON-NLS-1$
}
}
public static class Column {
public static final String TAG = "column"; //$NON-NLS-1$
public static class Attributes {
public static final String NAME = "name"; //$NON-NLS-1$
public static final String ALIAS = "alias"; //$NON-NLS-1$
public static final String UUID = "uuid"; //$NON-NLS-1$
public static final String DESCRIPTION = "description"; //$NON-NLS-1$
public static final String PATH_IN_MODEL = "pathInModel"; //$NON-NLS-1$
public static final String TYPE = "type"; //$NON-NLS-1$
public static final String DEFAULT_VALUE = "initialValue"; //$NON-NLS-1$
public static final String LENGTH = "length"; //$NON-NLS-1$
public static final String PRECISION = "precision"; //$NON-NLS-1$
public static final String SCALE = "scale"; //$NON-NLS-1$
public static final String IS_FIXED_LENGTH = "isLengthFixed"; //$NON-NLS-1$
public static final String IS_NULLABLE = "isNullable"; //$NON-NLS-1$
public static final String SUPPORTS_SELECT = "supportsSelect"; //$NON-NLS-1$
public static final String SUPPORTS_UPDATE = "supportsUpdate"; //$NON-NLS-1$
public static final String IS_CASE_SENSITIVE = "isCaseSensitive"; //$NON-NLS-1$
public static final String IS_SIGNED = "isSigned"; //$NON-NLS-1$
public static final String IS_CURRENCY = "isCurrency"; //$NON-NLS-1$
public static final String IS_AUTOINCREMENTED = "isAutoIncremented"; //$NON-NLS-1$
public static final String SEARCH_TYPE = "searchType"; //$NON-NLS-1$
}
}
public static class PrimaryKey {
public static final String TAG = "primaryKey"; //$NON-NLS-1$
public static class Attributes {
public static final String NAME = "name"; //$NON-NLS-1$
public static final String UUID = "uuid"; //$NON-NLS-1$
public static final String TABLE_NAME = "tableName"; //$NON-NLS-1$
public static final String PATH_IN_MODEL = "pathInModel"; //$NON-NLS-1$
}
}
public static class PrimaryKeyColumn {
public static final String TAG = "column"; //$NON-NLS-1$
public static class Attributes {
public static final String NAME = "name"; //$NON-NLS-1$
public static final String UUID = "uuid"; //$NON-NLS-1$
}
}
public static class UniqueKey {
public static final String TAG = "uniqueKey"; //$NON-NLS-1$
public static class Attributes {
public static final String NAME = "name"; //$NON-NLS-1$
public static final String UUID = "uuid"; //$NON-NLS-1$
public static final String TABLE_NAME = "tableName"; //$NON-NLS-1$
public static final String PATH_IN_MODEL = "pathInModel"; //$NON-NLS-1$
}
}
public static class UniqueKeyColumn {
public static final String TAG = "column"; //$NON-NLS-1$
public static class Attributes {
public static final String NAME = "name"; //$NON-NLS-1$
public static final String UUID = "uuid"; //$NON-NLS-1$
}
}
public static class ForeignKey {
public static final String TAG = "foreignKey"; //$NON-NLS-1$
public static class Attributes {
public static final String NAME = "name"; //$NON-NLS-1$
public static final String UUID = "uuid"; //$NON-NLS-1$
public static final String TABLE_NAME = "tableName"; //$NON-NLS-1$
public static final String PK_TABLE_NAME = "pkTableName"; //$NON-NLS-1$
public static final String PATH_IN_MODEL = "pathInModel"; //$NON-NLS-1$
}
}
public static class ForignKeyColumn {
public static final String TAG = "column"; //$NON-NLS-1$
public static class Attributes {
public static final String NAME = "name"; //$NON-NLS-1$
public static final String UUID = "uuid"; //$NON-NLS-1$
public static final String PK_COLUMN_NAME = "pkColumnName"; //$NON-NLS-1$
}
}
public static class Index {
public static final String TAG = "index"; //$NON-NLS-1$
public static class Attributes {
public static final String NAME = "name"; //$NON-NLS-1$
public static final String UUID = "uuid"; //$NON-NLS-1$
public static final String TABLE_NAME = "tableName"; //$NON-NLS-1$
public static final String PATH_IN_MODEL = "pathInModel"; //$NON-NLS-1$
}
}
public static class IndexColumn {
public static final String TAG = "column"; //$NON-NLS-1$
public static class Attributes {
public static final String NAME = "name"; //$NON-NLS-1$
public static final String UUID = "uuid"; //$NON-NLS-1$
}
}
public static class IndexColumns {
public static final String TAG = "indexColumn"; //$NON-NLS-1$
}
}
public class RelationalEntityUniquenessEnforcer implements ModelVisitor {
private final Set primaryKeys;
private final Set foreignKeys;
private final Set uniqueKeys;
private final Set indexes;
/**
* Construct an instance of RelationalObjectFinder.
*/
public RelationalEntityUniquenessEnforcer() {
super();
this.primaryKeys = new HashSet();
this.foreignKeys = new HashSet();
this.uniqueKeys = new HashSet();
this.indexes = new HashSet();
}
/**
* @see org.teiid.designer.core.util.ModelVisitor#visit(org.eclipse.emf.ecore.EObject)
*/
public boolean visit( final EObject object ) {
if (object instanceof Catalog || object instanceof Schema || object instanceof Table) {
return true;
} else if (object instanceof PrimaryKey) {
found((PrimaryKey)object, this.primaryKeys);
} else if (object instanceof ForeignKey) {
found((ForeignKey)object, this.foreignKeys);
} else if (object instanceof UniqueKey) {
found((UniqueKey)object, this.uniqueKeys);
} else if (object instanceof Index) {
found((Index)object, this.indexes);
}
return false;
}
/**
* @see org.teiid.designer.core.util.ModelVisitor#visit(org.eclipse.emf.ecore.resource.Resource)
*/
public boolean visit( final Resource resource ) {
return true;
}
protected void found( final RelationalEntity entity,
final Set uniqueEntities ) {
String name = IntermediateFormat.this.getObjectNameInDdl(entity);
if (uniqueEntities.contains(name)) {
boolean isNameUnique = false;
int index = 1;
while (!isNameUnique) {
String newName = name + String.valueOf(index);
if (!uniqueEntities.contains(newName)) {
name = newName;
break;
}
index++;
}
}
uniqueEntities.add(name);
IntermediateFormat.this.relationalEntities.put(entity, name);
}
}
final Map relationalEntities;
private final List modelWrappers;
private final DdlOptions options;
// private final IProgressMonitor monitor;
private String exporterTool;
private String exporterVersion;
private WeakReference<ModelEditor> editorRef;
/**
* Construct an instance of IntermediateFormat.
*/
public IntermediateFormat( final ModelWrapper modelWrapper,
final DdlOptions options,
final IProgressMonitor monitor ) {
super();
CoreArgCheck.isNotNull(modelWrapper);
CoreArgCheck.isNotNull(options);
this.modelWrappers = new ArrayList();
this.modelWrappers.add(modelWrapper);
this.options = options;
// this.monitor = monitor != null ? monitor : new NullProgressMonitor();
this.relationalEntities = new HashMap();
}
/**
* Construct an instance of IntermediateFormat.
*/
public IntermediateFormat( final List modelWrappers,
final DdlOptions options,
final IProgressMonitor monitor ) {
super();
CoreArgCheck.isNotNull(modelWrappers);
CoreArgCheck.isNotNull(options);
this.modelWrappers = new ArrayList(modelWrappers);
this.options = options;
// this.monitor = monitor != null ? monitor : new NullProgressMonitor();
this.relationalEntities = new HashMap();
}
protected ModelEditor getModelEditor() {
return ModelerCore.getModelEditor();
}
/**
* @return
*/
public String getExporterTool() {
return exporterTool;
}
/**
* @return
*/
public String getExporterVersion() {
return exporterVersion;
}
/**
* @param string
*/
public void setExporterTool( String string ) {
exporterTool = string;
}
/**
* @param string
*/
public void setExporterVersion( String string ) {
exporterVersion = string;
}
// =========================================================================
// Helper methods for setting attributes
// =========================================================================
protected void setAttribute( final Element element,
final String attributeName,
final String value ) {
if (value != null && value.trim().length() != 0) {
final Attribute attrib = new Attribute(attributeName, value);
element.setAttribute(attrib);
}
}
protected void setAttribute( final Element element,
final String attributeName,
final Object value ) {
if (value != null) {
final Attribute attrib = new Attribute(attributeName, value.toString());
element.setAttribute(attrib);
}
}
protected void setAttribute( final Element element,
final String attributeName,
final boolean value ) {
final String strValue = value ? TRUE_VALUE : FALSE_VALUE;
final Attribute attrib = new Attribute(attributeName, strValue);
element.setAttribute(attrib);
}
protected void setAttribute( final Element element,
final String attributeName,
final int value ) {
final String strValue = Integer.toString(value);
final Attribute attrib = new Attribute(attributeName, strValue);
element.setAttribute(attrib);
}
// =========================================================================
// Methods to create document content from RelationalEntities
// =========================================================================
/**
* @param emfResource
* @param monitor
* @return
*/
public Document createDocument() {
final Element ddlElement = new Element(Xml.DDL.TAG);
final Document doc = new Document(ddlElement);
final Date now = new Date(System.currentTimeMillis());
// Set the model-level attributes ...
setAttribute(ddlElement, Xml.Model.Attributes.GENERATE_INFO_COMMENTS, options.isGenerateInfoComments());
setAttribute(ddlElement, Xml.Model.Attributes.GENERATE_TABLE_COMMENTS, options.isGenerateTableComments());
setAttribute(ddlElement, Xml.Model.Attributes.GENERATE_COLUMN_COMMENTS, options.isGenerateColumnComments());
setAttribute(ddlElement, Xml.Model.Attributes.GENERATE_DROPS, options.isGenerateDropStatements());
setAttribute(ddlElement, Xml.Model.Attributes.EXPORT_TOOL, exporterTool);
setAttribute(ddlElement, Xml.Model.Attributes.EXPORT_VERSION, exporterVersion);
setAttribute(ddlElement, Xml.Model.Attributes.EXPORT_DATE, DATE_FORMATTER.format(now));
setAttribute(ddlElement, Xml.Model.Attributes.EXPORT_TIME, TIME_FORMATTER.format(now));
// -------------------------------------------------------------------------
// Walk the models that have at least some content to be written out ...
// -------------------------------------------------------------------------
// visit the model here
final ModelVisitor visitor = new RelationalEntityUniquenessEnforcer();
final ModelVisitorProcessor processor = new ConcurrentModelVisitorProcessor(visitor);
final Iterator iter = modelWrappers.iterator();
while (iter.hasNext()) {
final ModelWrapper wrapper = (ModelWrapper)iter.next();
try {
processor.walk(wrapper.getEmfResource(), ModelVisitorProcessor.DEPTH_INFINITE);
} catch (ModelerCoreException e) {
// handle the exception
}
create(ddlElement, wrapper); // this method calls other methods to walk the tree
}
return doc;
}
/**
* Method to create document contents for a ModelWrapper object.
*
* @param parent the Element that is the parent of any created Elements or Attributes; may not be null
* @param eobj the ModelWrapper that contains some objects to be written to the document content; may not be null
*/
protected void create( final Element parent,
final ModelWrapper wrapper ) {
final Resource emfResource = wrapper.getEmfResource();
final ModelAnnotation modelAnnotation = wrapper.getContents().getModelAnnotation();
final ModelType modelTypeEnum = modelAnnotation.getModelType();
Type type = Type.getType(modelTypeEnum.getValue());
String modelType = null;
switch (type) {
case PHYSICAL:
case VIRTUAL:
case UNKNOWN:
modelType = type.getCamelCaseName();
break;
default:
modelType = modelTypeEnum.getName();
}
final String primaryMetamodelUri = modelAnnotation.getPrimaryMetamodelUri();
final MetamodelDescriptor mmDesc = ModelerCore.getMetamodelRegistry().getMetamodelDescriptor(primaryMetamodelUri);
final String primaryMetamodel = mmDesc != null ? mmDesc.getName() : primaryMetamodelUri;
// Set the model-level attributes ...
final Element modelElement = new Element(Xml.Model.TAG);
parent.addContent(modelElement);
setAttribute(modelElement, Xml.Model.Attributes.NAME, wrapper.getModelName());
setAttribute(modelElement, Xml.Model.Attributes.UUID, getModelEditor().getObjectID(modelAnnotation));
setAttribute(modelElement, Xml.Model.Attributes.MODEL_FILENAME, wrapper.getModelFilename());
if (modelType != null) {
setAttribute(modelElement, Xml.Model.Attributes.MODEL_TYPE, modelType);
}
setAttribute(modelElement, Xml.Model.Attributes.METAMODEL, primaryMetamodel);
setAttribute(modelElement, Xml.Model.Attributes.METAMODEL_URL, primaryMetamodelUri);
// -------------------------------------------------------------------------
// Walk the root-level objects and call the corresponding method ...
// -------------------------------------------------------------------------
final Iterator iter = emfResource.getContents().iterator();
while (iter.hasNext()) {
final EObject eObj = (EObject)iter.next();
create(modelElement, eObj, wrapper); // this method calls other methods to walk the tree
}
}
/**
* Method to create document contents for a general EObject. This method does nothing, since there are overloaded forms of
* this method that handle specific types of EObjects.
*
* @param parent the Element that is the parent of any created Elements or Attributes; may not be null
* @param eobj the EObject representing the graph of objects for which document content may be created
*/
protected void create( final Element parent,
final EObject eObj,
final ModelWrapper wrapper ) {
if (eObj instanceof Catalog) {
create(parent, (Catalog)eObj, wrapper);
} else if (eObj instanceof Schema) {
create(parent, (Schema)eObj, wrapper);
} else if (eObj instanceof Table) {
create(parent, (Table)eObj, wrapper);
} else if (eObj instanceof Index) {
create(parent, (Index)eObj, wrapper);
} else if (eObj instanceof Column) {
create(parent, (Column)eObj, wrapper);
} else if (eObj instanceof ForeignKey) {
create(parent, (ForeignKey)eObj, wrapper);
} else if (eObj instanceof PrimaryKey) {
create(parent, (PrimaryKey)eObj, wrapper);
} else if (eObj instanceof UniqueKey) {
create(parent, (UniqueKey)eObj, wrapper);
}
// else, do nothing
}
/**
* Method to create document contents for a Catalog object. This method does nothing for processing the Catalog object itself,
* but
*
* @param parent the Element that is the parent of any created Elements or Attributes; may not be null
* @param eobj the Catalog representing the graph of objects for which document content may be created; may not be null
*/
protected void create( final Element parent,
final Catalog catalog,
final ModelWrapper wrapper ) {
CoreArgCheck.isNotNull(parent);
CoreArgCheck.isNotNull(catalog);
// Skip this object if it is not to be exported ...
if (!wrapper.isSelected(catalog)) {
return;
}
// Walk the contents and create any elements for this object's children ...
final Iterator iter = catalog.eContents().iterator();
while (iter.hasNext()) {
final EObject eobj = (EObject)iter.next();
create(parent, eobj, wrapper);
}
}
/**
* Method to create document contents for a Schema object.
*
* @param parent the Element that is the parent of any created Elements or Attributes; may not be null
* @param eobj the Schema representing the graph of objects for which document content may be created; may not be null
*/
protected void create( final Element parent,
final Schema schema,
final ModelWrapper wrapper ) {
CoreArgCheck.isNotNull(parent);
CoreArgCheck.isNotNull(schema);
// Skip this object if it is not to be exported ...
if (!wrapper.isSelected(schema)) {
return;
}
Element parentOfNewElements = parent;
if (this.options.isGenerateSchema()) {
final Element schemaElement = new Element(Xml.Schema.TAG);
parent.addContent(schemaElement);
setAttribute(schemaElement, Xml.Schema.Attributes.NAME, getObjectNameInDdl(schema));
setAttribute(schemaElement, Xml.Schema.Attributes.UUID, getModelEditor().getObjectID(schema));
setAttribute(schemaElement, Xml.Schema.Attributes.PATH_IN_MODEL, getModelEditor().getModelRelativePath(schema));
parentOfNewElements = schemaElement;
}
// Walk the contents and create any elements for this object's children ...
final Iterator iter = schema.eContents().iterator();
while (iter.hasNext()) {
final EObject eobj = (EObject)iter.next();
create(parentOfNewElements, eobj, wrapper);
}
}
/**
* Method to create document contents for a Table object.
*
* @param parent the Element that is the parent of any created Elements or Attributes; may not be null
* @param eobj the EObject representing the graph of objects for which document content may be created; may not be null
*/
protected void create( final Element parent,
final Table table,
final ModelWrapper wrapper ) {
CoreArgCheck.isNotNull(parent);
CoreArgCheck.isNotNull(table);
// Skip this object if it is not to be exported ...
if (!wrapper.isSelected(table)) {
return;
}
final Element tableElement = new Element(Xml.Table.TAG);
parent.addContent(tableElement);
setAttribute(tableElement, Xml.Table.Attributes.NAME, getObjectNameInDdl(table));
setAttribute(tableElement, Xml.Table.Attributes.UUID, getModelEditor().getObjectID(table));
setAttribute(tableElement, Xml.Table.Attributes.PATH_IN_MODEL, getModelEditor().getModelRelativePath(table));
final Annotation annotation = wrapper.getContents().getAnnotation(table);
if (annotation != null) {
setAttribute(tableElement, Xml.Table.Attributes.DESCRIPTION, annotation.getDescription());
}
// Process the columns ...
final Iterator iter = table.getColumns().iterator();
while (iter.hasNext()) {
final EObject eobj = (EObject)iter.next();
create(tableElement, eobj, wrapper);
}
if (table instanceof BaseTable) {
final BaseTable baseTable = (BaseTable)table;
// Process the primary key ...
final PrimaryKey pk = baseTable.getPrimaryKey();
if (pk != null) {
create(parent, pk, wrapper); // primary keys go under model, not under table
}
// Process the foreign key ...
final Iterator fkIter = baseTable.getForeignKeys().iterator();
while (fkIter.hasNext()) {
final EObject fkey = (EObject)fkIter.next();
create(parent, fkey, wrapper); // foreign keys go under model, not under table
}
// Process the unique keys ...
final Iterator ukIter = baseTable.getUniqueConstraints().iterator();
while (ukIter.hasNext()) {
final EObject ukey = (EObject)ukIter.next();
create(parent, ukey, wrapper); // foreign keys go under model, not under table
}
}
}
/**
* Method to create document contents for a Column object.
*
* @param parent the Element that is the parent of any created Elements or Attributes; may not be null
* @param eobj the EObject representing the graph of objects for which document content may be created; may not be null
*/
protected void create( final Element parent,
final Column column,
final ModelWrapper wrapper ) {
CoreArgCheck.isNotNull(parent);
CoreArgCheck.isNotNull(column);
final Element columnElement = new Element(Xml.Column.TAG);
parent.addContent(columnElement);
setAttribute(columnElement, Xml.Column.Attributes.NAME, getObjectNameInDdl(column));
setAttribute(columnElement, Xml.Column.Attributes.UUID, getModelEditor().getObjectID(column));
final Annotation annotation = wrapper.getContents().getAnnotation(column);
if (annotation != null) {
setAttribute(columnElement, Xml.Column.Attributes.DESCRIPTION, annotation.getDescription());
}
// Set the type and length information
setAttribute(columnElement, Xml.Column.Attributes.TYPE, getType(column));
final int precision = column.getPrecision();
final int scale = column.getScale();
final int length = column.getLength();
if (precision != 0) {
setAttribute(columnElement, Xml.Column.Attributes.PRECISION, precision);
}
if (length != 0) {
setAttribute(columnElement, Xml.Column.Attributes.LENGTH, length);
}
if (scale != 0) {
setAttribute(columnElement, Xml.Column.Attributes.SCALE, scale);
}
setAttribute(columnElement, Xml.Column.Attributes.IS_FIXED_LENGTH, column.isFixedLength());
// Set the default value ...
final String defaultValue = column.getDefaultValue();
if (defaultValue != null && defaultValue.trim().length() != 0) {
setAttribute(columnElement, Xml.Column.Attributes.DEFAULT_VALUE, defaultValue);
}
// The column is nullable only if known to be nullable ...
final boolean isNullable = column.getNullable() != null && NullableType.NULLABLE_LITERAL.equals(column.getNullable());
setAttribute(columnElement, Xml.Column.Attributes.IS_NULLABLE, isNullable);
setAttribute(columnElement, Xml.Column.Attributes.SUPPORTS_SELECT, column.isSelectable());
setAttribute(columnElement, Xml.Column.Attributes.SUPPORTS_UPDATE, column.isUpdateable());
setAttribute(columnElement, Xml.Column.Attributes.IS_CASE_SENSITIVE, column.isCaseSensitive());
setAttribute(columnElement, Xml.Column.Attributes.IS_SIGNED, column.isSigned());
setAttribute(columnElement, Xml.Column.Attributes.IS_CURRENCY, column.isCurrency());
setAttribute(columnElement, Xml.Column.Attributes.IS_AUTOINCREMENTED, column.isAutoIncremented());
final SearchabilityType searchType = column.getSearchability();
if (searchType != null) {
}
setAttribute(columnElement, Xml.Column.Attributes.SEARCH_TYPE, null);
}
/**
* Return the datatype name for the supplied column.
*
* @param column the column; may not be null;
* @return the String name for the datatype; if null, then no datatype name will be written to the
*/
protected String getType( final Column column ) {
final String nativeType = column.getNativeType();
if (nativeType != null && this.options.isNativeTypeUsed()) {
return nativeType;
}
final EObject dt = column.getType();
if (dt != null) {
return getType(column, dt);
}
return null;
}
/**
* Return the datatype name for the supplied simple datatype.
*
* @param datatype the datatype; may not be null
* @return the String name for the datatype; if null, then no datatype name will be written to the output
*/
protected String getType( final Column column,
final EObject datatype ) {
final DatatypeManager dtManager = ModelerCore.getDatatypeManager(column, true);
// Look for a runtime type on the type ...
final String runtimeType = dtManager.getRuntimeTypeName(datatype);
if (runtimeType != null) {
return runtimeType;
}
// Find the supertype that is a builtin ...
EObject builtin = datatype;
while (builtin != null) {
builtin = dtManager.getBaseType(builtin);
if (builtin == null) {
break;
}
// Look for a runtime type on the type ...
final String builtinRuntimeType = dtManager.getRuntimeTypeName(builtin);
if (builtinRuntimeType != null) {
return builtinRuntimeType;
}
}
// If we've gotten to here, then try to get the JDBC type name ...
return dtManager.getName(datatype);
}
/**
* Method to create document contents for a PrimaryKey object.
*
* @param parent the Element that is the parent of any created Elements or Attributes; may not be null
* @param eobj the EObject representing the graph of objects for which document content may be created; may not be null
*/
protected void create( final Element parent,
final PrimaryKey pkey,
final ModelWrapper wrapper ) {
CoreArgCheck.isNotNull(parent);
CoreArgCheck.isNotNull(pkey);
final Element pkElement = new Element(Xml.PrimaryKey.TAG);
parent.addContent(pkElement);
setAttribute(pkElement, Xml.PrimaryKey.Attributes.NAME, getUniqueObjectName(pkey));
setAttribute(pkElement, Xml.PrimaryKey.Attributes.UUID, getModelEditor().getObjectID(pkey));
setAttribute(pkElement, Xml.PrimaryKey.Attributes.PATH_IN_MODEL, getModelEditor().getModelRelativePath(pkey));
// Process the table that contains the primary key ...
final Table pkTable = pkey.getTable();
if (pkTable != null) { // should never be null, but check just in case ...
setAttribute(pkElement, Xml.PrimaryKey.Attributes.TABLE_NAME, getObjectNameInDdl(pkTable));
}
// Process the columns that the primary key references ...
final List columns = pkey.getColumns();
final Iterator iter = columns.iterator();
while (iter.hasNext()) {
final Column column = (Column)iter.next();
final Element pkColumnElement = new Element(Xml.PrimaryKeyColumn.TAG);
setAttribute(pkColumnElement, Xml.PrimaryKeyColumn.Attributes.NAME, getObjectNameInDdl(column));
setAttribute(pkColumnElement, Xml.PrimaryKeyColumn.Attributes.UUID, getModelEditor().getObjectID(column));
pkElement.addContent(pkColumnElement);
}
}
/**
* Method to create document contents for a UniqueKey object.
*
* @param parent the Element that is the parent of any created Elements or Attributes; may not be null
* @param eobj the EObject representing the graph of objects for which document content may be created; may not be null
*/
protected void create( final Element parent,
final UniqueKey ukey,
final ModelWrapper wrapper ) {
CoreArgCheck.isNotNull(parent);
CoreArgCheck.isNotNull(ukey);
final Element pkElement = new Element(Xml.UniqueKey.TAG);
parent.addContent(pkElement);
setAttribute(pkElement, Xml.UniqueKey.Attributes.NAME, getUniqueObjectName(ukey));
setAttribute(pkElement, Xml.UniqueKey.Attributes.UUID, getModelEditor().getObjectID(ukey));
setAttribute(pkElement, Xml.UniqueKey.Attributes.PATH_IN_MODEL, getModelEditor().getModelRelativePath(ukey));
// Process the table that contains the primary key ...
final Table ukTable = ukey.getTable();
if (ukTable != null) { // should never be null, but check just in case ...
setAttribute(pkElement, Xml.PrimaryKey.Attributes.TABLE_NAME, getObjectNameInDdl(ukTable));
}
// Process the columns that the unique key references ...
final List columns = ukey.getColumns();
final Iterator iter = columns.iterator();
while (iter.hasNext()) {
final Column column = (Column)iter.next();
final Element pkColumnElement = new Element(Xml.UniqueKeyColumn.TAG);
setAttribute(pkColumnElement, Xml.UniqueKeyColumn.Attributes.NAME, getObjectNameInDdl(column));
setAttribute(pkColumnElement, Xml.UniqueKeyColumn.Attributes.UUID, getModelEditor().getObjectID(column));
pkElement.addContent(pkColumnElement);
}
}
/**
* Method to create document contents for a ForeignKey object.
*
* @param parent the Element that is the parent of any created Elements or Attributes; may not be null
* @param eobj the EObject representing the graph of objects for which document content may be created; may not be null
*/
protected void create( final Element parent,
final ForeignKey fkey,
final ModelWrapper wrapper ) {
CoreArgCheck.isNotNull(parent);
CoreArgCheck.isNotNull(fkey);
final Element fkElement = new Element(Xml.ForeignKey.TAG);
parent.addContent(fkElement);
setAttribute(fkElement, Xml.ForeignKey.Attributes.NAME, getUniqueObjectName(fkey));
setAttribute(fkElement, Xml.ForeignKey.Attributes.UUID, getModelEditor().getObjectID(fkey));
setAttribute(fkElement, Xml.ForeignKey.Attributes.PATH_IN_MODEL, getModelEditor().getModelRelativePath(fkey));
// Process the table that contains the foreign key ...
final Table fkTable = fkey.getTable();
if (fkTable != null) { // should never be null, but just in case ...
setAttribute(fkElement, Xml.ForeignKey.Attributes.TABLE_NAME, getObjectNameInDdl(fkTable));
}
// Process the table of the primary key ...
final UniqueKey ukey = fkey.getUniqueKey();
List pkColumns = null;
if (ukey != null) { // should never be null, but check just in case ...
final Table ukeyTable = ukey.getTable();
if (ukeyTable != null) { // should never be null, but check just in case ...
setAttribute(fkElement, Xml.ForeignKey.Attributes.PK_TABLE_NAME, getObjectNameInDdl(ukeyTable));
}
pkColumns = ukey.getColumns();
}
// Process the columns that the foreign key references ...
final List columns = fkey.getColumns();
int index = 0;
final Iterator iter = columns.iterator();
while (iter.hasNext()) {
final Column column = (Column)iter.next();
final Element fkColumnElement = new Element(Xml.ForignKeyColumn.TAG);
setAttribute(fkColumnElement, Xml.ForignKeyColumn.Attributes.NAME, getObjectNameInDdl(column));
setAttribute(fkColumnElement, Xml.ForignKeyColumn.Attributes.UUID, getModelEditor().getObjectID(column));
// Find the corresponding column in the primary key; do this by order, but be tolerant
// of when the # of pk columns is different than the number of fk columns
if (pkColumns != null && pkColumns.size() > index) {
final Column pkColumn = (Column)pkColumns.get(index);
setAttribute(fkColumnElement, Xml.ForignKeyColumn.Attributes.PK_COLUMN_NAME, getObjectNameInDdl(pkColumn));
}
fkElement.addContent(fkColumnElement);
++index;
}
}
/**
* Method to create document contents for an Index object.
*
* @param parent the Element that is the parent of any created Elements or Attributes; may not be null
* @param eobj the Index representing the graph of objects for which document content may be created; may not be null
*/
protected void create( final Element parent,
final Index index,
final ModelWrapper wrapper ) {
CoreArgCheck.isNotNull(parent);
CoreArgCheck.isNotNull(index);
// Skip this object if it is not to be exported ...
if (!wrapper.isSelected(index)) {
return;
}
final Element indexElement = new Element(Xml.Index.TAG);
parent.addContent(indexElement);
setAttribute(indexElement, Xml.Index.Attributes.NAME, getUniqueObjectName(index));
setAttribute(indexElement, Xml.Index.Attributes.UUID, getModelEditor().getObjectID(index));
setAttribute(indexElement, Xml.Index.Attributes.PATH_IN_MODEL, getModelEditor().getModelRelativePath(index));
// Process the columns that the primary key references ...
final List columns = index.getColumns();
final Element indexColumnElement = new Element(Xml.IndexColumns.TAG);
indexElement.addContent(indexColumnElement);
Table indexedTable = null;
final Iterator iter = columns.iterator();
while (iter.hasNext()) {
final Column column = (Column)iter.next();
final Element indexedColumnElement = new Element(Xml.IndexColumn.TAG);
setAttribute(indexedColumnElement, Xml.IndexColumn.Attributes.NAME, getObjectNameInDdl(column));
setAttribute(indexedColumnElement, Xml.IndexColumn.Attributes.UUID, getModelEditor().getObjectID(column));
indexColumnElement.addContent(indexedColumnElement);
indexedTable = (Table)column.getOwner();
}
// Process the table that contains the foreign key ...
if (indexedTable != null) { // should never be null, but just in case ...
setAttribute(indexElement, Xml.ForeignKey.Attributes.TABLE_NAME, getObjectNameInDdl(indexedTable));
}
}
/**
* Generate the name for the DDL object from the relational entity.
*
* @param entity the entity for which the name is to be determined
* @return the object name for use in the DDL
*/
protected String getObjectNameInDdl( final RelationalEntity entity ) {
if (this.options.isNameInSourceUsed()) {
// Should try to use the name-in-source if there is one ...
String name = entity.getNameInSource();
// Ensure there is a name ...
if (name == null || name.trim().length() == 0) {
// There is no name-in-source, so just use the entity's name ...
name = entity.getName();
}
return name;
}
// Just use the entity's name ...
return entity.getName();
}
/**
* Generate the name for the DDL object from the relational entity.
*
* @param entity the entity for which the name is to be determined
* @return the object name for use in the DDL
*/
protected String getUniqueObjectName( final RelationalEntity entity ) {
if (this.options.isUniqueNamesEnforced()) {
Object name = this.relationalEntities.get(entity);
if (name == null) {
DdlPlugin.Util.log(IStatus.WARNING, DdlPlugin.Util.getString("IntermediateFormat.0", entity)); //$NON-NLS-1$
return getObjectNameInDdl(entity);
} else {
name = getRealName((String)name);
}
return (String)name;
}
return getObjectNameInDdl(entity);
}
private String getRealName(String value) {
// looking for "PRIMARY"3 type values
// strip off the integer at end
if( value.indexOf('"') == 0) {
int lastQuoteIndex = value.lastIndexOf('"');
return value.substring(0, lastQuoteIndex+1);
}
return value;
}
}