blob: 1f806e5c089c91226afa8a7db4fff73ee39b7692 [file] [log] [blame]
/*******************************************************************************
* 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.wst.html.core.internal.document;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.wst.html.core.internal.contentproperties.HTMLContentProperties;
import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapterImpl;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocumentType;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Node;
/**
*/
public class HTMLDocumentTypeAdapter extends DocumentTypeAdapterImpl implements HTMLDocumentTypeConstants {
private HTMLDocumentTypeAdapterFactory fFactory = null;
private HTMLDocumentTypeEntry entry = null;
private boolean isXMLType = false;
private final static String XML = "xml"; //$NON-NLS-1$
private final static String XHTML = "xhtml"; //$NON-NLS-1$
private final static String WML = "wml"; //$NON-NLS-1$
/**
*/
protected HTMLDocumentTypeAdapter() {
super();
}
/**
*/
protected HTMLDocumentTypeAdapter(IDOMDocument document, HTMLDocumentTypeAdapterFactory factory) {
super(document);
this.fFactory = factory;
// initialize
documentTypeChanged();
}
/**
*/
private void documentTypeChanged() {
IDOMDocument document = getDocument();
if (document == null)
return; // error
IDOMModel model = document.getModel();
if (model == null)
return; // error
IFile file = getFile(model);
// find DOCTYPE delcaration and Public ID
String publicId = null;
DocumentType newDocumentType = findDocumentType(document);
if (newDocumentType != null) {
publicId = newDocumentType.getPublicId();
}
else {
// lookup default set by contentsettings
publicId = HTMLContentProperties.getProperty(HTMLContentProperties.DOCUMENT_TYPE, file, true);
}
// lookup DOCTYPE registry
HTMLDocumentTypeEntry newEntry = null;
if (publicId != null) {
newEntry = HTMLDocumentTypeRegistry.getInstance().getEntry(publicId);
}
boolean newXMLType = (newEntry != null ? newEntry.isXMLType() : false);
boolean newWMLType = (newEntry != null ? newEntry.isWMLType() : false);
if (!newXMLType) {
// find XML declaration
if (findXMLNode(document) != null) {
newXMLType = true;
}
// check file extension
if (file != null) {
String ext = file.getFileExtension();
if (ext != null && ext.equalsIgnoreCase(XHTML)) {
newXMLType = true;
}
if (ext != null && ext.equalsIgnoreCase(WML)) {
newXMLType = true;
newWMLType = true;
}
}
}
if (newEntry == null) {
// lookup system default
if (newXMLType && newDocumentType == null) {
// use default XHTML, if it's XML and no document type
// declared
if (newWMLType)
newEntry = HTMLDocumentTypeRegistry.getInstance().getDefaultEntry(HTMLDocumentTypeRegistry.DEFAULT_WML);
else
newEntry = HTMLDocumentTypeRegistry.getInstance().getDefaultEntry(HTMLDocumentTypeRegistry.DEFAULT_XHTML);
}
else {
newEntry = HTMLDocumentTypeRegistry.getInstance().getDefaultEntry(HTMLDocumentTypeRegistry.DEFAULT_HTML);
}
if (newEntry == null)
return; // error
}
if (newDocumentType == null) {
DocumentType oldDocumentType = getDocumentType();
if (oldDocumentType == null || oldDocumentType.getName() != newEntry.getName()) {
// create implicit DocumentType
DOMImplementation impl = document.getImplementation();
if (impl != null) {
String name = newEntry.getName();
publicId = newEntry.getPublicId();
String systemId = newEntry.getSystemId();
newDocumentType = impl.createDocumentType(name, publicId, systemId);
}
}
}
boolean notify = false;
if (this.entry != null) { // do not notify on initialization
notify = (newEntry != this.entry || newXMLType != this.isXMLType);
}
if (newDocumentType != null)
setDocumentType(newDocumentType);
this.entry = newEntry;
this.isXMLType = newXMLType;
if (notify)
notifyDocumentTypeChanged();
}
/**
*/
private IDOMDocumentType findDocumentType(IDOMDocument document) {
IDOMDocumentType documentType = (IDOMDocumentType) document.getDoctype();
if (documentType != null && documentType.getExistingAdapter(DocumentTypeAdapter.class) == null) {
// watch future changes
documentType.addAdapter(this);
}
return documentType;
}
/**
*/
private Node findXMLNode(Document document) {
for (Node child = document.getFirstChild(); child != null; child = child.getNextSibling()) {
if (child.getNodeType() != Node.PROCESSING_INSTRUCTION_NODE)
continue;
String target = child.getNodeName();
if (target != null && target.equals(XML)) {
return child;
}
}
return null;
}
/**
*/
public int getAttrNameCase() {
if (isXMLType())
return LOWER_CASE; // XHTML
return this.fFactory.getAttrNameCase();
}
private IFile getFile(IStructuredModel model) {
IFile result = null;
String location = model.getBaseLocation();
if (location != null) {
IPath path = new Path(location);
if (path.segmentCount() > 1) {
result = ResourcesPlugin.getWorkspace().getRoot().getFile(path);
}
}
return result;
}
/**
*/
public int getTagNameCase() {
if (isXMLType())
return LOWER_CASE; // XHTML
return this.fFactory.getTagNameCase();
}
/**
*/
public boolean hasFeature(String feature) {
if (feature == null)
return false;
if (feature.equals(HTML))
return true;
if (feature.equals(SSI))
return true;
if (feature.equals(FRAMESET)) {
if (this.entry == null)
return false;
return this.entry.hasFrameset();
}
return false;
}
/**
*/
public boolean isXMLType() {
return this.isXMLType;
}
/**
*/
public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
if (notifier == null)
return;
if (notifier instanceof IDOMDocument) {
if (eventType != INodeNotifier.STRUCTURE_CHANGED)
return;
}
else {
if (eventType != INodeNotifier.CHANGE)
return;
}
documentTypeChanged();
}
/**
*/
public void release() {
super.release();
}
}