/** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you 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.tuscany.sdo.helper; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.Reader; import java.io.StringWriter; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.apache.tuscany.sdo.impl.DynamicDataObjectImpl; import org.apache.tuscany.sdo.util.DataObjectUtil; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EModelElement; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.util.ExtendedMetaData; import org.eclipse.xsd.XSDSchema; import org.eclipse.xsd.ecore.XSDEcoreBuilder; import org.eclipse.xsd.util.XSDResourceImpl; import org.xml.sax.InputSource; import commonj.sdo.Property; import commonj.sdo.Type; import commonj.sdo.helper.TypeHelper; import commonj.sdo.helper.XSDHelper; /** * Provides access to additional information when the * Type or Property is defined by an XML Schema (XSD). * Methods return null/false otherwise or if the information is unavailable. * Defines Types from an XSD. */ public class XSDHelperImpl implements XSDHelper { private XSDEcoreBuilder ecoreBuilder; private ExtendedMetaData extendedMetaData; public XSDHelperImpl(ExtendedMetaData extendedMetaData) { this.extendedMetaData = extendedMetaData; ecoreBuilder = new SDOXSDEcoreBuilder(extendedMetaData); } public XSDHelperImpl(TypeHelper typeHelper) { this(((TypeHelperImpl)typeHelper).extendedMetaData); } public String getLocalName(Type type) { return extendedMetaData.getName((EClassifier)type); } public String getLocalName(Property property) { return extendedMetaData.getName((EStructuralFeature)property); } public String getNamespaceURI(Property property) { return extendedMetaData.getNamespace((EStructuralFeature)property); } public boolean isAttribute(Property property) { return extendedMetaData.getFeatureKind((EStructuralFeature)property) == ExtendedMetaData.ATTRIBUTE_FEATURE; } public boolean isElement(Property property) { return extendedMetaData.getFeatureKind((EStructuralFeature)property) == ExtendedMetaData.ELEMENT_FEATURE; } public boolean isMixed(Type type) { if (type instanceof EClass) { return extendedMetaData.getContentKind((EClass)type) == ExtendedMetaData.MIXED_CONTENT; } else { return false; } } public boolean isXSD(Type type) { return ((EModelElement)type).getEAnnotation(ExtendedMetaData.ANNOTATION_URI) != null; } public Property getGlobalProperty(String uri, String propertyName, boolean isElement) { if (isElement) { return (Property)extendedMetaData.getElement(uri, propertyName); } else { return (Property)extendedMetaData.getAttribute(uri, propertyName); } } public String getAppinfo(Type type, String source) { return getAppinfo((EModelElement)type, source); } public String getAppinfo(Property property, String source) { return getAppinfo((EModelElement)property, source); } protected String getAppinfo(EModelElement eModelElement, String source) { return (String)eModelElement.getEAnnotation(source).getDetails().get("appinfo"); } public List /*Type*/define(String xsd) { InputStream inputStream = new ByteArrayInputStream(xsd.getBytes()); return define(inputStream, "*.xsd"); } public List /*Type*/define(Reader xsdReader, String schemaLocation) { InputSource inputSource = new InputSource(xsdReader); return define(inputSource, schemaLocation); } public List /*Type*/define(InputStream xsdInputStream, String schemaLocation) { InputSource inputSource = new InputSource(xsdInputStream); return define(inputSource, schemaLocation); } protected List /*Type*/define(InputSource inputSource, String schemaLocation) { try { ResourceSet resourceSet = DataObjectUtil.createResourceSet(); Resource model = resourceSet.createResource(URI.createURI(schemaLocation != null ? schemaLocation : "null.xsd")); ((XSDResourceImpl)model).load(inputSource, null); List newTypes = new ArrayList(); for (Iterator schemaIter = model.getContents().iterator(); schemaIter.hasNext(); ) { XSDSchema schema = (XSDSchema)schemaIter.next(); EPackage ePackage = extendedMetaData.getPackage(schema.getTargetNamespace()); if (ePackage == null) { Collection originalEPackages = new HashSet(ecoreBuilder.getTargetNamespaceToEPackageMap().values()); ecoreBuilder.generate(schema); Collection newEPackages = ecoreBuilder.getTargetNamespaceToEPackageMap().values(); for (Iterator iter = newEPackages.iterator(); iter.hasNext();) { EPackage currentPackage = (EPackage)iter.next(); if (!originalEPackages.contains(currentPackage)) { currentPackage.setEFactoryInstance(new DynamicDataObjectImpl.FactoryImpl()); EcoreUtil.freeze(currentPackage); newTypes.addAll(currentPackage.getEClassifiers()); } } } } return newTypes; } catch (Exception e) { //e.printStackTrace(); throw new IllegalArgumentException(e.getMessage()); } } public String generate(List /*Type*/types) throws IllegalArgumentException { return generate(types, new Hashtable()); } public String generate(List /*Type*/types, Map /*String, String*/namespaceToSchemaLocation) throws IllegalArgumentException { if ( types != null && !types.isEmpty() ) { Hashtable schemaMap = new Hashtable(); Hashtable nsPrefixMap = new Hashtable(); TypeTable typeTable = new TypeTable(); SchemaBuilder schemaBuilder = new SchemaBuilder( schemaMap, nsPrefixMap, typeTable, namespaceToSchemaLocation); Iterator iterator = types.iterator(); Type dataType = null; try { while ( iterator.hasNext() ) { dataType = (Type)iterator.next(); schemaBuilder.buildSchema(dataType); } XSDSchema xmlSchema = null; iterator = schemaMap.values().iterator(); StringWriter writer = new StringWriter(); TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty(OutputKeys.METHOD, "xml"); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); while ( iterator.hasNext() ) { xmlSchema = (XSDSchema)iterator.next(); if(xmlSchema.getElement() == null) { xmlSchema.updateElement(); } transformer.transform(new DOMSource(xmlSchema.getElement().getOwnerDocument()), new StreamResult(writer)); } writer.close(); return writer.getBuffer().toString(); } catch ( Exception e ) { //System.out.println("Unable to generate schema due to ..." + e); //e.printStackTrace(); throw new IllegalArgumentException(e.getMessage()); } } else { //System.out.println("No SDO Types to generate schema ..."); return ""; } } }