?? schemagenerator.java
字號:
/*Copyright (c) 2007, Dennis M. SosnoskiAll rights reserved.Redistribution and use in source and binary forms, with or without modification,are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of JiBX nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ANDANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIEDWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE AREDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FORANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ONANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THISSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/package org.jibx.binding.generator;import java.io.IOException;import java.io.InputStream;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.util.AbstractList;import java.util.ArrayList;import java.util.Collection;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import org.jibx.binding.model.CollectionElement;import org.jibx.binding.model.ContainerElementBase;import org.jibx.binding.model.DocumentFormatter;import org.jibx.binding.model.IClass;import org.jibx.binding.model.IClassItem;import org.jibx.binding.model.IClassLocator;import org.jibx.binding.model.IComponent;import org.jibx.binding.model.MappingElement;import org.jibx.binding.model.StructureElement;import org.jibx.binding.model.StructureElementBase;import org.jibx.binding.model.TemplateElementBase;import org.jibx.binding.model.ValidationContext;import org.jibx.binding.model.ValidationProblem;import org.jibx.binding.model.ValueElement;import org.jibx.runtime.QName;import org.jibx.schema.ISchemaResolver;import org.jibx.schema.TreeWalker;import org.jibx.schema.elements.AllElement;import org.jibx.schema.elements.AnnotatedBase;import org.jibx.schema.elements.AnnotationElement;import org.jibx.schema.elements.AttributeElement;import org.jibx.schema.elements.AttributeGroupElement;import org.jibx.schema.elements.AttributeGroupRefElement;import org.jibx.schema.elements.ChoiceElement;import org.jibx.schema.elements.CommonCompositorDefinition;import org.jibx.schema.elements.ComplexContentElement;import org.jibx.schema.elements.ComplexExtensionElement;import org.jibx.schema.elements.ComplexTypeElement;import org.jibx.schema.elements.DocumentationElement;import org.jibx.schema.elements.ElementElement;import org.jibx.schema.elements.GroupElement;import org.jibx.schema.elements.GroupRefElement;import org.jibx.schema.elements.SchemaElement;import org.jibx.schema.elements.SequenceElement;import org.jibx.schema.elements.SimpleContentElement;import org.jibx.schema.elements.SimpleRestrictionElement;import org.jibx.schema.elements.SimpleTypeElement;import org.jibx.schema.elements.FacetElement.Enumeration;import org.jibx.schema.types.Count;import org.jibx.schema.validation.PrevalidationVisitor;import org.jibx.schema.validation.RegistrationVisitor;import org.jibx.schema.validation.ValidationVisitor;import org.jibx.util.Types;import org.w3c.dom.Node;/** * Schema generator from binding definition. */public class SchemaGenerator{ /** Locator for class information (<code>null</code> if none). */ private final IClassLocator m_locator; /** Binding customization information. */ private final GlobalCustom m_custom; /** Document used for annotations (<code>null</code> if none). */ private final DocumentFormatter m_formatter; /** Map from fully-qualified class name to qualified simple type name. */ private final Map m_simpleTypeMap; /** Map from namespace to schema holder. */ private final Map m_uriSchemaMap; /** Validation context for bindings. */ private final ValidationContext m_context; /** Details for mappings and enum usages. */ private final SchemaDetailDirectory m_detailDirectory; /** * Constructor. * * @param loc locator for class information (<code>null</code> if none) * @param custom binding customization information (used for creating names * as needed) */ public SchemaGenerator(IClassLocator loc, GlobalCustom custom) { m_locator = loc; if (loc == null) { m_formatter = null; } else { m_formatter = new DocumentFormatter(); } m_custom = custom; m_simpleTypeMap = new HashMap(); m_uriSchemaMap = new HashMap(); m_context = new ValidationContext(loc); m_detailDirectory = new SchemaDetailDirectory(loc, custom, m_context); } /** * Find the schema to be used for a particular namespace. If this is the * first time a particular namespace was requested, a new schema will be * created for that namespace and returned, using a default file name. * * @param uri namespace URI (<code>null</code> if no namespace) * @return schema holder */ public SchemaHolder findSchema(String uri) { SchemaHolder hold = (SchemaHolder)m_uriSchemaMap.get(uri); if (hold == null) { hold = new SchemaHolder(uri); m_uriSchemaMap.put(uri, hold); String sname; if (uri == null) { sname = "nonamespace.xsd"; } else { sname = uri.substring(uri.lastIndexOf('/')+1) + ".xsd"; } hold.setFileName(sname); } return hold; } /** * Get the qualified name of the simple type used for a component, if a * named simple type. If this returns <code>null</code>, the {@link * #buildSimpleType(IComponent)} method needs to be able to construct the * appropriate simple type definition. * * @param comp * @return qualified type name, <code>null</code> if inline definition * needed */ private QName getSimpleTypeQName(IComponent comp) { IClass type = comp.getType(); String tname = comp.getType().getName(); QName qname = Types.schemaType(tname); if (qname == null) { qname = (QName)m_simpleTypeMap.get(tname); if (qname == null) { if (!type.isSuperclass("java.lang.Enum")) { m_context.addWarning("No schema equivalent known for type - treating as string", comp); qname = Types.STRING_QNAME; } } } return qname; } /** * Add class-level documentation to a schema component. * * @param info * @param root */ private void addDocumentation(IClass info, AnnotatedBase root) { if (info != null) { List nodes = m_formatter.docToNodes(info.getJavaDoc()); if (nodes != null) { AnnotationElement anno = new AnnotationElement(); DocumentationElement doc = new DocumentationElement(); for (Iterator iter = nodes.iterator(); iter.hasNext();) { Node node = (Node)iter.next(); doc.addContent(node); } anno.getItemsList().add(doc); root.setAnnotation(anno); } } } /** * Set the documentation for a schema component matching a class member. * * @param elem * @param item */ private void setDocumentation(IClassItem item, AnnotatedBase elem) { List nodes = m_formatter.docToNodes(item.getJavaDoc()); if (nodes != null) { AnnotationElement anno = new AnnotationElement(); DocumentationElement doc = new DocumentationElement(); for (Iterator iter = nodes.iterator(); iter.hasNext();) { Node node = (Node)iter.next(); doc.addContent(node); } anno.getItemsList().add(doc); elem.setAnnotation(anno); } } /** * Add documentation for a particular field or property. * * @param struct * @param elem */ private void addItemDocumentation(StructureElementBase struct, AnnotatedBase elem) { IClassItem item = struct.getField(); if (item == null) { item = struct.getGet(); } if (item != null) { setDocumentation(item, elem); } } /** * Add documentation for a particular field or property. * * @param value * @param elem */ private void addItemDocumentation(ValueElement value, AnnotatedBase elem) { IClassItem item = value.getField(); if (item == null) { item = value.getGet(); } if (item != null) { setDocumentation(item, elem); } } /** * Create the simple type definition for a type. This is only used for cases * where {@link #getSimpleTypeQName(IComponent)} returns <code>null</code>. * The current implementation only supports Java 5 Enum types, but in the * future should be extended to support <format>-type conversions with * supplied schema definitions. * * @param type * @return type definition */ private SimpleTypeElement buildSimpleType(IClass type) { SchemaEnumDetail detail = m_detailDirectory.getSimpleDetail(type.getName()); try { Class clas = type.loadClass(); Method method = clas.getMethod("values", (Class[])null); try { method.setAccessible(true); } catch (RuntimeException e) { /* deliberately empty */ } Enum[] values = (Enum[])method.invoke(null, (Object[])null); SimpleTypeElement simple = new SimpleTypeElement(); SimpleRestrictionElement restr = new SimpleRestrictionElement(); restr.setBase(Types.STRING_QNAME); for (int i = 0; i < values.length; i++) { Enumeration enumel = new Enumeration(); enumel.setValue(values[i].name()); restr.getFacetsList().add(enumel); } simple.setDerivation(restr); addDocumentation(detail.getCustom().getClassInformation(), simple); return simple; } catch (SecurityException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } /** * Convenience method to create the simple type definition for the type of a * component. * * @param comp * @return type definition */ private SimpleTypeElement buildSimpleType(IComponent comp) { return buildSimpleType(comp.getType()); } /** * General object comparison method. Don't know why Sun hasn't seen fit to * include this somewhere, but at least it's easy to write (over and over * again). * * @param a first object to be compared * @param b second object to be compared * @return <code>true</code> if both objects are <code>null</code>, or if * <code>a.equals(b)</code>; <code>false</code> otherwise */ public static boolean isEqual(Object a, Object b) { return (a == null) ? b == null : a.equals(b); } /** * Check for dependency on another schema. *
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -