001: /*
002: * ChainBuilder ESB
003: * Visual Enterprise Integration
004: *
005: * Copyright (C) 2007 Bostech Corporation
006: *
007: * This program is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU General Public License as published by the
009: * Free Software Foundation; either version 2 of the License, or (at your option)
010: * any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
014: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
015: * for more details.
016: *
017: * You should have received a copy of the GNU General Public License along with
018: * this program; if not, write to the Free Software Foundation, Inc.,
019: * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020: *
021: *
022: * $Id: SchemaUtil.java 6621 2007-04-11 01:08:00Z zjin $
023: */
024:
025: package com.bostechcorp.cbesb.common.wsdl;
026:
027: import java.io.File;
028: import java.io.IOException;
029: import java.util.Collections;
030: import java.util.Iterator;
031: import java.util.Map;
032:
033: import org.apache.commons.logging.Log;
034: import org.apache.commons.logging.LogFactory;
035: import org.eclipse.emf.common.util.URI;
036: import org.eclipse.emf.ecore.resource.Resource;
037: import org.eclipse.emf.ecore.resource.ResourceSet;
038: import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
039: import org.eclipse.xsd.XSDAnnotation;
040: import org.eclipse.xsd.XSDAttributeDeclaration;
041: import org.eclipse.xsd.XSDAttributeGroupDefinition;
042: import org.eclipse.xsd.XSDConcreteComponent;
043: import org.eclipse.xsd.XSDElementDeclaration;
044: import org.eclipse.xsd.XSDFacet;
045: import org.eclipse.xsd.XSDFactory;
046: import org.eclipse.xsd.XSDIdentityConstraintDefinition;
047: import org.eclipse.xsd.XSDImport;
048: import org.eclipse.xsd.XSDInclude;
049: import org.eclipse.xsd.XSDModelGroup;
050: import org.eclipse.xsd.XSDModelGroupDefinition;
051: import org.eclipse.xsd.XSDNotationDeclaration;
052: import org.eclipse.xsd.XSDPackage;
053: import org.eclipse.xsd.XSDSchema;
054: import org.eclipse.xsd.XSDTypeDefinition;
055: import org.eclipse.xsd.XSDWildcard;
056: import org.eclipse.xsd.XSDXPathDefinition;
057: import org.eclipse.xsd.util.XSDConstants;
058: import org.eclipse.xsd.util.XSDResourceFactoryImpl;
059: import org.eclipse.xsd.util.XSDResourceImpl;
060: import org.w3c.dom.Element;
061:
062: /**
063: * @author mpreston
064: *
065: */
066: public class SchemaUtil {
067:
068: /**
069: * A cached XSDFactory: one per lifetime.
070: * @see #getXSDFactory()
071: */
072: protected static XSDFactory xsdFactory = null;
073:
074: protected static transient Log logger = LogFactory
075: .getLog(SchemaUtil.class);
076: /**
077: * A cached XSDPackage: one per lifetime.
078: * @see #getXSDFactory()
079: */
080: protected static XSDPackage xsdPackage = null;
081:
082: /**
083: * <p>
084: * The initialization sequence depends on some specific versions of
085: * Eclipse and may depend on how your application is run (as an Eclipse
086: * plugin or as a headless program, etc.). Note this caches the package
087: * and factory objects, and does not bother to re-call init() unless
088: * needed. This actual implementation is meant to be run as a standalone
089: * headless program although it may be suitable for other applications.
090: * </p>
091: *
092: * @return an XSDFactory already initialized; or a cached one if we've
093: * been previously called
094: */
095: public static XSDFactory getXSDFactory() {
096: // If cached, return previous factory
097: if (xsdFactory != null) {
098: return xsdFactory;
099: }
100:
101: Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap()
102: .put("xsd", new XSDResourceFactoryImpl());
103:
104: // Also get the factory implementation here as well
105: xsdPackage = XSDPackage.eINSTANCE;
106: xsdFactory = XSDFactory.eINSTANCE;
107: return xsdFactory;
108: }
109:
110: public static XSDSchema createBlankSchema() {
111: XSDFactory factory = getXSDFactory();
112: XSDSchema schema = factory.createXSDSchema();
113: schema.setSchemaForSchemaQNamePrefix("xsd");
114: Map namespaces = schema.getQNamePrefixToNamespaceMap();
115: namespaces.put(schema.getSchemaForSchemaQNamePrefix(),
116: XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001);
117: return schema;
118: }
119:
120: public static XSDSchema createBlankSchema(String targetNamespace,
121: String targetPrefix) {
122: XSDFactory factory = getXSDFactory();
123: XSDSchema schema = factory.createXSDSchema();
124:
125: // Set target namespace
126: schema.setTargetNamespace(targetNamespace);
127:
128: // Choose the prefix used for this schema's namespace,
129: // and the schema for schema's namespace
130: schema.setSchemaForSchemaQNamePrefix("xsd");
131: Map namespaces = schema.getQNamePrefixToNamespaceMap();
132: namespaces.put(targetPrefix, schema.getTargetNamespace());
133: namespaces.put(schema.getSchemaForSchemaQNamePrefix(),
134: XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001);
135:
136: return schema;
137: }
138:
139: public static XSDSchema createSchemaFromElement(
140: Element schemaElement) {
141: XSDSchema xsdSchema = null;
142: // Create a schema from an element.
143: //
144: // Test if the element is really a schema element.
145: //
146: if (schemaElement.getLocalName().equals("schema")
147: && XSDConstants
148: .isSchemaForSchemaNamespace(schemaElement
149: .getNamespaceURI())) {
150: // Create the schema.
151: //
152: xsdSchema = XSDFactory.eINSTANCE.createXSDSchema();
153:
154: // Set the element to the schema.
155: // This it will build the corresponding component structure.
156: //
157: xsdSchema.setElement(schemaElement);
158: }
159: return xsdSchema;
160: }
161:
162: /**
163: * Use the ResourceSet to load a schema into the library.
164: *
165: * <p>
166: * This performs initialization of various dependencies and then asks a
167: * ResourceSet to parse and load the schema and any dependencies into
168: * memory. We then iterate through the Resources in the Resource set to find
169: * the first one which is the specific schema we asked for. If this schema
170: * included, imported, or redefined any other schemas, they would be
171: * reflected as additional Resources in the set that we could also access.
172: * </p>
173: *
174: * @param URL
175: * of a schema.xsd file
176: * @return a schema object constructed from that model; null if error
177: * @throws any
178: * underlying exceptions
179: */
180: public static XSDSchema loadSchema(File schema) {
181: // One-time initalization of the Resource framework and
182: // related classes; needed when running standalone
183: // This is needed because we can't have the following in the plugin.xml
184: //
185: // <extension point = "com.eclipse.emf.ecore.extension_parser">
186: // <parser type="xsd" class="org.eclipse.xsd.util.XSDResourceFactoryImpl"/>
187: // </extension>
188: //
189: Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap()
190: .put("xsd", new XSDResourceFactoryImpl());
191:
192: // Create a resource set and load the main schema file into it.
193: ResourceSet resourceSet = new ResourceSetImpl();
194:
195: String schemaURL = "file:/" + schema.getAbsolutePath();
196: resourceSet.getLoadOptions().put(
197: XSDResourceImpl.XSD_TRACK_LOCATION, Boolean.TRUE);
198: XSDResourceImpl xsdSchemaResource = (XSDResourceImpl) resourceSet
199: .getResource(URI.createURI(schemaURL), true);
200:
201: // getResources() returns an iterator over all the resources, i.e., the main resource
202: // and those that have been included, imported, or redefined.
203: for (Iterator resources = resourceSet.getResources().iterator(); resources
204: .hasNext(); /* no-op */) {
205: // Return the first schema object found
206: Resource resource = (Resource) resources.next();
207: if (resource instanceof XSDResourceImpl) {
208: XSDResourceImpl xsdResource = (XSDResourceImpl) resource;
209: return xsdResource.getSchema();
210: }
211: }
212: System.err.println("loadSchemaUsingResourceSet(" + schemaURL
213: + ") did not contain any schemas!");
214: return null;
215: }
216:
217: public static void saveXSDSchema(XSDSchema xsdSchema, File destFile)
218: throws IOException {
219: // Create a resource set and a resource with an extent.
220: // Add the schema to the extent, add the resource to the set,
221: // and save the resource.
222: //
223: ResourceSet resourceSet = new ResourceSetImpl();
224: Resource resource = new XSDResourceImpl(URI
225: .createFileURI(destFile.getAbsolutePath()));
226: resource.getContents().add(xsdSchema);
227: resourceSet.getResources().add(resource);
228: resource.save(Collections.EMPTY_MAP);
229: }
230:
231: /**
232: * Add a local annotation with userInfo to the given item.
233: *
234: * <p>Note: We take an XSDConcreteComponent, however we must
235: * then cast it to one of the types that has a setAnnotation
236: * call defined, since it doesn't have a clear 'parent'
237: * interface for annotations.</p>
238: *
239: * <p>Also note that UserInformation and ApplicationInformation
240: * objects can only be added <b>after</b> the parent of the
241: * annotation has been added to an XSDSchema object. This is
242: * because these objects are modeled in the concrete DOM
243: * layer only, and otherwise will throw a DOMException.<p>
244: *
245: * @param component to add annotation to; may be any kind of
246: * XSDConcreteComponent object including an XSDSchema
247: * @param sourceURI to set for the userInformation
248: * @param text text to add as the userInformation
249: * (xsd:documentation) node to the annotation
250: * @return the XSDAnnotation object created, after having been
251: * added to the component; null if any error occoured
252: */
253: public static XSDAnnotation addUserInformation(
254: XSDConcreteComponent component, String sourceURI,
255: String text) {
256: // Note that null is a legal value for the sourceURI
257: if ((null == component) || (null == text)) {
258: throw new IllegalArgumentException(
259: "addUserInformation called with null component or text");
260: }
261: try {
262: // First get the factory from the component: this is
263: // roundabout, but saves the user from having to
264: // pass it in
265: XSDFactory xsdFactory = XSDFactory.eINSTANCE;
266:
267: // Create an XSDAnnotation object to hold everything
268: XSDAnnotation xsdAnnotation = xsdFactory
269: .createXSDAnnotation();
270:
271: // Depending on the XSDConcreteComponent type, cast to
272: // the appropriate type and add the annotation
273: if (component instanceof XSDAttributeDeclaration) {
274: ((XSDAttributeDeclaration) component)
275: .setAnnotation(xsdAnnotation);
276: } else if (component instanceof XSDAttributeGroupDefinition) {
277: ((XSDAttributeGroupDefinition) component)
278: .setAnnotation(xsdAnnotation);
279: } else if (component instanceof XSDElementDeclaration) {
280: ((XSDElementDeclaration) component)
281: .setAnnotation(xsdAnnotation);
282: } else if (component instanceof XSDFacet) {
283: ((XSDFacet) component).setAnnotation(xsdAnnotation);
284: } else if (component instanceof XSDIdentityConstraintDefinition) {
285: ((XSDIdentityConstraintDefinition) component)
286: .setAnnotation(xsdAnnotation);
287: } else if (component instanceof XSDImport) {
288: ((XSDImport) component).setAnnotation(xsdAnnotation);
289: } else if (component instanceof XSDInclude) {
290: ((XSDInclude) component).setAnnotation(xsdAnnotation);
291: } else if (component instanceof XSDModelGroup) {
292: ((XSDModelGroup) component)
293: .setAnnotation(xsdAnnotation);
294: } else if (component instanceof XSDModelGroupDefinition) {
295: ((XSDModelGroupDefinition) component)
296: .setAnnotation(xsdAnnotation);
297: } else if (component instanceof XSDNotationDeclaration) {
298: ((XSDNotationDeclaration) component)
299: .setAnnotation(xsdAnnotation);
300: } else if (component instanceof XSDTypeDefinition) {
301: ((XSDTypeDefinition) component)
302: .setAnnotation(xsdAnnotation);
303: } else if (component instanceof XSDWildcard) {
304: ((XSDWildcard) component).setAnnotation(xsdAnnotation);
305: } else if (component instanceof XSDXPathDefinition) {
306: ((XSDXPathDefinition) component)
307: .setAnnotation(xsdAnnotation);
308: } else if (component instanceof XSDSchema) {
309: // Note that this adds a global annotation to the
310: // schema itself, not to any subcomponent
311: ((XSDSchema) component).getContents()
312: .add(xsdAnnotation);
313: } else {
314: // Whoops, asked us to annotate an unannotateable item
315: throw new IllegalArgumentException(
316: "Unable to addUserInformation onto type: "
317: + component);
318: }
319:
320: // Now that the xsdAnnotation is added to a parent
321: // XSDConcreteComponent, go ahead and create the
322: // UserInformation node (xsd:documentation) and
323: // add a DOM textNode to it containing the information
324: Element userInfo = xsdAnnotation
325: .createUserInformation(sourceURI);
326: userInfo.appendChild(userInfo.getOwnerDocument()
327: .createTextNode(text));
328:
329: // Add the finished userInfo object to the concrete
330: // element of the xsdAnnotation
331: xsdAnnotation.getElement().appendChild(userInfo);
332: return xsdAnnotation;
333: } catch (Exception e) {
334:
335: logger.error("addUserInformation threw an Exception: "
336: + e.getMessage());
337: if (logger.isDebugEnabled()) {
338: logger.debug("addUserInformation threw an Exception:",
339: e);
340: }
341: return null;
342: }
343: }
344:
345: }
|