/*******************************************************************************
 * Copyright (c) 2001, 2010 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.dtd.core.internal.contentmodel;

import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.ibm.icu.util.StringTokenizer;

import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.wst.dtd.core.internal.emf.DTDAnyContent;
import org.eclipse.wst.dtd.core.internal.emf.DTDAttribute;
import org.eclipse.wst.dtd.core.internal.emf.DTDBasicType;
import org.eclipse.wst.dtd.core.internal.emf.DTDBasicTypeKind;
import org.eclipse.wst.dtd.core.internal.emf.DTDDefaultKind;
import org.eclipse.wst.dtd.core.internal.emf.DTDElement;
import org.eclipse.wst.dtd.core.internal.emf.DTDElementContent;
import org.eclipse.wst.dtd.core.internal.emf.DTDElementReferenceContent;
import org.eclipse.wst.dtd.core.internal.emf.DTDEmptyContent;
import org.eclipse.wst.dtd.core.internal.emf.DTDEntity;
import org.eclipse.wst.dtd.core.internal.emf.DTDEnumerationType;
import org.eclipse.wst.dtd.core.internal.emf.DTDFile;
import org.eclipse.wst.dtd.core.internal.emf.DTDGroupContent;
import org.eclipse.wst.dtd.core.internal.emf.DTDGroupKind;
import org.eclipse.wst.dtd.core.internal.emf.DTDInternalEntity;
import org.eclipse.wst.dtd.core.internal.emf.DTDOccurrenceType;
import org.eclipse.wst.dtd.core.internal.emf.DTDPCDataContent;
import org.eclipse.wst.dtd.core.internal.emf.DTDRepeatableContent;
import org.eclipse.wst.dtd.core.internal.emf.DTDType;
import org.eclipse.wst.dtd.core.internal.emf.impl.DTDBasicTypeImpl;
import org.eclipse.wst.dtd.core.internal.emf.impl.DTDPackageImpl;
import org.eclipse.wst.dtd.core.internal.emf.util.DTDMetrics;
import org.eclipse.wst.dtd.core.internal.emf.util.DTDUtil;
import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocumentation;
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMEntityDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
import org.eclipse.wst.xml.core.internal.contentmodel.annotation.AnnotationMap;
import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMDataTypeImpl;
import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMEntityDeclarationImpl;
import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl;
import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNodeListImpl;
import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDescriptionBuilder;


public class DTDImpl {
	static {
		// Call init on the DTD package to avoid strange initialization bugs
		//
		DTDPackageImpl.init();
	}

	protected static DTDAdapterFactoryImpl dtdAdapterFactoryImpl = new DTDAdapterFactoryImpl();
	protected static CMDataTypeInfoTable cmDataTypeInfoTable = new CMDataTypeInfoTable();

	public static CMDocument buildCMDocument(String uri) {
		DTDFile dtdFile = buildDTDModel(uri);
		CMDocument cmDocument = (CMDocument) getAdapter(dtdFile);
		
		return cmDocument;
	}

	public static DTDFile buildDTDModel(String uri) {
		DTDUtil dtdUtil = new DTDUtil();
		dtdUtil.setexpandEntityReferences(true);
		dtdUtil.parse(new ResourceSetImpl(), uri);
		return dtdUtil.getDTDFile();
	}

	public static CMDocument buildCMDocument(DTDFile dtdFile) {
		return (CMDocument) getAdapter(dtdFile);
	}

	public static CMNode getAdapter(Notifier o) {
		return (CMNode) dtdAdapterFactoryImpl.adapt(o);
	}

	public static int getMinOccurHelper(DTDRepeatableContent content) {
		int occurence = content.getOccurrence().getValue();
		boolean isOptional = (occurence == DTDOccurrenceType.OPTIONAL || occurence == DTDOccurrenceType.ZERO_OR_MORE);
		return isOptional ? 0 : 1;
	}

	public static int getMaxOccurHelper(DTDRepeatableContent content) {
		int occurence = content.getOccurrence().getValue();
		boolean isMulti = (occurence == DTDOccurrenceType.ONE_OR_MORE || occurence == DTDOccurrenceType.ZERO_OR_MORE);
		return isMulti ? -1 : 1;
	}

	public static class DTDAdapterFactoryImpl extends AdapterFactoryImpl {
		public Adapter createAdapter(Notifier target) {
			Adapter result = null;
			if (target != null) {
				if (target instanceof DTDAttribute) {
					result = new DTDAttributeAdapter((DTDAttribute) target);
				}
				else if (target instanceof DTDElement) {
					result = new DTDElementAdapter((DTDElement) target);
				}
				else if (target instanceof DTDElementReferenceContent) {
					result = new DTDElementReferenceContentAdapter((DTDElementReferenceContent) target);
				}
				else if (target instanceof DTDFile) {
					result = new DTDFileAdapter((DTDFile) target);
				}
				else if (target instanceof DTDGroupContent) {
					result = new DTDGroupContentAdapter((DTDGroupContent) target);
				}
				else if (target instanceof DTDEntity) {
					result = new DTDEntityAdapter((DTDEntity) target);
				}
			}
			return result;
		}

		public synchronized Adapter adapt(Notifier target) {
			return adapt(target, this);
		}
	}

	/**
	 * DTDBaseAdapter
	 */
	public static abstract class DTDBaseAdapter extends CMNodeImpl {
		public String getNodeName() {
			return ""; //$NON-NLS-1$
		}

		public boolean isAdapterForType(Object type) {
			return type == dtdAdapterFactoryImpl;
		}

		public Object getProperty(String propertyName) {
			Object result = null;
			if (propertyName.equals("CMDocument")) { //$NON-NLS-1$
				result = getCMDocument();
			}
			else if (propertyName.equals(PROPERTY_DOCUMENTATION)) {
				result = getDocumentation();
			}
			else if (propertyName.equals(PROPERTY_DEFINITION_INFO)) {
				result = getDefinitionInfo();
			}
			else if (propertyName.equals(PROPERTY_DEFINITION)) {
				result = getDefinition();
			}
			else if (propertyName.equals(PROPERTY_MOF_NOTIFIER)) {
				result = getKey();
			}
			else if (propertyName.equals("spec")) { //$NON-NLS-1$
				result = getSpec();
			}
			else {
				result = super.getProperty(propertyName);
				if (result == null) {
					CMDocument cmDocument = getCMDocument();
					if (cmDocument instanceof DTDFileAdapter) {
						AnnotationMap map = ((DTDFileAdapter) cmDocument).annotationMap;
						if (map != null) {
							String spec = getSpec();
							if (spec != null) {
								result = map.getProperty(getSpec(), propertyName);
							}
						}
						if (result == null) {
							Map globalPropertyMap = ((DTDFileAdapter) cmDocument).globalPropertyMap;
							result = globalPropertyMap.get(propertyName);
						}
					}
				}
			}
			return result;
		}

		public CMDocument getCMDocument() {
			return null;
		}

		protected CMNodeList getDocumentation() {
			return new CMNodeListImpl();
		}

		public String getDefinitionInfo() {
			return null;
		}

		public CMNode getDefinition() {
			return null;
		}

		public String getSpec() {
			return getNodeName();
		}
	}

	/**
	 * DTDAttributeAdapter
	 */
	public static class DTDAttributeAdapter extends DTDBaseAdapter implements CMAttributeDeclaration {
		protected DTDAttribute attribute;
		protected CMDataType dataType;

		public DTDAttributeAdapter(DTDAttribute attribute) {
			this.attribute = attribute;
			dataType = new DataTypeImpl();
		}

		public Object getKey() {
			return attribute;
		}

		public String getSpec() {
			return attribute.getDTDElement().getName() + "/@" + attribute.getName(); //$NON-NLS-1$
		}

		public int getNodeType() {
			return ATTRIBUTE_DECLARATION;
		}

		public String getNodeName() {
			return attribute.getName();
		}

		public String getAttrName() {
			return attribute.getName();
		}

		public CMDataType getAttrType() {
			return dataType;
		}

		public String getDefaultValue() {
			return attribute.getDefaultValueString();
		}

		public Enumeration getEnumAttr() {
			return Collections.enumeration(attribute.getEnumeratedValues());
		}

		public int getUsage() {
			int usage = OPTIONAL;
			switch (attribute.getDefaultKind().getValue()) {
				case DTDDefaultKind.REQUIRED : {
					usage = REQUIRED;
					break;
				}
				case DTDDefaultKind.FIXED : {
					usage = FIXED;
					break;
				}
			}
			return usage;
		}

		public CMDocument getCMDocument() {
			DTDFile dtdFile = attribute.getDTDElement().getDTDFile();
			return dtdFile != null ? (CMDocument) getAdapter(dtdFile) : null;
		}

		public class DataTypeImpl implements CMDataType {
			public int getNodeType() {
				return CMNode.DATA_TYPE;
			}

			public String getNodeName() {
				return getDataTypeName();
			}

			public boolean supports(String propertyName) {
				return false;
			}

			public Object getProperty(String propertyName) {
				Object result = null;
				if (propertyName.equals("isValidEmptyValue")) { //$NON-NLS-1$
					String dataTypeName = getDataTypeName();
					result = (dataTypeName == null || dataTypeName.equals(CMDataType.CDATA)) ? "true" : "false"; //$NON-NLS-1$ //$NON-NLS-2$
				}
				return result;
			}

			public String getDataTypeName() {
				return cmDataTypeInfoTable.getDataTypeName(attribute.getDTDType());
			}

			public String generateInstanceValue() {
				return cmDataTypeInfoTable.getInstanceValue(attribute.getDTDType());
			}

			public int getImpliedValueKind() {
				int result = IMPLIED_VALUE_NONE;
				int defaultValueKind = attribute.getDefaultKind().getValue();
				if (defaultValueKind == DTDDefaultKind.NOFIXED) {
					result = IMPLIED_VALUE_DEFAULT;
				}
				else if (defaultValueKind == DTDDefaultKind.FIXED) {
					result = IMPLIED_VALUE_FIXED;
				}
				return result;
			}

			public String getImpliedValue() {
				return attribute.getDefaultValueString();
			}

			public String[] getEnumeratedValues() {
				Object[] objectList = attribute.getEnumeratedValues().toArray();
				String[] result = new String[objectList.length];
				for (int i = 0; i < objectList.length; i++) {
					result[i] = objectList[i].toString();
				}
				return result;
			}
		}
	}


	/**
	 * DTDElementBaseAdapter
	 */
	public static abstract class DTDElementBaseAdapter extends DTDBaseAdapter implements CMElementDeclaration {
		protected CMDataType dataType;

		protected abstract DTDElement getDTDElement();

		protected CMDocumentation documentation = null;

		public int getNodeType() {
			return ELEMENT_DECLARATION;
		}

		public String getNodeName() {
			return getDTDElement().getName();
		}

		public CMNamedNodeMap getAttributes() {
			CMNamedNodeMapImpl result = new CMNamedNodeMapImpl();
			List attributeList = getDTDElement().getDTDAttribute();
			for (Iterator i = attributeList.iterator(); i.hasNext();) {
				DTDAttribute attribute = (DTDAttribute) i.next();
				result.getHashtable().put(attribute.getName(), getAdapter(attribute));
			}
			return result;
		}

		public CMContent getContent() {
			return (CMContent) getAdapter(getDTDElement().getContent());
		}

		public int getContentType() {
			// todo
			int result = ELEMENT;
			DTDElementContent dtdElementContent = getDTDElement().getContent();
			if (dtdElementContent instanceof DTDPCDataContent) {
				result = PCDATA;
			}
			else if (dtdElementContent instanceof DTDGroupContent) {
				DTDGroupContent groupContent = (DTDGroupContent) dtdElementContent;
				int groupKind = groupContent.getGroupKind().getValue();
				if (groupKind == DTDGroupKind.CHOICE) {
					List list = groupContent.getContent();
					if (list.size() > 0 && list.get(0) instanceof DTDPCDataContent) {
						result = MIXED;
					}
				}
			}
			else if (dtdElementContent instanceof DTDAnyContent) {
				result = ANY;
			}
			else if (dtdElementContent instanceof DTDEmptyContent) {
				result = EMPTY;
			}

			return result;
		}

		public String getElementName() {
			return getDTDElement().getName();
		}

		public CMDataType getDataType() {
			int contentType = getContentType();
			boolean hasDataType = contentType == PCDATA || contentType == MIXED;
			return hasDataType ? dataType : null;
		}

		public CMNamedNodeMap getLocalElements() {
			return CMNamedNodeMapImpl.EMPTY_NAMED_NODE_MAP;
		}

		public CMDocument getCMDocument() {
			DTDFile dtdFile = getDTDElement().getDTDFile();
			return dtdFile != null ? (CMDocument) getAdapter(dtdFile) : null;
		}

		protected CMNodeList getDocumentation() {
			CMNodeListImpl nodeList = new CMNodeListImpl();
			if (documentation == null) {
				String comment = getDTDElement().getComment();
				if (comment != null) {
					String value = ""; //$NON-NLS-1$
					StringTokenizer st = new StringTokenizer(comment, "\n"); //$NON-NLS-1$
					while (st.hasMoreTokens()) {
						value += st.nextToken().trim() + "\n"; //$NON-NLS-1$
					}
					documentation = new CMDocumentationImpl(value);
				}
			}
			if (documentation != null) {
				nodeList.getList().add(documentation);
			}
			return nodeList;
		}
	}


	public static class CMDocumentationImpl implements CMDocumentation {
		protected String value;

		public CMDocumentationImpl(String value) {
			this.value = value;
		}

		public String getNodeName() {
			return ""; //$NON-NLS-1$
		}

		public int getNodeType() {
			return DOCUMENTATION;
		}

		public boolean supports(String propertyName) {
			return false;
		}

		public Object getProperty(String propertyName) {
			return null;
		}

		public String getValue() {
			return value;
		}

		public String getLanguage() {
			return null;
		}

		public String getSource() {
			return null;
		}
	}


	/**
	 * DTDElementAdapter
	 */
	public static class DTDElementAdapter extends DTDElementBaseAdapter {
		protected DTDElement element;

		public DTDElementAdapter(DTDElement element) {
			this.element = element;			
			dataType = new CMDataTypeImpl("#PCDATA", getDTDElement().getName()); //$NON-NLS-1$
		}

		public Object getKey() {
			return element;
		}

		protected DTDElement getDTDElement() {
			return element;
		}

		public int getMinOccur() {
			if(element.getContent() instanceof DTDRepeatableContent){
				return getMinOccurHelper((DTDRepeatableContent) element.getContent());
			}
			return 1;
		}

		public int getMaxOccur() {
			if(element.getContent() instanceof DTDRepeatableContent){
				return getMaxOccurHelper((DTDRepeatableContent) element.getContent());
			}
			return 1;
		}

		public String getDefinitionInfo() {
			return "global"; //$NON-NLS-1$
		}

		public CMNode getDefinition() {
			return this;
		}
	}


	/**
	 * DTDElementReferenceContentAdapter
	 */
	public static class DTDElementReferenceContentAdapter extends DTDElementBaseAdapter {
		protected DTDElementReferenceContent content;

		public DTDElementReferenceContentAdapter(DTDElementReferenceContent content) {
			this.content = content;
			dataType = new CMDataTypeImpl("#PCDATA", getDTDElement().getName()); //$NON-NLS-1$
		}

		public Object getKey() {
			return content;
		}

		protected DTDElement getDTDElement() {
			return content.getReferencedElement();
		}

		public int getMinOccur() {
			return getMinOccurHelper(content);
		}

		public int getMaxOccur() {
			return getMaxOccurHelper(content);
		}


		public CMNode getDefinition() {
			return getAdapter(getDTDElement());
		}
	}


	/**
	 * DTDEntityAdapter
	 */
	public static class DTDEntityAdapter extends DTDBaseAdapter implements CMEntityDeclaration {
		protected DTDEntity dtdEntity;

		public DTDEntityAdapter(DTDEntity dtdEntity) {
			this.dtdEntity = dtdEntity;
		}

		public int getNodeType() {
			return ENTITY_DECLARATION;
		}

		public Object getKey() {
			return dtdEntity;
		}

		public String getName() {
			return dtdEntity.getName();
		}

		public String getValue() {
			String value = ""; //$NON-NLS-1$
			if (dtdEntity.getContent() instanceof DTDInternalEntity) {
				DTDInternalEntity content = (DTDInternalEntity) dtdEntity.getContent();
				value = content.getValue();
			}
			return value;
		}
	}


	/**
	 * DTDGroupContentAdapter
	 */
	public static class DTDGroupContentAdapter extends DTDBaseAdapter implements CMGroup {
		protected DTDGroupContent content;

		public DTDGroupContentAdapter(DTDGroupContent content) {
			this.content = content;
		}

		public Object getKey() {
			return content;
		}

		public int getNodeType() {
			return GROUP;
		}

		public String getNodeName() {
			CMDescriptionBuilder descriptionBuilder = new CMDescriptionBuilder();
			return descriptionBuilder.buildDescription(this);
		}

		public CMNodeList getChildNodes() {
			List list = content.getContent();
			CMNodeListImpl result = new CMNodeListImpl();
			for (Iterator i = list.iterator(); i.hasNext();) {
				CMNode node = getAdapter((Notifier) i.next());
				if (node != null) {
					result.getList().add(node);
				}
			}
			return result;
		}


		public int getMaxOccur() {
			return getMaxOccurHelper(content);
		}

		public int getMinOccur() {
			return getMinOccurHelper(content);
		}

		public int getOperator() {
			// todo... handle ALONE case by checkig if child count == 1
			int groupKind = content.getGroupKind().getValue();
			return (groupKind == DTDGroupKind.CHOICE) ? CHOICE : SEQUENCE;
		}
	}

	/**
	 * DTDFileAdapter
	 */
	public static class DTDFileAdapter extends DTDBaseAdapter implements CMDocument {
		protected final String DEFAULT_ROOT_NAME = "http://org.eclipse.wst/cm/properties/defaultRootName"; //$NON-NLS-1$

		protected DTDFile dtdFile;
		protected CMNamedNodeMapImpl namedNodeMap;
		protected CMNamedNodeMapImpl entityNodeMap;

		protected AnnotationMap annotationMap = new AnnotationMap();
		protected Map globalPropertyMap = new HashMap();

		public DTDFileAdapter(DTDFile dtdFile) {
			this.dtdFile = dtdFile;
		}

		public Object getKey() {
			return dtdFile;
		}

		public AnnotationMap getAnnotationMap() {
			return annotationMap;
		}

		public CMNamedNodeMap getElements() {
			if (namedNodeMap == null) {
				namedNodeMap = new CMNamedNodeMapImpl();
				for (Iterator iterator = dtdFile.listDTDElement().iterator(); iterator.hasNext();) {
					DTDElement dtdElement = (DTDElement) iterator.next();
					namedNodeMap.getHashtable().put(dtdElement.getName(), getAdapter(dtdElement));
				}
			}
			return namedNodeMap;
		}

		public CMNamedNodeMap getEntities() {
			if (entityNodeMap == null) {
				entityNodeMap = new CMNamedNodeMapImpl();

				// add the built in entity declarations
				//
				entityNodeMap.getHashtable().put("amp", new CMEntityDeclarationImpl("amp", "&")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				entityNodeMap.getHashtable().put("lt", new CMEntityDeclarationImpl("lt", "<")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				entityNodeMap.getHashtable().put("gt", new CMEntityDeclarationImpl("gt", ">")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				entityNodeMap.getHashtable().put("quot", new CMEntityDeclarationImpl("quot", "\"")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				entityNodeMap.getHashtable().put("apos", new CMEntityDeclarationImpl("apos", "'")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

				for (Iterator i = dtdFile.listDTDEntity().iterator(); i.hasNext();) {
					DTDEntity dtdEntity = (DTDEntity) i.next();
					if (!dtdEntity.isParameterEntity() && dtdEntity.getName() != null) {
						// for now... just handle DTDInternalEntity
						//
						if (dtdEntity.getContent() instanceof DTDInternalEntity) {
							entityNodeMap.getHashtable().put(dtdEntity.getName(), getAdapter(dtdEntity));
						}
					}
				}
			}
			return entityNodeMap;
		}

		public CMNamespace getNamespace() {
			return null;
		}

		public int getNodeType() {
			return DOCUMENT;
		}

		public String getNodeName() {
			return dtdFile.getName() + ".dtd"; //$NON-NLS-1$
		}

		public Object getProperty(String propertyName) {
			Object result = null;
			if (propertyName.equals(DEFAULT_ROOT_NAME)) {
				DTDMetrics metrics = new DTDMetrics(dtdFile);
				DTDElement dtdElement = metrics.getLeastReferencedElement();
				if (dtdElement != null) {
					result = dtdElement.getName();
				}
			}
			else if (propertyName.equals("annotationMap")) { //$NON-NLS-1$
				result = annotationMap;
			}
			else if (propertyName.equals("globalPropertyMap")) { //$NON-NLS-1$
				result = globalPropertyMap;
			}
			else {
				result = super.getProperty(propertyName);
			}
			return result;
		}
	}


	public static class CMDataTypeInfoTable {
		protected String[] instanceValueTable;
		protected String[] dataTypeNameTable;

		public CMDataTypeInfoTable() {
			// hashtable.put(DTDType.CDATA, null));
			instanceValueTable = new String[DTDBasicTypeImpl.basicTypeKinds.length];
			instanceValueTable[DTDBasicTypeKind.ENTITY] = "entity"; //$NON-NLS-1$
			instanceValueTable[DTDBasicTypeKind.ENTITIES] = "entities"; //$NON-NLS-1$
			instanceValueTable[DTDBasicTypeKind.NMTOKEN] = "nmtoken"; //$NON-NLS-1$
			instanceValueTable[DTDBasicTypeKind.NMTOKENS] = "nmtokens"; //$NON-NLS-1$

			dataTypeNameTable = new String[DTDBasicTypeImpl.basicTypeKinds.length];
			dataTypeNameTable[DTDBasicTypeKind.CDATA] = CMDataType.CDATA;
			dataTypeNameTable[DTDBasicTypeKind.ID] = CMDataType.ID;
			dataTypeNameTable[DTDBasicTypeKind.IDREF] = CMDataType.IDREF;
			dataTypeNameTable[DTDBasicTypeKind.IDREFS] = CMDataType.IDREFS;
			dataTypeNameTable[DTDBasicTypeKind.ENTITY] = CMDataType.ENTITY;
			dataTypeNameTable[DTDBasicTypeKind.ENTITIES] = CMDataType.ENTITIES;
			dataTypeNameTable[DTDBasicTypeKind.NMTOKEN] = CMDataType.NMTOKEN;
			dataTypeNameTable[DTDBasicTypeKind.NMTOKENS] = CMDataType.NMTOKENS;
		}

		public String getInstanceValue(DTDType dtdType) {
			String result = null;
			if (dtdType instanceof DTDBasicType) {
				int kind = ((DTDBasicType) dtdType).getKind().getValue();
				if (kind >= 0 && kind < DTDBasicTypeImpl.basicTypeDescriptions.length) {
					result = instanceValueTable[kind];
				}
			}
			return result;
		}

		public String getDataTypeName(DTDType dtdType) {
			String result = null;
			if (dtdType instanceof DTDBasicType) {
				int kind = ((DTDBasicType) dtdType).getKind().getValue();
				if (kind >= 0 && kind < DTDBasicTypeImpl.basicTypeDescriptions.length) {
					result = dataTypeNameTable[kind];
				}
			}
			else if (dtdType instanceof DTDEnumerationType) {
				result = CMDataType.ENUM;
			}
			return result;
		}
	}
}
