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

org.eclipse.persistence.sdo.helper.jaxb.JAXBHelperContext Maven / Gradle / Ivy

There is a newer version: 5.0.0-B03
Show newest version
/*
 * Copyright (c) 1998, 2020 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:
//     bdoughan - Jan 27/2009 - 1.1 - Initial implementation
package org.eclipse.persistence.sdo.helper.jaxb;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import jakarta.xml.bind.JAXBContext;
import javax.xml.namespace.QName;

import org.eclipse.persistence.exceptions.SDOException;
import org.eclipse.persistence.internal.helper.IdentityWeakHashMap;
import org.eclipse.persistence.internal.oxm.XPathFragment;
import org.eclipse.persistence.oxm.XMLDescriptor;
import org.eclipse.persistence.oxm.schema.XMLSchemaReference;
import org.eclipse.persistence.sdo.SDODataObject;
import org.eclipse.persistence.sdo.SDOType;
import org.eclipse.persistence.sdo.helper.SDOCopyHelper;
import org.eclipse.persistence.sdo.helper.SDODataHelper;
import org.eclipse.persistence.sdo.helper.SDOEqualityHelper;
import org.eclipse.persistence.sdo.helper.SDOHelperContext;
import org.eclipse.persistence.sdo.helper.delegates.SDOTypeHelperDelegate;
import org.eclipse.persistence.sdo.helper.delegates.SDOXSDHelperDelegate;

import commonj.sdo.DataObject;
import commonj.sdo.Property;
import commonj.sdo.Type;

/**
 * 

The JAXBHelperContext is a bridge between POJOs and SDO DataObjects. The bridge * is based on their corresponding XML representations. For the POJOs the XML * representation is specified using JAXB annotations or object-to-XML mappings.

* *

The following steps are required to create the JAXBHelperContext. The XML schema * used in step #3 is the same one that the POJOs are mapped to. This step has been * separated so that SDO annotations could be added to the XML schema. *

Step #1 - Create the JAXBContext

*
 * JAXBContext jaxbContext = JAXBContext.newInstance("com.example.customer");
 * 
*

Step #2 - Create the JAXBHelperContext

*
 * JAXBHelperContext jaxbHelperContext = new JAXBHelperContext(jaxbContext);
 * 
*

Step #3 - Create the SDO Metadata from an XML Schema

*
 * jaxbHelperContext.getXSDHelper().define(xmlSchema);
 * 
* *

* The JAXBHelperContext allows you to convert between POJOs and DataObjects using * a wrap operation. *

 * Customer customer = new Customer();
 * Address address new Address();
 * address.setStreet("123 Any Street");
 * customer.set(address);
 *
 * DataObject customerDO = jaxbHelperContext.wrap(customer);
 * customerDO.getString("address/street");  // returns "123 Any Street"
 * 
* *

* The JAXBHelperContext allows you to convert between DataObjects and POJOs using * an unwrap operation. *

 * Type customerType = jaxbHelperContext.getType(Customer.class);
 * DataObject customerDO = jaxbHelperContext.getDataFactory().create(customerType);
 * customerDO.set("first-name", "Jane");
 *
 * Customer customer = jaxbHelperContext.unwrap(customerDO);
 * customer.getFirstName();  // returns "Jane"
 * 
* *

* Of course the POJOs may be JPA entities. Below is an example of wrapping the * results of a JPA query. *

 * EntityManagerFactory emf = Persistence.createEntityManagerFactory("CustomerExample");
 * EntityManager em = emf.createEntityManager();
 * {@literal List} entities = em.createQuery("SELECT e FROM MyEntity e WHERE ...").getResultList();
 * {@literal List} dataObjects = hc.wrap(entities);
 * 
*/ public class JAXBHelperContext extends SDOHelperContext { private org.eclipse.persistence.jaxb.JAXBContext jaxbContext; private Map wrapperDataObjects; /** * Create a new instance of JAXBHelperContext * @param aJAXBContext - The JAXBContext representing the class to XML schema mapping. */ public JAXBHelperContext(JAXBContext aJAXBContext) { this(aJAXBContext, Thread.currentThread().getContextClassLoader()); } /** * Create a new instance of JAXBHelperContext * @param aJAXBContext - The JAXBContext representing the class to XML schema mapping. * @param aClassLoader - The ClassLoader containing the generated SDO classes/interfaces (if any). */ public JAXBHelperContext(JAXBContext aJAXBContext, ClassLoader aClassLoader) { super(aClassLoader); wrapperDataObjects = new IdentityWeakHashMap(); jaxbContext = (org.eclipse.persistence.jaxb.JAXBContext) aJAXBContext; } /** * Override the default helpers/factories, replacing them * with JAXB aware ones where necessary. */ @Override protected void initialize(ClassLoader aClassLoader) { copyHelper = new SDOCopyHelper(this); dataFactory = new JAXBDataFactory(this); dataHelper = new SDODataHelper(this); equalityHelper = new SDOEqualityHelper(this); xmlHelper = new JAXBXMLHelper(this, aClassLoader); typeHelper = new SDOTypeHelperDelegate(this); xsdHelper = new SDOXSDHelperDelegate(this); } /** * Return the JAXBContext. The JAXBContext represents the Java * class to XML schema information for the POJOs. */ public JAXBContext getJAXBContext() { return jaxbContext; } /** * Return the SDO type corresponding to the wrapped class. *
     * Type customerType = jaxbHelperContext.getType(Customer.class);
     * DataObject customerDO = jaxbHelperContext.getDataFactory().create(customerType);
     * 
*/ public Type getType(Class entityClass) { if(null == entityClass) { return null; } XMLDescriptor entityDescriptor = null; try { entityDescriptor = (XMLDescriptor) jaxbContext.getXMLContext().getSession(entityClass).getDescriptor(entityClass); } catch(Exception e) { return null; } XMLSchemaReference schemaReference = entityDescriptor.getSchemaReference(); if(null == schemaReference) { throw SDOException.sdoJaxbNoSchemaReference(entityClass); } QName qName = schemaReference.getSchemaContextAsQName(entityDescriptor.getNamespaceResolver()); if(null == qName) { throw SDOException.sdoJaxbNoSchemaContext(entityClass); } Type wrapperType; if(entityDescriptor.getSchemaReference().getType() == XMLSchemaReference.COMPLEX_TYPE) { wrapperType = getTypeHelper().getType(qName.getNamespaceURI(), qName.getLocalPart()); } else { Property property = getXSDHelper().getGlobalProperty(qName.getNamespaceURI(), qName.getLocalPart(), true); wrapperType = property.getType(); } if(null == wrapperType) { throw SDOException.sdoJaxbNoTypeForClassBySchemaContext(entityClass, qName); } return wrapperType; } /** * Return the wrapped class corresponding to the SDO type. *
     * Type customerType = jaxbHelperContext.getTypeHelper().getType("urn:customer", "customer");
     * Class customerClass = jaxbHelperContext.getClass(customerType);
     * 
*/ public Class getClass(Type type) { if(null == type) { return null; } return getObjectDescriptor((SDOType) type).getJavaClass(); } /** * Return a DataObject that wraps a POJO. This call should be * made on the root POJO. *
     * Customer customer = new Customer();
     * Address address new Address();
     * address.setStreet("123 Any Street");
     * customer.set(address);
     *
     * DataObject customerDO = jaxbHelperContext.wrap(customer);
     * customerDO.getString("address/street");  // returns "123 Any Street"
     * 
* Multiple calls to wrap for the same instance POJO return the * same instance of DataObject, in other words the following is * always true: *
     * jaxbHelperContext.wrap(customer123) == jaxbHelperContext.wrap(customer123)
     * jaxbHelperContext.wrap(customer123) != jaxbHelperContext.wrap(customer456)
     * 
*/ public DataObject wrap(Object entity) { if(null == entity) { return null; } SDODataObject wrapperDO = wrapperDataObjects.get(entity); if(null != wrapperDO) { return wrapperDO; } Type wrapperType = getType(entity.getClass()); if(null == wrapperType) { throw SDOException.sdoJaxbNoTypeForClass(entity.getClass()); } wrapperDO = (SDODataObject) getDataFactory().create(wrapperType); JAXBValueStore jaxbValueStore = new JAXBValueStore(this, entity); wrapperDO._setCurrentValueStore(jaxbValueStore); jaxbValueStore.initialize(wrapperDO); wrapperDataObjects.put(entity, wrapperDO); return wrapperDO; } /** * Helper method that configures container information. */ DataObject wrap(Object entity, Property containmentProperty, DataObject container) { SDODataObject sdoDataObject = (SDODataObject) wrap(entity); if(null == container) { sdoDataObject._setContainmentPropertyName(null); } else { sdoDataObject._setContainmentPropertyName(containmentProperty.getName()); } sdoDataObject._setContainer(container); return sdoDataObject; } /** * Perform the wrap operation on each of the POJOs in the collection, * and return the results as a List. */ public List wrap(Collection entities) { return wrap(entities, null, null); } /** * Helper method that configures container information. */ List wrap(Collection entities, Property containmentProperty, DataObject container) { if(null == entities) { return new ArrayList(0); } List dataObjects = new ArrayList(entities.size()); for(Object entity: entities) { dataObjects.add(wrap(entity, containmentProperty, container)); } return dataObjects; } /** * Return the POJO that is wrapped by the DataObject. *
     * Type customerType = jaxbHelperContext.getType(Customer.class);
     * DataObject customerDO = jaxbHelperContext.getDataFactory().create(customerType);
     * DataObject addressDO = customerDO.create("address");
     * addressDO.set("street", "123 Any Street");
     *
     * Customer customer = (Customer) jaxbHelperContext.unwrap(customerDO);
     * customer.getAddress().getStreet();  // returns "123 Any Street"
     * 
* Multiple calls to unwrap for the same DataObject must return the * same instance of Object, in other words the following is always true: *
     * jaxbHelperContext.unwrap(customerDO123) == jaxbHelperContext.unwrap(customerDO123)
     * jaxbHelperContext.unwrap(customerDO123) != jaxbHelperContext.unwrap(customerDO456)
     * customer123 == jaxbHelperContext.unwrap(jaxbHelperContext.wrap(customer123))
     * 
*/ public Object unwrap(DataObject dataObject) { try { if(null == dataObject) { return null; } SDODataObject sdoDataObject = (SDODataObject) dataObject; JAXBValueStore jpaValueStore = (JAXBValueStore) sdoDataObject._getCurrentValueStore(); return jpaValueStore.getEntity(); } catch(ClassCastException e) { return null; } } /** * Perform the unwrap operation on each of the DataObjects in the collection, * and return the results as a List. */ public List unwrap(Collection dataObjects) { if(null == dataObjects) { return new ArrayList(0); } List entities = new ArrayList(dataObjects.size()); for(DataObject dataObject: dataObjects) { entities.add(unwrap(dataObject)); } return entities; } /** * Maintain an association between this POJO and DataObject. */ void putWrapperDataObject(Object anObject, SDODataObject aDataObject) { wrapperDataObjects.put(anObject, aDataObject); } /** * Get the XML descriptor for the entity class corresponding to the SDO type. */ XMLDescriptor getObjectDescriptor(SDOType sdoType) { QName xsdQName = sdoType.getXsdType(); if(null == xsdQName) { xsdQName = sdoType.getQName(); } XPathFragment xPathFragment = new XPathFragment(xsdQName.getLocalPart()); xPathFragment.setNamespaceURI(xsdQName.getNamespaceURI()); XMLDescriptor xmlDescriptor = jaxbContext.getXMLContext().getDescriptorByGlobalType(xPathFragment); if (null == xmlDescriptor) { xmlDescriptor = jaxbContext.getXMLContext().getDescriptor(xsdQName); if (null == xmlDescriptor) { throw SDOException.sdoJaxbNoDescriptorForType(sdoType.getQName(), xsdQName); } } return xmlDescriptor; } }