package com.jxml.quick.model.qdml;
import com.jxml.quick.ocm.*;
import com.jxml.quick.*;
import org.xml.sax.*;
import java.util.*;
import java.io.*;

/**
 * Models the abstract element contentModel in QDML.
 * The contentModel elements form a tree under the elements element, and
 * are used to define the element content of a bean element.
 */
public abstract class QDMContentModel extends QDMCloneable
{
	/**
	 * Models the label attribute on contentModel elements.
	 * The label attribute gives a name to a contentModel element that can then
	 * be referenced by a cref attribute on another contentModel element.
	 * The label attribute is optional.
	 */
	public String label="";

	/**
	 * Models the cref attribute on contentModel elements.
	 * A cref attribute names another contentModel element. 
	 * By this means the attribute values and element content of one 
	 * contentModel element are copied to another.
	 * The cref attribute is optional.
	 */
	public String cref="";

	/**
	 * Models the optional attribute on contentModel elements.
	 * When set to true, the optional attribute indicates that the element content
	 * is not required.
	 * The optional attribute has a default value of false.
	 */
	public boolean optional=false;

	/**
	 * Models the repeating attribute on contentModel elements.
	 * When set true, the repeating attribute indicates that the element content
	 * can occur more than once.
	 * The repeating attribute has a default value of false.
	 */
	public boolean repeating=false;

	/**
	 * A container for QDMRem objects, which model rem elements.
	 * The rem elements are optional and repeating.
	 */
	public ArrayList remList=new ArrayList();

	/**
	 * The QDMContentModel object which models the element named by the cref attribute.
	 * This variable is populated when the data model is initialized.
	 */
	public transient QDMContentModel content=null;

	/**
	 * Used to prevent multiple initializations.
	 */
	protected transient boolean initialized=false;

	/**
	 * The name of the enclosing coin.
	 */
	public transient QDMCoin enclosingCoin=null;

	/**
	 * Returns a deep copy of this object, but in an uninitialized form.
	 */
	public Object clone()
	{
		QDMContentModel rv=(QDMContentModel)super.clone();
		rv.remList=clone(remList);
		rv.content=null;
		rv.initialized=false;
		return rv;
	}

	/**
	 * Builds the maps.
	 * This method is called during initialization of the data model.
	 */
	public void buildMaps(Map coinMap, Map contentMap, QDMCoin coin)
		throws SAXException
	{
		enclosingCoin=coin;
		if (!"".equals(label))
		{
			if (contentMap.containsKey(label))
				throw new SAXException("Duplicate content model label: "+label);
			contentMap.put(label,this);
		}
	}

	/**
	 * Resolve references, inheritance.
	 * This method is called during initialization of the data model.
	 */
	public void init(Map coinMap, Map contentMap)
		throws SAXException
	{
		if (initialized)
			return;
		initialized=true;
		if (!"".equals(cref))
		{
			content=(QDMContentModel)contentMap.get(cref);
			if (content==null)
				throw new SAXException("Undefined contentModel: "+cref);
			content.init(coinMap,contentMap);
			if (!optional)
				optional=content.optional;
			if (!repeating)
				repeating=content.repeating;
		}
	}

	public abstract boolean isContainedBy(String label, TreeMap coinMap);
}
