blob: dab2031f4de9a939978c70f7a20fc1b5318c6aa2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Florian Thienel 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:
* Florian Thienel - initial API and implementation
* Carsten Hiesserich - do not add text nodes containing only whitespace when reading the document (bug 407803)
*******************************************************************************/
package org.eclipse.vex.core.internal.io;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import org.eclipse.vex.core.IFilter;
import org.eclipse.vex.core.internal.dom.DummyValidator;
import org.eclipse.vex.core.provisional.dom.BaseNodeVisitorWithResult;
import org.eclipse.vex.core.provisional.dom.DocumentContentModel;
import org.eclipse.vex.core.provisional.dom.IAxis;
import org.eclipse.vex.core.provisional.dom.IComment;
import org.eclipse.vex.core.provisional.dom.IDocument;
import org.eclipse.vex.core.provisional.dom.IElement;
import org.eclipse.vex.core.provisional.dom.INode;
import org.eclipse.vex.core.provisional.dom.IProcessingInstruction;
import org.eclipse.vex.core.provisional.dom.IText;
import org.eclipse.vex.core.tests.TestResources;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.contentmodel.ContentModelManager;
import org.junit.Test;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
public class DocumentReaderTest {
@Test
public void readDocumentWithDtdPublic() throws Exception {
final DocumentReader reader = new DocumentReader();
final IDocument document = reader.read(TestResources.get("documentWithDtdPublic.xml"));
assertEquals("-//Eclipse Foundation//DTD Vex Test//EN", document.getPublicID());
assertEquals("test1.dtd", document.getSystemID());
}
@Test
public void readDocumentWithDtdSystem() throws Exception {
final DocumentReader reader = new DocumentReader();
final URL documentUrl = TestResources.get("documentWithDtdSystem.xml");
final IDocument document = reader.read(documentUrl);
assertNull(document.getPublicID());
assertEquals("test1.dtd", document.getSystemID());
}
@Test
public void resolveDtdWithSystemId() throws Exception {
final URL documentUrl = TestResources.get("documentWithDtdSystem.xml");
final ContentModelManager modelManager = ContentModelManager.getInstance();
final URL dtdUrl = new URL(documentUrl, "test1.dtd");
final CMDocument dtd = modelManager.createCMDocument(dtdUrl.toString(), null);
assertNotNull(dtd.getElements().getNamedItem("section"));
}
@Test
public void useDocumentContentModelAsEntityResolver() throws Exception {
final DocumentReader reader = new DocumentReader();
final boolean[] called = new boolean[1];
reader.setValidator(new DummyValidator(new DocumentContentModel() {
@Override
public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException {
if (TestResources.TEST_DTD.equals(publicId)) {
called[0] = true;
}
return super.resolveEntity(publicId, systemId);
}
}));
reader.read(TestResources.get("documentWithDtdPublic.xml"));
assertTrue(called[0]);
}
@Test
public void preferEntityResolver() throws Exception {
final DocumentReader reader = new DocumentReader();
final boolean[] documentContentModelCalled = new boolean[1];
final boolean[] entityResolverCalled = new boolean[1];
reader.setValidator(new DummyValidator(new DocumentContentModel() {
@Override
public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException {
if (TestResources.TEST_DTD.equals(publicId)) {
documentContentModelCalled[0] = true;
}
return super.resolveEntity(publicId, systemId);
}
}));
reader.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException {
if (TestResources.TEST_DTD.equals(publicId)) {
entityResolverCalled[0] = true;
}
return new InputSource(TestResources.get("test1.dtd").toString());
}
});
reader.read(TestResources.get("documentWithDtdPublic.xml"));
assertFalse(documentContentModelCalled[0]);
assertTrue(entityResolverCalled[0]);
}
@Test
public void useDocumentContentModelAsEntityResolverBackup() throws Exception {
final DocumentReader reader = new DocumentReader();
final int[] callPosition = new int[1];
final int[] documentContentModelPosition = new int[1];
final int[] entityResolverPosition = new int[1];
reader.setValidator(new DummyValidator(new DocumentContentModel() {
@Override
public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException {
if (TestResources.TEST_DTD.equals(publicId)) {
documentContentModelPosition[0] = ++callPosition[0];
}
return super.resolveEntity(publicId, systemId);
}
}));
reader.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException {
if (TestResources.TEST_DTD.equals(publicId)) {
entityResolverPosition[0] = ++callPosition[0];
}
return null;
}
});
reader.read(TestResources.get("documentWithDtdPublic.xml"));
assertEquals(2, documentContentModelPosition[0]);
assertEquals(1, entityResolverPosition[0]);
}
@Test
public void readDocumentWithComments() throws Exception {
final DocumentReader reader = new DocumentReader();
final IDocument document = reader.read(TestResources.get("documentWithComments.xml"));
final Iterator<INode> documentChildren = document.children().iterator();
final IComment documentComment1 = (IComment) documentChildren.next();
assertEquals("A comment before the root element.", documentComment1.getText());
assertSame(document.getRootElement(), documentChildren.next());
final IComment documentComment2 = (IComment) documentChildren.next();
assertEquals("A final comment after the root element.", documentComment2.getText());
assertFalse(documentChildren.hasNext());
final IElement rootElement = document.getRootElement();
final Iterator<INode> rootChildren = rootElement.children().iterator();
final IComment comment1 = (IComment) rootChildren.next();
assertEquals("A comment within the root element.", comment1.getText());
final IComment comment2 = (IComment) ((IElement) rootChildren.next()).children().get(1);
assertEquals("A comment within text.", comment2.getText());
final IComment comment3 = (IComment) rootChildren.next();
assertEquals("Another comment between two child elements.", comment3.getText());
rootChildren.next();
assertFalse(rootChildren.hasNext());
}
@Test
public void readDocumentWithProcessingInstruction() throws Exception {
final DocumentReader reader = new DocumentReader();
final IDocument document = reader.read(TestResources.get("documentWithProcessingInstr.xml"));
final Iterator<INode> documentChildren = document.children().iterator();
final IProcessingInstruction pi1 = (IProcessingInstruction) documentChildren.next();
assertEquals("position=beforeRoot", pi1.getText());
assertEquals("pi", pi1.getTarget());
assertSame(document.getRootElement(), documentChildren.next());
final IProcessingInstruction pi2 = (IProcessingInstruction) documentChildren.next();
assertEquals("position=afterRoot", pi2.getText());
final IProcessingInstruction pi3 = (IProcessingInstruction) documentChildren.next();
assertEquals("Entity references should not be parsed", "&lt;test&gt;", pi3.getText());
assertFalse(documentChildren.hasNext());
final IElement rootElement = document.getRootElement();
final Iterator<INode> rootChildren = rootElement.children().iterator();
final IProcessingInstruction pi4 = (IProcessingInstruction) rootChildren.next();
assertEquals("position=begin", pi4.getText());
rootChildren.next();
final IElement para = (IElement) rootChildren.next();
final IProcessingInstruction pi5 = (IProcessingInstruction) para.children().get(1);
assertEquals("position=inline A very long data with whitespace end", pi5.getText());
assertEquals("Before PI position=inline A very long data with whitespace end After PI", para.getText());
assertFalse(rootChildren.hasNext());
}
@Test
public void shouldNotAddWhitespaceTextNodesInDocumentWithoutDTD() throws Exception {
final DocumentReader reader = new DocumentReader();
final IDocument document = reader.read(TestResources.get("documentWithoutDTD.xml"));
final IElement rootElement = document.getRootElement();
final IFilter<INode> recursiveWhitespaceTextNodeFilter = new IFilter<INode>() {
public boolean matches(final INode node) {
return node.accept(new BaseNodeVisitorWithResult<Boolean>(false) {
@Override
public Boolean visit(final IElement element) {
return containsEmptyTextNodes(element);
}
@Override
public Boolean visit(final IText text) {
return text.getText().trim().length() == 0;
}
});
}
private boolean containsEmptyTextNodes(final IElement element) {
return !element.children().matching(this).isEmpty();
}
};
final IAxis<? extends INode> nodesWithEmptyTextNodes = rootElement.children().matching(recursiveWhitespaceTextNodeFilter);
assertEquals("whitespace text nodes", 0, nodesWithEmptyTextNodes.count());
}
}