package osa.attribute.atgrammar.grammar.symbols;

import java.util.*;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2005</p>
 * <p>Company: </p>
 * @author not attributable
 * @version 1.0
 */

public class Attribute
  implements Cloneable
  {
  public static final int UNDEFINED =   0;
  public static final int INHERITED =   1;
  public static final int SYNTHESIZED = 2;

  protected Object value_reference;
  protected AttributeType type_reference;
  protected String name;

  protected Symbol owner;

  protected int class_type;

  protected ArrayList deferred_assignments;

  protected Attribute deferred_assignment_source;

  protected boolean is_cloned; // mean that symbol _was_ cloned!
  protected Attribute original_reference;


  public Attribute(String name)
    {
    this.name=name;
    deferred_assignments=new ArrayList();
    is_cloned=false;
    original_reference=this;
    this.type_reference=AttributeType.VOID_TYPE;
    }

  public String getName()
    {
    return name;
    }

  public boolean setName(String name)
    {
    boolean is_renamed=false;
    if(owner.findAttribute(name)==null)
      {
      this.name=name;
      is_renamed=true;
      }
    return is_renamed;
    }

  public Object getValue()
    {
    return value_reference;
    }

  public void setValue(Object value_reference)
    {
    this.value_reference=value_reference;
    executeDeferredAssignments();
    }


  public AttributeType getType()
    {
    return type_reference;
    }

  public void setType(AttributeType type_reference)
    {
    this.type_reference=type_reference;
    }


  public int getClassType()
    {
    return class_type;
    }

  public void setClassType(int class_type)
    {
    this.class_type=class_type;
    }



  public void addDeferredAssignment(Attribute recipient)
    {
    deferred_assignments.add(recipient);
    }

  public void removeDeferredAssignment(Attribute recipient)
    {
    deferred_assignments.remove(recipient);
    }

  public ArrayList getDeferredAssignments()
    {
    return deferred_assignments;
    }

  public Attribute getSourceOfAssignment()
    {
    return deferred_assignment_source;
    }




  public void assign(Attribute source)
    {
    System.err.println("Assign "+this+":="+source);
    if(source.getValue()==null)
      {
      source.addDeferredAssignment(this);
      deferred_assignment_source=source;
      }
    else
      {
      setValue(source.getValue());
      }
    }

  protected void executeDeferredAssignments()
    {
    Attribute temp_attribute;
    int list_size=deferred_assignments.size();
    for(int i=0;i<list_size;i++)
       {
       temp_attribute=(Attribute)deferred_assignments.get(i);
       temp_attribute.setValue(this.getValue());
       }
    }


  public Symbol getOwner()
    {
    return owner;
    }

  public void setOwner(Symbol owner)
    {
    this.owner=owner;
    }

  public Object clone()
    {
    Attribute cloned=new Attribute(name);
    cloned.class_type=class_type;
    cloned.type_reference=cloned.type_reference;

    cloned.is_cloned=true;
    if(is_cloned)
      {
      cloned.original_reference=original_reference;
      }
    else
      {
      cloned.original_reference=this;
      }
//    cloned.deferred_assignments=(ArrayList)deferred_assignments.clone();
    return cloned;
    }

  public String toString()
    {
    return getName();
    }


  }