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

/**
 * Models a text element in QJML.
 * A text element is used to describe an attribute or a simple element that has 
 * text content and no attributes.
 <pre>
DTD:

&lt;!ELEMENT text (<a href="QMCoin.html#remList">rem*</a>, <a href="#extendor">extends?</a>, <a href="#implementsList">implements*</a>,
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#target">(targetClass|targetEditor|targetFactory)?</a>,
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#fieldList">field*</a>, <a href="#propertyList">property*</a>, <a href="#validList">(enum|range)*</a>)>

&lt;!ATTLIST text
&nbsp;&nbsp;&nbsp;&nbsp;<a href="QMCoin.html#label">label</a> CDATA #IMPLIED
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#tag">tag</a> CDATA #IMPLIED
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#wild">wild</a> CDATA "False"
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#type">type</a> (idref|PCDATA|CDATA|int|short|long|byte|
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;boolean|float|double|base64|url|char|BigDecimal) "PCDATA"
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#inline">inline</a> CDATA "False"
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#trim">trim</a> CDATA "True"
&nbsp;&nbsp;&nbsp;&nbsp;<a href="QMCoin.html#generate">generate</a> CDATA "True"
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#validInherited">validInherited</a> CDATA "True"
&nbsp;&nbsp;&nbsp;&nbsp;ID id #IMPLIED
>
 </pre>
 */
public class QMText extends QMCoin
	implements QMElement, QMData
{
	/**
	 * <p>
	 * Models the tag attribute on the text element.
	 * The tag attribute holds the XML tag name for the element or attribute
	 * being defined by the text element.
	 * </p><p>
	 * When the label attribute is not present, the tag attribute is used to name the text coin.
	 * </p>
	 */
	public String tag="";

	/**
	 * <p>
	 * Models the wild attribute on the text coin.
	 * The wild attribute defaults to false.
	 * When the wild attribute is true,
	 * the text element can be used to represent an element or attribute with any tag name.
	 * </p><p>
	 * When the wild attribute is false, the tag attribute is required, but
	 * when the wild attribute is true, the tag attribute must not be present.
	 * </p><p>
	 * When the wild attribute is false, the label attribute is optional,
	 * but when the wild attribute is true, the label attribute is required.
	 * </p>
	 */
	public boolean wild=false;

	/**
	 * <p>
	 * Models the type attribute on the text coin.
	 * The type attribute defaults to a value of PCDATA.
	 * </p><p>
	 * The following values are allowed:
	 * <ul>
	 * </ul>
	 * <li>
	 * idref -- The content of the attribute being defined
	 * is the id assigned to another element in the same document.
	 * (A type of id is only valid when the text coin is used to define an attribute.)
	 * </li>
	 * <li>
	 * CDATA -- When creating an XML document, the content of the text coin
	 * will be wrapped in a CDATA section. The text content converts to a String by default.
	 * </li>
	 * <li>
	 * PCDATA -- The text content converts to a String by default.
	 * </li>
	 * <li>
	 * int --  The text content is an int.
	 * </li>
	 * <li>
	 * short --  The text content is a short.
	 * </li>
	 * <li>
	 * long --  The text content is a long.
	 * </li>
	 * <li>
	 * byte --  The text content is a byte.
	 * </li>
	 * <li>
	 * float--  The text content is a float.
	 * </li>
	 * <li>
	 * double --  The text content is a double.
	 * </li>
	 * <li>
	 * base64--  Base64 encoding is used for the text content.
	 * This is converted to an array of bytes.
	 * </li>
	 * <li>
	 * url --  The text content is a URL.
	 * </li>
	 * <li>
	 * BigDecimal --  The text content converts to a BigDecimal.
	 * </li>
	 * </p>
	 */
	public String type="PCDATA";

	/**
	 * Models the inline attribute on the text element.
	 * The inline attribute is optional, with a default value of false.
	 * When creating an XML document, the element is begun on a new line
	 * unless inline is set to true.
	 * (This attribute is ignored when the text coin is used to define an attribute.)
	 */
	public boolean inline=false;

	/**
	 * Models the trim attribute on the text element.
	 * The trim attribute is optional, with a default value of true.
	 * When true, leading and trailing whitespace is removed from the text content.
	 */
	public boolean trim=true;

	/**
	 * Models the validInherited attribute on the text element.
	 * The validInherited attribute is optional, with a default value of true.
	 * The enum and range elements of the abstract or text coin which this coin extends
	 * are normally inherited, except when validInherited is set to false.
	 */
	public boolean validInherited=true;

	/**
	 * Models an extends element, which is optional.
	 * A text coin can extend an abstract coin or another text coin,
	 * which is named by the extends element.
	 */
	public QMExtends extendor=null;

	/**
	 * A container for QMImplements objects, which model implements elements.
	 * The implements elements are optional and repeating.
	 * These implements elements name the interface coins which this text coin "implements".
	 * (A text element can impliment any number of interfaces.)
	 */
	public ArrayList implementsList=new ArrayList();

	/**
	 * Models target, which is an interface element. 
	 * The target element (targetClass, targetEditor, or targetFactory) is optional.
	 * The target element names the Java class which this text element describes.
	 * The target element can only be present when the type attribute is PCDATA, or CDATA.
	 */
	public QMTarget target=null;

	/**
	 * A container for QMField objects, which model field elements.
	 * The field elements are optional and repeating.
	 * These field elements describe the variables of the Java class which
	 * this text element describes.
	 */
	public ArrayList fieldList=new ArrayList();

	/**
	 * A container for QMProperty objects, which model property elements.
	 * The property elements are optional and repeating.
	 * These property elements describe the bean property methods of the Java class which
	 * this text element describes.
	 */
	public ArrayList propertyList=new ArrayList();

	/**
	 * A container for QMEnum and QMRange objects, which model enum and range elements.
	 * The enum and range elements are optional and repeating.
	 * These valid elements are used to describe acceptable text content of this text coin.
	 */
	public ArrayList validList=new ArrayList();

	/**
	 * The QMAbstract or QMText object named by the extends element.
	 * This variable is set when the data model is initialized.
	 */
	public transient QMCoin extendsCoin=null;

	/**
	 * A container for QMEnum and QMRange objects for this element, 
	 * including enum and range elements defined on abstract and text coins
	 * which this text coin extends.
	 * This list is populated when the data model is initialized.
	 */
	public transient ArrayList valids=null;

	public Object clone()
	{
		QMText rv=(QMText)super.clone();
		rv.extendor=(QMExtends)clone(extendor);
		rv.implementsList=clone(implementsList);
		rv.target=(QMTarget)clone((QMCloneable)target);
		rv.fieldList=clone(fieldList);
		rv.propertyList=clone(propertyList);
		rv.extendsCoin=null;
		rv.valids=null;
		return rv;
	}

	/**
	 * Returns the unique (within the scope of the QJML document) name of the coin,
	 * as specified by the coin's label.
	 * When the label attribute is present, its value is returned. 
	 * Otherwise the value of the tag attribute is returned.
	 */
	public String getLabel()
	{
		if (!"".equals(label))
			return label;
		return tag;
	}

	/**
	 * Returns the XML tag name assigned to the text element.
	 * When wild is true, the value of the label attribute is returned.
	 */
	public String getTag()
	{
		if (wild)
			return label;
		return tag;
	}

	public void buildMaps(Map coinMap, Map contentMap)
		throws SAXException
	{
		int i;
		int s;

		String l=getLabel();
		if ("".equals(l))
			throw new SAXException(
				"Text coin has no label or element tag.");
		if (coinMap.containsKey(l))
			throw new SAXException("Duplicate label: "+l);
		coinMap.put(l,this);

		s=fieldList.size();
		for (i=0;i<s;++i)
		{
			QMField f=(QMField)fieldList.get(i);
			f.buildMaps(coinMap,contentMap,this);
		}

		s=propertyList.size();
		for (i=0;i<s;++i)
		{
			QMProperty p=(QMProperty)propertyList.get(i);
			p.buildMaps(coinMap,contentMap,this);
		}
	}

	public QMAccess getAccessor(Map coinMap, String name)
		throws SAXException
	{
		QMAccess a=null; 

		if (extendor!=null)
		{
			if (extendsCoin==null)
			{
				extendsCoin=(QMCoin)coinMap.get(extendor.text);
				if (extendsCoin==null)
					throw new SAXException("Undefined coin: "+extendor.text);
			}
			a=extendsCoin.getAccessor(coinMap,name);
		}
		if (a!=null)
			return a;

		int i;
		int s=implementsList.size();
		for (i=0;(a==null && i<s);++i)
		{
			String l=((QMImplements)implementsList.get(i)).text;
			QMCoin c=(QMCoin)coinMap.get(l);
			if (c==null)
				throw new SAXException("Undefined coin: "+l);
			a=c.getAccessor(coinMap,name);
		}
		if (a!=null)
			return a;

		a=(QMAccess)accessors.get(name);

		return a;
	}

	public void init(Map coinMap, Map contentMap)
		throws SAXException
	{
		int i;
		int s;
		QMCoin c;

		if (extendor!=null)
		{
			extendsCoin=(QMCoin)coinMap.get(extendor.text);
			if (extendsCoin==null)
				throw new SAXException("Undefined coin: "+extendor.text);
			extendsCoin.extensions.add(this);
		}


		s=implementsList.size();
		for (i=0;i<s;++i)
		{
			String l=((QMImplements)implementsList.get(i)).text;
			c=(QMCoin)coinMap.get(l);
			if (c==null)
				throw new SAXException("Undefined coin: "+l);
			c.implementations.add(this);
		}

		s=fieldList.size();
		for (i=0;i<s;++i)
		{
			QMField f=(QMField)fieldList.get(i);
			f.init(coinMap,contentMap,this,null);
		}

		s=propertyList.size();
		for (i=0;i<s;++i)
		{
			QMProperty p=(QMProperty)propertyList.get(i);
			p.init(coinMap,contentMap,this,null);
		}
		if ("java.lang.Object".equals(getClassName()))
			generate=false;
	}

	public Map getAtts()
		throws SAXException
	{
		return new HashMap();
	}

	public ArrayList getValidList()
		throws SAXException
	{
		if (valids!=null)
			return valids;
		valids=new ArrayList(validList);
		if (extendsCoin==null || !validInherited)
			return valids;
		valids.addAll(((QMData)extendsCoin).getValidList());
		return valids;
	}

	public String getClassName()
		throws SAXException
	{
		if (target==null)
		{
			if ("PCDATA".equals(type) || "CDATA".equals(type))
				return "java.lang.String";
			else
				return TypeManager.getGenClass(type);
		}
		return target.getClassName();
	}
}
