/*
* 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.ui.viewsupport;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.teiid.core.designer.ModelerCoreException;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.types.DatatypeConstants;
import org.teiid.designer.jdbc.relational.impl.RelationalModelProcessorImpl;
import org.teiid.designer.metamodels.core.Annotation;
import org.teiid.designer.metamodels.core.AnnotationContainer;
import org.teiid.designer.metamodels.core.CoreFactory;
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.RelationalFactory;
import org.teiid.designer.metamodels.relational.RelationalPackage;
import org.teiid.designer.metamodels.relational.Schema;
import org.teiid.designer.metamodels.relational.Table;
import org.teiid.designer.metamodels.relational.View;
import org.teiid.designer.metamodels.relational.util.RelationalTypeMapping;
import org.teiid.designer.metamodels.relational.util.RelationalTypeMappingImpl;
import org.teiid.designer.transformation.util.TransformationHelper;
import org.teiid.designer.ui.UiConstants;
/**
* @since 8.0
*/
public class RelationalObjectBuilder implements UiConstants {
// ============================================================================================================================
// Static Constants
private static final String SLASH = "/"; //$NON-NLS-1$
public static final String RELATIONAL_PACKAGE_URI = RelationalPackage.eNS_URI;
public static final RelationalFactory factory = RelationalFactory.eINSTANCE;
public static final String BASE_TABLE_STRING = "TABLE"; //$NON-NLS-1$
public static final String VIEW_STRING = "VIEW"; //$NON-NLS-1$
public static final String INDEX_STRING = "INDEX"; //$NON-NLS-1$
public static final String COLUMN_STRING = "COLUMN"; //$NON-NLS-1$
public static final String UNIQUE_KEY_STRING = "UNIQUEKEY"; //$NON-NLS-1$
public static final String PRIMARY_KEY_STRING = "PRIMARYKEY"; //$NON-NLS-1$
public static final String SCHEMA_STRING = "SCHEMA"; //$NON-NLS-1$
public static final String CATALOG_STRING = "CATALOG"; //$NON-NLS-1$
private final Resource resource;
private final MyRelationalModelProcessor processor;
public static boolean HEADLESS = false;// Flag to use for JUnit testing
// ============================================================================================================================
private Object[] datatypesArray = null;
/**
* @since 4.2
*/
public RelationalObjectBuilder( final Resource resource ) {
CoreArgCheck.isNotNull(resource);
this.resource = resource;
if (!HEADLESS) {
// Can't utilize this entity when UnitTesting as it utilizes the DTMgr
processor = new MyRelationalModelProcessor(RelationalFactory.eINSTANCE, RelationalTypeMappingImpl.getInstance());
} else {
processor = null;
}
}
public String getRelationalPackageURI() {
return RELATIONAL_PACKAGE_URI;
}
public EObject createColumn( final String name,
final Object location,
final String description,
final XSDSimpleTypeDefinition builtInType,
final XSDSimpleTypeDefinition actualType ) {
CoreArgCheck.isNotNull(name);
CoreArgCheck.isNotNull(location);
Column col = factory.createColumn();
col.setName(name);
int actualLength = 255;
if (builtInType != null && actualType != null) {
EList validFacets = actualType.getValidFacets();
boolean lengthDone = false;
if (validFacets.contains("length") && actualType.getLengthFacet() != null) {//$NON-NLS-1$
actualLength = actualType.getLengthFacet().getValue();
lengthDone = true;
}
if (!lengthDone && validFacets.contains("maxLength") && actualType.getMaxLengthFacet() != null) {//$NON-NLS-1$
actualLength = actualType.getMaxLengthFacet().getValue();
}
if (validFacets.contains("fractionDigits") && actualType.getFractionDigitsFacet() != null) {//$NON-NLS-1$
col.setPrecision(actualType.getFractionDigitsFacet().getValue());
}
col.setType(builtInType);
col.setLength(actualLength);
}
// Set Description
createAnnotation(col, description);
return col;
}
public void createTransformation( EObject baseTable,
String selectSql ) {
if (HEADLESS) {
// Don't do anything with the transformations when Unit Testing
return;
}
TransformationHelper.createTransformation(baseTable, selectSql);
// TransformationDiagramUtil.createTransformationDiagram(baseTable,resource, true);
}
public String getTypeName( EObject column ) {
if (column instanceof Column) {
EObject type = ((Column)column).getType();
if (type instanceof XSDSimpleTypeDefinition) {
return ((XSDSimpleTypeDefinition)type).getName();
}
}
return new String();
}
public EObject createBaseTable( final String name,
final Object location,
final boolean supportsUpdate,
final String description ) {
CoreArgCheck.isNotNull(name);
CoreArgCheck.isNotNull(location);
// Create and Set Name
BaseTable bt = factory.createBaseTable();
bt.setName(name);
bt.setSupportsUpdate(supportsUpdate);
// add table to container
if (location instanceof Resource) {
((Resource)location).getContents().add(bt);
} else if (location instanceof Schema) {
((Schema)location).getTables().add(bt);
} else if (location instanceof Catalog) {
((Catalog)location).getTables().add(bt);
}
// Set Description
createAnnotation(bt, description);
return bt;
}
public void addColumns( final Object table,
final Collection columns ) {
if (table instanceof Table) {
((Table)table).getColumns().addAll(columns);
}
}
public void createXPathNIS( final EObject table,
final XSDConcreteComponent xsdComp ) {
CoreArgCheck.isNotNull(xsdComp);
CoreArgCheck.isNotNull(table);
if (!(table instanceof BaseTable)) {
return;
}
XSDElementDeclaration element = null;
EObject owner = xsdComp;
boolean done = false;
while (!done && owner != null) {
if (owner instanceof XSDElementDeclaration) {
element = (XSDElementDeclaration)xsdComp;
done = true;
} else {
owner = owner.eContainer();
}
}
if (element == null) {
return;
}
final Stack elements = new Stack();
owner = element;
while (owner != null) {
if (owner instanceof XSDElementDeclaration) {
elements.push(owner);
}
owner = owner.eContainer();
}
final StringBuffer xpath = new StringBuffer();
while (!elements.isEmpty()) {
xpath.append(SLASH);
final XSDElementDeclaration next = (XSDElementDeclaration)elements.pop();
xpath.append(next.getName());
}
((BaseTable)table).setNameInSource(xpath.toString());
}
public void createColXPathNIS( final EObject col,
final Stack elementStack ) {
CoreArgCheck.isNotNull(col);
CoreArgCheck.isNotNull(elementStack);
if (!(col instanceof Column)) {
return;
}
final Stack copy = (Stack)elementStack.clone();
final Stack topDownStack = new Stack();
while (!copy.isEmpty()) {
topDownStack.push(copy.pop());
}
final StringBuffer nis = new StringBuffer();
while (!topDownStack.isEmpty()) {
nis.append(SLASH);
final XSDElementDeclaration next = (XSDElementDeclaration)topDownStack.pop();
nis.append(next.getName());
}
((Column)col).setNameInSource(nis.toString());
}
public EObject createView( final String name,
final Object location,
final boolean supportsUpdate,
final String description ) {
CoreArgCheck.isNotNull(name);
CoreArgCheck.isNotNull(location);
// Create and Set Name
View view = factory.createView();
view.setName(name);
view.setSupportsUpdate(supportsUpdate);
// add table to container
if (location instanceof Resource) {
((Resource)location).getContents().add(view);
} else if (location instanceof Schema) {
((Schema)location).getTables().add(view);
} else if (location instanceof Catalog) {
((Catalog)location).getTables().add(view);
}
// Set Description
createAnnotation(view, description);
return view;
}
private void createAnnotation( EObject eObject,
String description ) {
if (description != null && description.trim().length() > 0) {
AnnotationContainer annotations = null;
final Iterator contents = this.resource.getContents().iterator();
while (contents.hasNext()) {
final Object next = contents.next();
if (next instanceof AnnotationContainer) {
annotations = (AnnotationContainer)next;
}
} // while
if (annotations == null) {
annotations = CoreFactory.eINSTANCE.createAnnotationContainer();
this.resource.getContents().add(annotations);
}
Annotation annotation = annotations.findAnnotation(eObject);
if (annotation == null) {
annotation = CoreFactory.eINSTANCE.createAnnotation();
annotations.getAnnotations().add(annotation);
annotation.setAnnotatedObject(eObject);
}
annotation.setDescription(description);
}
}
public EObject getDatatype( String datatype ) {
if (HEADLESS) {
// Can't utilize DTMgr when running headless
return null;
}
if (datatypesArray == null) {
try {
datatypesArray = ModelerCore.getWorkspaceDatatypeManager().getAllDatatypes();
} catch (ModelerCoreException e) {
Util.log(e);
}
}
if (datatypesArray != null) {
String dtName = null;
for (int i = 0; i < datatypesArray.length; i++) {
dtName = ModelerCore.getWorkspaceDatatypeManager().getName((EObject)datatypesArray[i]);
if (dtName != null && dtName.equals(datatype)) return (EObject)datatypesArray[i];
}
}
List problems = new ArrayList();
EObject dType = processor.findType(datatype, problems);
if (dType != null) {
return dType;
}
return null;
}
class MyRelationalModelProcessor extends RelationalModelProcessorImpl {
private static final String VARCHAR2_TYPE_NAME = "VARCHAR2"; //$NON-NLS-1$
private static final String NVARCHAR2_TYPE_NAME = "NVARCHAR2"; //$NON-NLS-1$
private static final String TIMESTAMP_TYPE_NAME = "TIMESTAMP("; //$NON-NLS-1$
/**
* Construct an instance of OracleModelProcessor.
*/
public MyRelationalModelProcessor() {
super();
}
/**
* Construct an instance of OracleModelProcessor.
*
* @param factory
*/
public MyRelationalModelProcessor( final RelationalFactory factory ) {
super(factory);
}
/**
* Construct an instance of OracleModelProcessor.
*
* @param factory
*/
public MyRelationalModelProcessor( final RelationalFactory factory,
final RelationalTypeMapping mapping ) {
super(factory, mapping);
setDatatypeManager(ModelerCore.getWorkspaceDatatypeManager());
}
/**
* Find the type given the supplied information. This method is called by the various <code>create*</code> methods, and is
* currently implemented to use {@link #findType(int, int, List)} when a numeric type and {@link #findType(String, List)}
* (by name) for other types.
*
* @param type
* @param typeName
* @return
*/
@Override
protected EObject findType( final int jdbcType,
final String typeName,
final int length,
final int precision,
final int scale,
final List problems ) {
EObject result = null;
// Oracle 9i introduced the "timestamp" type name (with type=1111, or OTHER)
if (typeName.startsWith(TIMESTAMP_TYPE_NAME)) {
result = findBuiltinType(DatatypeConstants.BuiltInNames.TIMESTAMP, problems);
}
if (result != null) {
return result;
}
return super.findType(jdbcType, typeName, length, precision, scale, problems);
}
/**
* Overrides the method to find a type simply by name. This method converts some Oracle-specific (non-numeric) types to
* standard names, and then simply delegates to the superclass. Find the datatype by name.
*
* @param jdbcTypeName the name of the JDBC (or DBMS) type
* @param problems the list if {@link IStatus} into which problems and warnings are to be placed; never null
* @return the datatype that is able to represent data with the supplied criteria, or null if no datatype could be found
* @see org.teiid.designer.jdbc.relational.impl.RelationalModelProcessorImpl#findType(java.lang.String,
* java.util.List)
*/
@Override
protected EObject findType( final String jdbcTypeName,
final List problems ) {
String standardName = jdbcTypeName;
if (VARCHAR2_TYPE_NAME.equalsIgnoreCase(jdbcTypeName) || NVARCHAR2_TYPE_NAME.equalsIgnoreCase(jdbcTypeName)) {
standardName = RelationalTypeMapping.SQL_TYPE_NAMES.VARCHAR;
}
return super.findType(standardName, problems);
}
@Override
protected boolean isFixedLength( final int type,
final String typeName ) {
if (NVARCHAR2_TYPE_NAME.equalsIgnoreCase(typeName)) {
return false;
}
return super.isFixedLength(type, typeName);
}
}
}