// (c) MIT 2003.  All rights reserved.

// -*-Mode: Java-*- 
// $Id: Entity.java,v 1.2 2003/03/06 00:40:43 moltmans Exp $
// Entity.java -- 
// Author: Michael Oltmans <moltmans@ai.mit.edu> 
// Created: <Wed Mar 15 17:06:48 2000> 
// Time-stamp: <2000-04-12 23:03:26 moltmans> 
package rec.annotate;

import java.util.*;
import rec.sys.*;
import rec.util.*;

public class Entity implements Cloneable
{
  private HashSet m_names;
  private Widget m_widget;
  private AnnotationNotebook m_notebook;

  public Entity( AnnotationNotebook book ) 
  {
    m_names = new HashSet();
    m_widget = null;
    m_notebook = book;
  }
  

  public Entity( AnnotationNotebook book, Widget w, HashSet names ) 
  {
    this( book );
    m_names = (HashSet)names.clone();
    m_widget = w;
  }
  
  public Entity( AnnotationNotebook book, String name ) 
  {
    this( book );

    if( name != null )
      m_names.add( name );
  }

  public Entity( AnnotationNotebook book, Widget w ) 
  {
    this( book );
    m_widget = w;
    m_names = new HashSet();
  }

  /**
   * @return one of the names associated with this widget
   **/
  public String getAName() 
  {
    Iterator it = m_names.iterator();
    if ( it.hasNext() )
      return (String)it.next();
    return null;
  }
  
  public Set getNames()
  {
    return (HashSet)m_names.clone();
  }
  
  public void addName( String name ) 
  {
    if( name != null ) {
      // add the name
      m_names.add( name );

      Widget w = m_notebook.lookupWidget( name );

      // check if it is consistant, and if possible add in the widget
      // this name maps to
      if( m_widget == null ) {
	m_widget = w;
      }
      else if( w != null && !w.equals( m_widget ) ) {
	DebugWindow.addLine( "Warnings",
			     "Contradictory name to widget mapping:\n" +
			     name + " maps to " + w + " and " + m_widget );
      }
    }
  }

  public Widget getWidget() 
  {
    return m_widget;
  }
  
  public void setWidget( Widget w ) 
  {
    m_widget = w;

    String name = m_notebook.lookupName( w );
    addName( name );
  }

  /** @return true if this and e have the same non-null widget. **/
  public boolean sameWidget( Entity e ) 
  {
    return(m_widget != null) &&  m_widget.equals( e.m_widget );
  }

  public boolean isEmpty() 
  {
    return ( (m_widget == null) && m_names.isEmpty() );
  }

  public Object clone()
  {
    Entity e = null;
    try {
      e = (Entity)super.clone();
    }
    catch ( CloneNotSupportedException cnse ) {
      return null;
    }
    
    e.m_names = (HashSet)m_names.clone();
    return e;
  }
  
   
  public void updateBindings( AnnotationNotebook noteBook ) 
  {
    if ( !m_names.isEmpty() && m_widget != null ) {
      Iterator names = m_names.iterator();
      while ( names.hasNext() ) {
	noteBook.addName( (String)names.next(), m_widget );
      }
    }
  }

  public void retractBindings( AnnotationNotebook noteBook )
  {
    if ( !m_names.isEmpty() && m_widget != null ) {
      Iterator names = m_names.iterator();
      while ( names.hasNext() ) {
	noteBook.removeName( (String)names.next(), m_widget );
      }
    }
  }
  

  public static Entity merge( Entity e1, Entity e2 ) 
  {
    if ( e1 == null )
      return e2;
    if ( e2 == null )
      return e1;

    return e1.merge( e2 );
  }

  /**
   * @return A new entity if the widgets are mergable.  i.e. if one is
   *         null or if they are the same.  The names are simply
   *         concatenated.
   **/
  public Entity merge( Entity e )
  {
    if ( e == null )
      return null;
    
    Widget w = null;
    if ( m_widget == null )
      w = e.m_widget;
    else if ( e.m_widget == null )
      w = m_widget;
    // they need to be equal if neither is null
    else if ( sameWidget( e ) )
      w = m_widget;
    // they cannot be merged they are different objects
    else 
      return null;

    HashSet names = (HashSet)m_names.clone();
    names.addAll( e.m_names );
    
    return new Entity( m_notebook, w, names );
  }


  public String toString() 
  {
    String name = getAName();
    if ( name == null && m_widget == null )
      return "Empty Entity";


    if ( name == null )
      name = m_widget.toString();
    else
      name += "=" + m_widget; 

    return name;
  }
  
    

}



  
  
