/*
* @(#)$Id: ComplexTypeDeclState.java,v 1.18 2002/03/09 16:33:21 kk122374 Exp $
*
* Copyright 2001 Sun Microsystems, Inc. All Rights Reserved.
*
* This software is the proprietary information of Sun Microsystems, Inc.
* Use is subject to license terms.
*
*/
package com.sun.msv.reader.xmlschema;
import com.sun.msv.datatype.xsd.XSDatatype;
import com.sun.msv.grammar.Expression;
import com.sun.msv.grammar.SimpleNameClass;
import com.sun.msv.grammar.ReferenceContainer;
import com.sun.msv.grammar.xmlschema.AttributeWildcard;
import com.sun.msv.grammar.xmlschema.ComplexTypeExp;
import com.sun.msv.util.StartTagInfo;
import com.sun.msv.reader.State;
import org.xml.sax.Locator;
/**
* used to parse <complexType> element.
*
* @author <a href="mailto:kohsuke.kawaguchi@eng.sun.com">Kohsuke KAWAGUCHI</a>
*/
public class ComplexTypeDeclState extends RedefinableDeclState implements AnyAttributeOwner {
/** ComplexType object that we are now constructing. */
protected ComplexTypeExp decl;
protected ReferenceContainer getContainer() {
return ((XMLSchemaReader)reader).currentSchema.complexTypes;
}
protected void startSelf() {
super.startSelf();
final XMLSchemaReader reader = (XMLSchemaReader)this.reader;
String name = startTag.getAttribute("name");
if( name==null ) {
if( isGlobal() )
reader.reportError( reader.ERR_MISSING_ATTRIBUTE, "complexType", "name" );
decl = new ComplexTypeExp( reader.currentSchema, null );
} else {
if( isRedefine() )
// in redefine mode, use temporary object.
// parsed complexType will be copied into the original one.
decl = new ComplexTypeExp( reader.currentSchema, name );
else {
decl = reader.currentSchema.complexTypes.getOrCreate(name);
// MSV has pre-defiend types in xsd namespace (such as xs:anyType)
// this causes a problem when we are parsing schema4schema.
// to avoid this problem, we won't issue this error when we are
// parsing schema4schema.
//
// But this is more like a quick hack. What is the correct way to
// solve this problem?
if( decl.body.exp!=null && reader.currentSchema!=reader.xsdSchema )
reader.reportError(
new Locator[]{this.location,reader.getDeclaredLocationOf(decl)},
reader.ERR_DUPLICATE_COMPLEXTYPE_DEFINITION,
new Object[]{name} );
}
}
// set the final attribute to ComplexTypeExp.
decl.finalValue = parseFinalValue( "final", reader.finalDefault );
decl.block = parseFinalValue( "block", reader.blockDefault );
}
/**
* parses the value of the block/finel attribute.
*/
private int parseFinalValue( String attName, String defaultValue ) {
int r = 0;
String value = startTag.getAttribute(attName);
if( value==null ) value = defaultValue;
if( value!=null ) {
if( value.indexOf("#all")>=0 )
r |= ComplexTypeExp.RESTRICTION|ComplexTypeExp.EXTENSION;
if( value.indexOf("extension")>=0 )
r |= ComplexTypeExp.EXTENSION;
if( value.indexOf("restriction")>=0 )
r |= ComplexTypeExp.RESTRICTION;
}
return r;
}
public void setAttributeWildcard( AttributeWildcard local ) {
decl.wildcard = local;
}
protected State createChildState( StartTagInfo tag ) {
final XMLSchemaReader reader = (XMLSchemaReader)this.reader;
// simpleContent, ComplexContent, group, all, choice, and sequence
// are allowed only when we haven't seen type definition.
if(tag.localName.equals("simpleContent") ) return reader.sfactory.simpleContent(this,tag,decl);
if(tag.localName.equals("complexContent") ) return reader.sfactory.complexContent(this,tag,decl);
State s = reader.createModelGroupState(this,tag);
if(s!=null) return s;
if( super.exp==null ) {
// no content model was given.
// I couldn't "decipher" what should we do in this case.
// I assume "empty" just because it's most likely.
exp = Expression.epsilon;
}
// TODO: attributes are prohibited after simpleContent/complexContent.
// attribute, attributeGroup, and anyAttribtue can be specified
// after content model is given.
return reader.createAttributeState(this,tag);
}
protected Expression castExpression( Expression halfCastedExpression, Expression newChildExpression ) {
if( halfCastedExpression==null )
return newChildExpression; // the first one
// only the first one contains element.
// the rest consists of attributes.
// so this order of parameters is fine.
return reader.pool.createSequence( newChildExpression, halfCastedExpression );
}
protected Expression defaultExpression() {
// if no content model is given, then this complex type is empty
return Expression.epsilon;
}
protected Expression annealExpression(Expression contentType) {
final XMLSchemaReader reader = (XMLSchemaReader)this.reader;
String abstract_ = startTag.getAttribute("abstract");
if( "false".equals(abstract_) || abstract_==null )
// allow the content model to directly appear as this type.
decl.setAbstract(false);
else {
decl.setAbstract(true);
if( !"true".equals(abstract_) )
reader.reportError( reader.ERR_BAD_ATTRIBUTE_VALUE, "abstract", abstract_ );
// recover by ignoring this error.
}
String mixed = startTag.getAttribute("mixed");
if( "true".equals(mixed) )
contentType = reader.pool.createMixed(contentType);
else
if( mixed!=null && !"false".equals(mixed) )
reader.reportError( reader.ERR_BAD_ATTRIBUTE_VALUE, "mixed", mixed );
// recover by ignoring this error.
decl.body.exp = contentType;
if( isRedefine() ) {
// copy new definition back into the original definition.
oldDecl.redefine(decl);
decl = (ComplexTypeExp)oldDecl;
}
reader.setDeclaredLocationOf(decl);
reader.setDeclaredLocationOf(decl.body);
return decl;
}
}