/*******************************************************************************
 * Copyright (c) 2002, 2003 Object Factory Inc.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *		Object Factory Inc. - Initial implementation
 *******************************************************************************/
package org.eclipse.ant.ui.internal.dtd.schema;

import java.text.MessageFormat;
import java.util.HashSet;
import java.util.LinkedList;

import org.eclipse.ant.ui.internal.dtd.IModel;
import org.eclipse.ant.ui.internal.dtd.ISchema;
import org.xml.sax.SAXException;
import org.xml.sax.ext.DeclHandler;

/**
 * SchemaFactory is a SAX DeclHandler that converts DTD ELEMENT and ATTLIST
 * declarations to schema form on the fly. The only two methods available to
 * external users of SchemaFactory are its constructor and
 * <code>getSchema()</code>. The latter returns the schema built by this process
 * and should not be called until the XML parser to which this handler is
 * attached has finished parsing.
 * @author Bob Foster
 */
public class SchemaFactory implements DeclHandler {
	// used for parsing models
	private char[] fBuf;
	private int fLen;
	private int fPos;
	private Element fElement;
	
	private Schema fSchema;
	private static HashSet fTypes = new HashSet();
	private Exception fErrorException;
	static {
		fTypes.add("CDATA"); //$NON-NLS-1$
		fTypes.add("ID"); //$NON-NLS-1$
		fTypes.add("IDREF"); //$NON-NLS-1$
		fTypes.add("IDREFS"); //$NON-NLS-1$
		fTypes.add("NMTOKEN"); //$NON-NLS-1$
		fTypes.add("NMTOKENS"); //$NON-NLS-1$
		fTypes.add("ENTITY"); //$NON-NLS-1$
		fTypes.add("ENTITIES"); //$NON-NLS-1$
	}
	
	/**
	 * Constructor.
	 */
	public SchemaFactory() {
		fSchema = new Schema();
	}
	
	/**
	 * @return ISchema produced from the DeclHandler. The schema is always
	 * correct, though it may be incomplete if the parse was interrupted due to
	 * validation or well-formed errors.
	 */
	public ISchema getSchema() {
		fSchema.setErrorException(fErrorException);
		return fSchema;
	}
	
	/**
	 * @see org.xml.sax.ext.DeclHandler#attributeDecl(java.lang.String, java.lang.String, java.lang.String, java.lang.String, java.lang.String)
	 */
	public void attributeDecl(String eName, String aName, String type, String valueDefault, String value) throws SAXException {
		Element element = getElement(eName);
		Attribute attr = (Attribute) element.getAttributes().get(aName);
		if (attr == null) {
			attr = new Attribute(aName, element);
			element.addAttribute(attr);
			
			String[] enum = null;
			if (fTypes.contains(type))
				attr.setType(type);
			else if (type.startsWith("NOTATION")) //$NON-NLS-1$
				enum = parseValues(type.substring("NOTATION".length()+1), ','); //$NON-NLS-1$
			else {
			    type = stripSurroundingParentheses(type);
				enum = parseValues(type, '|');
			}
			attr.setEnum(enum);
			
			attr.setRequired(valueDefault == null || !valueDefault.equals("#IMPLIED")); //$NON-NLS-1$
			attr.setFixed(valueDefault != null && valueDefault.equals("#FIXED")); //$NON-NLS-1$
			attr.setDefault(value);
		}
	}
	

    /**
     * Strips the surrounding parentheses from <code>aString</code>.
     * <P>
     * i.e.: (true|false) -> true|false
     */
    private String stripSurroundingParentheses(String aString) {
        if(aString.startsWith("(")) { //$NON-NLS-1$
            aString = aString.substring(1);
        }
        if(aString.endsWith(")")) { //$NON-NLS-1$
            aString = aString.substring(0, aString.length()-1);
        }
        return aString;
    }
	
	
	/**
	 * @param eName Element name
	 * @return Element from schema or new element. Either way
	 * the element is in the schema upon return.
	 */
	private Element getElement(String eName) {
		Element element = (Element) fSchema.getElement(eName);
		if (element == null) {
			element = new Element(eName);
			fSchema.addElement(element); 
		}
		return element;
	}

	private String[] parseValues(String type, char separator) {
		int start = 0, pos, len = type.length();
		LinkedList values = new LinkedList();
		while (start < len) {
			pos = type.indexOf(separator, start);
			if (pos < 0) pos = len;
			String term = type.substring(start, pos);
			start = pos + 1;
			values.add(term);
		}
		return (String[]) values.toArray(new String[values.size()]);
	}

	/**
	 * @see org.xml.sax.ext.DeclHandler#elementDecl(java.lang.String, java.lang.String)
	 */
	public void elementDecl(String name, String model) throws SAXException {
		Element element = getElement(name);
		if (!element.isUndefined()) {
			// if the element has already been defined, this is an error
			throw new SAXException(MessageFormat.format(AntDTDSchemaMessages.getString("SchemaFactory.Doubly_defined"), new String[]{name})); //$NON-NLS-1$
		}
		
		fElement = element;
		if (model.equals("ANY")) //$NON-NLS-1$
			element.setAny(true);
		else if (model.equals("EMPTY")) //$NON-NLS-1$
			element.setEmpty(true);
		else if (model.equals("(#PCDATA)")) //$NON-NLS-1$
			element.setText(true);
		else if (model.startsWith("(#PCDATA")) //$NON-NLS-1$
			element.setMixed(true);
		else
			element.setContentModel(parseModel(model));
	}

	/**
	 * Convert model string to IModel. The <code>fElement</code>
	 * variable is an implicit argument to this method, and it
	 * sets <code>fBuf</code>, <code>fPos</code> and <code>fLen</code> for use
	 * by other parser methods.
	 * @param model String from DTD, with parameter entities replaced.
	 * @return IModel
	 * @throws SAXException if syntax error detected in model. This is a
	 * validation error. Since the DTD is usually not read unless the parser is
	 * validating, we may not ever be handed a bad content model, but we need to
	 * check them, just the same.
	 */
	private IModel parseModel(String model) throws SAXException {
		fBuf = model.toCharArray();
		fLen = fBuf.length;
		if (fBuf[0] != '(') {
			throw new SAXException(
				MessageFormat.format(AntDTDSchemaMessages.getString("SchemaFactory.Start_with_left_parenthesis"), new String[]{fElement.getName()})); //$NON-NLS-1$
		}

		IModel emodel;
		boolean ortext = model.startsWith("(#PCDATA|"); //$NON-NLS-1$
		if (ortext) {
			fPos = "(#PCDATA".length() + 1; //$NON-NLS-1$
			emodel = scanExpr();
		}
		else {
			fPos = 0;
			emodel = scanExpr();
		}
		return emodel;
	}

	/**
	 * Scan a parenthesized expression starting
	 * from the left parenthesis or leftmost operator.
	 * @return IModel
	 */
	private IModel scanExpr() throws SAXException {
		// skip opening ( or |
		fPos++;
		return scanExpr(scanElement());
	}
	
	/**
	 * Scan a parenthesized expression with the
	 * first term in hand.
	 * @param term The first operand in the expression, pre-scanned.
	 * @return IModel
	 * @throws SAXException if errors are detected in the model.
	 */
	private IModel scanExpr(IModel term) throws SAXException {
		checkLen();
		if (fBuf[fPos] != ')') {
			char op = fBuf[fPos];
			if (op != '|' && op != ',') {
				throw new SAXException(
					MessageFormat.format(AntDTDSchemaMessages.getString("SchemaFactory.Expecting_operator_or_right_parenthesis"),  //$NON-NLS-1$
						new String[]{fElement.getName(),String.valueOf(fBuf)}));
			}
			Model model = new Model(op == '|' ? IModel.CHOICE : IModel.SEQUENCE);
			model.addModel(term);
			term = model;
			
			while (fBuf[fPos] == op) {
				fPos++;
				IModel next = scanElement();
				model.addModel(next);
			}
			if (fBuf[fPos] != ')') {
				throw new SAXException(
						MessageFormat.format(AntDTDSchemaMessages.getString("SchemaFactory.Expecting_operator_or_right_parenthesis"),  //$NON-NLS-1$
						new String[]{fElement.getName(), String.valueOf(fBuf)}));					
			}
			fPos++;
		}
		return term;
	}

	/**
	 * Scan an element name or a parenthesized sub-expression.
	 * @return IModel
	 * @throws SAXException
	 */
	private IModel scanElement() throws SAXException {
		checkLen();
		if (fBuf[fPos] == '(')
			return scanExpr();
		StringBuffer sb = new StringBuffer();
		while (fBuf[fPos] != '|' && fBuf[fPos] != ',' && fBuf[fPos] != ')'
		&& fBuf[fPos] != '*' && fBuf[fPos] != '+' && fBuf[fPos] != '?' ) {
			sb.append(fBuf[fPos++]);
			checkLen();
		}
		String name = sb.toString();
		Element element = getElement(name);
		Model model = new Model(IModel.LEAF);
		model.setLeaf(element);
		return model;
	}

	private void checkLen() throws SAXException {
		if (fPos == fLen) {
			throw new SAXException(
				MessageFormat.format(AntDTDSchemaMessages.getString("SchemaFactory.Unexpected_end"),  //$NON-NLS-1$
					new String[]{fElement.getName(),
						String.valueOf(fBuf)}));
		}	
	}

	/**
	 * @see org.xml.sax.ext.DeclHandler#externalEntityDecl(java.lang.String, java.lang.String, java.lang.String)
	 */
	public void externalEntityDecl(String name, String publicId, String systemId) throws SAXException {
	}

	/**
	 * @see org.xml.sax.ext.DeclHandler#internalEntityDecl(java.lang.String, java.lang.String)
	 */
	public void internalEntityDecl(String name, String value) throws SAXException {
	}

	public void setErrorException(Exception e) {
		fErrorException = e;
	}
}
