package osa.attribute.atgrammar.grammar;

import java.util.*;
import osa.attribute.atgrammar.grammar.symbols.*;



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

public class GrammarProduction
  {
  protected NonTerminalSymbol left_part;
  protected SymbolsString right_part;
  protected ArrayList assignments_list=new ArrayList();
  protected int assignments_list_size;

  protected Grammar owner_grammar;

  public GrammarProduction(Grammar owner_grammar,NonTerminalSymbol left_part,SymbolsString right_part)
    {
    this.owner_grammar=owner_grammar;
    this.left_part=left_part;
    this.right_part=right_part;
    }

  public NonTerminalSymbol getLeftPart()
    {
    return left_part;
    }

  public SymbolsString getRightPart()
    {
    return right_part;
    }

  public String toString()
    {
    String result=new String();

    result+=left_part.toString();
    result+="::=";
    result+=right_part.toString();

    return result;
    }

  protected void setLeftPart(NonTerminalSymbol left_part)
    {
    this.left_part=left_part;
    }

  protected void setRightPart(SymbolsString right_part)
    {
    this.right_part=right_part;
    }

  public void addAssignment(SimpleAssignment assignment)
    {
    assignment.setOwner(this);
    assignments_list.add(assignment);
    assignments_list_size++;
    }

  public SymbolsString executeProduction(NonTerminalSymbol non_terminal)
    {
    if(!non_terminal.getOriginalName().equals(getLeftPart().getOriginalName()))
      {
      return null;
      }

    SymbolsString result_string=(SymbolsString)getRightPart().clone();

    SimpleAssignment temp_assignment;

    for(int i=0;i<assignments_list_size;i++)
       {
       temp_assignment=(SimpleAssignment)assignments_list.get(i);
       temp_assignment.executeAssignment(non_terminal,result_string);
       }

    non_terminal.tranferDefferedAssignments();

    return result_string;
    }

  public int getAsslignmentsCount()
    {
    return this.assignments_list_size;
    }

  public SimpleAssignment getAssignmentAt(int index)
    {
    if(index>=assignments_list_size)
      {
      return null;
      }
    return (SimpleAssignment)assignments_list.get(index);
    }

  public boolean setAssignmentAt(int index, SimpleAssignment assignment)
    {
    if(index>=assignments_list_size)
      {
      return false;
      }
    assignments_list.set(index, assignment);
    return true;
    }

  public boolean removeAssignmentAt(int index)
    {
    if(index>=assignments_list_size||index<0)
      {
      return false;
      }
    assignments_list.remove(index);
    assignments_list_size--;
    return true;
    }

  public boolean removeAssignment(SimpleAssignment assignment)
    {
    if(assignments_list.contains(assignment))
      {
      assignments_list.remove(assignment);
      assignments_list_size--;
      return false;
      }
    return true;
    }

  public void updateProduction()
    {
    owner_grammar.getDictionary().resetAllCounters();
    left_part=(NonTerminalSymbol)left_part.getOriginalReference().clone();
    right_part=(SymbolsString)right_part.clone();
    }

  public void updateAssignmentsIndexes()
    {
    for(int i=0;i<this.assignments_list_size;i++)
       {
       ((SimpleAssignment)assignments_list.get(i)).updateIndexes();
       }
    }

  public void updateAssignmentLabels()
    {
    for(int i=0;i<this.assignments_list_size;i++)
       {
       ((SimpleAssignment)assignments_list.get(i)).updateLabels();
       }
    }

  public void removeInvalidAssignments()
    {
    SimpleAssignment temp_assignment;
    for(int i=0;i<this.assignments_list_size;i++)
       {
       temp_assignment=(SimpleAssignment)assignments_list.get(i);
       if(temp_assignment.isValid())
         {
         assignments_list.remove(i);
         i++;
         }
       }
    }

  public ArrayList getAssignmentsList()
    {
    return assignments_list;
    }

  public void setAssignmentsList(ArrayList assignments_list)
    {
    this.assignments_list=assignments_list;
    this.assignments_list_size=assignments_list.size();
    }

  }