/******************************************************************************* * Copyright (c) 2004, 2006 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.FileLocator; 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.internal.provisional.HTML40Namespace; import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML; import org.eclipse.wst.sse.core.StructuredModelManager; import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryProvider; import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryRegistry; 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.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML; import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; 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(); } /** * 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. * * @throws IOException */ public void testDTDLoadFromSystemID_1() throws IOException { if (testShippedDTDLookup) { setUpXML(); URL installationPath = Platform.getBundle(JSPUITestsPlugin.ID).getEntry("/"); String diskLocation = null; diskLocation = FileLocator.resolve(installationPath).toExternalForm(); 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. * @throws IOException */ public void testDTDLoadFromSystemID_2() throws IOException { if (testShippedDTDLookup) { URL installationPath = Platform.getBundle(JSPUITestsPlugin.ID).getEntry("/"); String diskLocation = null; diskLocation = FileLocator.resolve(installationPath).toExternalForm(); 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); // } } 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 XMLPropertySource */ 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; } }