You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@xmlbeans.apache.org by ce...@apache.org on 2004/08/07 22:10:15 UTC
cvs commit: xml-xmlbeans/v2/src/tools/org/apache/xmlbeans/impl/inst2xsd/util Attribute.java Element.java Type.java TypeSystemHolder.java
cezar 2004/08/07 13:10:15
Added: v2/src/tools/org/apache/xmlbeans/impl/inst2xsd Inst2Xsd.java
Inst2XsdOptions.java RussianDollStrategy.java
SalamiSliceStrategy.java VenetianBlindStrategy.java
XsdGenStrategy.java
v2/src/tools/org/apache/xmlbeans/impl/inst2xsd/util
Attribute.java Element.java Type.java
TypeSystemHolder.java
Log:
Instance 2 schema tool.
checkintest: passes
Revision Changes Path
1.1 xml-xmlbeans/v2/src/tools/org/apache/xmlbeans/impl/inst2xsd/Inst2Xsd.java
Index: Inst2Xsd.java
===================================================================
/* Copyright 2004 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.xmlbeans.impl.inst2xsd;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.XmlBeans;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.XmlOptions;
import org.w3.x2001.xmlSchema.SchemaDocument;
import org.apache.xmlbeans.impl.inst2xsd.util.TypeSystemHolder;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @author Cezar Andrei (cezar.andrei at bea.com) Date: Jul 16, 2004
*
* This class generates a set of XMLSchemas from an instance XML document.
*
* How it works:
* - first: pass through all the instances, building a TypeSystemHolder structure
* - second: serialize the TypeSystemHolder structure into
*/
public class Inst2Xsd
{
public static void main(String[] args)
throws IOException, XmlException
{
if (args.length != 1)
{
System.out.println("Usage: Inst2xsd instance.xml");
return;
}
File instFile = new File(args[0]);
Inst2XsdOptions inst2XsdOptions = new Inst2XsdOptions();
inst2XsdOptions.setDesign(Inst2XsdOptions.DESIGN_VENETIAN_BLIND);
SchemaDocument[] schemas = inst2xsd(new Reader[] {new FileReader(instFile)}, inst2XsdOptions);
}
private Inst2Xsd() {}
public static SchemaDocument[] inst2xsd(Reader[] instReaders, Inst2XsdOptions options)
throws IOException, XmlException
{
XmlObject[] instances = new XmlObject[ instReaders.length ];
for (int i = 0; i < instReaders.length; i++)
{
instances[i] = XmlObject.Factory.parse(instReaders[i]);
}
return inst2xsd(instances, options);
}
public static SchemaDocument[] inst2xsd(XmlObject[] instances, Inst2XsdOptions options)
{
if (options==null)
options = new Inst2XsdOptions();
// create structure
TypeSystemHolder typeSystemHolder = new TypeSystemHolder();
XsdGenStrategy strategy;
switch (options.getDesign())
{
case Inst2XsdOptions.DESIGN_RUSSIAN_DOLL:
strategy = new RussianDollStrategy();
break;
case Inst2XsdOptions.DESIGN_SALAMI_SLICE:
strategy = new SalamiSliceStrategy();
break;
case Inst2XsdOptions.DESIGN_VENETIAN_BLIND:
strategy = new VenetianBlindStrategy();
break;
default:
throw new IllegalArgumentException("Unknown design.");
}
// processDoc the instance
strategy.processDoc(instances, options, typeSystemHolder);
// debug only
//System.out.println("typeSystemHolder.toString(): " + typeSystemHolder);
SchemaDocument[] sDocs = typeSystemHolder.getSchemaDocuments();
for (int i = 0; i < sDocs.length; i++)
{
System.out.println("--------------------\n\n" + sDocs[i] );
}
assert validateInstances(sDocs, instances);
// end debug only
return sDocs;
}
private static boolean validateInstances(SchemaDocument[] sDocs, XmlObject[] instances)
{
SchemaTypeLoader sLoader;
Collection compErrors = new ArrayList();
XmlOptions schemaOptions = new XmlOptions();
schemaOptions.setErrorListener(compErrors);
try
{
sLoader = XmlBeans.loadXsd(sDocs, schemaOptions);
}
catch (Exception e)
{
if (compErrors.isEmpty() || !(e instanceof XmlException))
{
e.printStackTrace(System.out);
}
System.out.println("Schema invalid");
for (Iterator errors = compErrors.iterator(); errors.hasNext(); )
System.out.println(errors.next());
return false;
}
boolean result = true;
for (int i = 0; i < instances.length; i++)
{
String instance = instances[i].toString();
XmlObject xobj;
try
{
xobj = sLoader.parse( instance, null, new XmlOptions().setLoadLineNumbers() );
}
catch (XmlException e)
{
System.out.println("Error:\n" + instance + " not loadable: " + e);
e.printStackTrace(System.out);
result = false;
continue;
}
Collection errors = new ArrayList();
if (xobj.schemaType() == XmlObject.type)
{
System.out.println(instance + " NOT valid. ");
System.out.println(" Document type not found." );
result = false;
}
else if (xobj.validate(new XmlOptions().setErrorListener(errors)))
System.out.println("Instance[" + i + "] valid.");
else
{
System.out.println("Instance[" + i + "] NOT valid.");
for (Iterator it = errors.iterator(); it.hasNext(); )
{
System.out.println(" " + it.next());
}
result = false;
}
}
return result;
}
}
1.1 xml-xmlbeans/v2/src/tools/org/apache/xmlbeans/impl/inst2xsd/Inst2XsdOptions.java
Index: Inst2XsdOptions.java
===================================================================
/* Copyright 2004 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.xmlbeans.impl.inst2xsd;
/**
* @author Cezar Andrei (cezar.andrei at bea.com) Date: Jul 19, 2004
Options:
* Design
o Russian Doll Design
o Salami Slice Design
o Venetian Blind Design
* Simple content types (leafs)
o smart (default) - try to find out the right simple shema type
o always xsd:string
* Use enumeration - when there are multiple valid values in a list
o never
o only if not more than ( 20 ) - number option
*/
public class Inst2XsdOptions
{
// design
public static final int DESIGN_RUSSIAN_DOLL = 1;
public static final int DESIGN_SALAMI_SLICE = 2;
public static final int DESIGN_VENETIAN_BLIND = 3;
private int _design = DESIGN_RUSSIAN_DOLL;
// schema type for simple content values
public static final int SIMPLE_CONTENT_TYPES_SMART = 1;
public static final int SIMPLE_CONTENT_TYPES_STRING = 2;
private int _simpleContentTypes = SIMPLE_CONTENT_TYPES_SMART;
// use enumeration
public static final int ENUMERATION_NEVER = 1;
public static final int ENUMERATION_NOT_MORE_THAN_DEFAULT = 10;
private int _enumerations = ENUMERATION_NOT_MORE_THAN_DEFAULT;
public int getDesign()
{
return _design;
}
/**
* Design
o Russian Doll Design
o Salami Slice Design
o Venetian Blind Design
* @param designType
* @see #DESIGN_RUSSIAN_DOLL
* @see #DESIGN_SALAMI_SLICE
* @see #DESIGN_VENETIAN_BLIND
*/
public void setDesign(int designType)
{
_design = designType;
}
public boolean isUseEnumerations()
{
return _enumerations>ENUMERATION_NEVER;
}
public int getUseEnumerations()
{
return _enumerations;
}
public void setUseEnumerations(int useEnumerations)
{
_enumerations = useEnumerations;
}
public int getSimpleContentTypes()
{
return _simpleContentTypes;
}
public void setSimpleContentTypes(int simpleContentTypes)
{
_simpleContentTypes = simpleContentTypes;
}
}
1.1 xml-xmlbeans/v2/src/tools/org/apache/xmlbeans/impl/inst2xsd/RussianDollStrategy.java
Index: RussianDollStrategy.java
===================================================================
/* Copyright 2004 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.xmlbeans.impl.inst2xsd;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.common.PrefixResolver;
import org.apache.xmlbeans.impl.common.ValidationContext;
import org.apache.xmlbeans.impl.common.XmlWhitespace;
import org.apache.xmlbeans.impl.inst2xsd.util.Attribute;
import org.apache.xmlbeans.impl.inst2xsd.util.Element;
import org.apache.xmlbeans.impl.inst2xsd.util.TypeSystemHolder;
import org.apache.xmlbeans.impl.inst2xsd.util.Type;
import org.apache.xmlbeans.impl.util.XsTypeConverter;
import org.apache.xmlbeans.impl.values.*;
import javax.xml.namespace.QName;
import java.util.*;
/**
* @author Cezar Andrei ( cezar.andrei at bea.com )
* Date: Jul 26, 2004
*/
public class RussianDollStrategy
implements XsdGenStrategy
{
public void processDoc(XmlObject[] instances, Inst2XsdOptions options, TypeSystemHolder typeSystemHolder)
{
for (int i = 0; i < instances.length; i++)
{
XmlObject instance = instances[i];
XmlCursor xc = instance.newCursor();
// xc on start doc
StringBuffer comment = new StringBuffer();
while( !xc.isStart() )
{
xc.toNextToken();
if( xc.isComment() )
comment.append(xc.getTextValue());
}
// xc now on the root element
Element withElem = processElement(xc, comment.toString(), options, typeSystemHolder);
withElem.setGlobal(true);
Element intoElem = typeSystemHolder.getGlobalElement(withElem.getName());
if (intoElem==null)
typeSystemHolder.addGlobalElement(withElem);
else
{
combineTypes(intoElem.getType(), withElem.getType(), options);
combineElementComments(intoElem, withElem);
}
}
}
protected Element processElement(XmlCursor xc, String comment,
Inst2XsdOptions options, TypeSystemHolder typeSystemHolder)
{
assert xc.isStart();
Element element = new Element();
element.setName(xc.getName());
element.setGlobal(false);
Type elemType = Type.createUnnamedType(Type.SIMPLE_TYPE_SIMPLE_CONTENT); //assume simple, set later
element.setType(elemType);
StringBuffer textBuff = new StringBuffer();
StringBuffer commentBuff = new StringBuffer();
List children = new ArrayList();
List attributes = new ArrayList();
loop: do
{
XmlCursor.TokenType tt = xc.toNextToken();
switch (tt.intValue())
{
case XmlCursor.TokenType.INT_ATTR:
// todo check for xsi:type
attributes.add(processAttribute(xc, options, element.getName().getNamespaceURI(), typeSystemHolder));
break;
case XmlCursor.TokenType.INT_START:
children.add(processElement(xc, commentBuff.toString(), options, typeSystemHolder));
commentBuff.delete(0, commentBuff.length());
break;
case XmlCursor.TokenType.INT_TEXT:
textBuff.append(xc.getChars());
break;
case XmlCursor.TokenType.INT_COMMENT:
commentBuff.append(xc.getTextValue());
break;
case XmlCursor.TokenType.INT_NAMESPACE:
// ignore for now,
// each element and attribute will take care to define itself in the right targetNamespace
break;
case XmlCursor.TokenType.INT_END:
break loop;
case XmlCursor.TokenType.INT_PROCINST:
// ignore
break;
case XmlCursor.TokenType.INT_ENDDOC:
throw new IllegalStateException();
case XmlCursor.TokenType.INT_NONE:
throw new IllegalStateException();
case XmlCursor.TokenType.INT_STARTDOC:
throw new IllegalStateException();
default:
throw new IllegalStateException("Unknown TokenType.");
}
}
while( true );
String collapsedText = XmlWhitespace.collapse(textBuff.toString(), XmlWhitespace.WS_COLLAPSE);
String commnetStr = (comment == null ?
( commentBuff.length() == 0 ? null : commentBuff.toString() ) :
( commentBuff.length() == 0 ? comment : commentBuff.insert(0, comment).toString()) );
element.setComment(commnetStr);
if (children.size()>0)
{
// complex content
if (collapsedText.length()>0)
{
elemType.setContentType(Type.COMPLEX_TYPE_MIXED_CONTENT);
}
else
{
elemType.setContentType(Type.COMPLEX_TYPE_COMPLEX_CONTENT);
}
processElementsInComplexType(elemType, children, element.getName().getNamespaceURI(), typeSystemHolder, options);
processAttributesInComplexType(elemType, attributes);
}
else
{
// simple content
xc.toParent(); // hack workaround for being able to call xc.getNamespaceForPrefix()
if (attributes.size()>0)
{
elemType.setContentType(Type.COMPLEX_TYPE_SIMPLE_CONTENT);
Type extendedType = Type.createNamedType(
processSimpleContentType(textBuff.toString(), options, xc), Type.SIMPLE_TYPE_SIMPLE_CONTENT);
elemType.setExtensionType(extendedType);
processAttributesInComplexType(elemType, attributes);
}
else
{
elemType.setContentType(Type.SIMPLE_TYPE_SIMPLE_CONTENT);
elemType.setName(processSimpleContentType(textBuff.toString(), options, xc));
// add enumeration value
String enumValue = XmlString.type.getName().equals(elemType.getName()) ? textBuff.toString() : collapsedText;
elemType.addEnumerationValue(enumValue);
}
xc.toEndToken(); // end hack
}
checkIfReferenceToGlobalTypeIsNeeded( element, typeSystemHolder, options);
xc.toNextToken(); // advance over end element
return element;
}
protected void processElementsInComplexType(Type elemType, List children, String parentNamespace,
TypeSystemHolder typeSystemHolder, Inst2XsdOptions options)
{
Map elemNamesToElements = new HashMap();
Element currentElem = null;
for (Iterator iterator = children.iterator(); iterator.hasNext();)
{
Element child = (Element) iterator.next();
if (currentElem==null)
{ // first element in this type
checkIfElementReferenceIsNeeded(child, parentNamespace, typeSystemHolder);
elemType.addElement(child);
elemNamesToElements.put(child.getName(), child);
currentElem = child;
continue;
}
if (currentElem.getName()==child.getName())
{ // same contiguos element
combineTypes(currentElem.getType(), child.getType(), options); // unify types
combineElementComments(currentElem, child);
// minOcc=0 maxOcc=unbounded
currentElem.setMinOccurs(0);
currentElem.setMaxOccurs(Element.UNBOUNDED);
}
else
{
Element sameElem = (Element)elemNamesToElements.get(child.getName());
if (sameElem==null)
{ // new element name
checkIfElementReferenceIsNeeded(child, parentNamespace, typeSystemHolder);
elemType.addElement(child);
elemNamesToElements.put(child.getName(), child);
}
else
{ //same non contiguos
combineTypes(currentElem.getType(), child.getType(), options);
combineElementComments(currentElem, child);
elemType.setTopParticleForComplexOrMixedContent(Type.PARTICLE_CHOICE_UNBOUNDED);
}
currentElem = child;
}
}
}
protected void checkIfElementReferenceIsNeeded(Element child, String parentNamespace, TypeSystemHolder typeSystemHolder)
{
if (!child.getName().getNamespaceURI().equals(parentNamespace))
{
Element referencedElem = new Element();
referencedElem.setGlobal(true);
referencedElem.setName(child.getName());
referencedElem.setType(child.getType());
typeSystemHolder.addGlobalElement(referencedElem);
child.setRef(referencedElem); // clears child's type
}
}
protected void checkIfReferenceToGlobalTypeIsNeeded(Element elem, TypeSystemHolder typeSystemHolder,
Inst2XsdOptions options)
{
// RussianDollDesign doesn't define global types
}
protected void processAttributesInComplexType(Type elemType, List attributes)
{
assert elemType.isComplexType();
for (Iterator iterator = attributes.iterator(); iterator.hasNext();)
{
Attribute att = (Attribute) iterator.next();
elemType.addAttribute(att);
}
}
protected Attribute processAttribute(XmlCursor xc, Inst2XsdOptions options, String parentNamespace,
TypeSystemHolder typeSystemHolder)
{
Attribute attribute = new Attribute();
QName attName = xc.getName();
attribute.setName(attName);
Type simpleContentType = Type.createNamedType(
processSimpleContentType(xc.getTextValue(), options, xc), Type.SIMPLE_TYPE_SIMPLE_CONTENT);
attribute.setType(simpleContentType);
checkIfAttributeReferenceIsNeeded(attribute, parentNamespace, typeSystemHolder);
return attribute;
}
protected void checkIfAttributeReferenceIsNeeded(Attribute attribute, String parentNamespace, TypeSystemHolder typeSystemHolder)
{
if (!attribute.getName().getNamespaceURI().equals("") &&
!attribute.getName().getNamespaceURI().equals(parentNamespace))
{
// make attribute be a reference to a top level attribute in a different targetNamespace
Attribute referencedAtt = new Attribute();
referencedAtt.setGlobal(true);
referencedAtt.setName(attribute.getName());
referencedAtt.setType(attribute.getType());
typeSystemHolder.addGlobalAttribute(referencedAtt);
attribute.setRef(referencedAtt);
}
}
protected class SCTValidationContext
implements ValidationContext
{
protected boolean valid = true;
public boolean isValid()
{
return valid;
}
public void resetToValid()
{
valid = true;
}
public void invalid(String message)
{
valid = false;
}
}
private SCTValidationContext _validationContext = new SCTValidationContext();
// List of precedence for smart simple primitive type determination
// byte, short, int, long, integer, float, double, decimal,
// boolean
// date, dateTime, time, gDuration,
// QName ?,
// anyUri ? - triggered only for http:// or www. constructs,
// list types ?
// string
protected QName processSimpleContentType(String lexicalValue, Inst2XsdOptions options, final XmlCursor xc)
{
// check options and return xsd:string or if smart is enabled, look for a better type
if (options.getSimpleContentTypes()==Inst2XsdOptions.SIMPLE_CONTENT_TYPES_STRING)
return XmlString.type.getName();
if (options.getSimpleContentTypes()!=Inst2XsdOptions.SIMPLE_CONTENT_TYPES_SMART)
throw new IllegalArgumentException("Unknown value for Inst2XsdOptions.getSimpleContentTypes() :" + options.getSimpleContentTypes());
// Inst2XsdOptions.SIMPLE_CONTENT_TYPES_SMART case
try
{
XsTypeConverter.lexByte(lexicalValue);
return XmlByte.type.getName();
}
catch (Exception e) {}
try
{
XsTypeConverter.lexShort(lexicalValue);
return XmlShort.type.getName();
}
catch (Exception e) {}
try
{
XsTypeConverter.lexInt(lexicalValue);
return XmlInt.type.getName();
}
catch (Exception e) {}
try
{
XsTypeConverter.lexLong(lexicalValue);
return XmlLong.type.getName();
}
catch (Exception e) {}
try
{
XsTypeConverter.lexInteger(lexicalValue);
return XmlInteger.type.getName();
}
catch (Exception e) {}
try
{
XsTypeConverter.lexFloat(lexicalValue);
return XmlFloat.type.getName();
}
catch (Exception e) {}
// // this not needed because it's lexical space is covered by float
// try
// {
// XsTypeConverter.lexDouble(lexicalValue);
// return XmlDouble.type.getName();
// }
// catch (Exception e) {}
//
// try
// {
// XsTypeConverter.lexDecimal(lexicalValue);
// return XmlDecimal.type.getName();
// }
// catch (Exception e) {}
XmlDateImpl.validateLexical(lexicalValue, XmlDate.type, _validationContext);
if (_validationContext.isValid())
return XmlDate.type.getName();
_validationContext.resetToValid();
XmlDateTimeImpl.validateLexical(lexicalValue, XmlDateTime.type, _validationContext);
if (_validationContext.isValid())
return XmlDateTime.type.getName();
_validationContext.resetToValid();
XmlTimeImpl.validateLexical(lexicalValue, XmlTime.type, _validationContext);
if (_validationContext.isValid())
return XmlTime.type.getName();
_validationContext.resetToValid();
XmlDurationImpl.validateLexical(lexicalValue, XmlDuration.type, _validationContext);
if (_validationContext.isValid())
return XmlDuration.type.getName();
_validationContext.resetToValid();
// check for uri
if (lexicalValue.startsWith("http://") || lexicalValue.startsWith("www."))
{
XmlAnyUriImpl.validateLexical(lexicalValue, _validationContext);
if (_validationContext.isValid())
return XmlAnyURI.type.getName();
_validationContext.resetToValid();
}
// check for QName
if (lexicalValue.indexOf(':')>=0 && lexicalValue.indexOf(':')==lexicalValue.lastIndexOf(':'))
{
PrefixResolver prefixResolver = new PrefixResolver()
{
public String getNamespaceForPrefix(String prefix)
{ return xc.prefixForNamespace(prefix); }
};
XmlQNameImpl.validateLexical(lexicalValue, _validationContext, prefixResolver);
if (_validationContext.isValid())
return XmlQName.type.getName();
_validationContext.resetToValid();
}
//the check for lists is probably too expensive
return XmlString.type.getName();
}
protected void combineTypes(Type into, Type with, Inst2XsdOptions options)
{
if (into.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT &&
with.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT)
{
combineSimpleTypes(into, with, options);
return;
}
if ((into.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT ||
into.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT) &&
(with.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT ||
with.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT) )
{
//complex type simple content
into.setContentType(Type.COMPLEX_TYPE_SIMPLE_CONTENT);
// take the extension name if it's a complex type
QName intoTypeName = into.isComplexType() ? into.getExtensionType().getName() : into.getName();
QName withTypeName = with.isComplexType() ? with.getExtensionType().getName() : with.getName();
QName moreGeneralTypeName = combineToMoreGeneralSimpleType(intoTypeName, withTypeName);
if (into.isComplexType())
{
Type extendedType = Type.createNamedType(moreGeneralTypeName, Type.SIMPLE_TYPE_SIMPLE_CONTENT);
into.setExtensionType(extendedType);
}
else
into.setName(moreGeneralTypeName);
combineAttributesOfTypes(into, with);
return;
}
if (into.getContentType()==Type.COMPLEX_TYPE_COMPLEX_CONTENT &&
with.getContentType()==Type.COMPLEX_TYPE_COMPLEX_CONTENT)
{
combineAttributesOfTypes(into, with);
combineElementsOfTypes(into, with, false, options);
return;
}
if (into.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT ||
into.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT ||
with.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT ||
with.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT)
{
into.setContentType(Type.COMPLEX_TYPE_MIXED_CONTENT);
combineAttributesOfTypes(into, with);
combineElementsOfTypes(into, with, true, options);
return;
}
if ((into.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT ||
into.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT ||
into.getContentType()==Type.COMPLEX_TYPE_COMPLEX_CONTENT ||
into.getContentType()==Type.COMPLEX_TYPE_MIXED_CONTENT) &&
(with.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT ||
with.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT ||
with.getContentType()==Type.COMPLEX_TYPE_COMPLEX_CONTENT ||
with.getContentType()==Type.COMPLEX_TYPE_MIXED_CONTENT) )
{
into.setContentType(Type.COMPLEX_TYPE_MIXED_CONTENT);
combineAttributesOfTypes(into, with);
combineElementsOfTypes(into, with, false, options);
return;
}
throw new IllegalArgumentException("Unknown content type.");
}
protected void combineSimpleTypes(Type into, Type with, Inst2XsdOptions options)
{
assert (into.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT &&
with.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT) : "Invalid arguments";
//simple type simple content
into.setName(combineToMoreGeneralSimpleType(into.getName(), with.getName()));
// take care of enumeration values
if (options.isUseEnumerations())
{
for (int i = 0; i < with.getEnumerationValues().size(); i++)
{
String enumValue = (String) with.getEnumerationValues().get(i);
into.addEnumerationValue(enumValue);
}
if (into.getEnumerationValues().size()>options.getUseEnumerations())
{
into.closeEnumeration();
}
}
}
protected QName combineToMoreGeneralSimpleType(QName t1, QName t2)
{
if (t1.equals(t2))
return t1;
if (t2.equals(XmlShort.type.getName()) && t1.equals(XmlByte.type.getName()))
return t2;
if (t1.equals(XmlShort.type.getName()) && t2.equals(XmlByte.type.getName()))
return t1;
if (t2.equals(XmlInt.type.getName()) &&
(t1.equals(XmlShort.type.getName()) || t1.equals(XmlByte.type.getName())) )
return t2;
if (t1.equals(XmlInt.type.getName()) &&
(t2.equals(XmlShort.type.getName()) || t2.equals(XmlByte.type.getName())) )
return t1;
if (t2.equals(XmlLong.type.getName()) &&
(t1.equals(XmlInt.type.getName()) || t1.equals(XmlShort.type.getName()) || t1.equals(XmlByte.type.getName())) )
return t2;
if (t1.equals(XmlLong.type.getName()) &&
(t2.equals(XmlInt.type.getName()) || t2.equals(XmlShort.type.getName()) || t2.equals(XmlByte.type.getName())) )
return t1;
if (t2.equals(XmlInteger.type.getName()) &&
(t1.equals(XmlLong.type.getName()) || t1.equals(XmlInt.type.getName()) ||
t1.equals(XmlShort.type.getName()) || t1.equals(XmlByte.type.getName())) )
return t2;
if (t1.equals(XmlInteger.type.getName()) &&
(t2.equals(XmlLong.type.getName()) || t2.equals(XmlInt.type.getName()) ||
t2.equals(XmlShort.type.getName()) || t2.equals(XmlByte.type.getName())) )
return t1;
if (t2.equals(XmlFloat.type.getName()) &&
(t1.equals(XmlInteger.type.getName()) ||
t1.equals(XmlLong.type.getName()) || t1.equals(XmlInt.type.getName()) ||
t1.equals(XmlShort.type.getName()) || t1.equals(XmlByte.type.getName())) )
return t2;
if (t1.equals(XmlFloat.type.getName()) &&
(t2.equals(XmlInteger.type.getName()) ||
t2.equals(XmlLong.type.getName()) || t2.equals(XmlInt.type.getName()) ||
t2.equals(XmlShort.type.getName()) || t2.equals(XmlByte.type.getName())) )
return t1;
//double, decimal will never get here since they don't get generated
//the rest of the combinations are not compatible, so they will combine in xsd:string
return XmlString.type.getName();
}
protected void combineAttributesOfTypes(Type into, Type from)
{
// loop through attributes: add fromAtt if they don't exist, combine them if they exist
outterLoop:
for (int i = 0; i < from.getAttributes().size(); i++)
{
Attribute fromAtt = (Attribute)from.getAttributes().get(i);
for (int j = 0; j < into.getAttributes().size(); j++)
{
Attribute intoAtt = (Attribute)into.getAttributes().get(j);
if (intoAtt.getName().equals(fromAtt.getName()))
{
intoAtt.getType().setName(
combineToMoreGeneralSimpleType(intoAtt.getType().getName(), fromAtt.getType().getName()));
continue outterLoop;
}
}
// fromAtt doesn't exist in into type, will add it right now
into.addAttribute(fromAtt);
}
//optional attributes: if there are atts in into that are not in from, make them optional
outterLoop:
for (int i = 0; i < into.getAttributes().size(); i++)
{
Attribute intoAtt = (Attribute)into.getAttributes().get(i);
for (int j = 0; j < from.getAttributes().size(); j++)
{
Attribute fromAtt = (Attribute)from.getAttributes().get(j);
if (fromAtt.getName().equals(intoAtt.getName()))
{
continue;
}
}
// intoAtt doesn't exist in into type, will add it right now
intoAtt.setOptional(true);
}
}
protected void combineElementsOfTypes(Type into, Type from, boolean makeElementsOptional, Inst2XsdOptions options)
{
// loop through elements: add fromElem if they don't exist, combine them if they exist
outterLoop:
for (int i = 0; i < from.getElements().size(); i++)
{
Element fromElem = (Element)from.getElements().get(i);
for (int j = 0; j < into.getElements().size(); j++)
{
Element intoElem = (Element)into.getElements().get(j);
if (intoElem.getName().equals(fromElem.getName()))
{
combineTypes(intoElem.getType(), fromElem.getType(), options);
combineElementComments(intoElem, fromElem);
if (fromElem.getMaxOccurs()==Element.UNBOUNDED)
intoElem.setMaxOccurs(Element.UNBOUNDED);
combineElementComments(intoElem, fromElem);
continue outterLoop;
}
}
// fromElem doesn't exist in into type, will add it right now
into.addElement(fromElem);
}
// for all the elements that are in into and not in from they need to be optional
outterLoop:
for (int i = 0; i < into.getElements().size(); i++)
{
Element intoElem = (Element)into.getElements().get(i);
if (makeElementsOptional)
{
intoElem.setMinOccurs(0);
continue;
}
for (int j = 0; j < from.getElements().size(); j++)
{
Element fromElem = (Element)from.getElements().get(j);
if (intoElem.getName().equals(fromElem.getName()))
{
continue outterLoop;
}
}
// intoElem doesn't exist in from type, make it optional
intoElem.setMinOccurs(0);
//intoElem.setMaxOccurs(Element.UNBOUNDED);
}
}
protected void combineElementComments(Element into, Element with)
{
if (with.getComment()!=null || with.getComment().length()>0)
{
if (into.getComment()==null)
into.setComment(with.getComment());
else
into.setComment(into.getComment() + with.getComment());
}
}
}
1.1 xml-xmlbeans/v2/src/tools/org/apache/xmlbeans/impl/inst2xsd/SalamiSliceStrategy.java
Index: SalamiSliceStrategy.java
===================================================================
/* Copyright 2004 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.xmlbeans.impl.inst2xsd;
import org.apache.xmlbeans.impl.inst2xsd.util.Element;
import org.apache.xmlbeans.impl.inst2xsd.util.TypeSystemHolder;
/**
* @author Cezar Andrei ( cezar.andrei at bea.com )
* Date: Jul 26, 2004
*/
public class SalamiSliceStrategy
extends RussianDollStrategy
implements XsdGenStrategy
{
protected void checkIfElementReferenceIsNeeded(Element child, String parentNamespace, TypeSystemHolder typeSystemHolder)
{
// always add element references
Element referencedElem = new Element();
referencedElem.setGlobal(true);
referencedElem.setName(child.getName());
referencedElem.setType(child.getType());
typeSystemHolder.addGlobalElement(referencedElem);
child.setRef(referencedElem); // clears child's type
}
}
1.1 xml-xmlbeans/v2/src/tools/org/apache/xmlbeans/impl/inst2xsd/VenetianBlindStrategy.java
Index: VenetianBlindStrategy.java
===================================================================
/* Copyright 2004 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.xmlbeans.impl.inst2xsd;
import org.apache.xmlbeans.impl.inst2xsd.util.Element;
import org.apache.xmlbeans.impl.inst2xsd.util.TypeSystemHolder;
import org.apache.xmlbeans.impl.inst2xsd.util.Type;
import javax.xml.namespace.QName;
/**
* @author Cezar Andrei ( cezar.andrei at bea.com )
* Date: Jul 26, 2004
*/
public class VenetianBlindStrategy
extends RussianDollStrategy
implements XsdGenStrategy
{
protected void checkIfReferenceToGlobalTypeIsNeeded(Element elem,
TypeSystemHolder typeSystemHolder, Inst2XsdOptions options)
{
// VenetianBlindDesign defines global complex types
Type elemType = elem.getType();
QName elemName = elem.getName();
if (elemType.isGlobal())
// is already global, do nothing
return;
if (elemType.isComplexType())
{
for (int i = 0; ; i++)
{
elemType.setName(new QName(elemName.getNamespaceURI(), elemName.getLocalPart() + "Type" + (i==0 ? "" : "" + i)));
Type candidate = typeSystemHolder.getGlobalType(elemType.getName());
if (candidate==null)
{
elemType.setGlobal(true);
typeSystemHolder.addGlobalType(elemType);
break;
}
else
{
if (compatibleTypes(elemType, candidate))
{
combineTypes(candidate, elemType, options);
elem.setType(candidate);
break;
}
}
}
}
}
private boolean compatibleTypes(Type elemType, Type candidate)
{
// when two types look like they are the same ?
if (!elemType.isComplexType() && !candidate.isComplexType())
return true;
if (elemType.isComplexType() && !candidate.isComplexType())
return false;
if (!elemType.isComplexType() && candidate.isComplexType())
return false;
// both complex after this point
//todo: be smarter: look at att and elem names and types - compute a difference index
return true;
}
}
1.1 xml-xmlbeans/v2/src/tools/org/apache/xmlbeans/impl/inst2xsd/XsdGenStrategy.java
Index: XsdGenStrategy.java
===================================================================
/**
* Author: Cezar Andrei ( cezar.andrei at bea.com )
* Date: Jul 26, 2004
*/
package org.apache.xmlbeans.impl.inst2xsd;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.impl.inst2xsd.util.TypeSystemHolder;
import org.apache.xmlbeans.impl.inst2xsd.Inst2XsdOptions;
interface XsdGenStrategy
{
void processDoc(XmlObject[] instances, Inst2XsdOptions options, TypeSystemHolder typeSystemHolder);
}
1.1 xml-xmlbeans/v2/src/tools/org/apache/xmlbeans/impl/inst2xsd/util/Attribute.java
Index: Attribute.java
===================================================================
/* Copyright 2004 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.xmlbeans.impl.inst2xsd.util;
import javax.xml.namespace.QName;
/**
* @author Cezar Andrei (cezar.andrei at bea.com) Date: Jul 18, 2004
*/
public class Attribute
{
private QName _name;
private Type _type;
private Attribute _ref = null;
private boolean _isGlobal = false;
private boolean _isOptional = false;
public QName getName()
{
return _name;
}
public void setName(QName name)
{
_name = name;
}
public Type getType()
{
return isRef() ? getRef().getType() : _type;
}
public void setType(Type type)
{
assert !isRef();
_type = type;
}
public boolean isRef()
{
return _ref!=null;
}
public Attribute getRef()
{
return _ref;
}
public void setRef(Attribute ref)
{
assert !isGlobal();
_ref = ref;
_type = null;
}
public boolean isGlobal()
{
return _isGlobal;
}
public void setGlobal(boolean isGlobal)
{
_isGlobal = isGlobal;
}
public boolean isOptional()
{
return _isOptional;
}
public void setOptional(boolean isOptional)
{
assert isOptional && !isGlobal() : "Global attributes cannot be optional.";
_isOptional = isOptional;
}
public String toString()
{
return "\n Attribute{" +
"_name=" + _name +
", _type=" + _type +
", _ref=" + (_ref!=null) +
", _isGlobal=" + _isGlobal +
", _isOptional=" + _isOptional +
"}";
}
}
1.1 xml-xmlbeans/v2/src/tools/org/apache/xmlbeans/impl/inst2xsd/util/Element.java
Index: Element.java
===================================================================
/* Copyright 2004 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.xmlbeans.impl.inst2xsd.util;
import javax.xml.namespace.QName;
/**
* @author Cezar Andrei (cezar.andrei at bea.com) Date: Jul 16, 2004
*/
public class Element
{
private QName _name = null; // if isRef is true is the name of the referenced name
private Element _ref = null;
private boolean _isGlobal = false;
private int _minOccurs = 1;
private int _maxOccurs = 1;
public static final int UNBOUNDED = -1;
private Type _type = null;
private String _comment = null;
public QName getName()
{
return _name;
}
public void setName(QName name)
{
_name = name;
}
public boolean isRef()
{
return _ref!=null;
}
public Element getRef()
{
return _ref;
}
public void setRef(Element ref)
{
assert _isGlobal==false;
_ref = ref;
_type = null;
}
public boolean isGlobal()
{
return _isGlobal;
}
public void setGlobal(boolean isGlobal)
{
_isGlobal = isGlobal;
_minOccurs = 1;
_maxOccurs = 1;
}
public int getMinOccurs()
{
return _minOccurs;
}
public void setMinOccurs(int minOccurs)
{
_minOccurs = minOccurs;
}
public int getMaxOccurs()
{
return _maxOccurs;
}
public void setMaxOccurs(int maxOccurs)
{
_maxOccurs = maxOccurs;
}
public Type getType()
{
return isRef() ? getRef().getType() : _type;
}
public void setType(Type type)
{
assert !isRef();
_type = type;
}
public String getComment()
{
return _comment;
}
public void setComment(String comment)
{
_comment = comment;
}
public String toString()
{
return "\n Element{" +
" _name = " + _name +
", _ref = " + (_ref!=null) +
", _isGlobal = " + _isGlobal +
", _minOccurs = " + _minOccurs +
", _maxOccurs = " + _maxOccurs +
", _comment = " + _comment +
",\n _type = " + _type +
"\n }";
}
}
1.1 xml-xmlbeans/v2/src/tools/org/apache/xmlbeans/impl/inst2xsd/util/Type.java
Index: Type.java
===================================================================
/* Copyright 2004 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.xmlbeans.impl.inst2xsd.util;
import javax.xml.namespace.QName;
import java.util.List;
import java.util.ArrayList;
/**
* @author Cezar Andrei (cezar.andrei at bea.com) Date: Jul 16, 2004
*/
public class Type
{
private QName _name;
private int _kind = SIMPLE_TYPE_SIMPLE_CONTENT;
// _kind value space
public static final int SIMPLE_TYPE_SIMPLE_CONTENT = 1; // ie no atts, no elems, just text
public static final int COMPLEX_TYPE_SIMPLE_CONTENT = 2; // ie atts*, no elems, text* - simple type extension
public static final int COMPLEX_TYPE_COMPLEX_CONTENT = 3; // ie atts*, elems, no text
public static final int COMPLEX_TYPE_MIXED_CONTENT = 4; // ie atts*, elems, text
private int _topParticleForComplexOrMixedContent = PARTICLE_SEQUENCE;
// _topParticleForComplexOrMixedContent
public static final int PARTICLE_SEQUENCE = 1;
public static final int PARTICLE_CHOICE_UNBOUNDED = 2;
private List _elements; // size>0 COMPLEX
private List _attributes; // size>0 COMPLEX
private Type _extensionType;
private boolean _isGlobal = false;
private List _enumerationValues;
private boolean _acceptsEnumerationValue = true;
private Type()
{}
public static Type createNamedType(QName name, int contentType)
{
assert name!=null;
Type type = new Type();
type.setName(name);
type.setContentType(contentType);
return type;
}
public static Type createUnnamedType(int contentType)
{
assert contentType==SIMPLE_TYPE_SIMPLE_CONTENT ||
contentType==COMPLEX_TYPE_SIMPLE_CONTENT ||
contentType==COMPLEX_TYPE_COMPLEX_CONTENT ||
contentType==COMPLEX_TYPE_MIXED_CONTENT : "Unknown contentType: " + contentType;
Type type = new Type();
type.setContentType(contentType);
return type;
}
public QName getName()
{
return _name;
}
public void setName(QName name)
{
this._name = name;
}
public int getContentType()
{
return _kind;
}
public void setContentType(int kind)
{
this._kind = kind;
}
public List getElements()
{
ensureElements();
return _elements;
}
public void addElement(Element element)
{
ensureElements();
_elements.add(element);
}
private void ensureElements()
{
if (_elements==null)
_elements = new ArrayList();
}
public List getAttributes()
{
ensureAttributes();
return _attributes;
}
public void addAttribute(Attribute attribute)
{
ensureAttributes();
_attributes.add(attribute);
}
public Attribute getAttribute(QName name)
{
for (int i = 0; i < _attributes.size(); i++)
{
Attribute attribute = (Attribute) _attributes.get(i);
if (attribute.getName().equals(name))
return attribute;
}
return null;
}
private void ensureAttributes()
{
if (_attributes==null)
_attributes = new ArrayList();
}
public boolean isComplexType()
{
return (_kind==COMPLEX_TYPE_COMPLEX_CONTENT ||
_kind==COMPLEX_TYPE_MIXED_CONTENT||
_kind==COMPLEX_TYPE_SIMPLE_CONTENT);
}
public boolean hasSimpleContent()
{
return (_kind==SIMPLE_TYPE_SIMPLE_CONTENT ||
_kind==COMPLEX_TYPE_SIMPLE_CONTENT);
}
public int getTopParticleForComplexOrMixedContent()
{
return _topParticleForComplexOrMixedContent;
}
public void setTopParticleForComplexOrMixedContent(int _topParticleForComplexOrMixedContent)
{
this._topParticleForComplexOrMixedContent = _topParticleForComplexOrMixedContent;
}
public boolean isGlobal()
{
return _isGlobal;
}
public void setGlobal(boolean isGlobal)
{
assert isGlobal && getName()!=null;
_isGlobal = isGlobal;
}
public Type getExtensionType()
{
return _extensionType;
}
public void setExtensionType(Type extendedType)
{
assert _kind == COMPLEX_TYPE_SIMPLE_CONTENT : "Extension used only for type which are COMPLEX_TYPE_SIMPLE_CONTENT";
assert extendedType!=null && extendedType.getName()!=null : "Extended type must be a named type.";
_extensionType = extendedType;
}
public List getEnumerationValues()
{
ensureEnumerationValues();
return _enumerationValues;
}
public void addEnumerationValue(String enumerationValue)
{
assert _kind==SIMPLE_TYPE_SIMPLE_CONTENT || _kind==COMPLEX_TYPE_SIMPLE_CONTENT : "Enumerations possible only on simple content";
ensureEnumerationValues();
if (_acceptsEnumerationValue && !_enumerationValues.contains(enumerationValue))
{
_enumerationValues.add(enumerationValue);
}
}
private void ensureEnumerationValues()
{
if (_enumerationValues==null)
_enumerationValues = new ArrayList();
}
public boolean isEnumeration()
{
return _acceptsEnumerationValue && _enumerationValues!=null && _enumerationValues.size()>1;
}
public void closeEnumeration()
{
_acceptsEnumerationValue=false;
}
public String toString()
{
return "Type{" +
"_name = " + _name +
", _extensionType = " + _extensionType +
", _kind = " + _kind +
", _elements = " + _elements +
", _attributes = " + _attributes +
"}";
}
}
1.1 xml-xmlbeans/v2/src/tools/org/apache/xmlbeans/impl/inst2xsd/util/TypeSystemHolder.java
Index: TypeSystemHolder.java
===================================================================
/* Copyright 2004 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.xmlbeans.impl.inst2xsd.util;
import org.w3.x2001.xmlSchema.SchemaDocument;
import org.apache.xmlbeans.XmlString;
import javax.xml.namespace.QName;
import java.math.BigInteger;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* @author Cezar Andrei (cezar.andrei at bea.com) Date: Jul 16, 2004
*/
public class TypeSystemHolder
{
Map _globalElements; // QName -> Element
Map _globalAttributes; // QName -> Attribute
Map _globalTypes; // QName -> Type
public TypeSystemHolder()
{
_globalElements = new HashMap();
_globalAttributes = new HashMap();
_globalTypes = new HashMap();
}
public void addGlobalElement(Element element)
{
assert element.isGlobal() && !element.isRef();
_globalElements.put(element.getName(), element);
}
public Element getGlobalElement(QName name)
{
return (Element)_globalElements.get(name);
}
public Element[] getGlobalElements()
{
Collection col = _globalElements.values();
return (Element[])col.toArray(new Element[col.size()]);
}
public void addGlobalAttribute(Attribute attribute)
{
assert attribute.isGlobal() && !attribute.isRef();
_globalAttributes.put(attribute.getName(), attribute);
}
public Attribute getGlobalAttribute(QName name)
{
return (Attribute)_globalAttributes.get(name);
}
public Attribute[] getGlobalAttributes()
{
Collection col = _globalAttributes.values();
return (Attribute[])col.toArray(new Attribute[col.size()]);
}
public void addGlobalType(Type type)
{
assert type.isGlobal() && type.getName()!=null : "type must be a global type before being added.";
_globalTypes.put(type.getName(), type);
}
public Type getGlobalType(QName name)
{
return (Type)_globalTypes.get(name);
}
public Type[] getGlobalTypes()
{
Collection col = _globalTypes.values();
return (Type[])col.toArray(new Type[col.size()]);
}
public SchemaDocument[] getSchemaDocuments()
{
// recompute everything, should cache it and track changes
Map nsToSchemaDocs = new HashMap();
for (Iterator iterator = _globalElements.keySet().iterator(); iterator.hasNext();)
{
QName globalElemName = (QName) iterator.next();
String tns = globalElemName.getNamespaceURI();
SchemaDocument schDoc = getSchemaDocumentForTNS(nsToSchemaDocs, tns);
fillUpGlobalElement((Element)_globalElements.get(globalElemName), schDoc, tns);
}
for (Iterator iterator = _globalAttributes.keySet().iterator(); iterator.hasNext();)
{
QName globalAttName = (QName) iterator.next();
String tns = globalAttName.getNamespaceURI();
SchemaDocument schDoc = getSchemaDocumentForTNS(nsToSchemaDocs, tns);
fillUpGlobalAttribute((Attribute)_globalAttributes.get(globalAttName), schDoc, tns);
}
for (Iterator iterator = _globalTypes.keySet().iterator(); iterator.hasNext();)
{
QName globalTypeName = (QName) iterator.next();
String tns = globalTypeName.getNamespaceURI();
SchemaDocument schDoc = getSchemaDocumentForTNS(nsToSchemaDocs, tns);
fillUpGlobalType((Type)_globalTypes.get(globalTypeName), schDoc, tns);
}
Collection schDocColl = nsToSchemaDocs.values();
return (SchemaDocument[])schDocColl.toArray(new SchemaDocument[schDocColl.size()]);
}
private static SchemaDocument getSchemaDocumentForTNS(Map nsToSchemaDocs, String tns)
{
SchemaDocument schDoc = (SchemaDocument)nsToSchemaDocs.get(tns);
if (schDoc==null)
{
schDoc = SchemaDocument.Factory.newInstance();
nsToSchemaDocs.put(tns, schDoc);
}
return schDoc;
}
private static org.w3.x2001.xmlSchema.SchemaDocument.Schema getTopLevelSchemaElement(SchemaDocument schDoc,
String tns)
{
org.w3.x2001.xmlSchema.SchemaDocument.Schema sch = schDoc.getSchema();
if (sch==null)
{
sch = schDoc.addNewSchema();
sch.setAttributeFormDefault(org.w3.x2001.xmlSchema.FormChoice.Enum.forString("unqualified"));
sch.setElementFormDefault(org.w3.x2001.xmlSchema.FormChoice.Enum.forString("qualified"));
if (!tns.equals(""))
sch.setTargetNamespace(tns);
}
return sch;
}
// Global Elements
private void fillUpGlobalElement(Element globalElement, SchemaDocument schDoc, String tns)
{
assert tns.equals(globalElement.getName().getNamespaceURI());
org.w3.x2001.xmlSchema.SchemaDocument.Schema sch = getTopLevelSchemaElement(schDoc, tns);
org.w3.x2001.xmlSchema.TopLevelElement topLevelElem = sch.addNewElement();
topLevelElem.setName(globalElement.getName().getLocalPart());
fillUpElementDocumentation(topLevelElem, globalElement.getComment());
Type elemType = globalElement.getType();
fillUpTypeOnElement(elemType, topLevelElem, tns);
}
private void fillUpLocalElement(Element element, org.w3.x2001.xmlSchema.LocalElement localSElement, String tns)
{
fillUpElementDocumentation(localSElement, element.getComment());
if (!element.isRef())
{
assert element.getName().getNamespaceURI().equals(tns);
fillUpTypeOnElement(element.getType(), localSElement, tns);
localSElement.setName(element.getName().getLocalPart());
}
else
{
localSElement.setRef(element.getName());
}
if (element.getMaxOccurs()==Element.UNBOUNDED)
{
localSElement.setMaxOccurs("unbounded");
}
if (element.getMinOccurs()!=1)
{
localSElement.setMinOccurs(new BigInteger("" + element.getMinOccurs()));
}
}
private void fillUpTypeOnElement(Type elemType, org.w3.x2001.xmlSchema.Element parentSElement, String tns)
{
if (elemType.isGlobal())
{
assert elemType.getName()!=null : "Global type must have a name.";
parentSElement.setType(elemType.getName());
}
else if (elemType.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT)
{
if (elemType.isEnumeration())
fillUpEnumeration(elemType, parentSElement);
else
parentSElement.setType(elemType.getName());
}
else
{
org.w3.x2001.xmlSchema.LocalComplexType localComplexType = parentSElement.addNewComplexType();
fillUpContentForComplexType(elemType, localComplexType, tns);
}
}
private void fillUpEnumeration(Type type, org.w3.x2001.xmlSchema.Element parentSElement)
{
assert type.isEnumeration() && !type.isComplexType() : "Enumerations must be on simple types only.";
org.w3.x2001.xmlSchema.RestrictionDocument.Restriction restriction = parentSElement.addNewSimpleType().addNewRestriction();
restriction.setBase(type.getName());
for (int i = 0; i < type.getEnumerationValues().size(); i++)
{
String value = (String) type.getEnumerationValues().get(i);
restriction.addNewEnumeration().setValue(XmlString.Factory.newValue(value));
}
}
private void fillUpAttributesInComplexTypesSimpleContent(Type elemType,
org.w3.x2001.xmlSchema.SimpleExtensionType sExtension, String tns)
{
for (int i = 0; i < elemType.getAttributes().size(); i++)
{
Attribute att = (Attribute) elemType.getAttributes().get(i);
org.w3.x2001.xmlSchema.Attribute sAttribute = sExtension.addNewAttribute();
fillUpLocalAttribute(att, sAttribute, tns);
}
}
private void fillUpAttributesInComplexTypesComplexContent(Type elemType,
org.w3.x2001.xmlSchema.ComplexType localSComplexType, String tns)
{
for (int i = 0; i < elemType.getAttributes().size(); i++)
{
Attribute att = (Attribute) elemType.getAttributes().get(i);
org.w3.x2001.xmlSchema.Attribute sAttribute = localSComplexType.addNewAttribute();
fillUpLocalAttribute(att, sAttribute, tns);
}
}
private void fillUpLocalAttribute(Attribute att, org.w3.x2001.xmlSchema.Attribute sAttribute, String tns)
{
if (att.isRef())
{
sAttribute.setRef(att.getName());
}
else
{
assert att.getName().getNamespaceURI()==tns || att.getName().getNamespaceURI().equals("");
sAttribute.setType(att.getType().getName());
sAttribute.setName(att.getName().getLocalPart());
if (att.isOptional())
sAttribute.setUse(org.w3.x2001.xmlSchema.Attribute.Use.OPTIONAL);
}
}
private void fillUpContentForComplexType(Type type, org.w3.x2001.xmlSchema.ComplexType sComplexType, String tns)
{
if (type.getContentType()==Type.COMPLEX_TYPE_SIMPLE_CONTENT)
{
org.w3.x2001.xmlSchema.SimpleContentDocument.SimpleContent simpleContent = sComplexType.addNewSimpleContent();
assert type.getExtensionType()!=null && type.getExtensionType().getName()!=null : "Extension type must exist and be named for a COMPLEX_TYPE_SIMPLE_CONTENT";
org.w3.x2001.xmlSchema.SimpleExtensionType ext = simpleContent.addNewExtension();
ext.setBase(type.getExtensionType().getName());
fillUpAttributesInComplexTypesSimpleContent(type, ext, tns);
}
else
{
if (type.getContentType()==Type.COMPLEX_TYPE_MIXED_CONTENT)
{
sComplexType.setMixed(true);
}
org.w3.x2001.xmlSchema.ExplicitGroup explicitGroup;
if (type.getTopParticleForComplexOrMixedContent()==Type.PARTICLE_SEQUENCE)
{
explicitGroup = sComplexType.addNewSequence();
}
else if (type.getTopParticleForComplexOrMixedContent()==Type.PARTICLE_CHOICE_UNBOUNDED)
{
explicitGroup = sComplexType.addNewChoice();
explicitGroup.setMaxOccurs("unbounded");
explicitGroup.setMinOccurs(new BigInteger("0"));
}
else { throw new IllegalStateException("Unknown particle type in complex and mixed content"); }
for (int i = 0; i < type.getElements().size(); i++)
{
Element child = (Element) type.getElements().get(i);
org.w3.x2001.xmlSchema.LocalElement childLocalElement = explicitGroup.addNewElement();
fillUpLocalElement(child, childLocalElement, tns);
}
fillUpAttributesInComplexTypesComplexContent(type, sComplexType, tns);
}
}
// Global Attributes
private void fillUpGlobalAttribute(Attribute globalAttribute, SchemaDocument schDoc, String tns)
{
assert tns.equals(globalAttribute.getName().getNamespaceURI());
org.w3.x2001.xmlSchema.SchemaDocument.Schema sch = getTopLevelSchemaElement(schDoc, tns);
org.w3.x2001.xmlSchema.TopLevelAttribute topLevelAtt = sch.addNewAttribute();
topLevelAtt.setName(globalAttribute.getName().getLocalPart());
Type elemType = globalAttribute.getType();
if (elemType.getContentType()==Type.SIMPLE_TYPE_SIMPLE_CONTENT)
{
topLevelAtt.setType(elemType.getName());
}
else
{
//org.w3.x2001.xmlSchema.LocalSimpleType localSimpleType = topLevelAtt.addNewSimpleType();
throw new IllegalStateException();
}
}
private static void fillUpElementDocumentation(org.w3.x2001.xmlSchema.Element element, String comment)
{
if (comment!=null && comment.length()>0)
{
org.w3.x2001.xmlSchema.DocumentationDocument.Documentation documentation = element.addNewAnnotation().addNewDocumentation();
documentation.set(org.apache.xmlbeans.XmlString.Factory.newValue(comment));
}
}
// Global Types
private void fillUpGlobalType(Type globalType, SchemaDocument schDoc, String tns)
{
assert tns.equals(globalType.getName().getNamespaceURI());
org.w3.x2001.xmlSchema.SchemaDocument.Schema sch = getTopLevelSchemaElement(schDoc, tns);
org.w3.x2001.xmlSchema.TopLevelComplexType topLevelComplexType = sch.addNewComplexType();
topLevelComplexType.setName(globalType.getName().getLocalPart());
fillUpContentForComplexType(globalType, topLevelComplexType, tns);
}
public String toString()
{
return "TypeSystemHolder{" +
"_globalElements=" + _globalElements +
"}";
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: xmlbeans-cvs-unsubscribe@xml.apache.org
For additional commands, e-mail: xmlbeans-cvs-help@xml.apache.org