/*
* 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.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.emf.ecore.EObject;
import org.teiid.designer.core.metamodel.aspect.sql.SqlColumnAspect;
/**
* BindingList class - for maintaining the list of attribute - SQL Symbol bindings.
*
*
* @since 8.0
*/
public class BindingList {
private final int COUNT = 10;
private List<Binding> bindings = new ArrayList<Binding>(COUNT);
private List removedBindings = new ArrayList();
private Set<IBindingListViewer> changeListeners = new HashSet<IBindingListViewer>();
/**
* Constructor
*/
public BindingList() {
}
/**
* Return the Binding at the supplied index
* @param index the list index
* @return the binding at the supplied index
*/
public Binding get(int index) {
if(index>=0 && index<bindings.size()) {
return bindings.get(index);
}
return null;
}
/**
* Return the List of all bindings
* @return the list of Binding objects
*/
public List getAll() {
return bindings;
}
/**
* Return the List of bindings which have been removed from the main list, but
* saved for reuse.
* @return the list of removed Bindings
*/
public List getRemovedList() {
return removedBindings;
}
/**
* Return the number of bindings
*/
public int size() {
return bindings.size();
}
/**
* Return whether any of the bindings is bound and has a type conflict.
* @return 'true' if isBound and the types conflict.
*/
public boolean hasTypeConflict() {
boolean hasConflict = false;
Iterator iter = bindings.iterator();
while(iter.hasNext()) {
Binding binding = (Binding)iter.next();
if( binding.hasTypeConflict() ) {
hasConflict = true;
break;
}
}
return hasConflict;
}
/**
* Add a new Binding to the list
* @param binding the binding to add
*/
public void add(Binding binding) {
bindings.add(bindings.size(), binding);
Iterator<IBindingListViewer> iterator = changeListeners.iterator();
while (iterator.hasNext())
iterator.next().addBinding(binding);
}
/**
* Add a List of bindings to the binding list.
* @param bindings the list of Binding object to add
*/
public void addAll(List bindings) {
Iterator iter = bindings.iterator();
while(iter.hasNext()) {
add((Binding)iter.next());
}
}
/**
* Insert a new Binding at the specified index
* @param binding the binding to insert.
* @param index the index location for insertion
*/
public void insert(Binding binding,int index) {
bindings.add(index, binding);
Iterator<IBindingListViewer> iterator = changeListeners.iterator();
while (iterator.hasNext())
iterator.next().insertBinding(binding,index);
}
/**
* Remove the supplied binding from the binding list
* @param binding the binding to remove
*/
public void remove(Binding binding) {
bindings.remove(binding);
if(!removedBindings.contains(binding)) {
removedBindings.add(binding);
}
Iterator<IBindingListViewer> iterator = changeListeners.iterator();
while (iterator.hasNext())
iterator.next().removeBinding(binding);
}
/**
* Remove the supplied list of bindings from the binding list
* @param bindings the bindings to remove
*/
public void removeAll(List bindings) {
Iterator iter = bindings.iterator();
while(iter.hasNext()) {
remove((Binding)iter.next());
}
}
/**
* Method to determine if there is a removed binding whose attribute name matches the supplied name.
* @param attrName the supplied attribute name
* @return 'true' if the removeList has a matching Binding, 'false' if not.
*/
public boolean hasRemovedBindingMatch(String attrName) {
boolean hasMatch = false;
Iterator iter = removedBindings.iterator();
while(iter.hasNext()) {
Binding binding = (Binding)iter.next();
Object attr = binding.getAttribute();
if( attr!=null && (attr instanceof EObject) && org.teiid.designer.core.metamodel.aspect.sql.SqlAspectHelper.isColumn((EObject)attr) ) {
SqlColumnAspect columnAspect = (SqlColumnAspect)org.teiid.designer.core.metamodel.aspect.sql.SqlAspectHelper.getSqlAspect((EObject)attr);
String currentName = columnAspect.getName((EObject)attr);
if(currentName!=null && currentName.equalsIgnoreCase(attrName)) {
hasMatch = true;
break;
}
}
}
return hasMatch;
}
/**
* Remove the binding in the removed list whose attribute name matches the supplied name.
* @param attrName the supplied attribute name
* @return the removed Binding, null if not found.
*/
public Binding getRemovedBindingMatch(String attrName) {
int bindingIndex = -1;
Binding bindingMatch = null;
for(int i=0; i<removedBindings.size(); i++) {
Binding binding = (Binding)removedBindings.get(i);
Object attr = binding.getAttribute();
if( attr!=null && (attr instanceof EObject) && org.teiid.designer.core.metamodel.aspect.sql.SqlAspectHelper.isColumn((EObject)attr) ) {
SqlColumnAspect columnAspect = (SqlColumnAspect)org.teiid.designer.core.metamodel.aspect.sql.SqlAspectHelper.getSqlAspect((EObject)attr);
String currentName = columnAspect.getName((EObject)attr);
if(currentName!=null && currentName.equalsIgnoreCase(attrName)) {
bindingIndex = i;
break;
}
}
}
if(bindingIndex>=0) {
bindingMatch = (Binding)removedBindings.remove(bindingIndex);
}
return bindingMatch;
}
/**
* Method to notify that the supplied binding has changed
* @param binding that changed.
*/
public void bindingChanged(Binding binding) {
Iterator<IBindingListViewer> iterator = changeListeners.iterator();
while (iterator.hasNext())
iterator.next().updateBinding(binding);
}
/**
* Method to notify that a refresh is required
* @param updateLabels 'true' if label update is required, 'false' if not.
*/
public void refresh(boolean updateLabels) {
Iterator<IBindingListViewer> iterator = changeListeners.iterator();
while (iterator.hasNext())
iterator.next().refresh(updateLabels);
}
/**
* Get the index of a binding in the list
* @param binding the Binding to find the index for
* @return the index of the binding, -1 if not found.
*/
public int indexOf(Binding binding) {
return bindings.indexOf(binding);
}
/**
* Get the first Unbound binding in the list
* @return the first unbound binding in the List, null if none exist
*/
public Binding getFirstUnbound() {
Binding result = null;
// Iterate and find the first unbound
Iterator iter = bindings.iterator();
while(iter.hasNext()) {
Binding binding = (Binding)iter.next();
if(!binding.isBound()) {
result = binding;
break;
}
}
return result;
}
/**
* Get the first Bound binding in the list
* @return the first bound binding in the List, null if none exist
*/
public Binding getFirstBound() {
Binding result = null;
// Iterate and find the first bound
Iterator iter = bindings.iterator();
while(iter.hasNext()) {
Binding binding = (Binding)iter.next();
if(binding.isBound()) {
result = binding;
break;
}
}
return result;
}
/**
* Get the first binding in the list with a type conflict
* @return the first binding in the List with a type conflict, null if none exist
*/
public Binding getFirstTypeConflict() {
Binding result = null;
// Iterate and find the first bound
Iterator iter = bindings.iterator();
while(iter.hasNext()) {
Binding binding = (Binding)iter.next();
if(binding.hasTypeConflict()) {
result = binding;
break;
}
}
return result;
}
/**
* Get the next Unbound binding in the list, after the supplied Binding
* @param the supplied binding
* @return the next unbound binding in the List, null if none exist
*/
public Binding getNextUnbound(Binding binding) {
Binding result = null;
// Index of the supplied binding
int index = indexOf(binding);
// Look from the current index to the end of the list
for(int i=index+1; i<size(); i++) {
Binding nextBinding = bindings.get(i);
if(!nextBinding.isBound()) {
result = nextBinding;
break;
}
}
// If not found so far, start at the top
if(result==null) {
return getFirstUnbound();
}
return result;
}
/**
* Get the next Bound binding in the list, after the supplied Binding
* @param the supplied binding
* @return the next bound binding in the List, null if none exist
*/
public Binding getNextBound(Binding binding) {
Binding result = null;
// Index of the supplied binding
int index = indexOf(binding);
// Look from the current index to the end of the list
for(int i=index+1; i<size(); i++) {
Binding nextBinding = bindings.get(i);
if(nextBinding.isBound()) {
result = nextBinding;
break;
}
}
// If not found so far, start at the top
if(result==null) {
return getFirstBound();
}
return result;
}
/**
* Get the next binding with a type conflict in the list, after the supplied Binding
* @param the supplied binding
* @return the next binding with a type Conflict in the List, null if none exist
*/
public Binding getNextTypeConflict(Binding binding) {
Binding result = null;
// Index of the supplied binding
int index = indexOf(binding);
// Look from the current index to the end of the list
for(int i=index+1; i<size(); i++) {
Binding nextBinding = bindings.get(i);
if(nextBinding.hasTypeConflict()) {
result = nextBinding;
break;
}
}
// If not found so far, start at the top
if(result==null) {
return getFirstTypeConflict();
}
return result;
}
/**
* Move a Binding up in the list
* @param binding the binding to move down
*/
public void moveUp(Binding binding) {
int currentIndex = indexOf(binding);
if(currentIndex>0) {
Binding removedBinding = bindings.remove(currentIndex);
bindings.add(--currentIndex,removedBinding);
refresh(true);
}
}
/**
* Move a Binding up to top of the list
* @param binding the binding to move to top
*/
public void moveTop(Binding binding) {
int currentIndex = indexOf(binding);
if(currentIndex>0) {
Binding removedBinding = bindings.remove(currentIndex);
bindings.add(0,removedBinding);
refresh(true);
}
}
/**
* Move a Binding up to top of the list
* @param binding the binding to move to top
*/
public void moveBottom(Binding binding) {
int currentIndex = indexOf(binding);
if(currentIndex>-1 && currentIndex<bindings.size()-1) {
Binding removedBinding = bindings.remove(currentIndex);
bindings.add(removedBinding);
refresh(true);
}
}
/**
* Move a Binding down in the list
* @param binding the binding to move down
*/
public void moveDown(Binding binding) {
int index = indexOf(binding);
if(index>-1 && index<bindings.size()-1) {
Binding removedBinding = bindings.remove(index);
bindings.add(++index,removedBinding);
refresh(true);
}
}
/**
* Swap Bindings in the list
* @param binding1 the binding to swap with the second binding
* @param binding2 the binding to swap with the first binding
*/
public void swap(Binding binding1, Binding binding2) {
int index1 = indexOf(binding1);
int index2 = indexOf(binding2);
if(index1>-1 && index2>-1) {
Binding obj1 = bindings.get(index1);
Binding obj2 = bindings.get(index2);
bindings.set(index2,obj1);
bindings.set(index1,obj2);
refresh(true);
}
}
/**
* Remove the ChangeListener
* @param viewer the change listener to remove
*/
public void removeChangeListener(IBindingListViewer viewer) {
changeListeners.remove(viewer);
}
/**
* Add the supplied ChangeListener
* @param viewer the change listener to add
*/
public void addChangeListener(IBindingListViewer viewer) {
changeListeners.add(viewer);
}
}