/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ws.jaxme.generator.sg.impl.ccsg;
import org.apache.ws.jaxme.generator.sg.ComplexTypeSG;
import org.apache.ws.jaxme.generator.sg.GroupSG;
import org.apache.ws.jaxme.generator.sg.ParticleSG;
import org.apache.ws.jaxme.impl.JMUnmarshallerHandlerImpl;
import org.apache.ws.jaxme.js.DirectAccessible;
import org.apache.ws.jaxme.js.JavaComment;
import org.apache.ws.jaxme.js.JavaField;
import org.apache.ws.jaxme.js.JavaMethod;
import org.apache.ws.jaxme.js.JavaSource;
import org.apache.ws.jaxme.js.LocalJavaField;
import org.xml.sax.SAXException;
/** Creates an instance of
* {@link org.apache.ws.jaxme.impl.JMSAXElementParser},
* or {@link org.apache.ws.jaxme.impl.JMSAXGroupParser},
* which parses a sequence.
*/
public class SequenceHandlerSG extends GroupHandlerSG {
/** Creates a new instance, which generates a handler for
* the complex type <code>pTypeSG</code> by adding methods
* and fields to the Java class <code>pJs</code>.
*/
public SequenceHandlerSG(ComplexTypeSG pTypeSG, JavaSource pJs)
throws SAXException {
super(pTypeSG, pJs);
}
SequenceHandlerSG(ComplexTypeSG pTypeSG, GroupSG pGroup, JavaSource pJs)
throws SAXException {
super(pTypeSG, pGroup, pJs);
}
protected DirectAccessible getEndElementState() throws SAXException {
return getStateField();
}
protected int getState(int pNum) {
return pNum+1;
}
private int fromState(int pState) {
return pState-1;
}
protected JavaField newStateField() throws SAXException {
JavaField jf = getJavaSource().newJavaField("__state", int.class, JavaSource.PRIVATE);
JavaComment jc = jf.newComment();
jc.addLine("The current state. The following values are valid states:");
jc.addLine(" 0 = Before parsing the element");
for (int i = 0; i < particles.length; i++) {
ParticleSG particle = particles[i];
if (particle.isGroup()) {
GroupSG group = particle.getGroupSG();
if (group.isGlobal()) {
jc.addLine(" " + getState(i) + " = While parsing the nested group " + group.getName());
} else {
jc.addLine(" " + getState(i) + " = While parsing the nested group " + GroupUtil.getGroupName(group));
}
} else if (particle.isElement()) {
jc.addLine(" " + getState(i) + " = While or after parsing the child element " + particle.getObjectSG().getName());
} else if (particle.isWildcard()) {
throw new IllegalStateException("TODO: Add support for wildcards.");
} else {
throw new IllegalStateException("Invalid particle type.");
}
}
return jf;
}
protected void acceptParticle(JavaMethod pJm, int pNum) throws SAXException {
pJm.addLine(getStateField(), " = " + getState(pNum) + ";");
}
public JavaMethod newStartElementMethod() throws SAXException {
JavaMethod result = super.newStartElementMethod();
LocalJavaField unmarshallerHandler = result.newJavaField(JMUnmarshallerHandlerImpl.class);
unmarshallerHandler.addLine("getHandler()");
result.addSwitch(getStateField());
result.addCase(new Integer(0));
handleStartElementStates(unmarshallerHandler,
result, getFirstValidParticle(0),
getLastValidParticle(0));
result.addBreak();
for (int i = 0; i < particles.length; i++) {
int state = getState(i);
result.addCase(new Integer(state));
handleStartElementStates(unmarshallerHandler,
result, getFirstValidParticle(state),
getLastValidParticle(state));
result.addBreak();
}
result.addDefault();
result.addThrowNew(IllegalStateException.class,
JavaSource.getQuoted("Invalid state: "),
" + ", getStateField());
result.addEndSwitch();
result.addLine("return false;");
return result;
}
/** Assuming, we are currently in state <code>pState</code>,
* returns the index of the first valid particle. Returns
* -1, if there is no valid particle.
*/
private int getFirstValidParticle(int pState) {
if (pState == 0) {
return 0;
} else {
int i = fromState(pState);
ParticleSG particle = particles[i];
if (particle.isMultiple()) {
return i;
} else if (i+1 < particles.length) {
return i+1;
} else {
return -1;
}
}
}
/** Assuming, we are currently in state <code>pState</code>,
* returns the index of the last valid particle. Returns
* -1, if there is no valid particle.
*/
private int getLastValidParticle(int pState) {
int lastParticle;
if (pState == 0) {
lastParticle = 0;
} else {
lastParticle = fromState(pState)+1;
if (lastParticle >= particles.length) {
return fromState(pState);
}
}
while (lastParticle < particles.length-1) {
ParticleSG particle = particles[lastParticle];
if (isRequiredParticle(particle)) {
break;
} else {
++lastParticle;
}
}
return lastParticle;
}
public JavaMethod newIsFinishedMethod() throws SAXException {
JavaMethod result = super.newIsFinishedMethod();
result.addSwitch(getStateField());
boolean allOptional = true;
for (int i = particles.length-1; i >= 0; i--) {
ParticleSG particle = particles[i];
result.addCase(new Integer(getState(i)));
if (isRequiredParticle(particle)) {
allOptional = false;
break;
}
}
if (allOptional) {
result.addCase(new Integer(0));
}
result.addLine("return true;");
result.addDefault();
result.addLine("return false;");
result.addEndSwitch();
return result;
}
}