blob: 89ceb63f33736dcf5864373e48e91f38d651297b [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.internal.modelgroup;
import java.util.Hashtable;
import org.eclipse.actf.model.dom.sgml.ISGMLConstants;
import org.eclipse.actf.model.dom.sgml.SGMLParser;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
public class SeqModelGroup extends CompositeModelGroup {
public SeqModelGroup(IModelGroup modelGroup) {
super(modelGroup);
}
public void add(IModelGroup modelGroup) {
/*
* (a , b, (c, d)) == (a, b, c, d)
*/
if (modelGroup instanceof SeqModelGroup) {
SeqModelGroup another = (SeqModelGroup) modelGroup;
for (int i = 0; i < another.childLength; i++) {
another.children[i].refer(false);
this.children[this.childLength++] = another.children[i];
}
} else {
children[childLength++] = modelGroup;
modelGroup.refer(false);
}
}
// for debug.
public String toString() {
String ret = new String("(");
for (int i = 0; i < childLength - 1; i++) {
ret = ret + children[i] + ',';
}
ret = ret + children[childLength - 1] + ')';
return ret;
}
// TODO support nested seqModel
public boolean match(SGMLParser parser, Node parent, Node child) {
Hashtable<Node, Integer> map = parser.getSeqMap();
Integer current = (Integer) map.get(parent);
IModelGroup mg;
int index = current == null ? 0 : current.intValue();
// prefetch 2
int rest = 0;
// int curIndex = index;
IModelGroup skipped[] = parser.getSeqArray();
int skippedNum = 0;
// System.out.println("match: 1st");
while (index < childLength) {
mg = children[index];
if (mg.match(parser, parent, child)) {
if (!(mg instanceof PlusModelGroup)
&& !(mg instanceof RepModelGroup)) {
index++;
}
if (skippedNum > 0) {
parser.error(ISGMLConstants.ILLEGAL_CHILD, "Order of "
+ parent + "'s children is wrong.");
}
// System.out.println("match: true "+index);
map.put(parent, new Integer(index));
return true;
} else if (mg.optional()) {
index++;
} else if (rest < 2) {
skipped[skippedNum++] = mg;
rest++;
index++;
} else {
System.out.println("match: false");
return false;
}
}
// System.out.println("match: 2nd");
// search before index, if found -> error
/*
* for (int i = curIndex - 2; i >= 0; i--) { mg = children[i]; if
* (mg.match(parser, parent, child)) { // map.put(parent, new Integer(i +
* 1)); outer1: for (Node prev = child.getPreviousSibling(); prev !=
* null; ) { int prevID = child instanceof Element ?
* parser.getDTD().getElementDefinition(prev.getNodeName()).number :
* parser.pcdataNumber; for (int j = i + 1; j < curIndex; j++) { mg =
* children[j]; if (mg.match(prevID)) { parent.removeChild(child);
* parent.insertBefore(child, prev); prev = child.getPreviousSibling();
* continue outer1; } } prev = prev.getPreviousSibling(); }
* parser.error(SGMLConstants.ILLEGAL_CHILD, "Order of " + parent + "'s
* children is wrong."); return true; } }
*/
Node sibling = parent.getLastChild();
if (sibling instanceof Element && child instanceof Element
&& sibling.getNodeName().equalsIgnoreCase(child.getNodeName())
&& parser.autoGenerated((Element) sibling)) {
// must be error
while (sibling.hasChildNodes()) {
Node sibChild = sibling.getFirstChild();
sibling.removeChild(sibChild);
child.appendChild(sibChild);
}
parent.replaceChild(child, sibling);
return true;
}
return false;
}
public boolean optional() {
for (int i = childLength - 1; i >= 0; i--) {
if (!children[i].optional())
return false;
}
return true;
}
}