/*
* 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.reconciler;
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 java.util.Map;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.swt.widgets.Shell;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.metamodels.transformation.SqlAlias;
import org.teiid.designer.metamodels.transformation.TransformationFactory;
import org.teiid.designer.query.IQueryFactory;
import org.teiid.designer.query.IQueryService;
import org.teiid.designer.query.sql.IElementCollectorVisitor;
import org.teiid.designer.query.sql.lang.ICommand;
import org.teiid.designer.query.sql.lang.IExpression;
import org.teiid.designer.query.sql.lang.IQuery;
import org.teiid.designer.query.sql.lang.IQueryCommand;
import org.teiid.designer.query.sql.lang.ISPParameter;
import org.teiid.designer.query.sql.lang.ISelect;
import org.teiid.designer.query.sql.lang.ISetQuery;
import org.teiid.designer.query.sql.lang.util.CommandHelper;
import org.teiid.designer.query.sql.symbol.IAliasSymbol;
import org.teiid.designer.query.sql.symbol.IElementSymbol;
import org.teiid.designer.query.sql.symbol.IGroupSymbol;
import org.teiid.designer.transformation.ui.UiConstants;
import org.teiid.designer.transformation.ui.UiPlugin;
import org.teiid.designer.transformation.util.TransformationHelper;
import org.teiid.designer.transformation.util.TransformationSqlHelper;
/**
* Reconciler Business Object that the Reconciler Panel works with
*
* @since 8.0
*/
public class ReconcilerObject {
private final String BIND_ATTRIBUTES_MESSAGE = UiConstants.Util.getString("ReconcilerObject.statusMessage.bindTheAttributes"); //$NON-NLS-1$
private final String HAS_UNMATCHED_SQL_MESSAGE = UiConstants.Util.getString("ReconcilerObject.statusMessage.hasUnmatchedSQL"); //$NON-NLS-1$
private final String HAS_UNBOUND_ATTRIBUTES_MESSAGE = UiConstants.Util.getString("ReconcilerObject.statusMessage.hasUnboundAttributes"); //$NON-NLS-1$
private final String HAS_TYPE_CONFLICTS_MESSAGE = UiConstants.Util.getString("ReconcilerObject.statusMessage.hasTypeConflicts"); //$NON-NLS-1$
private final String NO_SQL_PROJECTED_SYMBOLS_MESSAGE = UiConstants.Util.getString("ReconcilerObject.statusMessage.noSqlProjectedSymbols"); //$NON-NLS-1$
private final String IS_RECONCILED_MESSAGE = UiConstants.Util.getString("ReconcilerObject.statusMessage.isReconciled"); //$NON-NLS-1$
private final String NEW_COLUMN_DIALOG_TITLE = UiConstants.Util.getString("ReconcilerObject.newColumnDialog.title"); //$NON-NLS-1$
// ============================================================
// Instance variables
// ============================================================
private EObject targetGroup; // the transformation target group
private boolean isTargetLocked = false; // lock state of the transformation target
private BindingList bindingList = new BindingList();
private SqlList sqlList = new SqlList();
private ICommand originalCommand = null;
private List originalSymbols = new ArrayList();
private List originalInputParamSymbols = new ArrayList();
private IQueryCommand modifiedCommand = null;
private boolean sqlModifiable = true; // mdTODO: should be false when not a QueryCommand
private boolean isSelectDistinct = false;
// ============================================================
// Constructors
// ============================================================
/**
* Constructor.
*
* @param transformationObj the TransformationMappingRoot this is based on.
*/
public ReconcilerObject( EObject targetGroup,
ICommand originalCommand,
boolean targetLocked ) {
this.originalCommand = originalCommand;
this.targetGroup = targetGroup;
this.isTargetLocked = targetLocked;
init();
}
// ============================================================
// Instance methods
// ============================================================
/**
* Initialize the reconciler business object. This method creates attribute / Symbol bindings for each attribute. If a symbol
* whose name matches the attribute is found, it is bound to the attribute. Any remaining unbound symbols are used to create
* the sqlList.
*
* @param mappingRoot the TransformationMappingRoot object
*/
private void init() {
// Get projected symbols from the SELECT, retain for future use
if (originalCommand != null && originalCommand instanceof IQueryCommand) {
this.sqlModifiable = true;
modifiedCommand = (IQueryCommand)originalCommand.clone();
originalSymbols.addAll(CommandHelper.getProjectedSymbols(modifiedCommand));
// Remember if the the SELECT is select distinct
this.isSelectDistinct = isSelectDistinct((IQueryCommand)originalCommand);
}
// Get the procedure InputParameters from the SQL command
List originalInputParams = TransformationSqlHelper.getProcedureInputParams(originalCommand);
Iterator paramIter = originalInputParams.iterator();
while (paramIter.hasNext()) {
ISPParameter param = (ISPParameter)paramIter.next();
IElementSymbol eSymbol = param.getParameterSymbol();
this.originalInputParamSymbols.add(eSymbol);
}
// Get the target Attributes
List targetAttributes = TransformationHelper.getTargetAttributes(targetGroup);
// Working symbols list - will be modified as symbols are bound
List workingSymbolList = new ArrayList(originalSymbols.size());
workingSymbolList.addAll(originalSymbols);
// Create a Binding for each targetAttribute
Iterator attrIter = targetAttributes.iterator();
while (attrIter.hasNext()) {
EObject attribute = (EObject)attrIter.next();
String attrShortName = TransformationHelper.getSqlEObjectName(attribute);
// If a matching symbol is found, use it in the binding. And remove from working list
IExpression seSymbol = getSymbolWithShortName(attrShortName, workingSymbolList);
if (seSymbol != null) {
bindingList.add(new Binding(attribute, seSymbol));
} else {
bindingList.add(new Binding(attribute));
}
}
// Check the remaining symbols for Procedure InputParameters
if (!workingSymbolList.isEmpty()) {
// Create the SqlList using the left-over (unbound) Sql Symbols
sqlList.addAll(workingSymbolList);
}
}
/**
* Get Symbol from the supplied workingSymbolList, which matches the supplied name. If found, it is removed from the working
* list. If not found, returns null.
*
* @param name the symbolName to find in the supplied symbol list.
* @param workingSymbolList the workingList of symbols to search
* @return the matching symbol from the list, if found. If not found, returns null.
*/
private IExpression getSymbolWithShortName( String name,
List<IExpression> workingSymbolList ) {
IExpression result = null;
Iterator iter = workingSymbolList.iterator();
while (iter.hasNext()) {
IExpression seSymbol = (IExpression)iter.next();
String symbolName = TransformationSqlHelper.getSingleElementSymbolShortName(seSymbol, false);
if (symbolName != null && symbolName.equalsIgnoreCase(name)) {
result = seSymbol;
iter.remove();
break;
}
}
return result;
}
/**
* Get the status string for the current state of the object
*
* @return the current reconciled status
*/
public String getStatus() {
boolean hasUnboundAttributes = hasUnboundBindings();
boolean hasUnmatchedSQL = hasUnmatchedSQL();
boolean hasTypeConflicts = hasTypeConflicts();
String message = IS_RECONCILED_MESSAGE;
if (!modifiedSqlHasProjectedSymbols()) {
message = NO_SQL_PROJECTED_SYMBOLS_MESSAGE;
// There are unmatched SQL Sybmols
} else if (hasUnmatchedSQL) {
// If attributes are unbound, message to bind unbound symbols
if (hasUnboundAttributes) {
message = BIND_ATTRIBUTES_MESSAGE;
// All attributes bound, message to eliminate extra symbols
} else {
message = HAS_UNMATCHED_SQL_MESSAGE;
}
// No unmatched SQL Symbols
} else {
// Unbound attributes, can eliminate them message
if (hasUnboundAttributes) {
message = HAS_UNBOUND_ATTRIBUTES_MESSAGE;
// All attributes bound, check for type conflicts
} else if (hasTypeConflicts) {
message = HAS_TYPE_CONFLICTS_MESSAGE;
}
}
return message;
}
/**
* Get the status type for the current state of the object
*
* @return the current reconciled status type (INFO, WARNING, ERROR, ..)
*/
public int getStatusType() {
int statusType = IMessageProvider.NONE;
boolean hasUnboundAttributes = hasUnboundBindings();
boolean hasUnmatchedSQL = hasUnmatchedSQL();
boolean hasTypeConflicts = hasTypeConflicts();
boolean sqlHasProjectedSymbols = modifiedSqlHasProjectedSymbols();
if (hasUnboundAttributes || hasUnmatchedSQL || hasTypeConflicts || !sqlHasProjectedSymbols) {
statusType = IMessageProvider.ERROR;
}
return statusType;
}
/**
* Get Binding List
*
* @return the list of Bindings for this object
*/
public BindingList getBindingList() {
return bindingList;
}
/**
* Get SQL List
*
* @return the list of SQL symbols for this object
*/
public SqlList getSqlList() {
return sqlList;
}
/**
* Refresh lists
*/
public void refresh() { // NO_UCD
bindingList.refresh(true);
sqlList.refresh(true);
updateCommandFromBindings();
}
/**
* get the current SQL string to display for this object
*
* @return the SQL String to display
*/
public String getOriginalSql() {
return originalCommand.toString();
}
/**
* Add a new binding to the end of the bindings list
*
* @param binding the binding to add
*/
public void addBinding( Binding binding ) {
bindingList.add(binding);
updateCommandFromBindings();
}
/**
* remove the supplied symbol from the symbols list
*
* @param symbol the symbol to remove
*/
public void removeSymbol( IExpression symbol ) {
sqlList.remove(symbol);
updateCommandFromBindings();
}
/**
* add the supplied List of symbols to the symbols list
*
* @param symbols the list of symbols to add
*/
public void addSymbols( List symbols ) {
sqlList.addAll(symbols);
updateCommandFromBindings();
}
/**
* remove the supplied List of symbols from the symbols list
*
* @param symbols the list of symbols to remove
*/
public void removeSymbols( List symbols ) {
sqlList.removeAll(symbols);
updateCommandFromBindings();
}
/**
* determine if any of the current bindings are unbound
*
* @return 'true' if any of the bindings are unbound
*/
public boolean hasUnboundBindings() {
boolean hasUnbound = false;
List bindings = bindingList.getAll();
Iterator iter = bindings.iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
if (!binding.isBound()) {
hasUnbound = true;
break;
}
}
return hasUnbound;
}
/**
* determine if there are any unmatched SQL symbols
*
* @return 'true' if any unmatched sql symbols
*/
public boolean hasUnmatchedSQL() {
return sqlList.size() > 0;
}
/**
* determine if there are any type conflicts
*
* @return 'true' if any type conflicts
*/
public boolean hasTypeConflicts() {
return bindingList.hasTypeConflict();
}
/**
* determine if there are any type conflicts
*
* @return 'true' if any type conflicts
*/
public boolean hasTypeConflict( int index ) { // NO_UCD
boolean hasConflict = false;
if (index >= 0 && index < bindingList.size()) {
Binding binding = bindingList.get(index);
hasConflict = binding.hasTypeConflict();
}
return hasConflict;
}
public void unbind( List bindings ) {
// Save the unbound SQL symbols
List unboundSQL = new ArrayList(bindings.size());
// Iterate and unbind the supplied bindings
Iterator iter = bindings.iterator();
Binding binding = null;
while (iter.hasNext()) {
binding = (Binding)iter.next();
IExpression symbol = binding.getCurrentSymbol();
// Add the current symbol to the list, if not null
if (symbol != null) {
unboundSQL.add(symbol);
}
// Set the binding symbol null
binding.setOriginalSymbol(null);
}
// refresh the binding list
bindingList.refresh(true);
// add the symbols back into the symbols list
addSymbols(unboundSQL);
}
public void bind( List bindings,
List sqlSymbols ) {
Binding binding = null;
IExpression sqlSymbol = null;
if (bindings.size() == sqlSymbols.size()) {
for (int i = 0; i < bindings.size(); i++) {
binding = (Binding)bindings.get(i);
sqlSymbol = (IExpression)sqlSymbols.get(i);
if (binding.getCurrentSymbol() == null) {
binding.setNewSymbol(sqlSymbol);
}
}
}
bindingList.refresh(true);
removeSymbols(sqlSymbols);
}
public void createNewBindings( List<IExpression> sqlSymbols ) {
if (sqlSymbols!=null && !sqlSymbols.isEmpty()) {
for (IExpression symbol : sqlSymbols) {
String symbolShortName = TransformationSqlHelper.getSingleElementSymbolShortName(symbol, false);
if (bindingList.hasRemovedBindingMatch(symbolShortName)) {
Binding removedBinding = bindingList.getRemovedBindingMatch(symbolShortName);
removedBinding.setNewSymbol(symbol);
addBinding(removedBinding);
} else {
Binding newBinding = new Binding(symbolShortName, symbol);
addBinding(newBinding);
}
removeSymbol(symbol);
}
} else {
Shell shell = UiPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow().getShell();
ColumnEntryDialog dialog = new ColumnEntryDialog(shell, NEW_COLUMN_DIALOG_TITLE);
dialog.open();
String newColumnName = dialog.getColumnName();
EObject datatype = dialog.getDatatype();
if (newColumnName != null) {
// no symbol provided, so assume "New"
Binding newBinding = new Binding(newColumnName);
newBinding.setNewAttrDatatype(datatype);
addBinding(newBinding);
}
}
}
public boolean shouldEnableBind( List selectedBindings,
List selectedSymbols ) {
boolean bindEnabled = false;
if (sqlModifiable) {
int nBindings = selectedBindings.size();
int nSymbols = selectedSymbols.size();
if (nBindings > 0 && nSymbols > 0 && nBindings == nSymbols) {
bindEnabled = true;
// All rows must have null symbol values
Iterator iter = selectedBindings.iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
if (binding.getCurrentSymbol() != null) {
bindEnabled = false;
break;
}
}
}
}
return bindEnabled;
}
public boolean shouldEnableUnbind( List selectedBindings ) {
boolean unbindEnabled = false;
if (sqlModifiable) {
if (selectedBindings.size() > 0) {
// At least one Binding must have non-null symbol value to enable
Iterator iter = selectedBindings.iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
if (binding.getCurrentSymbol() != null) {
unbindEnabled = true;
break;
}
}
}
}
return unbindEnabled;
}
public boolean shouldEnableCreateNew( List selectedSymbols ) { // NO_UCD
boolean enableCreate = false;
if (selectedSymbols.size() > 0) {
if (!isTargetLocked()) {
enableCreate = true;
// If any of the selected row names are already in attributes, disable
Iterator iter = selectedSymbols.iterator();
while (iter.hasNext()) {
iter.next();
// SingleElementSymbol symbol = (SingleIElementSymbol)iter.next();
// TableItem item = sqlListPanel.getTableViewer().getTable().getItem(rowIndex);
// Do Not allow creation of duplicate Attribute Names
// if( containsIgnoreCase(getTargetAttributeNamesOrdered(),sqlName) ) {
// enabled=false;
// break;
// }
}
}
}
return enableCreate;
}
/**
* Check whether there are any required mods to the SQL or targetGroup.
*
* @return true if there are pending modifications, false if not.
*/
public boolean hasValidModifications() {
boolean hasMods = false;
// If any of the following have changed, set hasMods to true
if (hasValidSqlModifications() || hasTargetAttributesToDelete() || hasTargetAttributesToCreate()
|| hasTargetAttributesToRename() || hasTargetAttributeTypeMods()) {
hasMods = true;
}
return hasMods;
}
/**
* Check whether there are valid mods to the SQL. The SQL must be different than the original SQL and the modified SQL must
* have at least one projected symbol.
*
* @return true if there are valid modifications, false if not.
*/
public boolean hasValidSqlModifications() {
boolean hasValidSqlMods = false;
if (hasModifiedSql() && modifiedSqlHasProjectedSymbols()) {
hasValidSqlMods = true;
}
return hasValidSqlMods;
}
/**
* Check whether there are any mods to the original SQL.
*
* @return true if there are SQL modifications, false if not.
*/
public boolean hasModifiedSql() {
// Determine if any SQL mods are required
boolean sqlModified = false;
// If SQL Modifiable, compare original command with modified command
if (sqlModifiable && originalCommand != null && modifiedCommand != null) {
String originalSQL = originalCommand.toString();
String modifiedSQL = modifiedCommand.toString();
// If the original Query was SELECT *, expand it for comparison
if (originalCommand instanceof IQueryCommand && isSelectStar((IQueryCommand)originalCommand)) {
originalSQL = expandSelectStar((IQueryCommand)originalCommand);
}
sqlModified = !modifiedSQL.equals(originalSQL);
}
return sqlModified;
}
/**
* Get the modified SQL statement string.
*
* @return the modified Commands SQL text
*/
public String getModifiedSql() {
String sql = null;
if (modifiedCommand != null) {
sql = modifiedCommand.toString();
}
return sql;
}
/**
* Check whether the modified SQL has any projected symbols
*
* @return true if there is one or more projected symbol, false if not.
*/
public boolean modifiedSqlHasProjectedSymbols() {
boolean hasSymbols = false;
if (modifiedCommand != null) {
List symbolList = CommandHelper.getProjectedSymbols(modifiedCommand);
if (symbolList != null && symbolList.size() > 0) {
hasSymbols = true;
}
}
return hasSymbols;
}
/**
* Determine whether the Target Virtual Group is Locked (ReadOnly)
*
* @return 'true' if the transformation target group is Locked (Readonly), 'false' if not.
*/
public boolean isTargetLocked() {
return this.isTargetLocked;
}
/**
* Determine if the supplied symbol is an inputParameter symbol.
*
* @param symbol the IElementSymbol to test.
* @return 'true' if supplied symbol is InputParameter, 'false' if not.
*/
public boolean isInputParameterSymbol( IExpression symbol ) {
boolean isInputParamSymbol = false;
// See if it's in the InputParameter symbol list.
if (this.originalInputParamSymbols.contains(symbol)) {
isInputParamSymbol = true;
}
return isInputParamSymbol;
}
/**
* Set the Target Virtual Group Locked state
*
* @param shouldLock 'true' if the transformation target group is to be Locked (Readonly), 'false' if not.
*/
public void setTargetLocked( boolean shouldLock ) {
// If different than current state, change it.
if (this.isTargetLocked != shouldLock) {
this.isTargetLocked = shouldLock;
}
}
/**
* Tests whether a QueryCommand is a SELECT *.
*
* @return true if the query is a SELECT *, false if not.
*/
private boolean isSelectStar( IQueryCommand queryCommand ) {
boolean isSelectStar = false;
if (queryCommand != null) {
ISelect select = queryCommand.getProjectedQuery().getSelect();
if (select != null) {
isSelectStar = select.isStar();
}
}
return isSelectStar;
}
/**
* Tests whether a QueryCommand is a SELECT DISTINCT.
*
* @return true if the query is a SELECT DISTINCT, false if not.
*/
private boolean isSelectDistinct( IQueryCommand queryCommand ) {
boolean isSelectDistinct = false;
if (queryCommand != null) {
ISelect select = queryCommand.getProjectedQuery().getSelect();
if (select != null) {
isSelectDistinct = select.isDistinct();
}
}
return isSelectDistinct;
}
/**
* Expands a QueryCommand if it has a SELECT *.
*
* @return the modified query string with the SELECT * expanded.
*/
private String expandSelectStar( IQueryCommand queryCommand ) {
IQueryCommand qComm = (IQueryCommand)queryCommand.clone();
if (qComm != null) {
ISelect select = queryCommand.getProjectedQuery().getSelect();
boolean isDistinct = select.isDistinct();
if (select.isStar()) {
// Get the list of SELECT symbols
List symbols = CommandHelper.getProjectedSymbols(queryCommand);
IQueryService queryService = ModelerCore.getTeiidQueryService();
IQueryFactory factory = queryService.createQueryFactory();
ISelect newSelect = factory.createSelect(symbols);
if (isDistinct) {
newSelect.setDistinct(isDistinct);
}
queryCommand.getProjectedQuery().setSelect(newSelect);
}
}
return qComm.toString();
}
/**
* determine if any of the bindings with attributes have pending name changes
*
* @return 'true' if pending attribute name changes, 'false' if not.
*/
public boolean hasTargetAttributesToRename() {
boolean hasNameChange = false;
if (!isTargetLocked()) {
Iterator iter = bindingList.getAll().iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
if (binding.hasAttrNameModification()) {
hasNameChange = true;
break;
}
}
}
return hasNameChange;
}
/**
* apply all pending pending name changes
*/
public void applyTargetAttributeRenames( Object txnSource ) {
if (!isTargetLocked()) {
Iterator iter = bindingList.getAll().iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
if (binding.hasAttrNameModification()) {
binding.applyAttrNameModification(txnSource);
}
}
}
}
/**
* determine if any of the bindings with attributes have pending type mods
*
* @return 'true' if pending attribute type changes, 'false' if not.
*/
public boolean hasTargetAttributeTypeMods() {
boolean hasTypeChange = false;
if (!isTargetLocked()) {
Iterator iter = bindingList.getAll().iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
if (binding.hasAttrTypeModification()) {
hasTypeChange = true;
break;
}
}
}
return hasTypeChange;
}
/**
* apply all pending pending type changes
*/
public void applyTargetAttributeTypeMods( Object txnSource ) {
if (!isTargetLocked()) {
Iterator iter = bindingList.getAll().iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
if (binding.hasAttrTypeModification()) {
binding.applyAttrTypeModification(txnSource);
}
}
}
}
/**
* Check whether there are any new Attributes to Create.
*
* @return true if there are attributes to create, false if not.
*/
public boolean hasTargetAttributesToCreate() {
boolean hasNew = false;
if (!isTargetLocked()) {
Iterator iter = bindingList.getAll().iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
Object attr = binding.getAttribute();
if (attr instanceof String) {
hasNew = true;
break;
}
}
}
return hasNew;
}
/**
* Get the list of Target Attributes to Create.
*
* @return the List of attribute names to create.
*/
public List getTargetAttributeNamesToCreate() {
if (isTargetLocked()) {
return Collections.EMPTY_LIST;
}
ArrayList newAttrNames = new ArrayList();
Iterator iter = bindingList.getAll().iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
Object attr = binding.getAttribute();
if (attr instanceof String) {
newAttrNames.add(attr);
}
}
return newAttrNames;
}
/**
* Get the Map of attribute name - to - type length for the attributes that are to be created.
*
* @return the Map of attribute names (key) to length (value).
*/
public Map getCreatedAttrLengthMap() {
// empty Map returned if target group is locked
if (isTargetLocked()) {
return Collections.EMPTY_MAP;
}
// Iterate thru the bindings
Map symbolLengthMap = new HashMap();
Iterator iter = bindingList.getAll().iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
// Get the binding attribute
Object attr = binding.getAttribute();
// If binding attribute is a string, then it's to be created new
if (attr instanceof String) {
// Get length for the bound symbol & put key-value into the Map
int length = binding.getCurrentSymbolLength();
symbolLengthMap.put(attr, new Integer(length));
}
}
return symbolLengthMap;
}
/**
* Check whether there are any Target Attributes to Delete.
*
* @return true if there are attributes to delete, false if not.
*/
public boolean hasTargetAttributesToDelete() {
boolean hasDeleteAttr = false;
if (!isTargetLocked()) {
List deletedBindings = bindingList.getRemovedList();
Iterator iter = deletedBindings.iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
Object attr = binding.getAttribute();
if (!(attr instanceof String)) {
hasDeleteAttr = true;
break;
}
}
}
return hasDeleteAttr;
}
/**
* Get the List of Target Attributes to Delete.
*
* @return the list of attributes to delete.
*/
public List getTargetAttributesToDelete() {
List attrs = new ArrayList();
if (!isTargetLocked()) {
List deletedBindings = bindingList.getRemovedList();
Iterator iter = deletedBindings.iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
Object attr = binding.getAttribute();
if (!(attr instanceof String)) {
attrs.add(attr);
}
}
}
return attrs;
}
/**
* Update the Modified Query using the current state of the Bindings
*/
public void updateCommandFromBindings() {
// Working list of unmatched SQL Symbols
List unmatchedSymbols = new ArrayList();
unmatchedSymbols.addAll(sqlList.getAll());
// List to hold the resulting symbols
ArrayList newSymbols = new ArrayList();
// -----------------------------
// Iterate thru the Bindings
// -----------------------------
Iterator iter = bindingList.getAll().iterator();
while (iter.hasNext()) {
Binding binding = (Binding)iter.next();
// --------------------------------------------------------------
// Bound - get the Symbol from the binding
// --------------------------------------------------------------
if (binding.isBound() && !binding.isInputParamBinding()) {
IExpression symbol = binding.createBindingSymbol();
if (!isInputParameterSymbol(symbol)) {
newSymbols.add(binding.createBindingSymbol());
}
// --------------------------------------------------------------
// Unbound - use seSymbol from the unmatched Symbol List
// --------------------------------------------------------------
} else {
// current attribute name
String attrName = binding.getCurrentAttrName();
// See if there is a matching symbol in the unmatched working list
IExpression seSymbol = getSymbolWithShortName(attrName, unmatchedSymbols);
if (seSymbol != null && !isInputParameterSymbol(seSymbol)) {
newSymbols.add(seSymbol);
} else {
if (!unmatchedSymbols.isEmpty()) {
seSymbol = (IExpression)unmatchedSymbols.get(0);
if (seSymbol != null && !isInputParameterSymbol(seSymbol)) {
newSymbols.add(seSymbol);
}
unmatchedSymbols.remove(0);
}
}
}
}
// Ensure that the "Removed SQL symbols" have been removed from the working list
// List removedSymbols = sqlList.getRemovedList();
// unmatchedSymbols.removeAll(removedSymbols);
// If there are unmatched symbols remaining, add them
iter = unmatchedSymbols.iterator();
while (iter.hasNext()) {
IExpression sym = (IExpression)iter.next();
if (sym != null && !isInputParameterSymbol(sym)) {
newSymbols.add(sym);
}
}
// Use the new list of symbols to update the modified Query
IQueryService queryService = ModelerCore.getTeiidQueryService();
IQueryFactory factory = queryService.createQueryFactory();
ISelect newSelect = factory.createSelect(newSymbols);
if (this.isSelectDistinct) {
newSelect.setDistinct(true);
}
if (modifiedCommand instanceof IQuery) {
((IQuery)modifiedCommand).setSelect(newSelect);
} else if (modifiedCommand instanceof ISetQuery) {
((ISetQuery)modifiedCommand).getProjectedQuery().setSelect(newSelect);
}
}
public List getOriginalSymbols() {
return this.originalSymbols;
}
public ICommand getModifiedCommand() {
return modifiedCommand;
}
public ICommand getOriginalCommand() {
return originalCommand;
}
/**
* Returns a Collection of Group symbols that are NOT referenced by ElementSymbols within a Query command
*
* @return
* @since 5.0
*/
public Collection getUnreferencedGroupSymbols() {
Collection allGroupSymbols = TransformationSqlHelper.getGroupSymbols(originalCommand);
Collection unreferencedGroupSymbols = new ArrayList(allGroupSymbols);
// Let's get list of all Element symbols...
IQueryService queryService = ModelerCore.getTeiidQueryService();
IElementCollectorVisitor elementCollectorVisitor = queryService.getElementCollectorVisitor(true);
Collection referencedElementSymbols = elementCollectorVisitor.findElements(originalCommand, true);
Iterator iter = referencedElementSymbols.iterator();
while (iter.hasNext()) {
IExpression nextSymbol = (IExpression)iter.next();
if (nextSymbol instanceof IAliasSymbol) {
IExpression theSymbol = ((IAliasSymbol)nextSymbol).getSymbol();
if (theSymbol instanceof IElementSymbol) {
IGroupSymbol nextGS = ((IElementSymbol)theSymbol).getGroupSymbol();
if (TransformationSqlHelper.containsGroupSymbol(allGroupSymbols, nextGS)) {
unreferencedGroupSymbols.remove(nextGS);
}
}
} else if (nextSymbol instanceof IElementSymbol) {
IGroupSymbol nextGS = ((IElementSymbol)nextSymbol).getGroupSymbol();
if (TransformationSqlHelper.containsGroupSymbol(allGroupSymbols, nextGS)) {
unreferencedGroupSymbols.remove(nextGS);
}
}
}
return unreferencedGroupSymbols;
}
/**
* Returns a Collection of Group symbols that are actually referenced by ElementSymbols within a Query command
*
* @return
* @since 5.0
*/
public Collection getReferencedGroupSymbols() {
Collection allGroupSymbols = TransformationSqlHelper.getGroupSymbols(originalCommand);
Collection referencedGroupSymbols = new ArrayList(allGroupSymbols.size());
Iterator iter = originalSymbols.iterator();
while (iter.hasNext()) {
IExpression nextSymbol = (IExpression)iter.next();
if (nextSymbol instanceof IAliasSymbol) {
IExpression theSymbol = ((IAliasSymbol)nextSymbol).getSymbol();
if (theSymbol instanceof IElementSymbol) {
IGroupSymbol nextGS = ((IElementSymbol)theSymbol).getGroupSymbol();
if (!TransformationSqlHelper.containsGroupSymbol(referencedGroupSymbols, nextGS)) {
referencedGroupSymbols.add(nextGS);
}
}
} else if (nextSymbol instanceof IElementSymbol) {
IGroupSymbol nextGS = ((IElementSymbol)nextSymbol).getGroupSymbol();
if (!TransformationSqlHelper.containsGroupSymbol(referencedGroupSymbols, nextGS)) {
referencedGroupSymbols.add(nextGS);
}
}
}
return referencedGroupSymbols;
}
/**
* Returns a list of ALL element symbols available for a Query command based on existing GROUP symbols in the Query
*
* @return
* @since 5.0
*/
public List getAvailableElementSymbols() {
List availableSymbolList = new ArrayList();
Collection groupSymbols = TransformationSqlHelper.getGroupSymbols(originalCommand);
if (!groupSymbols.isEmpty()) {
// Now we need to create Element Symbols for ALL unused group symbols
List extraGroupEObjects = TransformationSqlHelper.getGroupSymbolEObjects(groupSymbols);
for (Iterator iter = extraGroupEObjects.iterator(); iter.hasNext();) {
EObject nextGroup = (EObject)iter.next();
SqlAlias sqlAlias = TransformationFactory.eINSTANCE.createSqlAlias();
sqlAlias.setAliasedObject(nextGroup);
String aliasName = TransformationHelper.getSqlEObjectFullName(nextGroup);
sqlAlias.setAlias(aliasName);
List newElementSymbols = TransformationSqlHelper.createElemSymbols(sqlAlias);
if (!newElementSymbols.isEmpty()) {
availableSymbolList.addAll(newElementSymbols);
}
}
}
return availableSymbolList;
}
}