blob: 161bd569665dda82603dfa5adaca4fae49cd23ca [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 1998, 2008 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:
* Goh KONDOH - initial API and implementation
*******************************************************************************/
package org.eclipse.actf.model.dom.sgml;
import java.io.IOException;
import java.io.Reader;
import java.util.Hashtable;
/**
* This class represents Document Type Definition and holds <code>
* ElementntDefinition </code>
* instances created by the DTD, entity declarations and so on.
*/
public class SGMLDocTypeDef {
private static Hashtable<String, SGMLDocTypeDef> table = new Hashtable<String, SGMLDocTypeDef>();
private SGMLParser parser;
/**
* key: element name value: ElementDefinition instance
*/
protected UnsynchronizedHashtable elementDefs = new UnsynchronizedHashtable();
private Hashtable<String, SGMLEntityReference> entityRefs = new Hashtable<String, SGMLEntityReference>();
private Hashtable<String, SGMLEntityDeclaration> entityDecls = new Hashtable<String, SGMLEntityDeclaration>();
private String id;
protected SGMLDocTypeDef(SGMLParser parser, String id) {
this.parser = parser;
this.id = id;
}
static SGMLDocTypeDef createAnonymous(SGMLParser parser) {
return new SGMLDocTypeDef(parser, "anonymous");
}
/**
* Gets ElementDefinition instance with specified name. There is only one
* ElementDefinition instance that has the same name. So if a definition
* that has specified name already exists, return that variable. If not make
* new instance. Using singleton pattern.
*
* @param name
* name of element defined by a object.
* @return singleton instance.
*/
public ElementDefinition createElementDefinition(String name) {
name = name.toUpperCase();
ElementDefinition ret = elementDefs.get(name);
if (ret == null) {
ret = new ElementDefinition(name);
elementDefs.put(name, ret);
}
return ret;
}
/**
* Creates public <code>SGMLDocTypeDef</code> instance.
*
* @param publicID
* id related to public entity. For example <code>
* "-//W3C//DTD HTML 4.0 Transitional//EN" </code>
*/
public static SGMLDocTypeDef createPublic(String publicID, SGMLParser parser) {
return new SGMLDocTypeDef(parser, publicID);
}
static void putPublic(String publicID, SGMLDocTypeDef dtd) {
table.put(publicID, dtd);
}
/**
* Gets the ElementDefinition instance related to the argument.
*
* @param name
* ElementDefinition's name.
* @return ElementDefinition named name. If no instance, return null.
*/
public ElementDefinition getElementDefinition(String name) {
return elementDefs.get(name);
}
/**
* Gets the ElementDefinition instance whose Magic Number is specifed.
*
* @param num
* ElementDefinition's Magic Number.
* @return ElementDefinition named name. If no instance, return null.
*/
public ElementDefinition getElementDefinition(int num) {
try {
return elementDefs.get(num);
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
}
SGMLEntityDeclaration getEntityDeclaration(String entityName) {
return (SGMLEntityDeclaration) entityDecls.get(entityName);
}
SGMLEntityReference getEntityReference(String name) throws ParseException {
SGMLEntityReference ret = (SGMLEntityReference) entityRefs.get(name);
if (ret == null) {
SGMLEntityDeclaration ed = getEntityDeclaration(name);
if (ed == null) {
throw new DTDParseException("No Entity Definition: " + name);
}
ret = new SGMLEntityReference(name, ed);
entityRefs.put(name, ret);
}
return ret;
}
/**
* Gets public <code>SGMLDocTypeDef</code> instance.
*
* @param publicID
* id related to public entity. For example <code>
* "-//W3C//DTD HTML 4.0 Transitional//EN" </code>
*/
public static SGMLDocTypeDef getPublic(String publicID) {
return (SGMLDocTypeDef) table.get(publicID);
}
void putEntityDeclaration(String entityName, String entityString) {
if (entityDecls.get(entityName) != null)
return;
SGMLEntityDeclaration dec = new SGMLEntityDeclaration(entityName,
entityString, this);
entityDecls.put(entityName, dec);
}
void putPublicEntity(String entityName, String entityString, String filename) {
if (entityDecls.get(entityName) != null)
return;
class PUBLICEntity extends SGMLEntityDeclaration {
String filename;
Reader getReplacementReader() throws IOException {
return parser.getResource(filename);
}
PUBLICEntity(String entityName, String entityString,
String filename, SGMLDocTypeDef dtd) {
super(entityName, entityString, dtd);
this.filename = filename;
}
}
;
entityDecls.put(entityName, new PUBLICEntity(entityName, entityString,
filename, this));
}
/**
* returns its public id. For example "-//W3C//DTD HTML 4.0
* Transitional//EN".
*
* @return public id.
*/
public String toString() {
return id;
}
/**
* Checks if a element is singleton or not. A singleton element appears only
* once in a document. For example, HTML, HEAD and BODY are singleton in
* HTML, but not TABLE, LI.
*
* @param tagName
* element name to be checked.
*/
public boolean singleton(String tagName) {
ElementDefinition ed = getElementDefinition(tagName);
return ed != null && ed.isSingleton();
}
private int elementNum;
/**
* @return number of elements this DTD defines
*/
public int getElementCount() {
return elementNum;
}
void rehash() {
elementNum = elementDefs.size();
int size = elementNum + 2; // The second last element is for #PCDATA.
// The last element is for ANONYMOUS.
for (int i = elementNum - 1; i >= 0; i--) {
elementDefs.get(i).rehash(size);
}
}
int maxSeqLength = 0;
}