/*******************************************************************************
 * Copyright (c) 2004 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.jst.jsp.ui.tests.modelquery;

import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.textui.TestRunner;

import org.eclipse.core.runtime.Platform;
import org.eclipse.jst.jsp.ui.internal.JSPUIPlugin;
import org.eclipse.jst.jsp.ui.tests.JSPUITestsPlugin;
import org.eclipse.jst.jsp.ui.tests.Logger;
import org.eclipse.wst.html.core.HTML40Namespace;
import org.eclipse.wst.html.core.contenttype.ContentTypeIdForHTML;
import org.eclipse.wst.sse.core.IStructuredModel;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.ui.registry.AdapterFactoryProvider;
import org.eclipse.wst.sse.ui.registry.AdapterFactoryRegistry;
import org.eclipse.wst.xml.core.contenttype.ContentTypeIdForXML;
import org.eclipse.wst.xml.core.document.IDOMModel;
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.CMElementDeclaration;
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.CMNode;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * @author pavery
 */
public class ModelQueryTester extends TestCase {

	private final boolean testShippedDTDLookup = false;

	// Our Structured Model, which should always be an XMLModel (or subclass)
	protected IDOMModel fModel = null;

	protected ModelQuery fModelQuery = null;

	public ModelQueryTester(String name) {
		super(name);
	}

	protected static Test suite() {
		return new TestSuite(ModelQueryTester.class);
	}

	public static void main(java.lang.String[] args) {
		if (args == null || args.length == 0) {
			runAll();
		} else if (args.length == 1) {
			String methodToRun = args[0].trim();
			runOne(methodToRun);
		}

	}

	protected static void runAll() {
		TestRunner.run(suite());

	}

	protected static void runOne(String methodName) {
		TestSuite testSuite = new TestSuite();
		TestCase test = new ModelQueryTester(methodName);
		testSuite.addTest(test);
		junit.textui.TestRunner.run(testSuite);
	}

	/**
	 * Create an empty HTML model
	 */
	protected void setUpHTML() {
		fModel = (IDOMModel) createModel(ContentTypeIdForHTML.ContentTypeID_HTML);
		initVars();
	}

	/**
	 * Create an empty XML model
	 */
	protected void setUpXML() {
		fModel = (IDOMModel) createModel(ContentTypeIdForXML.ContentTypeID_XML);
		initVars();
	}

	/**
	 * @see junit.framework.TestCase#setUp()
	 */
	protected void setUp() throws Exception {
		super.setUp();

		// This method was emptied when a test case required a different model
		// type than HTML. At that point, we needed separate methods to create
		// each type
		// and had to call them from the test cases directly, like in
		// ScannerUnitTests
	}

	/**
	 * Initialize local fields for this test
	 */
	protected void initVars() {
		fModelQuery = ModelQueryUtil.getModelQuery(fModel.getDocument());


	}

	/**
	 * Test the HTML BODY Element for the "bgcolor" attribute declaration
	 */
	public void testBodyElement() {
		setUpHTML();
		fModel.getStructuredDocument().set("<html><body bgcolor=\"#ffffff\"><form method=\"post\"></form></body></html>"); // set
		// text

		// TEST getting a CMElementDeclaration
		Element bodyElement = (Element) fModel.getIndexedRegion(7); // node at
		// offset7--should
		// be
		// <body>
		CMElementDeclaration bodyDecl = fModelQuery.getCMElementDeclaration(bodyElement);

		int contentType = bodyDecl.getContentType();
		assertTrue("CMElementDeclaration CONTENT TYPE INCORRECT FOR BODY", (contentType == CMElementDeclaration.MIXED));

		// get permissible attrs
		CMNamedNodeMap map = bodyDecl.getAttributes();
		assertTrue("ATTRIBUTES FROM ELEMENT DECLARATION == NULL", (map != null));
		Vector allowed = new Vector();
		for (int i = 0; i < map.getLength(); i++) {
			CMAttributeDeclaration node = (CMAttributeDeclaration) map.item(i);
			String name = node.getNodeName();
			allowed.add(name);
			if (name.equalsIgnoreCase("bgcolor")) {
				assertTrue("GOT INCORRECT ATTRIBUTE NODE TYPE", (node.getNodeType() == CMNode.ATTRIBUTE_DECLARATION));

				CMDataType attrType = node.getAttrType();
				// System.out.println("attribute type > " + attrType);
				assertTrue("COULD NOT GET ATTRIBUTE TYPE", (attrType != null));
				assertTrue("COULDN'T GET IMPLIED VALUE KIND", (attrType.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_NONE));
			}
		}
	}

	/**
	 * Test the HTML HTML Element for its declared children
	 */
	public void testHtmlChildren() {
		setUpHTML();
		fModel.getStructuredDocument().set("<html></html>"); // set text
		Element htmlElement = fModel.getDocument().getDocumentElement();
		CMElementDeclaration htmlDecl = fModelQuery.getCMElementDeclaration(htmlElement);

		// HTML's children are within a group
		CMContent contents = htmlDecl.getContent();

		assertTrue("content type is not a group", contents.getNodeType() == CMNode.GROUP);

		CMGroup group = (CMGroup) contents;
		int operator = group.getOperator();
		CMNodeList childList = group.getChildNodes();
		int max = contents.getMaxOccur();
		int min = contents.getMinOccur();

		// the group should be allowed once, with a sequence whose first entry
		// is the declaration for HEAD
		assertTrue("occurrance of group", min == 1 && max == 1);
		assertTrue("relationship in group", operator == CMGroup.SEQUENCE);
		assertTrue("content descriptor type, position 0", contents.getNodeType() == CMNode.GROUP);
		assertTrue("child order (HEAD first)", childList.item(0).getNodeName().equalsIgnoreCase(HTML40Namespace.ElementName.HEAD));

		assertTrue("content descriptor type, position 1", childList.item(1).getNodeType() == CMNode.GROUP);
		// The second child should be a group as well, containing BODY and
		// FRAMESET with an
		// operator of CMGroup.CHOICE
		assertTrue("content descriptor type, position 1 - relationship of group", ((CMGroup) childList.item(1)).getOperator() == CMGroup.CHOICE);
	}

	public void testFormMethodAttr() {
		setUpHTML();
		fModel.getStructuredDocument().set("<html><body bgcolor=\"#ffffff\"><form method=\"post\"></form></body></html>"); // set
		// text

		// TEST GETTING A CMAttributeDeclaratoin
		Element formElement = (Element) fModel.getIndexedRegion(31); // <form>
		Attr attrNode = formElement.getAttributeNode(HTML40Namespace.ATTR_NAME_METHOD);
		CMAttributeDeclaration methodAttrDecl = fModelQuery.getCMAttributeDeclaration(attrNode);
		assertTrue("Content Model missing the attribute declaration for \"method\"", methodAttrDecl != null);

		List values = getValidStrings(formElement, methodAttrDecl);
		assertTrue("wrong number of values for attribute \"method\"", (values.size() == 2));
		assertTrue("default value for attribute \"method\" is wrong", (methodAttrDecl.getAttrType().getImpliedValue().equalsIgnoreCase("get")));
	}

	/**
	 * A short test to ensure that a DTD can be loaded from a system
	 * reference.
	 * 
	 * Note: May require a functioning network connection for the references
	 * to be resolved properly.
	 */
	public void testDTDLoadFromSystemID_1() {
		if (testShippedDTDLookup) {
			setUpXML();
			URL installationPath = Platform.getBundle(JSPUITestsPlugin.ID).getEntry("/");
			String diskLocation = null;
			try {
				diskLocation = Platform.resolve(installationPath).toExternalForm();
			} catch (IOException e) {
			} catch (NullPointerException e) {
			}
			assertTrue("failed to resolve plugin install path", diskLocation != null);
			String content = "<?xml version=\"1.0\"?><!DOCTYPE html SYSTEM " + diskLocation + "TestFiles/DTDs/wapDTDs/WAP-2-0/wml20.dtd\"" + "><html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:wml=\"http://www.wapforum.org/2001/wml\"></html>";
			fModel.getStructuredDocument().set(content);
			CMDocumentManager documentManagaer = fModelQuery.getCMDocumentManager();
			documentManagaer.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD, false);
			documentManagaer.setPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD, true);

			Node domNode = (Node) fModel.getIndexedRegion(content.length() - 2);
			CMNode node = fModelQuery.getCMNode(domNode);
			assertTrue("wml20.dtd failed to load", node != null && node.getNodeName().equalsIgnoreCase("html"));
		}
	}


	/**
	 * A short test to ensure that a DTD, the XHTML 1.0 Transitional one, can
	 * be loaded from a system reference.
	 * 
	 * Note: May require a functioning network connection for the references
	 * to be resolved properly.
	 */
	public void testDTDLoadFromSystemID_2() {
		if (testShippedDTDLookup) {
			URL installationPath = Platform.getBundle(JSPUITestsPlugin.ID).getEntry("/");
			String diskLocation = null;
			try {
				diskLocation = Platform.resolve(installationPath).toExternalForm();
			} catch (IOException e) {
			} catch (NullPointerException e) {
			}
			assertTrue("failed to resolve plugin install path", diskLocation != null);
			setUpXML();
			String content = "<?xml version=\"1.0\"?><!DOCTYPE html SYSTEM " + diskLocation + "testfiles/XHTML/xhtml1-transitional.dtd\"" + "><html></html>";
			fModel.getStructuredDocument().set(content);

			CMDocumentManager documentManagaer = fModelQuery.getCMDocumentManager();
			documentManagaer.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD, false);
			documentManagaer.setPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD, true);

			// see defect 282429
			CMElementDeclaration htmlDecl = (CMElementDeclaration) fModelQuery.getCMNode((Node) fModel.getIndexedRegion(content.length() - 2));
			assertTrue("xhtml1-transitional.dtd not loaded", htmlDecl != null);

			// HTML's children are within a group
			CMContent contents = htmlDecl.getContent();

			assertTrue("content type is not a group", contents.getNodeType() == CMNode.GROUP);

			CMGroup group = (CMGroup) contents;
			int operator = group.getOperator();
			CMNodeList childList = group.getChildNodes();
			int max = contents.getMaxOccur();
			int min = contents.getMinOccur();

			// the group should be allowed once, with a sequence whose first
			// entry
			// is the declaration for HEAD
			assertTrue("occurrance of group", min == 1 && max == 1);
			assertTrue("relationship in group", operator == CMGroup.SEQUENCE);
			assertTrue("content descriptor type, position 0", contents.getNodeType() == CMNode.GROUP);
			assertTrue("child order (HEAD first)", childList.item(0).getNodeName().equals(HTML40Namespace.ElementName.HEAD.toLowerCase()));
			assertTrue("child order (BODY second)", childList.item(1).getNodeName().equals(HTML40Namespace.ElementName.BODY.toLowerCase()));
		}
	}

	/**
	 * A short test to ensure that the DTD for JSP 1.2 tag libraries can be
	 * loaded from a public reference registered in the XML catalog
	 */
	public void testDTDLoadFromPublicID() {
		// No longer provided in WTP
		// TODO: provide DTD?
//		if (testShippedDTDLookup) {
//			setUpXML();
//			String contents = "<!DOCTYPE taglib PUBLIC \"-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN\"> <taglib><tag>foo</tag></taglib>";
//			fModel.getStructuredDocument().set(contents);
//
//			CMDocumentManager documentManagaer = fModelQuery.getCMDocumentManager();
//			documentManagaer.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD, false);
//			documentManagaer.setPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD, true);
//
//
//			// taglib
//			CMNode node = fModelQuery.getCMNode((Node) fModel.getIndexedRegion(contents.length() - 2));
//			assertTrue("web-jsptaglibrary_1_2.dtd failed to load through catalog", node != null && node.getNodeType() == CMNode.ELEMENT_DECLARATION && node.getNodeName().equalsIgnoreCase("taglib"));
//
//			// tag
//			node = fModelQuery.getCMNode((Node) fModel.getIndexedRegion(contents.length() - 12));
//			assertTrue("CMElementDeclaration for \"tag\" from web-jsptaglibrary_1_2.dtd is missing", node != null && node.getNodeType() == CMNode.ELEMENT_DECLARATION && node.getNodeName().equalsIgnoreCase("tag"));
//			CMContent content = ((CMElementDeclaration) node).getContent();
//			assertTrue("only one occurrence of child group allowed", content.getNodeType() == CMNode.GROUP && content.getMaxOccur() == 1);
//		}
	}

	/**
	 * @see junit.framework.TestCase#tearDown()
	 */
	protected void tearDown() throws Exception {
		super.tearDown();
	}

	public static IStructuredModel createModel(String contentTypeID) {
		// create an empty model with its default factories
		IStructuredModel model = StructuredModelManager.getModelManager().createUnManagedStructuredModelFor(contentTypeID);

		// add editor adapter factories
		AdapterFactoryRegistry adapterRegistry = JSPUIPlugin.getDefault().getAdapterFactoryRegistry();
		Iterator adapterList = adapterRegistry.getAdapterFactories();
		// And all those appropriate for this particular type of content
		while (adapterList.hasNext()) {
			try {
				AdapterFactoryProvider provider = (AdapterFactoryProvider) adapterList.next();
				if (provider.isFor(model.getModelHandler())) {
					provider.addAdapterFactories(model);
				}
			} catch (Exception e) {
				Logger.logException(e);
			}
		}
		return model;
	}

	/**
	 * Return the valid values for an attribute with the given declaration on
	 * the given element. Derived from XMLPropertySourceAdapter
	 */
	private List getValidStrings(Element element, CMAttributeDeclaration attrDecl) {
		CMDataType valuesHelper = attrDecl.getAttrType();
		Vector values = new Vector();

		if (valuesHelper.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED && valuesHelper.getImpliedValue() != null) {
			// FIXED value
			values.add(valuesHelper.getImpliedValue());
		} else {
			// ENUMERATED values
			String[] valueStrings = null;
			// new way
			valueStrings = fModelQuery.getPossibleDataTypeValues(element, attrDecl);
			if (valueStrings == null)
				// older way
				valueStrings = attrDecl.getAttrType().getEnumeratedValues();
			if (valueStrings != null) {
				for (int i = 0; i < valueStrings.length; i++) {
					values.add(valueStrings[i]);
				}
			}
		}
		if (valuesHelper.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_NONE && valuesHelper.getImpliedValue() != null) {
			if (!values.contains(valuesHelper.getImpliedValue()))
				values.add(valuesHelper.getImpliedValue());
		}

		return values;
	}

}