All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hfg.xml.xsd.Xsd Maven / Gradle / Ivy

There is a newer version: 20240423
Show newest version
package com.hfg.xml.xsd;

import java.io.*;
import java.util.*;

import org.xml.sax.*;

import com.hfg.util.StringBuilderPlus;
import com.hfg.util.collection.CollectionUtil;
import com.hfg.util.StringUtil;
import com.hfg.xml.XMLException;
import com.hfg.xml.XMLName;
import com.hfg.xml.XMLNamespace;
import com.hfg.xml.XMLTag;
import com.hfg.xml.parser.SaxyParser;
import com.hfg.xml.parser.XMLTagSAXBroadcaster;
import com.hfg.xml.parser.XMLTagSAXListener;

//------------------------------------------------------------------------------
/**
 XML Schema Definition (XSD) specification container.
 
@author J. Alex Taylor, hairyfatguy.com
*/ //------------------------------------------------------------------------------ // com.hfg XML/HTML Coding Library // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // // J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com // [email protected] //------------------------------------------------------------------------------ public class Xsd { private final Map mTypeMap = new HashMap<>(2500); private final Map mGroupMap = new HashMap<>(100); // We have seen some cases (OfficeOpenXML SpreadsheetML) where the same element name is used with different types. // Hence, the map allows a Set of elements. private Map> mElementMap = new HashMap<>(2500); private SaxyParser mParser; //########################################################################### // PUBLIC METHODS //########################################################################### //--------------------------------------------------------------------------- public void parse(File inFile) throws IOException, SAXException { BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(inFile)); parse(reader); } finally { if (reader != null) reader.close(); } } //--------------------------------------------------------------------------- public void parse(Reader inReader) throws IOException, SAXException { mParser = new SaxyParser(); XMLTagSAXListenerImpl listener = new XMLTagSAXListenerImpl(); XMLTagSAXBroadcaster contentHandler = new XMLTagSAXBroadcaster() .addListener(listener, XsdXML.SCHEMA.getLocalName()) .addListener(listener, XsdXML.COMPLEX_TYPE.getLocalName()) .addListener(listener, XsdXML.SIMPLE_TYPE.getLocalName()) .addListener(listener, XsdXML.GROUP.getLocalName()) .addListener(listener, XsdXML.ELEMENT.getLocalName()); mParser.setContentHandler(contentHandler); mParser.parse(new InputSource(inReader)); } //--------------------------------------------------------------------------- public Set getElements(XMLName inElementName) { return getElements(inElementName.getLocalName()); } //--------------------------------------------------------------------------- public Set getElements(String inElementName) { Set elementSet = mElementMap.get(inElementName); if (null == elementSet && inElementName.indexOf(":") > 0) { // Try to look it up w/o the namespace prefix String baseElementName = inElementName.substring(inElementName.indexOf(":") + 1); elementSet = mElementMap.get(baseElementName); } return elementSet; } //--------------------------------------------------------------------------- /** For debugging/logging purposes. * @return a summary of the cached XSD information. */ public CharSequence getConfigSummary() { StringBuilderPlus buffer = new StringBuilderPlus(); buffer.appendln("XSD Type Map Size: " + mTypeMap.size()); buffer.appendln("XSD Group Map Size: " + mGroupMap.size()); buffer.appendln("XSD Element Map Size: " + mElementMap.size()); return buffer; } //########################################################################### // PROTECTED METHODS //########################################################################### //--------------------------------------------------------------------------- protected void integrateTypesWithElements() { // Not all namespace prefixes may have been set at the time the element was inserted into the Map. // Hence, we need to rebuild the map so we can lookup elements using their qualified names. Map> readjustedElementMap = new HashMap<>(mElementMap.size()); for (Set elements : mElementMap.values()) { for (XsdElement element : elements) { Set elementSet = readjustedElementMap.get(element.getQualifiedName()); if (null == elementSet) { elementSet = new HashSet<>(4); readjustedElementMap.put(element.getQualifiedName(), elementSet); } elementSet.add(element); } } mElementMap = readjustedElementMap; // Flesh out the type object for ea. element. for (Set elements : mElementMap.values()) { for (XsdElement element : elements) { element.setType(mTypeMap.get(element.getQualifiedTypeName())); } } // Flesh out complex types for (XsdType xsdType : mTypeMap.values()) { if (xsdType instanceof XsdComplexType) { // Is there a base type that needs to be set? String baseTypeName = ((XsdComplexType) xsdType).getNameOfBaseType(); if (StringUtil.isSet(baseTypeName)) { ((XsdComplexType) xsdType).setBaseType((XsdComplexType) mTypeMap.get(baseTypeName)); } List contentList = ((XsdComplexType)xsdType).getContent(); if (CollectionUtil.hasValues(contentList)) { for (XsdContent content : contentList) { recursivelyFleshOutContent(content); } } } } } //########################################################################### // PRIVATE METHODS //########################################################################### //--------------------------------------------------------------------------- private void recursivelyFleshOutContent(XsdContent inContent) { if (inContent instanceof XsdSequence) { List sequenceContentList = ((XsdSequence)inContent).getContent(); if (CollectionUtil.hasValues(sequenceContentList)) { for (XsdContent sequenceContent : sequenceContentList) { recursivelyFleshOutContent(sequenceContent); } } } else if (inContent instanceof XsdChoice) { Set choiceContents = ((XsdChoice)inContent).getOptions(); if (CollectionUtil.hasValues(choiceContents)) { for (XsdContent choiceContent : choiceContents) { recursivelyFleshOutContent(choiceContent); } } } else if (inContent instanceof XsdGroup) { XsdGroup xsdGroup = (XsdGroup) inContent; if (null == xsdGroup.getContent()) { XsdGroup groupDef = mGroupMap.get(xsdGroup.getName()); if (groupDef != null && CollectionUtil.hasValues(groupDef.getContent())) { for (XsdContent groupContent : groupDef.getContent()) { recursivelyFleshOutContent(groupContent); ((XsdGroup) inContent).addContent(groupContent); } } } } else if (inContent instanceof XsdElement && ((XsdElement) inContent).getRef() != null) { // Flesh out ref elements XsdElement refElement = ((XsdElement) inContent); Set elementSet = mElementMap.get(refElement.getRef().getQualifiedName()); if (elementSet != null) { // TODO: Not sure what to do if we have multiple elements with the same name. XsdElement element = elementSet.iterator().next(); refElement.setName(element.getLocalName()); refElement.setType(element.getType()); } else { System.out.println("Dangling xsd ref: " + refElement.getRef().getQualifiedName()); } } } //########################################################################### // INNER CLASS //########################################################################### private class XMLTagSAXListenerImpl implements XMLTagSAXListener { //######################################################################## // CONSTRUCTORS //######################################################################## //------------------------------------------------------------------------ public XMLTagSAXListenerImpl() { } //######################################################################## // PUBLIC METHODS //######################################################################## //------------------------------------------------------------------------ public void receive(XMLTag inXMLTag) { try { XMLNamespace namespace = mParser.getCurrentDefaultNamespace(); if (inXMLTag.getTagName().equals(XsdXML.SIMPLE_TYPE.getLocalName())) { XsdSimpleType simpleType = new XsdSimpleType(inXMLTag); simpleType.setNamespace(namespace); mTypeMap.put(simpleType.getQualifiedName(), simpleType); } else if (inXMLTag.getTagName().equals(XsdXML.ELEMENT.getLocalName())) { if (inXMLTag.hasAttribute(XsdXML.NAME_ATT.getLocalName()) && ! mElementMap.containsKey(inXMLTag.getQualifiedTagName())) { XsdElement element = new XsdElement(inXMLTag); element.setNamespace(namespace); if (StringUtil.isSet(element.getLocalName())) { Set elementSet = mElementMap.get(element.getQualifiedName()); if (null == elementSet) { elementSet = new HashSet<>(4); mElementMap.put(element.getQualifiedName(), elementSet); } elementSet.add(element); } } } else if (inXMLTag.getTagName().equals(XsdXML.COMPLEX_TYPE.getLocalName())) { XsdComplexType complexType = new XsdComplexType(inXMLTag, namespace); mTypeMap.put(complexType.getQualifiedName(), complexType); } else if (inXMLTag.getTagName().equals(XsdXML.GROUP.getLocalName()) && inXMLTag.hasAttribute(XsdXML.NAME_ATT.getLocalName())) { XsdGroup group = new XsdGroup(inXMLTag, namespace); mGroupMap.put(group.getName(), group); } } catch (Exception e) { throw new XMLException("Problem parsing " + inXMLTag.toXML(), e); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy