/* * 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.transformation.ui.util; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.impl.EObjectImpl; import org.teiid.core.designer.ModelerCoreException; import org.teiid.core.designer.util.CoreArgCheck; import org.teiid.core.designer.util.CoreStringUtil; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.metamodel.aspect.sql.SqlColumnAspect; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.metamodels.transformation.TransformationMappingRoot; import org.teiid.designer.transformation.ui.UiConstants; import org.teiid.designer.transformation.ui.actions.TransformationSourceManager; import org.teiid.designer.transformation.util.TransformationHelper; import org.teiid.designer.ui.viewsupport.ModelObjectUtilities; import org.teiid.designer.ui.viewsupport.ModelUtilities; /** * @since 8.0 */ public class SqlDependencyHelper { private EObject vGroup; private HashMap sourceTables = new HashMap(); private ModelResource vResource; private final String STRING_STRING = "string"; //$NON-NLS-1$ private final String EMPTY_STRING = ""; //$NON-NLS-1$ private final char DOUBLE_QUOTE = '"'; private final String NEWLINE = CoreStringUtil.Constants.LINE_FEED; private Collection rows = new ArrayList(); private int maxDep = 0; private HashMap columnStrings = new HashMap(); boolean includeIntermediates = true; private String delimeter; private String nullValue; private String nullColumnString; private static final boolean ADD_NULL_COLUMN = true; private static final boolean DO_NOT_ADD_NULL_COLUMN = false; public static final int SEARCHABLE = 0; public static final int ALL_EXCEPT_LIKE = 1; public static final int LIKE_ONLY = 2; public static final int UNSEARCHABLE = 3; public static final String SEARCHABLE_STRING = "SEARCHABLE"; //$NON-NLS-1$ public static final String ALL_EXCEPT_LIKE_STRING = "ALL_EXCEPT_LIKE"; //$NON-NLS-1$ public static final String LIKE_ONLY_STRING = "LIKE_ONLY"; //$NON-NLS-1$ public static final String UNSEARCHABLE_STRING = "UNSEARCHABLE"; //$NON-NLS-1$ public static final String UNKNOWN_STRING = "UNKNOWN"; //$NON-NLS-1$ public static final String NULL_STRING = "NULL"; //$NON-NLS-1$ /** * @since 4.2 */ public SqlDependencyHelper( EObject virtualGroup, boolean includeIntermediates, String delimeter, String nullValue ) { super(); CoreArgCheck.isNotNull(virtualGroup, "SqlDependencyHelper got NULL virtual group. Expected Non-Null"); //$NON-NLS-1$ this.vGroup = virtualGroup; this.includeIntermediates = includeIntermediates; this.delimeter = delimeter; this.nullValue = nullValue; init(); } /** * @return Returns the vGroup. * @since 4.2 */ public EObject getVGroup() { return this.vGroup; } private void init() { vResource = ModelUtilities.getModelResourceForModelObject(vGroup); loadSourceTables(); loadDependentAttributes(); } private void loadSourceTables() { findSourceTables(); } private void findSourceTables() { // get transformation object EObject transformationEObject = getTransformation(vGroup); // get sources Iterator sourceIter = getSources(transformationEObject).iterator(); EObject nextSourceEObject = null; // walk through sources and add dependencies if "virtual" while (sourceIter.hasNext()) { nextSourceEObject = (EObject)sourceIter.next(); if( nextSourceEObject.eIsProxy() ) { nextSourceEObject = getRealEObjectFromProxy(nextSourceEObject); } if(nextSourceEObject!=null) { addSourceTable(nextSourceEObject); if (ModelObjectUtilities.isVirtual(nextSourceEObject)) addDependencies(nextSourceEObject); } } } /* * If the EObject is a proxy, use the uuid to lookup the real EObject * @param proxyEObj the proxied EObject * @return the real EObject, 'null' if not found */ private EObject getRealEObjectFromProxy(EObject proxyEObj) { EObject eObjectResult = null; if(proxyEObj.eIsProxy() && proxyEObj instanceof EObjectImpl) { try { String sUUIDFrag = ((EObjectImpl)proxyEObj).eProxyURI().fragment(); eObjectResult = (EObject)ModelerCore.getModelContainer().getEObjectFinder().find(sUUIDFrag); } catch (CoreException e) { String message = UiConstants.Util.getString("SqlDependencyHelper.getRealEObjectFromProxyError"); //$NON-NLS-1$ UiConstants.Util.log(IStatus.ERROR, e, message); } } return eObjectResult; } private void addSourceTable( EObject sourceTable ) { if (sourceTables.get(sourceTable) == null) { sourceTables.put(sourceTable, "x"); //$NON-NLS-1$ } } private void addDependencyStringRow( String rowString ) { rows.add(rowString); } private void addDependencies( EObject virtualSource ) { List virtualSources = new ArrayList(); EObject transformationEObject = getTransformation(virtualSource); if (transformationEObject != null) { // Get Source Tables for this transformation Iterator sourceIter = getSources(transformationEObject).iterator(); EObject nextSourceEObject = null; while (sourceIter.hasNext()) { nextSourceEObject = (EObject)sourceIter.next(); if( nextSourceEObject.eIsProxy() ) { nextSourceEObject = getRealEObjectFromProxy(nextSourceEObject); } if(nextSourceEObject!=null) { if (ModelObjectUtilities.isVirtual(nextSourceEObject)) virtualSources.add(nextSourceEObject); addSourceTable(nextSourceEObject); } } } if (!virtualSources.isEmpty()) { Iterator vIter = virtualSources.iterator(); while (vIter.hasNext()) { addDependencies((EObject)vIter.next()); } } } private void loadDependentAttributes() { // Let's get the columns for table List columns = TransformationHelper.getTableColumns(vGroup); Iterator iter = columns.iterator(); EObject nextColumn = null; while (iter.hasNext()) { nextColumn = (EObject)iter.next(); findAttributeDependencies(nextColumn); } } private void findAttributeDependencies( EObject selectedColumn ) { List targetList = Collections.EMPTY_LIST; // Let's check to see if the selected attribute is "virtual" or not. if (ModelObjectUtilities.isVirtual(selectedColumn)) { getSourceDependencies(selectedColumn, selectedColumn, targetList); } if (!includeIntermediates) maxDep = 1; } /* * This method initiates the search for source dependencies */ private boolean getSourceDependencies( EObject selectedColumn, EObject selectedAttribute, List targetList ) { boolean foundDependencies = false; // As long as it's virtual attribute we recursively search. if (ModelObjectUtilities.isVirtual(selectedAttribute)) { // Get the attribute's parent EObject virtualTarget = selectedAttribute.eContainer(); // if virtualTarget is a Procedure ResultSet, get the parent Procedure if (!TransformationHelper.isValidSqlTransformationTarget(virtualTarget) && TransformationHelper.isSqlColumnSet(virtualTarget)) { virtualTarget = virtualTarget.eContainer(); } if (virtualTarget != null) { TransformationMappingRoot tmr = (TransformationMappingRoot)getTransformation(virtualTarget); List attrDepList = new ArrayList(TransformationHelper.getSourceAttributesForTargetAttr(selectedAttribute, tmr)); if (attrDepList.size() == 0) { addDependencyStringRow(getDependentString(selectedColumn, (EObject)null, DO_NOT_ADD_NULL_COLUMN)); } else { EObject nextEObject = null; Iterator iter = attrDepList.iterator(); while (iter.hasNext()) { nextEObject = (EObject)iter.next(); if (!nextEObject.equals(selectedAttribute)) { // Now see if attribute's table is a source table EObject attributeParent = nextEObject.eContainer(); if (sourceTables.get(attributeParent) != null) { foundDependencies = true; if (!targetList.contains(nextEObject)) { // If we don't find a column string for the nextEObject, we create one and add it // to the columnStrings Map if (columnStrings.get(nextEObject) == null) columnStrings.put(nextEObject, getSourceColumnString(nextEObject)); List newTargetList = new ArrayList(targetList); newTargetList.add(nextEObject); if (ModelObjectUtilities.isVirtual(nextEObject)) { // Now get it's dependencies and add them. (recursive); // When there are no more dependencies (foundDep == FALSE) then we go ahead and create // the entire row string from the selectedColumn and the newTargetList of dependent // columns boolean foundDep = getSourceDependencies(selectedColumn, nextEObject, newTargetList); // If we didn't find any dependencies (virtual has no physical in workspace??) // We need to create a row here and treat it as an ending source. if (!foundDep) { // We need to add a "NULL" row for this case. This will help flag the user to indicate // that there were MISSING models in the workspace. if (includeIntermediates) { addDependencyStringRow(getDependentString(selectedColumn, newTargetList, ADD_NULL_COLUMN)); } else { addDependencyStringRow(getDependentString(selectedColumn, nextEObject, ADD_NULL_COLUMN)); } } } else { // Got a physical attribute, so let's create a row here!! if (includeIntermediates) { addDependencyStringRow(getDependentString(selectedColumn, newTargetList, DO_NOT_ADD_NULL_COLUMN)); } else { addDependencyStringRow(getDependentString(selectedColumn, nextEObject, DO_NOT_ADD_NULL_COLUMN)); } } } } } } } } } return foundDependencies; } private EObject getTransformation( EObject targetVirtualGroupEObject ) { return TransformationHelper.getTransformationMappingRoot(targetVirtualGroupEObject); } protected List getSources( EObject transformationEObject ) { return TransformationSourceManager.getSourceEObjects(transformationEObject); } /* * Create a row string comprising substrings for the virtual column * and the list of column dependencies */ private String getDependentString( EObject virtualColumn, List columnDependencies, boolean addNullColumn ) { StringBuffer buffer = new StringBuffer(); // --- Model Resource Name --------- int dotIndex = vResource.getResource().getName().indexOf(ModelerCore.MODEL_FILE_EXTENSION); buffer.append(getOutputString(vResource.getResource().getName().substring(0, dotIndex)) + delimeter); // --- Virtual Table Name --------- buffer.append(getOutputString(getName(vGroup)) + delimeter); // --- Virtual Column Name --------- SqlColumnAspect columnAspect = (SqlColumnAspect)org.teiid.designer.core.metamodel.aspect.sql.SqlAspectHelper.getSqlAspect(virtualColumn); buffer.append(getOutputString(columnAspect.getName(virtualColumn)) + delimeter); // --- DataType --------- String dName = columnAspect.getDatatypeName(virtualColumn); String rName = columnAspect.getRuntimeType(virtualColumn); int length = columnAspect.getLength(virtualColumn); if (dName == null) dName = CoreStringUtil.Constants.EMPTY_STRING; else if ((isStringType(dName) || isStringType(rName)) && length > 0) { dName = dName + "(" + length + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } buffer.append(getOutputString(dName) + delimeter); // --- Description --------- buffer.append(getOutputString(getDescription(virtualColumn)) + delimeter); // --- Searchable --------- buffer.append(getOutputString(getSearchableString(columnAspect.getSearchType(virtualColumn))) + delimeter); // --- Selectable --------- buffer.append(getOutputString(booleanString(columnAspect.isSelectable(virtualColumn))) + delimeter); // --- Added Dependent Column Info --------- EObject nextColumn = null; Iterator iter = columnDependencies.iterator(); while (iter.hasNext()) { nextColumn = (EObject)iter.next(); buffer.append((String)columnStrings.get(nextColumn)); } // Add NULL Column Info if no Depdendencies if (addNullColumn) buffer.append(getNullSourceColumnString()); if (columnDependencies.size() > maxDep) maxDep = columnDependencies.size(); return buffer.toString(); } private String booleanString( boolean value ) { if (value) { return "true"; //$NON-NLS-1$ } return "false"; //$NON-NLS-1$ } private String getDependentString( EObject virtualColumn, EObject lastDepColumn, boolean addNullColumn ) { StringBuffer buffer = new StringBuffer(); // --- Model Resource Name --------- int dotIndex = vResource.getResource().getName().indexOf(ModelerCore.MODEL_FILE_EXTENSION); buffer.append(getOutputString(vResource.getResource().getName().substring(0, dotIndex)) + delimeter); // --- Virtual Table Name --------- buffer.append(getOutputString(getName(vGroup)) + delimeter); // --- Virtual Column Name --------- SqlColumnAspect columnAspect = (SqlColumnAspect)org.teiid.designer.core.metamodel.aspect.sql.SqlAspectHelper.getSqlAspect(virtualColumn); buffer.append(getOutputString(columnAspect.getName(virtualColumn)) + delimeter); // --- Datatype --------- String dName = columnAspect.getDatatypeName(virtualColumn); String rName = columnAspect.getRuntimeType(virtualColumn); int length = columnAspect.getLength(virtualColumn); if (dName == null) dName = CoreStringUtil.Constants.EMPTY_STRING; else if ((isStringType(dName) || isStringType(rName)) && length > 0) { dName = dName + "(" + length + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } buffer.append(getOutputString(dName) + delimeter); // --- Description --------- String description = getDescription(virtualColumn); if (description == null) description = CoreStringUtil.Constants.EMPTY_STRING; buffer.append(getOutputString(description) + delimeter); // --- Searchable --------- buffer.append(getOutputString(getSearchableString(columnAspect.getSearchType(virtualColumn))) + delimeter); // --- Selectable --------- buffer.append(getOutputString(booleanString(columnAspect.isSelectable(virtualColumn))) + delimeter); // --- Add Last Dependent Column --------- if (lastDepColumn == null) { buffer.append(getNullSourceColumnString()); } else { buffer.append(columnStrings.get(lastDepColumn)); } // Add NULL Column Info if no Depdendencies if (addNullColumn) buffer.append(getNullSourceColumnString()); return buffer.toString(); } private String getSourceColumnString( EObject sourceColumn ) { StringBuffer buffer = new StringBuffer(); // --- Model and Path to Container --------- SqlColumnAspect columnAspect = (SqlColumnAspect)org.teiid.designer.core.metamodel.aspect.sql.SqlAspectHelper.getSqlAspect(sourceColumn); EObject table = sourceColumn.eContainer(); buffer.append(getOutputString(getPath(table)) + delimeter); // --- Name --------- buffer.append(getOutputString(columnAspect.getName(sourceColumn)) + delimeter); // --- Name In Source --------- String nis = columnAspect.getNameInSource(sourceColumn); if (nis == null) nis = CoreStringUtil.Constants.EMPTY_STRING; buffer.append(getOutputString(nis) + delimeter); // --- DataType --------- String dName = columnAspect.getDatatypeName(sourceColumn); String rName = columnAspect.getRuntimeType(sourceColumn); int length = columnAspect.getLength(sourceColumn); if (dName == null) dName = CoreStringUtil.Constants.EMPTY_STRING; else if ((isStringType(dName) || isStringType(rName)) && length > 0) { dName = dName + "(" + length + ")"; //$NON-NLS-1$ //$NON-NLS-2$ } buffer.append(getOutputString(dName) + delimeter); // --- Description --------- String description = getDescription(sourceColumn); if (description == null) description = CoreStringUtil.Constants.EMPTY_STRING; buffer.append(getOutputString(description) + delimeter); // --- Searchable --------- buffer.append(getOutputString(getSearchableString(columnAspect.getSearchType(sourceColumn))) + delimeter); // --- Selectable --------- buffer.append(getOutputString(booleanString(columnAspect.isSelectable(sourceColumn))) + delimeter); return buffer.toString(); } private String getNullSourceColumnString() { // Create this once if (nullColumnString == null) { StringBuffer buffer = new StringBuffer(); // --- Model and Path to Container --------- buffer.append(NULL_STRING + delimeter); // --- Name --------- buffer.append(NULL_STRING + delimeter); // --- Name In Source --------- buffer.append(NULL_STRING + delimeter); // --- DataType --------- buffer.append(NULL_STRING + delimeter); // --- Description --------- buffer.append(NULL_STRING + delimeter); // --- Selectable --------- buffer.append(NULL_STRING + delimeter); // --- Searchable --------- buffer.append(NULL_STRING + delimeter); nullColumnString = buffer.toString(); } return nullColumnString; } private String getName( EObject eObject ) { return ModelerCore.getModelEditor().getName(eObject); } private boolean isStringType( String type ) { if (type != null) { if (type.equalsIgnoreCase(STRING_STRING)) { return true; } } return false; } private String getDescription( EObject eObject ) { String description = CoreStringUtil.Constants.EMPTY_STRING; try { description = ModelerCore.getModelEditor().getDescription(eObject); if ((description != null) && (description.length() > 0)) { description = DOUBLE_QUOTE + description + DOUBLE_QUOTE; } } catch (ModelerCoreException err) { // NO DESCRIPTION. } return description; } private String getPath( EObject eObject ) { return ModelerCore.getModelEditor().getModelRelativePathIncludingModel(eObject).toString(); } private String getOutputString( String val ) { if (nullValue != null) { if (val == null || val.length() == 0 || val.equals(EMPTY_STRING)) { return nullValue; } } return val; } private String getHeaderString() { StringBuffer buffer = new StringBuffer(); buffer.append("VirtualModel" + delimeter); //$NON-NLS-1$ buffer.append("VirtualTableName" + delimeter); //$NON-NLS-1$ buffer.append("VirtualColumnName" + delimeter); //$NON-NLS-1$ buffer.append("DataType(LENGTH)" + delimeter); //$NON-NLS-1$ buffer.append("ColumnDescription" + delimeter); //$NON-NLS-1$ buffer.append("Searchable" + delimeter); //$NON-NLS-1$ buffer.append("Selectable" + delimeter); //$NON-NLS-1$ for (int i = 0; i < maxDep; i++) { buffer.append("SourceModel/TableName" + delimeter); //$NON-NLS-1$ buffer.append("SourceColumnName" + delimeter); //$NON-NLS-1$ buffer.append("ColumnNameInSource" + delimeter); //$NON-NLS-1$ // EnumeratedValues buffer.append("DataType(LENGTH)" + delimeter); //$NON-NLS-1$ buffer.append("ColumnDescription" + delimeter); //$NON-NLS-1$ buffer.append("Searchable" + delimeter); //$NON-NLS-1$ buffer.append("Selectable" + delimeter); //$NON-NLS-1$ } return buffer.toString(); } public String getFileString() { StringBuffer buffer = new StringBuffer(); buffer.append(getHeaderString() + NEWLINE); Iterator iter = rows.iterator(); String nextRow = null; while (iter.hasNext()) { nextRow = (String)iter.next(); buffer.append(nextRow + NEWLINE); } return buffer.toString(); } private String getSearchableString( int value ) { switch (value) { case SEARCHABLE: return SEARCHABLE_STRING; case ALL_EXCEPT_LIKE: return ALL_EXCEPT_LIKE_STRING; case LIKE_ONLY: return LIKE_ONLY_STRING; case UNSEARCHABLE: return UNSEARCHABLE_STRING; } return UNKNOWN_STRING; } /** * @return Returns the delimeter. * @since 4.2 */ public String getDelimeter() { return this.delimeter; } /** * @param delimeter The delimeter to set. * @since 4.2 */ public void setDelimeter( String delimeter ) { this.delimeter = delimeter; } }