package icsDyn;
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Vector;
import javax.swing.AbstractListModel;
import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JOptionPane;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.tree.DefaultMutableTreeNode;


/**
 * This calss allows the user selecting attributes to add or to remove from an object
 * @author  Rick Rivello
 */
public class AddRemoveAttr extends JPanel implements ActionListener, Observer{

  private static final long serialVersionUID = 1L;

  private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0);
  private static final String ADD_BUTTON_LABEL = "Add >>";
  private static final String REMOVE_BUTTON_LABEL = "<< Remove";
  private static final String DEFAULT_SOURCE_CHOICE_LABEL = "Available Attributes";
  private static final String DEFAULT_DEST_CHOICE_LABEL = "Attributes Selected";
  private JLabel sourceLabel;
  private JList sourceList;
  private SortedListModel sourceListModel;
  private JList destList;
  private SortedListModel destListModel;
  private JLabel destLabel;
  private JButton addButton;
  private JButton removeButton;
  private JButton btnClose;
  private JButton btnAddChanges;
  private JButton btnAddPrivateAtt;
  private JFrame f;

  private ICSModel icsModel;
 
  Vector dynattrs;
  Vector defattrs;
  MOCNode tempmoc;
  MOCNode defmocnode;
  MOCNode dynmocnode;
  DefaultMutableTreeNode cNode;
  
  Vector<AttributeNode> vectPrivateAttr;

  String[] selectedDyn;
  
  private Component parent;

  public AddRemoveAttr(Component p) {
	  parent = p;
	  vectPrivateAttr = new Vector<AttributeNode>();
    init();
  }

  public void setICSModel (ICSModel model) {
    icsModel = model;
    icsModel.addObserver(this);
  }

  public void mn(AddRemoveAttr attributes, Vector dynvmoc, Vector defvmoc,DefaultMutableTreeNode currentNode) {

    f = new JFrame("Attribute List ");
    f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    f.setLocationRelativeTo(parent);
    cNode = currentNode;

    MOCNode tempmoc = icsModel.getMOCNode();

    dynattrs = null;
    defattrs = null;


    // we initialize the source attributes
    int index = defvmoc.indexOf(tempmoc);
    if (index != -1) {
       defmocnode = (MOCNode) defvmoc.get(index);
       defattrs = defmocnode.getAttribute();
        
	    for (int i = 0; i < defattrs.size(); i++) {
	       DIMMOC obj = (DIMMOC) defattrs.get(i);
	       if(obj != null){
	    	   attributes.addSourceElements(new String[] {obj.getAttributeName()});
	    	   
	       }
	    }
    }

    int mocIdNumber = tempmoc.getMocIdNumber();    
    index = dynvmoc.indexOf(tempmoc);
    MOCNode dynmocnode = (MOCNode) dynvmoc.get(index);
    int tempmocIdNumber = dynmocnode.getMocIdNumber();

    while (tempmocIdNumber != mocIdNumber) {
       index = dynvmoc.indexOf(tempmoc,index+1);
       dynmocnode = (MOCNode) dynvmoc.get(index);
       tempmocIdNumber = dynmocnode.getMocIdNumber();
    }   
    dynattrs = dynmocnode.getAttribute();
 
    // we initialize the selected attribbutes
    selectedDyn = new String[dynattrs.size()];
    for (int i = 0; i < dynattrs.size(); i++) {
       attributes.addDestinationElements(new String[] {((DIMMOC) dynattrs.get(i)).getAttributeName()});
       selectedDyn[i] = ((DIMMOC) dynattrs.get(i)).getAttributeName();
       sourceListModel.removeElement(selectedDyn[i]);  
       
       
       // we initialize also the selected private attributes
       DIMMOC obj = (DIMMOC) dynattrs.get(i);
       if(obj != null){
    	   if(obj.isPrivate){
    		   ((MyListRenderer)destList.getCellRenderer()).addPrivate(obj.attribute_name);
    	   }
       }
    }
    sourceList.getSelectionModel().clearSelection();

    f.getContentPane().add(attributes, BorderLayout.CENTER);
    f.setSize(400, 300);
    f.setVisible(true);
}

  public String getSourceChoicesTitle() {
    return sourceLabel.getText();
  }

  public void setSourceChoicesTitle(String newValue) {
    sourceLabel.setText(newValue);
  }

  public String getDestinationChoicesTitle() {
    return destLabel.getText();
  }

  public void setDestinationChoicesTitle(String newValue) {
    destLabel.setText(newValue);
  }

  public void clearSourceListModel() {
    sourceListModel.clear();
  }

  public void clearDestinationListModel() {
    destListModel.clear();
  }

  public void addSourceElements(ListModel newValue) {
    fillListModel(sourceListModel, newValue);
  }

  public void setSourceElements(ListModel newValue) {
    clearSourceListModel();
    addSourceElements(newValue);
  }

  public void addDestinationElements(ListModel newValue) {
    fillListModel(destListModel, newValue);
  }

  private void fillListModel(SortedListModel model, ListModel newValues) {
    int size = newValues.getSize();
    for (int i = 0; i < size; i++) {
      model.add(newValues.getElementAt(i));
    }
  }

  public void addSourceElements(Object newValue[]) {
    fillListModel(sourceListModel, newValue);
  }

  public void setSourceElements(Object newValue[]) {
    clearSourceListModel();
    addSourceElements(newValue);
  }

  public void addDestinationElements(Object newValue[]) {
    fillListModel(destListModel, newValue);
  }

  private void fillListModel(SortedListModel model, Object newValues[]) {  
    model.addAll(newValues);
  }

  public Iterator sourceIterator() {
    return sourceListModel.iterator();
  }

  public Iterator destinationIterator() {
    return destListModel.iterator();
  }

  public void setSourceCellRenderer(ListCellRenderer newValue) {
    sourceList.setCellRenderer(newValue);
  }

  public ListCellRenderer getSourceCellRenderer() {
    return sourceList.getCellRenderer();
  }

  public void setDestinationCellRenderer(ListCellRenderer newValue) {
    destList.setCellRenderer(newValue);
  }

  public ListCellRenderer getDestinationCellRenderer() {
    return destList.getCellRenderer();
  }

  public void setVisibleRowCount(int newValue) {
    sourceList.setVisibleRowCount(newValue);
    destList.setVisibleRowCount(newValue);
  }

  public int getVisibleRowCount() {
    return sourceList.getVisibleRowCount();
  }

  public void setSelectionBackground(Color newValue) {
    sourceList.setSelectionBackground(newValue);
    destList.setSelectionBackground(newValue);
  }

  public Color getSelectionBackground() {
    return sourceList.getSelectionBackground();
  }

  public void setSelectionForeground(Color newValue) {
    sourceList.setSelectionForeground(newValue);
    destList.setSelectionForeground(newValue);
  }

  public Color getSelectionForeground() {
    return sourceList.getSelectionForeground();
  }

  private void clearSourceSelected() {
    Object selected[] = sourceList.getSelectedValues();
    for (int i = selected.length - 1; i >= 0; --i) {
      sourceListModel.removeElement(selected[i]);
    }
    sourceList.getSelectionModel().clearSelection();
  }

  private void clearDestinationSelected() {
    Object selected[] = destList.getSelectedValues();
    for (int i = selected.length - 1; i >= 0; --i) {
      destListModel.removeElement(selected[i]);
    }
    destList.getSelectionModel().clearSelection();
  }

  private void init() {

    setLayout(new GridBagLayout());
    
    JPanel p0 = new JPanel();
    
    MyListRenderer listRenderer = new MyListRenderer();
   
    p0.setLayout(new GridBagLayout());
    sourceLabel = new JLabel(DEFAULT_SOURCE_CHOICE_LABEL);
    sourceListModel = new SortedListModel();
    sourceList = new JList(sourceListModel);
    sourceList.setCellRenderer(listRenderer);
    p0.add(sourceLabel, new GridBagConstraints(0, 0, 1, 1, 0, 0,
        GridBagConstraints.CENTER, GridBagConstraints.NONE,
        EMPTY_INSETS, 0, 0));
    p0.add(new JScrollPane(sourceList), new GridBagConstraints(0, 1, 1, 5, .5,
        1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
        EMPTY_INSETS, 0, 0));

    
    
    addButton = new JButton(ADD_BUTTON_LABEL);
    p0.add(addButton, new GridBagConstraints(1, 2, 1, 2, 0, .25,
        GridBagConstraints.CENTER, GridBagConstraints.NONE,
        EMPTY_INSETS, 0, 0));
    addButton.addActionListener(this);
    removeButton = new JButton(REMOVE_BUTTON_LABEL);
    p0.add(removeButton, new GridBagConstraints(1, 4, 1, 2, 0, .25,
        GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(
            0, 5, 0, 5), 0, 0));
    removeButton.addActionListener(this);
    
    

    destLabel = new JLabel(DEFAULT_DEST_CHOICE_LABEL);
    destListModel = new SortedListModel();
    destList = new JList(destListModel);
       
    
    destList.setCellRenderer(listRenderer);
    
    
    p0.add(destLabel, new GridBagConstraints(2, 0, 1, 1, 0, 0,
        GridBagConstraints.CENTER, GridBagConstraints.NONE,
        EMPTY_INSETS, 0, 0));
    p0.add(new JScrollPane(destList), new GridBagConstraints(2, 1, 1, 5, .5,
        1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
        EMPTY_INSETS, 0, 0));
    
    add(p0, new GridBagConstraints(0,0,GridBagConstraints.REMAINDER, 1,
    		0,1,GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH, new Insets(5,5,5,5),0,0));
    
    JPanel p1 = new JPanel();
    p1.setLayout(new GridBagLayout());
    btnAddChanges = new JButton("Add changes");
    btnAddPrivateAtt = new JButton("<html>Add Private Attribute...</html>");
    btnClose = new JButton("Close");
    btnAddChanges.addActionListener(this);
    btnAddPrivateAtt.addActionListener(this);
    btnClose.addActionListener(this);
    btnAddChanges.setBackground(new Color(204, 204, 255));
    btnAddPrivateAtt.setBackground(new Color(204, 204, 255));
    btnClose.setBackground(new Color(204, 204, 255));
    
    btnAddPrivateAtt.setForeground(Color.red);
    btnAddChanges.setPreferredSize(new Dimension(110, 30));
    btnClose.setPreferredSize(new Dimension(110,30));
    btnAddPrivateAtt.setPreferredSize(new Dimension(110, 40));
    p1.add(btnAddChanges, new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.WEST,
    		GridBagConstraints.NONE, new Insets(5,5,5,5),0,0));
    
    p1.add(btnClose, new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.EAST,
    		GridBagConstraints.NONE, new Insets(5,5,5,5),0,0));
    p1.add(btnAddPrivateAtt, new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.CENTER,
    		GridBagConstraints.NONE, new Insets(5,5,5,5),0,0));
    p1.setBorder(BorderFactory.createEtchedBorder());
    add(p1, new GridBagConstraints(GridBagConstraints.RELATIVE,GridBagConstraints.RELATIVE,1,1,1,0,GridBagConstraints.NORTHWEST,
    		GridBagConstraints.BOTH, new Insets(5,5,5,5),0,0)); 

   }
 
  public void processUpdate() {

     String dynstring;
     String selectedString;

     int compareint;

     int dynlen = dynattrs.size();
     

     String[] attrSelected = new String[destListModel.getSize() - vectPrivateAttr.size()];
     
     int k = 0;
     for (int i = 0; i < destListModel.getSize(); i++) {
    	 boolean isPrivate = false;
        for(int j = 0; j < vectPrivateAttr.size(); j++)
        {
        	AttributeNode att = (AttributeNode)vectPrivateAttr.get(j);
    
        	if(att.attribute_name.equals((String) destListModel.getElementAt(i)))
        	{
        		isPrivate = true;
        		j = vectPrivateAttr.size();
        	}
        }
        if(!isPrivate){
        	attrSelected[k] = ((String) destListModel.getElementAt(i));
        	k++;
        	}
     }

     int selectedlen = attrSelected.length;
    
     int dyncnt = 0;
     int selectedcnt = 0;

     String[] dynattrsArray = new String[dynattrs.size()]; // contain old attributes
     
     for (int i = 0;i < dynattrs.size();i++) {
         dynattrsArray[i] = dynattrs.get(i).toString();
     }
     Arrays.sort(dynattrsArray);
     Arrays.sort(attrSelected);

     MOCNode mocNode = icsModel.getMOCNode();

     int mocIdNumber = mocNode.getMocIdNumber();
     int inx = icsModel.getcurVMoc().indexOf(mocNode);    		     
     MOCNode vmocNode = (MOCNode)icsModel.getcurVMoc().get(inx);
     int tempmocIdNumber = vmocNode.getMocIdNumber();

     // we look for the correspondant MOC
     while (tempmocIdNumber != mocIdNumber) {
        inx = icsModel.getcurVMoc().indexOf(mocNode,inx+1);
        vmocNode = (MOCNode)icsModel.getcurVMoc().get(inx);
        tempmocIdNumber = vmocNode.getMocIdNumber();
     }    
    
     while (dyncnt < dynlen && selectedcnt < selectedlen) {

        dynstring = dynattrsArray[dyncnt];
        selectedString = attrSelected[selectedcnt];
        compareint = dynstring.compareTo(selectedString);

        if (compareint < 0) {
           dyncnt = dyncnt + 1;             
           deleteVector(vmocNode,dynstring);
        }
        else if (compareint > 0) {
           // add vector
           addVector(vmocNode,selectedString);
           selectedcnt = selectedcnt +1;      
        }
        else {
           dyncnt = dyncnt + 1;
           selectedcnt = selectedcnt + 1;
        }
     }
     if (dyncnt < dynlen) {
        for (int i = dyncnt; i < dynlen; i++) {
           dynstring = dynattrsArray[dyncnt];
           deleteVector(vmocNode,dynstring);
        }
     }
     else if (selectedcnt < selectedlen) {
        for (int i = selectedcnt; i < selectedlen; i++) {
           selectedString = attrSelected[selectedcnt];
           addVector(vmocNode,selectedString);
           selectedcnt = selectedcnt + 1;
        }
     }
     
     for(int i = 0; i < vectPrivateAttr.size(); i++){
	    	 AttributeNode attr = (AttributeNode)vectPrivateAttr.get(i);
	    	 vmocNode.addAttribute(attr);
     }
     
     icsModel.fireEvent(new MVCArg("node",vmocNode));
  }

  public void addVector(MOCNode mnode, String vecToBeAdded) {

     Vector vmocDef = icsModel.getVMoc();
     
     MOCNode tempmoc = icsModel.getMOCNode();

     int index = vmocDef.indexOf(tempmoc);

     MOCNode mocNode = (MOCNode) vmocDef.get(index);
     Vector mocAttrs = mocNode.getAttribute();

       
        for (int i = 0; i < mocAttrs.size(); i++) {
           if (vecToBeAdded.equals(((DIMMOC) mocAttrs.get(i)).getAttributeName())) {
              AttributeNode newAttr = new AttributeNode();
              newAttr.setAttributeName(((AttributeNode) mocAttrs.get(i)).getAttributeName());
              newAttr.setAttributeGroupName(((AttributeNode) mocAttrs.get(i)).getAttributeGroupName());
              newAttr.setAttributeGroupId(((AttributeNode) mocAttrs.get(i)).getAttributeGroupId());
              newAttr.setAttributeGroupTermCode(((AttributeNode) mocAttrs.get(i)).getAttributeGroupTermCode());
              newAttr.setAttributeDerivedFrom(((AttributeNode) mocAttrs.get(i)).getAttributeDerivedFrom());
              newAttr.setAttributeKeyNumber(((AttributeNode) mocAttrs.get(i)).getAttributeKeyNumber());
              newAttr.setAttributeId(((AttributeNode) mocAttrs.get(i)).getAttributeId());
              newAttr.setAttributeType(((AttributeNode) mocAttrs.get(i)).getAttributeType());              
              newAttr.setAttributeTermCode(((AttributeNode) mocAttrs.get(i)).getAttributeTermCode());
              newAttr.setAttributeReference(((AttributeNode) mocAttrs.get(i)).getAttributeReference());
              newAttr.setAttributeQual(((AttributeNode) mocAttrs.get(i)).getAttributeQual());
              newAttr.setAttributeAccess(((AttributeNode) mocAttrs.get(i)).getAttributeAccess());
              newAttr.setAttributeValueRange(((AttributeNode) mocAttrs.get(i)).getAttributeValueRange());
              newAttr.setAttributeRestrictions(((AttributeNode) mocAttrs.get(i)).getAttributeRestrictions());
              newAttr.setAttributeApplicationGuidance(((AttributeNode) mocAttrs.get(i)).getAttributeApplicationGuidance());
              newAttr.setAttributeComment(((AttributeNode) mocAttrs.get(i)).getAttributeComment());
              mnode.addAttribute(newAttr);
              i = mocAttrs.size();
           } 
   
     }
  }

  public void deleteVector(MOCNode mnode, String vecToBeDeleted) {

     Vector vNode;
     vNode = mnode.getAttribute();

     int DeleteFlag = 0;
   
     while (DeleteFlag == 0  && vNode.size() != 0) {      
        for (int i = 0; i < vNode.size(); i++) {
           if (vecToBeDeleted.equals(((DIMMOC) vNode.get(i)).getAttributeName())) {
              vNode.remove(i);
              DeleteFlag = 1;
           } 
        }
     }
  }

  public void actionPerformed(ActionEvent arg0) {
     if(arg0.getSource() == btnAddChanges) {        
        // save changes
        processUpdate();
        f.dispose();
     }
     else if(arg0.getSource() == btnClose) {
	// exit
        f.dispose();
		icsModel = null;
     }
     else if(arg0.getSource() == removeButton)
     {
    	 Object selected[] = destList.getSelectedValues();
         int [] indices = destList.getSelectedIndices();
         int indices_cnt = 0;
         int Vector_Match_Flag = 0;
         String attributeNames = null;
         int numOfAttributes = 0;
         Vector vattrs = defattrs;
         for (int i = 0; i < selected.length; i++) {
//        	 we look for private attributes to delete
         	for(int p = 0; p < vectPrivateAttr.size(); p++){
         		if(selected[i].toString().equals(((DIMMOC) vectPrivateAttr.get(p)).getAttributeName())){
         			vectPrivateAttr.remove(p);
         			p = vectPrivateAttr.size();
         		}
         	}
        	 
            int Select_Match_Flag = 0;
            // we look for the selected attributes
            if(vattrs != null){
	            for (int x = 0; x < vattrs.size(); x++) {
	               if (selected[i].toString().equals(((DIMMOC) vattrs.get(x)).getAttributeName()) && 
	                  (((DIMMOC) vattrs.get(x)).getAttributeQual().equals("M") || ((DIMMOC) vattrs.get(x)).getAttributeQual().equals("n/a"))) {
	                  destList.removeSelectionInterval(indices[indices_cnt],indices[indices_cnt]);
	                  indices_cnt = indices_cnt + 1;
	                  if (Vector_Match_Flag == 0) {
	                     attributeNames = selected[i].toString();
	                     numOfAttributes = numOfAttributes + 1;
	                  }
	                  else {
	                     attributeNames = attributeNames+", "+selected[i].toString();
	                     numOfAttributes = numOfAttributes + 1;
	                  }
	                  Vector_Match_Flag = 1;
	                  Select_Match_Flag = 1;
	               }
	            }
            }
            // if the attribute is not mandatory we go to the next one
            if (Select_Match_Flag == 0) {
               indices_cnt = indices_cnt + 1;
            }
         }   
         
         // if the user want to delete a mandatory attribute he gets error message
         if (Vector_Match_Flag != 0) {
           selected = destList.getSelectedValues();
           String msg = null;
           if (numOfAttributes == 1 ) {
              msg = "The Attribute "+attributeNames+" CANNOT BE REMOVED because it is a MANDATORY ATTRIBUTE";
           }
           else {
              msg = "The Attributes "+attributeNames+" CANNOT BE REMOVED because they are MANDATORY ATTRIBUTES";
           }
           String title = "ATTRIBUTE WARNING MESSAGE";
           JOptionPane.showConfirmDialog(this, msg, title,JOptionPane.DEFAULT_OPTION,JOptionPane.WARNING_MESSAGE);
         } 
         selected = destList.getSelectedValues();
         addSourceElements(selected);
         clearDestinationSelected();
     }
     else if(arg0.getSource() == addButton)
     {
    	 Object selected[] = sourceList.getSelectedValues();
         addDestinationElements(selected);
         clearSourceSelected();
     }
     else if(arg0.getSource() == btnAddPrivateAtt)
     {
    	 JFrame f = new JFrame("Add private Attribute");
    	 
    	 
    	 String[] labels = new String[4];
    	 labels[0] = "Attribute ID:";
    	 labels[1] = "Attribute Name:";
    	 labels[2] = "Status:";
    	 labels[3] = "Term Code:";
    	 AddPrivateDialog dialog = new AddPrivateDialog(this,f,labels, AddPrivateDialog.privateAtt);
    	 dialog.setLocationRelativeTo(this);
    	 dialog.pack();
    	 
    	 ICSModel icsM = new ICSModel();
    	 icsM.addObserver(this);
    	 dialog.setICSModel(icsM);
    
    	 dialog.setVisible(true);
     }
  }
  
  public void update(Observable o, Object arg) {
		if(o instanceof ICSModel) {
			if(("private/"+AddPrivateDialog.privateAtt).equals(((MVCArg)arg).getName()) && icsModel != null) {
				String[] result = (String[]) ((MVCArg)arg).getOValue();
				AttributeNode attr = new AttributeNode();
			
				attr.attribute_name = result[1];
				attr.attribute_id = result[0];
				attr.attr_qual = result[2];
				attr.attr_termcode = result[3];
				attr.attribute_type = "private";
				attr.isPrivate = true;
				vectPrivateAttr.add(attr);
				MyListRenderer renderer = (MyListRenderer) destList.getCellRenderer();
				renderer.addPrivate(attr.attribute_name);
				destListModel.add(attr.attribute_name);
				
			}	
	}
}

}

class MyListRenderer extends DefaultListCellRenderer implements ListCellRenderer{

        private static final long serialVersionUID = 1L;

	protected Vector<String> vectStrPrivate;
	public MyListRenderer(){
		super();
		vectStrPrivate = new Vector<String>();
	}
	public void addPrivate(String strItem){
		vectStrPrivate.add(strItem);
	}
	public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean hasFocus) {
		
		Component c = super.getListCellRendererComponent(list, value, index, isSelected, hasFocus);
		try{
			String val = value.toString();
			for(int i = 0; i < vectStrPrivate.size(); i++){
				String strItem = (String)vectStrPrivate.get(i);
				if(val.equals(strItem)){
					c.setForeground(Color.RED);
					i = vectStrPrivate.size();
				}
			}
		}
		catch(Exception e){
			
		}
		return c;
	}
}


class SortedListModel extends AbstractListModel {

  private static final long serialVersionUID = 1L;

  SortedSet<Object> model;

  public SortedListModel() {
    model = new TreeSet<Object>();
  }

  public int getSize() {
    return model.size();
  }

  public Object getElementAt(int index) {
    return model.toArray()[index];
  }

  public void add(Object element) {
    if (model.add(element)) {
      fireContentsChanged(this, 0, getSize());
    }
  }

  public void addAll(Object elements[]) {
    Collection<Object> c = Arrays.asList(elements);
    model.addAll(c);
    fireContentsChanged(this, 0, getSize());
  }

  public void clear() {
    model.clear();
    fireContentsChanged(this, 0, getSize());
  }

  public boolean contains(Object element) {
    return model.contains(element);
  }

  public Object firstElement() {
    return model.first();
  }

  public Iterator iterator() {
    return model.iterator();
  }

  public Object lastElement() {
    return model.last();
  }

  public boolean removeElement(Object element) {
    boolean removed = model.remove(element);
    if (removed) {
      fireContentsChanged(this, 0, getSize());
    }
    return removed;
  }
}


