org.eclipse.persistence.sdo.helper.delegates.SDOXSDHelperDelegate Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of eclipselink Show documentation
Show all versions of eclipselink Show documentation
EclipseLink build based upon Git transaction f2b9fc5
/*
* Copyright (c) 1998, 2024 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.sdo.helper.delegates;
import commonj.sdo.Property;
import commonj.sdo.Type;
import commonj.sdo.helper.HelperContext;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.sdo.SDOConstants;
import org.eclipse.persistence.sdo.SDOProperty;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.sdo.helper.DefaultSchemaResolver;
import org.eclipse.persistence.sdo.helper.SDOSchemaGenerator;
import org.eclipse.persistence.sdo.helper.SDOTypesGenerator;
import org.eclipse.persistence.sdo.helper.SDOXSDHelper;
import org.eclipse.persistence.sdo.helper.SchemaLocationResolver;
import org.eclipse.persistence.sdo.helper.SchemaResolver;
import org.eclipse.persistence.exceptions.SDOException;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.oxm.NamespaceResolver;
import org.eclipse.persistence.oxm.XMLField;
import org.eclipse.persistence.oxm.record.FormattedWriterRecord;
import org.eclipse.persistence.oxm.record.WriterRecord;
import org.w3c.dom.Element;
/**
* Purpose: Provides access to additional information when the Type or Property is defined by an XML Schema (XSD)..
*
Responsibilities:
* - Define methods defines Types from an XSD.
*
- Generate methods an XSD from Types.
*
- Other Methods return null/false otherwise or if the information is unavailable.
*
*/
public class SDOXSDHelperDelegate implements SDOXSDHelper {
/*Map of global attributes keyed on qname*/
private Map globalAttributes;
/*Map of global elements keyed on qname*/
private Map globalElements;
// hold the context containing all helpers so that we can preserve inter-helper relationships
private HelperContext aHelperContext;
public SDOXSDHelperDelegate(HelperContext aContext) {
aHelperContext = aContext;
globalAttributes = new HashMap();
initOpenProps();
globalElements = new HashMap();
}
/**
* Returns the local name as declared in the XSD.
* @param type to return local name for.
* @return the local name as declared in the XSD.
*/
@Override
public String getLocalName(Type type) {
if (type == null) {
return null;
}
return ((SDOType)type).getXsdLocalName();
}
/**
* Returns the local name as declared in the XSD.
* @param property to return local name for.
* @return the local name as declared in the XSD.
*/
@Override
public String getLocalName(Property property) {
if (property == null) {
return null;
}
return ((SDOProperty)property).getXsdLocalName();
}
/**
* Returns the namespace URI as declared in the XSD.
* @param type to return namespace URI for.
* @return the namespace URI as declared in the XSD.
*/
@Override
public String getNamespaceURI(Type type) {
if (type == null) {
return null;
}
return type.getURI();
}
/**
* Returns the namespace URI as declared in the XSD.
* @param property to return namespace URI for.
* @return the namespace URI as declared in the XSD.
*/
@Override
public String getNamespaceURI(Property property) {
if (property == null) {
return null;
}
String uri = null;
if (property.isOpenContent()) {
uri = ((SDOProperty)property).getUri();
} else {
DatabaseMapping mapping = ((SDOProperty)property).getXmlMapping();
if (mapping != null) {
XMLField xmlField = (XMLField) mapping.getField();
if (xmlField != null && xmlField.getXPathFragment() != null) {
uri = xmlField.getXPathFragment().getNamespaceURI();
}
}
}
return uri == null ? "" : uri;
}
/**
* Returns true if the property is declared as an attribute in the XSD.
* Returns false if not known or for advanced cases.
* It is possible for both isAttribute and isElement to return false
* but they will not both return true.
* @param property to identify if an attribute.
* @return true if the property is declared as an attribute in the XSD.
*/
@Override
public boolean isAttribute(Property property) {
if (property == null) {
return false;
}
SDOProperty sdoProperty = (SDOProperty) property;
Object value = sdoProperty.get(SDOConstants.XMLELEMENT_PROPERTY);
if ((value != null) && value instanceof Boolean) {
boolean isElement = (Boolean) value;
if (isElement) {
return false;
}
}
if ((sdoProperty.getOpposite() != null) && (sdoProperty.getOpposite().isContainment())) {
return false;
} else if (sdoProperty.isMany() || sdoProperty.isContainment() || sdoProperty.isNullable()) {
return false;
}
// Case: open content non-attribute property
return true;
}
/**
* Returns true if the property is declared as an element in the XSD.
* Returns false if not known or for advanced cases.
* It is possible for both isAttribute and isElement to return false
* but they will not both return true.
* @param property to identify if an element.
* @return true if the property is declared as an element in the XSD.
*/
@Override
public boolean isElement(Property property) {
if (property == null) {
return false;
}
SDOProperty sdoProperty = (SDOProperty) property;
Object value = sdoProperty.get(SDOConstants.XMLELEMENT_PROPERTY);
if ((value != null) && value instanceof Boolean) {
return (Boolean) value;
}
if ((sdoProperty.getOpposite() != null) && (sdoProperty.getOpposite().isContainment())) {
return false;
} else if (sdoProperty.isMany() || sdoProperty.isContainment() || sdoProperty.isNullable()) {
return true;
}
return false;
}
/**
* Returns true if the Type is declared to contain mixed content.
* A DataObject's mixed content values are typically accessed via a Sequence.
* @param type to identify if mixed content.
* @return true if the Type is declared to contain mixed content.
*/
@Override
public boolean isMixed(Type type) {
if (type == null) {
return false;
}
return type.isSequenced();
}
/**
* Indicates if this helper contains XSD information for the specified type.
* @param type the type.
* @return true if this helper contains XSD information for the specified type.
*/
@Override
public boolean isXSD(Type type) {
if (type == null) {
return false;
}
return ((SDOType)type).isXsd();
}
/**
* Returns the Property defined by the named global element or attribute
* in the targetNamespace uri, or null if not found.
* @param uri The uri of the targetNamespace.
* @param propertyName The name of the global property.
* @param isElement is true for global elements, false for global attributes.
* @return the Property defined by the named global element or attribute
* in the targetNamespace uri, or null if not found.
*/
@Override
public Property getGlobalProperty(String uri, String propertyName, boolean isElement) {
QName qname = new QName(uri, propertyName);
return getGlobalProperty(qname, isElement);
}
@Override
public Property getGlobalProperty(QName qname, boolean isElement) {
if (isElement) {
return (Property)getGlobalElements().get(qname);
} else {
return (Property)getGlobalAttributes().get(qname);
}
}
/**
* Return the appinfo declared for this Type and source.
* The appinfo start and end tags and content are returned.
* The xml namespace context is preserved in the appinfo element.
* If more than one appinfo with the same source is declared on the same
* Type their contents are concatenated.
* @param type the type with the appinfo declaration
* @param source the source of the appinfo declaration.
* @return the appinfo declared for this Type and source.
*/
@Override
public String getAppinfo(Type type, String source) {
if (type == null) {
throw SDOException.noAppInfoForNull();
}
if (source == null) {
source = "";
}
return (String)((SDOType)type).getAppInfoMap().get(source);
}
/**
* Return the content of the appinfo declared for this Property and source.
* If the property is defined by ref= the appinfo of the referenced
* element or attribute is included.
* The appinfo start and end tags and content are returned.
* The xml namespace context is preserved in the appinfo element.
* If more than one appinfo with the same source is declared on the same
* Type their contents are concatenated.
* @param property the Property with the appinfo declaration
* @param source the source of the appinfo declaration.
* @return the appinfo declared for this Property and source.
*/
@Override
public String getAppinfo(Property property, String source) {
if (property == null) {
throw SDOException.noAppInfoForNull();
}
if (source == null) {
source = "";
}
return (String)((SDOProperty)property).getAppInfoMap().get(source);
}
/**
* Define the XML Schema as Types.
* The Types are available through TypeHelper and DataGraph getType() methods.
* Same as define(new StringReader(xsd), null)
* @param xsd the XML Schema.
* @return the defined Types.
* @throws IllegalArgumentException if the Types could not be defined.
*/
@Override
public synchronized List define(String xsd) {
StringReader reader = new StringReader(xsd);
SchemaResolver schemaResolver = new DefaultSchemaResolver();
return define(reader, schemaResolver);
}
/**
* Define XML Schema as Types.
* The Types are available through TypeHelper and DataGraph getType() methods.
* @param xsdReader reader to an XML Schema.
* @param schemaLocation the URI of the location of the schema, used
* for processing relative imports and includes. May be null if not used.
* @return the defined Types.
* @throws IllegalArgumentException if the Types could not be defined.
*/
@Override
public synchronized List define(Reader xsdReader, String schemaLocation) {
DefaultSchemaResolver schemaResolver = new DefaultSchemaResolver();
schemaResolver.setBaseSchemaLocation(schemaLocation);
return define(new StreamSource(xsdReader), schemaResolver);
}
/**
* Define XML Schema as Types.
* The Types are available through TypeHelper and DataGraph getType() methods.
* @param xsdReader reader to an XML Schema.
* @param schemaResolver the URI of the location of the schema, used
* for processing relative imports and includes. May be null if not used.
* @return the defined Types.
* @throws IllegalArgumentException if the Types could not be defined.
*/
public synchronized List define(Reader xsdReader, SchemaResolver schemaResolver) {
return define(new StreamSource(xsdReader), schemaResolver);
}
@Override
public synchronized List define(Source xsdSource, SchemaResolver schemaResolver) {
return new SDOTypesGenerator(aHelperContext).define(xsdSource, schemaResolver);
}
/**
* Define XML Schema as Types.
* The Types are available through TypeHelper and DataGraph getType() methods.
* @param xsdInputStream input stream to an XML Schema.
* @param schemaLocation the URI of the location of the schema, used
* for processing relative imports and includes. May be null if not used.
* @return the defined Types.
* @throws IllegalArgumentException if the Types could not be defined.
*/
@Override
public synchronized List define(InputStream xsdInputStream, String schemaLocation) {
InputStreamReader xsdReader = new InputStreamReader(xsdInputStream);
return define(xsdReader, schemaLocation);
}
/**
* Generate an XML Schema Declaration (XSD) from Types.
* Same as generate(types, null);
* @param types a List containing the Types
* @return a String containing the generated XSD.
* @throws IllegalArgumentException if the XSD could not be generated.
*/
@Override
public String generate(List types) {
HashMap map = null;
return generate(types, map);
}
/**
* Generate an XML Schema Declaration (XSD) from Types.
* Round trip from SDO to XSD to SDO is supported.
* Round trip from XSD to SDO to XSD is not supported.
* Use the original schema if one exists instead of generating a new one, as
* the generated XSD validates a different set of documents than the original XSD.
* Generating an XSD does not affect the XSDHelper or the Types.
* The Types must all have the same URI.
* The result is a String containing the generated XSD.
* All Types referenced with the same URI will be generated in the XSD
* and the list will be expanded to include all types generated.
* Any Types referenced with other URIs will cause
* imports to be produced as appropriate.
* Imports will include a schemaLocation if a Map is provided with an entry
* of the form key=import target namespace, value=schemaLocation
* @param types a List containing the Types
* @param namespaceToSchemaLocation map of target namespace to schema locations or null
* @return a String containing the generated XSD.
* @throws IllegalArgumentException if the XSD could not be generated.
*/
@Override
public String generate(List types, Map namespaceToSchemaLocation) {
return new SDOSchemaGenerator(aHelperContext).generate(types, namespaceToSchemaLocation);
}
@Override
public String generate(List types, SchemaLocationResolver schemaLocationResolver) {
return new SDOSchemaGenerator(aHelperContext).generate(types, schemaLocationResolver);
}
/**
* Assign a map of properties representing global attributes keyed on QName
* @param globalAttributes a Map of global elements keyed on QName
*/
public void setGlobalAttributes(Map globalAttributes) {
this.globalAttributes = globalAttributes;
}
/**
* Return a map of properties representing global attributes keyed on QName
* @return a map of global attributes keyed on QName
*/
private Map getGlobalAttributes() {
return globalAttributes;
}
private void initOpenProps() {
getGlobalAttributes().put(SDOConstants.MIME_TYPE_QNAME, SDOConstants.MIME_TYPE_PROPERTY);
getGlobalAttributes().put(SDOConstants.MIME_TYPE_PROPERTY_QNAME, SDOConstants.MIME_TYPE_PROPERTY_PROPERTY);
Property xmlSchemaTypeProperty = aHelperContext.getTypeHelper().getOpenContentProperty(SDOConstants.SDO_URL, SDOConstants.XML_SCHEMA_TYPE_NAME);
getGlobalAttributes().put(SDOConstants.SCHEMA_TYPE_QNAME, xmlSchemaTypeProperty);
getGlobalAttributes().put(SDOConstants.JAVA_CLASS_QNAME, SDOConstants.JAVA_CLASS_PROPERTY);
getGlobalAttributes().put(SDOConstants.XML_ELEMENT_QNAME, SDOConstants.XMLELEMENT_PROPERTY);
Property xmlDataTypeProperty = aHelperContext.getTypeHelper().getOpenContentProperty(SDOConstants.SDOXML_URL, SDOConstants.SDOXML_DATATYPE);
getGlobalAttributes().put(SDOConstants.XML_DATATYPE_QNAME, xmlDataTypeProperty);
getGlobalAttributes().put(SDOConstants.XML_ID_PROPERTY_QNAME, SDOConstants.ID_PROPERTY);
getGlobalAttributes().put(SDOConstants.DOCUMENTATION_PROPERTY_QNAME, SDOConstants.DOCUMENTATION_PROPERTY);
getGlobalAttributes().put(SDOConstants.APPINFO_PROPERTY_QNAME, SDOConstants.APPINFO_PROPERTY);
}
/**
* Assign a map of properties representing global elements keyed on QName
* @param globalElements a Map of global elements keyed on QName
*/
public void setGlobalElements(Map globalElements) {
this.globalElements = globalElements;
}
/**
* Return a map of properties representing global elements keyed on QName
* @return a map of global elements keyed on QName
*/
private Map getGlobalElements() {
return globalElements;
}
/**
* INTERNAL:
*/
@Override
public Map buildAppInfoMap(List appInfoElements) {
HashMap appInfoMap = new HashMap();
// Build AppInfo map
if (appInfoElements != null) {
for (int i = 0; i < appInfoElements.size(); i++) {
Element nextElement = (Element)appInfoElements.get(i);
if (nextElement.getNamespaceURI().equals(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI) && nextElement.getLocalName().equals("appinfo")) {
String key = nextElement.getAttribute(SDOConstants.APPINFO_SOURCE_ATTRIBUTE);
String value = (String)appInfoMap.get(key);
StringWriter sw = new StringWriter();
WriterRecord wrec = new WriterRecord();
wrec.setWriter(sw);
wrec.node(nextElement, new NamespaceResolver());
wrec.flush();
appInfoMap.put(key, value == null ? sw.toString() : value + sw);
}
}
}
return appInfoMap;
}
@Override
public void reset() {
globalAttributes = new HashMap();
initOpenProps();
globalElements = new HashMap();
}
@Override
public HelperContext getHelperContext() {
return aHelperContext;
}
@Override
public void setHelperContext(HelperContext helperContext) {
aHelperContext = helperContext;
}
public String getStringFromAppInfoElement(Element appInfo) {
FormattedWriterRecord record = new FormattedWriterRecord();
record.setWriter(new StringWriter());
record.node(appInfo, new NamespaceResolver());
return record.getWriter().toString();
}
/**
* INTERNAL:
*
* @param qname
* @param prop
* @param isElement
* Register the given property with the given qname.
*/
@Override
public void addGlobalProperty(QName qname, Property prop, boolean isElement) {
((SDOProperty)prop).setUri(qname.getNamespaceURI());
if (isElement) {
getGlobalElements().put(qname, prop);
} else {
getGlobalAttributes().put(qname, prop);
}
}
}