blob: 7027058659382263c1dad82e7539180b296732ca [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2001, 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.wst.dtd.core.internal.saxparser;
import java.util.Vector;
/**
* Scanning / parsing the content string from the Decl statement
*
* @version
*/
public class DTDScanner {
// element content model strings
private static final char[] empty_string = {'E', 'M', 'P', 'T', 'Y'};
private static final char[] any_string = {'A', 'N', 'Y'};
private static final char[] pcdata_string = {'#', 'P', 'C', 'D', 'A', 'T', 'A'};
// attribute type and default type strings
private static final char[] cdata_string = {'C', 'D', 'A', 'T', 'A'};
private static final char[] id_string = {'I', 'D'};
private static final char[] ref_string = {'R', 'E', 'F'};
private static final char[] entit_string = {'E', 'N', 'T', 'I', 'T'};
private static final char[] ies_string = {'I', 'E', 'S'};
private static final char[] nmtoken_string = {'N', 'M', 'T', 'O', 'K', 'E', 'N'};
private static final char[] notation_string = {'N', 'O', 'T', 'A', 'T', 'I', 'O', 'N'};
private static final char[] required_string = {'#', 'R', 'E', 'Q', 'U', 'I', 'R', 'E', 'D'};
private static final char[] implied_string = {'#', 'I', 'M', 'P', 'L', 'I', 'E', 'D'};
private static final char[] fixed_string = {'#', 'F', 'I', 'X', 'E', 'D'};
private static final char[] system_string = {'S', 'Y', 'S', 'T', 'E', 'M'};
private static final char[] public_string = {'P', 'U', 'B', 'L', 'I', 'C'};
private static final char[] ndata_string = {'N', 'D', 'A', 'T', 'A'};
private int[] fOpStack = null;
private CMGroupNode[] fGrpStack = null;
private EntityPool entityPool;
/* Attribute Def scanner state */
static final int Att_Scanner_State_Name = 1, Att_Scanner_State_Type = 2, Att_Scanner_State_DefaultType = 3, Att_Scanner_State_DefaultValue = 4;
private StringParser contentString;
private String cData;
private int prevNodeOffset = 0;
private int nodeOffset = 1;
private String ownerDTD;
private String errorString;
public DTDScanner(String ownerDTD, String cm) {
// System.out.println("Cm: " + cm);
contentString = new StringParser(cm);
cData = cm;
this.ownerDTD = ownerDTD;
}
//
// [46] contentspec ::= 'EMPTY' | 'ANY' | Mixed | children
//
// Specific to VisualDTD : also allows %PEReference;
//
public CMNode scanContentModel() {
CMNode cmNode = null;
contentString.skipPastSpaces();
if (contentString.skippedString(empty_string)) {
cmNode = new CMBasicNode("EMPTY", CMNodeType.EMPTY); //$NON-NLS-1$
}
else if (contentString.skippedString(any_string)) {
cmNode = new CMBasicNode("ANY", CMNodeType.ANY); //$NON-NLS-1$
}
else if (contentString.lookingAtChar('%', true)) {
cmNode = new CMReferenceNode(contentString.getData(), CMNodeType.ENTITY_REFERENCE);
}
else if (!contentString.lookingAtChar('(', true)) {
// This means that the contentmodel string is bad...
// System.out.println("!!! exception - no (");
return cmNode;
}
else {
// System.out.println("Remaining String = " +
// contentString.getRemainingString());
contentString.skipPastSpaces();
boolean skippedPCDATA = contentString.skippedString(pcdata_string);
if (skippedPCDATA) {
cmNode = scanMixed();
}
else {
cmNode = scanChildren();
}
}
return cmNode;
}
//
// [51] Mixed ::= '(' S? '#PCDATA' (S? '|' S? Name)* S? ')*' | '(' S?
// '#PCDATA' S? ')'
//
// Called after scanning past '(' S? '#PCDATA'
//
private CMNode scanMixed() {
// System.out.println("ScanMixed...");
CMGroupNode cmNode = new CMGroupNode();
cmNode.setGroupKind(CMNodeType.GROUP_CHOICE);
cmNode.addChild(new CMBasicNode("#PCDATA", CMNodeType.PCDATA)); //$NON-NLS-1$
// int prevNodeIndex = -1;
boolean starRequired = false;
while (true) {
if (contentString.lookingAtSpace(true)) {
contentString.skipPastSpaces();
}
prevNodeOffset = contentString.getCurrentOffset();
if (!contentString.lookingAtChar('|', true)) {
if (!contentString.lookingAtChar(')', true)) {
break;
}
if (contentString.lookingAtChar('*', true)) {
cmNode.setOccurrence(CMNodeType.ZERO_OR_MORE);
}
else if (starRequired) {
// System.out.println(" * is required ... ");
}
break;
}
if (contentString.lookingAtSpace(true)) {
contentString.skipPastSpaces();
}
nodeOffset = contentString.getCurrentOffset();
if (nodeOffset != -1) {
// skip pass "|"
prevNodeOffset = nodeOffset;
}
starRequired = true;
contentString.skipPastNameAndPEReference(')');
nodeOffset = contentString.getCurrentOffset();
if (nodeOffset == -1)
break;
// add leave node
int len = nodeOffset - prevNodeOffset;
String refName = contentString.getString(prevNodeOffset, len);
prevNodeOffset = nodeOffset;
if (refName.startsWith("%")) //$NON-NLS-1$
cmNode.addChild(new CMReferenceNode(refName, CMNodeType.ENTITY_REFERENCE));
else
cmNode.addChild(new CMReferenceNode(refName, CMNodeType.ELEMENT_REFERENCE));
} // end while
if (cmNode.getChildren().size() == 1) {
// simplify the contentModel if the CMGroupNode only has one child
// node.
return (CMBasicNode) cmNode.getChildren().elementAt(0);
}
return cmNode;
}
//
// [47] children ::= (choice | seq) ('?' | '*' | '+')?
// [49] choice ::= '(' S? cp ( S? '|' S? cp )* S? ')'
// [50] seq ::= '(' S? cp ( S? ',' S? cp )* S? ')'
// [48] cp ::= (Name | choice | seq) ('?' | '*' | '+')?
//
// Called after scanning past '('
private CMNode scanChildren() {
// System.out.println("scanChildren...");
if (contentString.lookingAtSpace(true)) {
contentString.skipPastSpaces();
}
prevNodeOffset = contentString.getCurrentOffset();
nodeOffset = contentString.getCurrentOffset();
int depth = 1;
initializeContentModelStack(depth);
int len;
String nodeName;
CMGroupNode cmNode = new CMGroupNode();
fGrpStack[depth] = cmNode;
while (true) {
// System.out.println(" Begin outter while loop ..." );
if (contentString.lookingAtChar('(', true)) {
if (contentString.lookingAtSpace(true)) {
// skip past any white spaces after the '('
contentString.skipPastSpaces();
}
depth++;
initializeContentModelStack(depth);
fGrpStack[depth] = new CMGroupNode();
fGrpStack[depth - 1].addChild(fGrpStack[depth]);
continue;
}
prevNodeOffset = contentString.getCurrentOffset();
contentString.skipPastNameAndPEReference(')');
nodeOffset = contentString.getCurrentOffset();
/*
* System.out.println(" prevNodeOFfset " + prevNodeOffset);
* System.out.println(" currentNodeOFfset " + nodeOffset);
*/
len = nodeOffset - prevNodeOffset;
if (nodeOffset == -1 || len < 1) {
break;
}
nodeName = contentString.getString(prevNodeOffset, len);
CMRepeatableNode rn;
if (nodeName.startsWith("%")) { //$NON-NLS-1$
rn = new CMReferenceNode(nodeName, CMNodeType.ENTITY_REFERENCE);
}
else {
rn = new CMReferenceNode(nodeName, CMNodeType.ELEMENT_REFERENCE);
}
fGrpStack[depth].addChild(rn);
prevNodeOffset = nodeOffset;
if (contentString.lookingAtChar('?', true)) {
rn.setOccurrence(CMNodeType.OPTIONAL);
}
else if (contentString.lookingAtChar('*', true)) {
rn.setOccurrence(CMNodeType.ZERO_OR_MORE);
}
else if (contentString.lookingAtChar('+', true)) {
rn.setOccurrence(CMNodeType.ONE_OR_MORE);
}
if (contentString.lookingAtSpace(true)) {
contentString.skipPastSpaces();
}
prevNodeOffset = contentString.getCurrentOffset();
while (true) {
// System.out.println(" Begin inner while loop ... depth " +
// depth );
if (fOpStack[depth] != CMNodeType.GROUP_SEQUENCE && contentString.lookingAtChar('|', true)) {
fOpStack[depth] = CMNodeType.GROUP_CHOICE;
fGrpStack[depth].setGroupKind(CMNodeType.GROUP_CHOICE);
if (contentString.lookingAtSpace(true))
contentString.skipPastSpaces();
break;
}
else if (fOpStack[depth] != CMNodeType.GROUP_CHOICE && contentString.lookingAtChar(',', true)) {
fOpStack[depth] = CMNodeType.GROUP_SEQUENCE;
fGrpStack[depth].setGroupKind(CMNodeType.GROUP_SEQUENCE);
if (contentString.lookingAtSpace(true))
contentString.skipPastSpaces();
break;
}
else {
if (contentString.lookingAtSpace(true)) {
contentString.skipPastSpaces();
}
if (!contentString.lookingAtChar(')', true)) {
// System.out.println(" error ) not found");
}
// end of the curent group node
if (contentString.lookingAtChar('?', true)) {
fGrpStack[depth].setOccurrence(CMNodeType.OPTIONAL);
}
else if (contentString.lookingAtChar('*', true)) {
fGrpStack[depth].setOccurrence(CMNodeType.ZERO_OR_MORE);
}
else if (contentString.lookingAtChar('+', true)) {
fGrpStack[depth].setOccurrence(CMNodeType.ONE_OR_MORE);
}
depth--;
if (depth == 0) {
break;
}
if (contentString.lookingAtSpace(true))
contentString.skipPastSpaces();
// System.out.println(" End end inner while loop ... depth
// " + depth );
}
} // inner while
if (depth == 0) {
break;
}
} // outer while
if (cmNode.getChildren().size() == 1) {
// simplify the contentModel if the CMGroupNode only has one child
// node and that node is an element ref.
CMRepeatableNode rn = (CMRepeatableNode) cmNode.getChildren().elementAt(0);
if (rn instanceof CMReferenceNode) {
CMReferenceNode ref = (CMReferenceNode) rn;
if (ref.getType() == CMNodeType.ELEMENT_REFERENCE) {
if (ref.getOccurrence() == CMNodeType.ONE) {
ref.setOccurrence(cmNode.getOccurrence());
return ref;
}
else if (cmNode.getOccurrence() == CMNodeType.ONE) {
return ref;
}
} // end of if ()
}
}
return cmNode;
}
//
// [52] AttlistDecl ::= '<!ATTLIST' S Name AttDef* S? '>'
// [53] AttDef ::= S Name S AttType S DefaultDecl
// [60] DefaultDecl ::= '#REQUIRED' | '#IMPLIED' | (('#FIXED' S)?
// AttValue)
//
public Vector scanAttlistDecl(EntityPool entityPool) {
Vector attList = new Vector();
this.entityPool = entityPool;
int scannerState = Att_Scanner_State_Name;
AttNode attNode;
while (true) {
attNode = new AttNode();
// System.out.println(" scanner state: " + scannerState);
// scanning att name
if (scannerState == Att_Scanner_State_Name) {
// System.out.println("scan att Name...");
scannerState = checkForAttributeWithPEReference(attNode, scannerState);
if (scannerState == -1) {
return attList;
}
}
// scanning att type
if (scannerState == Att_Scanner_State_Type) {
// System.out.println("scan att type...");
if (contentString.skippedString(cdata_string)) {
attNode.type = new String(cdata_string);
scannerState = Att_Scanner_State_DefaultType;
}
else if (contentString.skippedString(id_string)) {
if (!contentString.skippedString(ref_string)) {
attNode.type = new String(id_string);
}
else if (!contentString.lookingAtChar('S', true)) {
attNode.type = "IDREF"; //$NON-NLS-1$
}
else {
attNode.type = "IDREFS"; //$NON-NLS-1$
}
scannerState = Att_Scanner_State_DefaultType;
}
else if (contentString.skippedString(entit_string)) {
if (contentString.lookingAtChar('Y', true)) {
attNode.type = "ENTITY"; //$NON-NLS-1$
}
else if (contentString.skippedString(ies_string)) {
attNode.type = "ENTITIES"; //$NON-NLS-1$
}
scannerState = Att_Scanner_State_DefaultType;
}
else if (contentString.skippedString(nmtoken_string)) {
if (contentString.lookingAtChar('S', true)) {
attNode.type = "NMTOKENS"; //$NON-NLS-1$
}
else {
attNode.type = "NMTOKEN"; //$NON-NLS-1$
}
scannerState = Att_Scanner_State_DefaultType;
}
else if (contentString.skippedString(notation_string)) {
if (contentString.lookingAtSpace(true)) {
contentString.skipPastSpaces();
}
if (!contentString.lookingAtChar('(', true)) {
System.out.println(" missing ( in notation "); //$NON-NLS-1$
}
attNode.type = "NOTATION"; //$NON-NLS-1$
attNode.enumList = scanEnumeration(contentString, true);
scannerState = Att_Scanner_State_DefaultType;
}
else if (contentString.lookingAtChar('(', true)) {
attNode.type = "ENUMERATION"; //$NON-NLS-1$
attNode.enumList = scanEnumeration(contentString, false);
scannerState = Att_Scanner_State_DefaultType;
}
else {
scannerState = checkForAttributeWithPEReference(attNode, scannerState);
if (scannerState == Att_Scanner_State_Type) {
setErrorString("Failed to find type for attribute '" + attNode.name + "'. Please refer to the original DTD file."); //$NON-NLS-1$ //$NON-NLS-2$
// we failed to find a type for this attribute
return attList;
}
}
}
if (scannerState == Att_Scanner_State_DefaultType) {
contentString.skipPastSpaces();
// System.out.println("scan default type...");
if (contentString.skippedString(required_string)) {
attNode.defaultType = new String(required_string);
}
else if (contentString.skippedString(implied_string)) {
attNode.defaultType = new String(implied_string);
}
else {
if (contentString.skippedString(fixed_string)) {
contentString.skipPastSpaces();
attNode.defaultType = new String(fixed_string);
}
else
// "default"
attNode.defaultType = "NOFIXED"; //$NON-NLS-1$
if (contentString.lookingAtSpace(true))
contentString.skipPastSpaces();
attNode.defaultValue = scanDefaultAttValue(contentString);
}
scannerState = Att_Scanner_State_Name; // next
}
attList.addElement(attNode);
if (contentString.lookingAtSpace(true))
contentString.skipPastSpaces();
nodeOffset = contentString.getCurrentOffset();
if (nodeOffset >= cData.length())
return attList;
prevNodeOffset = contentString.getCurrentOffset();
}// end while loop
}
//
// content model stack
//
private void initializeContentModelStack(int depth) {
if (fOpStack == null) {
fOpStack = new int[8];
fGrpStack = new CMGroupNode[8];
}
else if (depth == fOpStack.length) {
int[] newStack = new int[depth * 2];
System.arraycopy(fOpStack, 0, newStack, 0, depth);
fOpStack = newStack;
CMGroupNode[] newGrpStack = new CMGroupNode[depth * 2];
System.arraycopy(fGrpStack, 0, newGrpStack, 0, depth);
fGrpStack = newGrpStack;
}
fOpStack[depth] = -1;
fGrpStack[depth] = null;
}
//
private int checkForAttributeWithPEReference(AttNode attNode, int scannerState) {
int state = -1;
int len;
String rawText;
EntityDecl pEntity;
// System.out.println(" checkforATTPERReference- start scannerState: "
// + scannerState);
if (scannerState == Att_Scanner_State_Name) {
contentString.skipPastNameAndPEReference(' ');
nodeOffset = contentString.getCurrentOffset();
len = nodeOffset - prevNodeOffset;
rawText = contentString.getString(prevNodeOffset, len);
attNode.name = rawText;
// System.out.println("State_name : " + rawText);
if (rawText.startsWith("%") && rawText.endsWith(";")) { //$NON-NLS-1$ //$NON-NLS-2$
String pe = rawText.substring(1, rawText.length() - 1);
pEntity = entityPool.referPara(pe);
if (pEntity != null) {
// System.out.println(" name :" + rawText +" expandTo:" +
// pEntity.expandedValue);
state = whatIsTheNextAttributeScanningState(pEntity.expandedValue, scannerState);
// System.out.println("checkForAttrwithPER - nextstate: "
// + state);
}
else
state = Att_Scanner_State_Type;
}
else
state = Att_Scanner_State_Type;
}
else if (scannerState == Att_Scanner_State_Type) {
if (contentString.lookingAtChar('%', true)) {
rawText = getPEName();
attNode.type = "%" + rawText; //$NON-NLS-1$
String peName = rawText.substring(0, rawText.length() - 1);
// System.out.println("State_type : pe- " + peName);
pEntity = entityPool.referPara(peName);
if (pEntity != null) {
state = whatIsTheNextAttributeScanningState(pEntity.expandedValue, scannerState);
}
else
state = Att_Scanner_State_DefaultType;
}
else
state = Att_Scanner_State_Type;
}
else if (scannerState == Att_Scanner_State_DefaultType) {
if (contentString.lookingAtChar('%', true)) {
rawText = getPEName();
attNode.defaultType = rawText;
// System.out.println("State_defaultType : " + rawText);
pEntity = entityPool.referPara(rawText.substring(1, rawText.length() - 1));
if (pEntity != null) {
state = whatIsTheNextAttributeScanningState(pEntity.expandedValue, scannerState);
}
else
state = Att_Scanner_State_DefaultValue;
}
else
state = Att_Scanner_State_DefaultType;
}
else if (scannerState == Att_Scanner_State_DefaultValue) {
if (contentString.lookingAtChar('%', true)) {
rawText = getPEName();
attNode.defaultValue = rawText;
// System.out.println("State_defaultValue : " + rawText);
pEntity = entityPool.referPara(rawText.substring(1, rawText.length() - 1));
if (pEntity != null) {
state = whatIsTheNextAttributeScanningState(pEntity.expandedValue, scannerState);
}
else
state = Att_Scanner_State_DefaultValue;
}
else
state = Att_Scanner_State_DefaultValue;
}
if (contentString.lookingAtSpace(true))
contentString.skipPastSpaces();
prevNodeOffset = contentString.getCurrentOffset();
return state;
}
private String getPEName() {
prevNodeOffset = contentString.getCurrentOffset();
contentString.skipToChar(';', true);
nodeOffset = contentString.getCurrentOffset();
int len = nodeOffset - prevNodeOffset;
return contentString.getString(prevNodeOffset, len);
}
private int whatIsTheNextAttributeScanningState(String attrContentString, int currentState) {
StringParser sp = new StringParser(attrContentString.trim());
int nextState = currentState;
int nOffset = 0;
/*
* System.out.println("WhatistheNext AttContentStringt : " +
* attrContentString); System.out.println("WhatistheNext
* AttContentStringL : " + attrContentString.length());
* System.out.println("WhatistheNext currentstate : " + currentState);
*/
while (true) {
// System.out.println("WhatistheNext inside whil nextstate : " +
// nextState);
if (nextState == Att_Scanner_State_Name) { // the current
// scanning state is
// Attr Name, is the
// next part Attr Type
// ?
if (isAttrName(sp)) {
nextState = Att_Scanner_State_Type;
}
}
else if (nextState == Att_Scanner_State_Type) { // the current
// scanning state
// is Attr Type,
// is the next
// part Default
// Attr Type ?
if (isAttrType(sp)) {
nextState = Att_Scanner_State_DefaultType;
}
else
System.out.println("WhatistheNext Attr Part - is not an Attr Type"); //$NON-NLS-1$
}
if (nextState == Att_Scanner_State_DefaultType) {
int dType = isAttrDefaultType(sp);
// System.out.println("WhatistheNext inside dType : " +
// dType);
if (dType == 1) // #REQUIRED or #IMPLIED
{
nextState = Att_Scanner_State_Name;
}
else {
if (dType == 2) // #FIXED
{
// need to look at this again
nextState = Att_Scanner_State_DefaultType;
}
if (scanDefaultAttValue(sp) != null) {
nextState = Att_Scanner_State_Name;
}
}
}
sp.skipPastSpaces();
if (nOffset == sp.getCurrentOffset())
break;
nOffset = sp.getCurrentOffset();
if (nOffset >= attrContentString.length() || nOffset == -1)
break;
} // end while
return nextState;
}
private boolean isAttrName(StringParser sp) {
// System.out.println("isAttrName - sp:" + sp.fData);
// System.out.println("isAttrName - currentOffset:" +
// sp.getCurrentOffset());
boolean isAttrName = false;
int prev = sp.getCurrentOffset();
sp.skipPastName(' ');
if ((sp.getCurrentOffset() - prev) > 0)
isAttrName = true;
return isAttrName;
}
private boolean isAttrType(StringParser sp) {
// System.out.println("isAttrType - sp:" + sp.fData);
// System.out.println("isAttrType - currentOffset:" +
// sp.getCurrentOffset());
boolean isAttrType = false;
if (sp.skippedString(cdata_string)) {
isAttrType = true;
}
else if (sp.skippedString(id_string)) {
if (!sp.skippedString(ref_string)) {
isAttrType = true; // ID
}
else if (!sp.lookingAtChar('S', true)) {
isAttrType = true; // IDREFS
}
else {
isAttrType = true; // IDREF
}
}
else if (sp.skippedString(entit_string)) {
if (sp.lookingAtChar('Y', true)) {
isAttrType = true; // ENTITY
}
else if (sp.skippedString(ies_string)) {
isAttrType = true; // ENTITITES
}
}
else if (sp.skippedString(nmtoken_string)) {
if (sp.lookingAtChar('S', true)) {
isAttrType = true; // NMTOKENS
}
else {
isAttrType = true; // NMTOKEN
}
}
else if (sp.skippedString(notation_string)) {
if (!sp.lookingAtChar('(', true)) {
// System.out.println(" missing ( in notation ");
}
Vector enumList = scanEnumeration(sp, true);
if (enumList == null || enumList.size() == 0)
isAttrType = false;
else
isAttrType = true;
}
else if (sp.lookingAtChar('(', true)) {
// "ENUMERATION";
Vector enumList = scanEnumeration(sp, false);
if (enumList == null || enumList.size() == 0)
isAttrType = false;
else
isAttrType = true;
}
return isAttrType;
}
/*
* return 0 - not default type 1 - #REQUIRED or #IMPLIED 2 - #FIXED
*/
private int isAttrDefaultType(StringParser sp) {
// System.out.println("isAttrDefaultType - sp:" + sp.fData);
int result = 0;
if (sp.skippedString(required_string)) {
result = 1;
}
else if (sp.skippedString(implied_string)) {
result = 1;
}
else if (sp.skippedString(fixed_string)) {
result = 2;
}
return result;
}
//
// [58] NotationType ::= 'NOTATION' S '(' S? Name (S? '|' S? Name)* S? ')'
// [59] Enumeration ::= '(' S? Nmtoken (S? '|' S? Nmtoken)* S? ')'
//
// Called after scanning '('
//
private Vector scanEnumeration(StringParser sp, boolean isNotationType) {
// System.out.println(" scanEnum ...");
Vector enumList = null;
int len;
if (sp.lookingAtSpace(true))
sp.skipPastSpaces();
int prevNodeOffset = sp.getCurrentOffset();
int nodeOffset;
String nodeName;
while (true) {
if (isNotationType)
sp.skipPastNameAndPEReference(')');
else
sp.skipPastNmtokenAndPEReference(')');
nodeOffset = sp.getCurrentOffset();
if (nodeOffset == -1) {
return enumList;
}
len = nodeOffset - prevNodeOffset;
nodeName = sp.getString(prevNodeOffset, len);
if (enumList == null)
enumList = new Vector();
enumList.addElement(nodeName);
if (sp.lookingAtSpace(true))
sp.skipPastSpaces();
if (!sp.lookingAtChar('|', true)) {
if (!sp.lookingAtChar(')', true)) {
System.out.println("scanning enum values - error missing ')'"); //$NON-NLS-1$
break;
}
break;
}
if (sp.lookingAtSpace(true))
sp.skipPastSpaces();
prevNodeOffset = sp.getCurrentOffset();
}
return enumList;
}
//
// [10] AttValue ::= '"' ([^<&"] | Reference)* '"'
// | "'" ([^<&'] | Reference)* "'"
//
/**
* Scan the default value in an attribute declaration
*
* @param elementType
* handle to the element that owns the attribute
* @param attrName
* handle in the string pool for the attribute name
* @return handle in the string pool for the default attribute value
* @exception java.lang.Exception
*/
public String scanDefaultAttValue(StringParser sp) {
String value = null;
// System.out.println("scan default ATT Value... sp:" + sp.fData);
sp.skipPastSpaces();
boolean single;
if (!(single = sp.lookingAtChar('\'', true)) && !sp.lookingAtChar('\"', true)) {
return value;
}
char qchar = single ? '\'' : '\"';
int sOffset = sp.getCurrentOffset();
sp.skipToChar(qchar, true);
int len = sp.getCurrentOffset() - sOffset - 1;
if (len == 0)
value = ""; //$NON-NLS-1$
else
value = sp.getString(sOffset, len);
return value;
}
//
// [70] EntityDecl ::= GEDecl | PEDecl
// [71] GEDecl ::= '<!ENTITY' S Name S EntityDef S? '>'
// [72] PEDecl ::= '<!ENTITY' S '%' S Name S PEDef S? '>'
// [73] EntityDef ::= EntityValue | (ExternalID NDataDecl?)
// [74] PEDef ::= EntityValue | ExternalID
// [75] ExternalID ::= 'SYSTEM' S SystemLiteral
// | 'PUBLIC' S PubidLiteral S SystemLiteral
// [76] NDataDecl ::= S 'NDATA' S Name
// [9] EntityValue ::= '"' ([^%&"] | PEReference | Reference)* '"'
// | "'" ([^%&'] | PEReference | Reference)* "'"
//
// Called after scanning 'ENTITY'
//
public EntityDecl scanEntityDecl() {
prevNodeOffset = 1;
nodeOffset = 1;
int len;
boolean isPEDecl = false;
EntityDecl entityDecl = null;
String name = null;
String ndata = null;
if (contentString.lookingAtSpace(true)) {
contentString.skipPastSpaces();
if (!contentString.lookingAtChar('%', true)) {
isPEDecl = false; // <!ENTITY x "x">
}
else if (contentString.lookingAtSpace(true)) {
isPEDecl = true; // <!ENTITY % x "x">
}
prevNodeOffset = contentString.getCurrentOffset();
contentString.skipPastName(' ');
nodeOffset = contentString.getCurrentOffset();
len = nodeOffset - prevNodeOffset;
if (len > 0) {
name = contentString.getString(prevNodeOffset, len);
prevNodeOffset = nodeOffset;
}
}
if (name == null)
return null;
contentString.skipPastSpaces();
prevNodeOffset = contentString.getCurrentOffset();
boolean single;
if ((single = contentString.lookingAtChar('\'', true)) || contentString.lookingAtChar('\"', true)) {
String value = scanEntityValue(single);
entityDecl = new EntityDecl(name, ownerDTD, value, isPEDecl);
}
else {
// external entity
ExternalID xID = scanExternalID();
if (xID != null) {
if (!isPEDecl) // general entity
{
boolean unparsed = false;
contentString.skipPastSpaces();
unparsed = contentString.skippedString(ndata_string);
if (unparsed) {
contentString.skipPastSpaces();
prevNodeOffset = contentString.getCurrentOffset();
contentString.skipPastName(' ');
nodeOffset = contentString.getCurrentOffset();
len = nodeOffset - prevNodeOffset;
ndata = contentString.getString(prevNodeOffset, len);
}
}
entityDecl = new EntityDecl(name, ownerDTD, xID, isPEDecl, ndata);
}
}
return entityDecl;
}
//
// [82] NotationDecl ::= '<!NOTATION' S Name S (ExternalID | PublicID) S?
// '>'
// [75] ExternalID ::= 'SYSTEM' S SystemLiteral
// | 'PUBLIC' S PubidLiteral S SystemLiteral
// [83] PublicID ::= 'PUBLIC' S PubidLiteral
//
// Called after scanning 'NOTATION'
//
public NotationDecl scanNotationDecl() {
prevNodeOffset = 1;
nodeOffset = 1;
int len;
NotationDecl notationDecl = null;
String name = null;
if (contentString.lookingAtSpace(true)) {
contentString.skipPastSpaces();
prevNodeOffset = contentString.getCurrentOffset();
contentString.skipPastName(' ');
nodeOffset = contentString.getCurrentOffset();
len = nodeOffset - prevNodeOffset;
if (len > 0) {
name = contentString.getString(prevNodeOffset, len);
prevNodeOffset = nodeOffset;
}
}
if (name == null)
return null;
contentString.skipPastSpaces();
prevNodeOffset = contentString.getCurrentOffset();
notationDecl = new NotationDecl(name, ownerDTD);
ExternalID xID = scanExternalID();
if (xID != null) {
if (xID.getSystemLiteral() != null) {
notationDecl.setSystemId(xID.getSystemLiteral());
}
if (xID.getPubIdLiteral() != null) {
notationDecl.setPublicId(xID.getPubIdLiteral());
}
}
return notationDecl;
}
private String scanEntityValue(boolean single) {
char qchar = single ? '\'' : '\"';
prevNodeOffset = contentString.getCurrentOffset();
contentString.skipToChar(qchar, false);
int len = contentString.getCurrentOffset() - prevNodeOffset;
String value = contentString.getString(prevNodeOffset, len);
return value;
}
//
// [75] ExternalID ::= 'SYSTEM' S SystemLiteral
// | 'PUBLIC' S PubidLiteral S SystemLiteral
private ExternalID scanExternalID() {
ExternalID xID = null;
char qchar = '\"';
if (contentString.skippedString(system_string)) {
if (!contentString.lookingAtSpace(true)) {
return null;
}
contentString.skipPastSpaces();
if (contentString.lookingAtChar('\'', true))
qchar = '\'';
else if (contentString.lookingAtChar('\"', true))
qchar = '\"';
prevNodeOffset = contentString.getCurrentOffset();
contentString.skipToChar(qchar, true);
int len = contentString.getCurrentOffset() - prevNodeOffset - 1;
String systemId = contentString.getString(prevNodeOffset, len);
// System.out.println("systemid..." + systemId);
xID = new ExternalID(systemId);
}
else if (contentString.skippedString(public_string)) {
if (!contentString.lookingAtSpace(true)) {
return null;
}
contentString.skipPastSpaces();
if (contentString.lookingAtChar('\'', true))
qchar = '\'';
else if (contentString.lookingAtChar('\"', true))
qchar = '\"';
// publicLiteral
prevNodeOffset = contentString.getCurrentOffset();
contentString.skipToChar(qchar, true);
int len = contentString.getCurrentOffset() - prevNodeOffset - 1;
String publicId = contentString.getString(prevNodeOffset, len);
// systemLiteral
contentString.skipPastSpaces();
if (contentString.lookingAtChar('\'', true))
qchar = '\'';
else if (contentString.lookingAtChar('\"', true))
qchar = '\"';
prevNodeOffset = contentString.getCurrentOffset();
contentString.skipToChar(qchar, true);
len = contentString.getCurrentOffset() - prevNodeOffset - 1;
if (len > 0) {
String systemId = contentString.getString(prevNodeOffset, len);
xID = new ExternalID(publicId, systemId);
}
else {
xID = new ExternalID(publicId, null);
}
}
return xID;
}
//
// [83] PublicID ::= 'PUBLIC' S PubidLiteral
//
// dmw 11/15 private method never read locally
// TODO: change to private if used, otherwise should be removed
String scanPublicID() {
String pID = null;
if (contentString.skippedString(public_string)) {
if (!contentString.lookingAtSpace(true)) {
return pID;
}
contentString.skipPastSpaces();
prevNodeOffset = contentString.getCurrentOffset();
contentString.skipToChar(' ', true);
int len = contentString.getCurrentOffset() - prevNodeOffset;
pID = contentString.getString(prevNodeOffset, len);
}
return pID;
}
//
// Main
//
/** Main program entry point. */
public static void main(String argv[]) {
// is there anything to do?
if (argv.length == 0) {
System.exit(1);
}
// DTDScanner sc = new DTDScanner(argv[0]);
DTDScanner sc = new DTDScanner("hello.dtd", " gif SYSTEM \"GIF File\" "); //$NON-NLS-1$ //$NON-NLS-2$
NotationDecl n = sc.scanNotationDecl();
System.out.println("Noation Name: " + n.getNodeName()); //$NON-NLS-1$
System.out.println("SystemId: " + n.getSystemId()); //$NON-NLS-1$
// Attributes
// Vector lists = sc.scanAttlistDecl();
// sc.printAttList(lists);
// System.out.println("CM: " + sc.scanContentModel());
} // main(String[])
/**
* Gets the errorString
*
* @return Returns a String
*/
public String getErrorString() {
return errorString;
}
/**
* Sets the errorString
*
* @param errorString
* The errorString to set
*/
public void setErrorString(String errorString) {
this.errorString = errorString;
}
}