/*------------------------------------------------------------------------------------
Copyright (c)2000 TogetherSoft Corporation. Patents pending. All rights reserved. 
------------------------------------------------------------------------------------*/ 

package com.togethersoft.modules.xmleditor.xmltree;

import java.util.*;
import com.togethersoft.modules.xmleditor.dtd.*;

public class GroupInstHolder extends InstHolder
{
  private DTDGroupItemDef  m_groupDef;
  private boolean  m_emptyGroupIsComplete;

  //--------------------------------------------------------------------
  public GroupInstHolder (DTDGroupItemDef groupDef)
  {
    super (groupDef);
    m_groupDef = groupDef;

    // check if the empty group is complete
    m_emptyGroupIsComplete = GroupInst.newGroupInst (groupDef).isComplete();
  }

  //--------------------------------------------------------------------
  public boolean isComplete()
  {
    // check completeness by cardinality
    switch (m_groupDef.getCardinality())
    {
      case DTDItemDef.CARDINALITY_ONCE:
      case DTDItemDef.CARDINALITY_ONCE_OR_MORE:

        if (m_instances.size() == 0)
          return m_emptyGroupIsComplete;
    }

    return super.isComplete();
  }

  //--------------------------------------------------------------------
  public int checkElementInstAllowance (DTDElementDef elementDef)
  {
    int foundAllowance = ElementInst.NEA_PROHIBITED;

    if (m_groupDef.containsChildElement (elementDef))
    {
      Enumeration instEnum = m_instances.elements();
      while (instEnum.hasMoreElements())
      {
        GroupInst groupInst = (GroupInst) instEnum.nextElement();
        int allowance = groupInst.checkElementInstAllowance (elementDef);
        if (allowance == ElementInst.NEA_PROHIBITED)
          continue;

        foundAllowance = allowance;
        if (allowance == ElementInst.NEA_REQUIRED)
          break;
      }

      if (foundAllowance == ElementInst.NEA_PROHIBITED)
      {
        switch (m_groupDef.getCardinality())
        {
          case DTDItemDef.CARDINALITY_ONCE:

            if (m_instances.size() == 0)
            {
              GroupInst groupInst = GroupInst.newGroupInst (m_groupDef);
              foundAllowance = groupInst.checkElementInstAllowance (elementDef);
            }
            break;

          case DTDItemDef.CARDINALITY_ONCE_OR_NEVER:

            if (m_instances.size() == 0)
              foundAllowance = ElementInst.NEA_ALLOWED;
            break;

          case DTDItemDef.CARDINALITY_ONCE_OR_MORE:

            if (m_instances.size() == 0)
            {
              GroupInst groupInst = GroupInst.newGroupInst (m_groupDef);
              foundAllowance = groupInst.checkElementInstAllowance (elementDef);
              break;
            }

          case DTDItemDef.CARDINALITY_ANY_TIMES:

            foundAllowance = ElementInst.NEA_ALLOWED;
            break;
        }
      }
    }

    return foundAllowance;
  }

  //--------------------------------------------------------------------
  public boolean putElementInst (ElementInst elementInst)
  {
    GroupInst targetGroupInst = null;
    DTDElementDef elementDef = elementInst.getElementDef();

    if (m_groupDef.containsChildElement (elementDef))
    {
      Enumeration instEnum = m_instances.elements();
      while (instEnum.hasMoreElements())
      {
        GroupInst groupInst = (GroupInst) instEnum.nextElement();
        int allowance = groupInst.checkElementInstAllowance (elementDef);
        if (allowance == ElementInst.NEA_PROHIBITED)
          continue;

        if (allowance == ElementInst.NEA_REQUIRED)
        {
          targetGroupInst = groupInst;
          break;
        }

        if (targetGroupInst == null)
          targetGroupInst = groupInst;
      }

      if (targetGroupInst == null)
      {
        switch (m_groupDef.getCardinality())
        {
          case DTDItemDef.CARDINALITY_ONCE:
          case DTDItemDef.CARDINALITY_ONCE_OR_NEVER:

            if (m_instances.size() == 0)
            {
              targetGroupInst = GroupInst.newGroupInst (m_groupDef);
              m_instances.addElement (targetGroupInst);
            }
            break;

          case DTDItemDef.CARDINALITY_ONCE_OR_MORE:
          case DTDItemDef.CARDINALITY_ANY_TIMES:

            targetGroupInst = GroupInst.newGroupInst (m_groupDef);
            m_instances.addElement (targetGroupInst);
            break;
        }
      }
    }

    if (targetGroupInst == null)
      return false;

    targetGroupInst.putElementInst (elementInst);
    return true;
  }

  //--------------------------------------------------------------------
  public boolean deleteElementInst (ElementInst elementInst)
  {
    Enumeration instEnum = m_instances.elements();
    while (instEnum.hasMoreElements())
    {
      GroupInst groupInst = (GroupInst) instEnum.nextElement();
      if (groupInst.deleteElementInst (elementInst))
      {
        if (groupInst.isEmpty())
          m_instances.removeElement (groupInst);

        return true;
      }
    }

    return false;
  }

  //--------------------------------------------------------------------
  public Vector getContainedElements()
  {
    Vector allElements = new Vector();

    Enumeration instEnum = m_instances.elements();
    while (instEnum.hasMoreElements())
    {
      GroupInst groupInst = (GroupInst) instEnum.nextElement();
      Vector groupElements = groupInst.getContainedElements();
      allElements.addAll (groupElements);
    }

    return allElements;
  }

  //--------------------------------------------------------------------
}
