package org.opengroupware.jope.eoaccess;

import org.opengroupware.jope.foundation.NSObject;

/*
 * EOJoin
 * 
 * TODO: document
 */
public class EOJoin extends NSObject {

  EOAttribute source;
  EOAttribute destination;
  String      sourceName;
  String      destinationName;
  
  public EOJoin(EOAttribute _src, EOAttribute _dest) {
    this.source      = _src;
    this.destination = _dest;
  }
  public EOJoin(String _src, String _dest) {
    this.sourceName      = _src;
    this.destinationName = _dest;
  }
  
  /* accessors */
  
  public EOAttribute destinationAttribute() {
    return this.destination;
  }
  public EOAttribute sourceAttribute() {
    return this.source;
  }
  
  public boolean referencesProperty(Object _property) {
    // TODO: look into data-path for flattened relationships
    if (_property == null) return false;
    
    if (_property == this.source || _property.equals(this.source))
      return true;
    if (_property == this.destination || _property.equals(this.destination))
      return true;
    
    return false;
  }
  
  public void connectToEntities(EOEntity _from, EOEntity _dest) {
    if (_from != null)
      this.source = _from.attributeNamed(this.sourceName);
    if (_dest != null)
      this.destination = _dest.attributeNamed(this.destinationName);
  }
  
  /* operations */
  
  public boolean isReciprocalToJoin(EOJoin _other) {
    if (_other == null)
      return false;
    
    /* fast check (should work often) */
    if (this.source == _other.destination && _other.destination == this.source)
      return true;
    
    /* slow check */
    
    if (!this.source.equals(_other.destination))
      return false;
    if (!this.destination.equals(_other.source))
      return false;
    
    return true;
  }
  
  public boolean equals(Object _other) {
    if (_other == null)
      return false;
    if (_other == this)
      return true;
    
    if (!(_other instanceof EOJoin))
      return false;
    
    EOJoin other = (EOJoin)_other;
    
    /* fast check (should work often) */
    if (this.source == other.source && this.destination == other.destination)
      return true;

    /* slow check */
    
    if (!this.source.equals(other.source))
      return false;
    if (!this.destination.equals(other.destination))
      return false;
    
    return true;
  }
  
  /* description */
  
  public void appendAttributesToDescription(StringBuffer _d) {
    super.appendAttributesToDescription(_d);

    if (this.source      != null) _d.append(" src="  + this.source);
    if (this.destination != null) _d.append(" dest=" + this.destination);
  }
}
