| /* |
| * Copyright (c) 2014, 2021 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: |
| // Dmitry Kornilov - Initial implementation |
| package org.eclipse.persistence.jpa.rs.util.metadatasources; |
| |
| import org.eclipse.persistence.descriptors.ClassDescriptor; |
| import org.eclipse.persistence.internal.jpa.rs.weaving.RestCollectionAdapterClassWriter; |
| import org.eclipse.persistence.internal.jpa.rs.weaving.RestReferenceAdapterV2ClassWriter; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| import org.eclipse.persistence.jaxb.metadata.MetadataSource; |
| import org.eclipse.persistence.jaxb.xmlmodel.JavaType; |
| import org.eclipse.persistence.jaxb.xmlmodel.JavaType.JavaAttributes; |
| import org.eclipse.persistence.jaxb.xmlmodel.ObjectFactory; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlBindings.JavaTypes; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlElement; |
| import org.eclipse.persistence.jaxb.xmlmodel.XmlJavaTypeAdapter; |
| import org.eclipse.persistence.mappings.CollectionMapping; |
| import org.eclipse.persistence.mappings.DatabaseMapping; |
| import org.eclipse.persistence.mappings.DirectCollectionMapping; |
| import org.eclipse.persistence.mappings.ForeignReferenceMapping; |
| |
| import jakarta.xml.bind.JAXBElement; |
| import java.util.Collection; |
| import java.util.Map; |
| |
| /** |
| * {@link org.eclipse.persistence.jaxb.metadata.MetadataSource} used in the creation of dynamic JAXB contexts |
| * for applications in JPARS v2.0. |
| * |
| * @author Dmitry Kornilov |
| * @since EclipseLink 2.6.0 |
| */ |
| public class DynamicXmlV2MetadataSource implements MetadataSource { |
| private XmlBindings xmlBindings; |
| |
| /** |
| * Creates a new DynamicXmlV2MetadataSource. |
| * |
| * @param session the session. |
| * @param packageName the package name to process. |
| */ |
| public DynamicXmlV2MetadataSource(AbstractSession session, String packageName) { |
| final ObjectFactory objectFactory = new ObjectFactory(); |
| xmlBindings = new XmlBindings(); |
| xmlBindings.setPackageName(packageName); |
| |
| final JavaTypes javaTypes = new JavaTypes(); |
| xmlBindings.setJavaTypes(javaTypes); |
| |
| for (ClassDescriptor ormDescriptor : session.getProject().getOrderedDescriptors()) { |
| String descriptorPackageName = ""; |
| int index = ormDescriptor.getJavaClassName().lastIndexOf('.'); |
| if (index > 0) { |
| descriptorPackageName = ormDescriptor.getJavaClassName().substring(0, index); |
| } |
| if (descriptorPackageName.equals(packageName)) { |
| javaTypes.getJavaType().add(createJAXBType(ormDescriptor, objectFactory)); |
| } |
| } |
| } |
| |
| /** |
| * Create a javaType to be used by JAXB to map a particular class. |
| */ |
| private JavaType createJAXBType(ClassDescriptor classDescriptor, ObjectFactory objectFactory) { |
| JavaType javaType = new JavaType(); |
| String alias = classDescriptor.getAlias(); |
| if (alias == null || alias.isEmpty()) { |
| alias = classDescriptor.getJavaClass().getSimpleName(); |
| } |
| javaType.setName(alias); |
| |
| final JavaAttributes javaAttributes = new JavaAttributes(); |
| for (DatabaseMapping ormMapping : classDescriptor.getMappings()) { |
| JAXBElement<XmlElement> element = null; |
| if (ormMapping instanceof DirectCollectionMapping) { |
| // Direct mapping -> no adapter |
| continue; |
| } else if (ormMapping.isCollectionMapping()) { |
| // This is a collection mapping -> create collection adapter |
| element = createCollectionProperty(ormMapping, objectFactory); |
| } else if (ForeignReferenceMapping.class.isAssignableFrom(ormMapping.getClass())) { |
| // FK mapping -> create reference adapter |
| element = createProperty((ForeignReferenceMapping)ormMapping, objectFactory); |
| } |
| |
| if (element != null) { |
| javaAttributes.getJavaAttribute().add(element); |
| } |
| } |
| |
| if (!javaAttributes.getJavaAttribute().isEmpty()) { |
| javaType.setJavaAttributes(javaAttributes); |
| } |
| |
| return javaType; |
| } |
| |
| /** |
| * Create a JAXB property for given collection mapping. |
| */ |
| private JAXBElement<XmlElement> createCollectionProperty(DatabaseMapping mapping, ObjectFactory objectFactory) { |
| final XmlElement xmlElement = new XmlElement(); |
| xmlElement.setJavaAttribute(mapping.getAttributeName()); |
| xmlElement.setType(((CollectionMapping) mapping).getReferenceClassName()); |
| |
| final XmlJavaTypeAdapter adapter = new XmlJavaTypeAdapter(); |
| final String adapterName = RestCollectionAdapterClassWriter.getClassName(((CollectionMapping) mapping).getReferenceClassName()); |
| adapter.setValue(adapterName); |
| adapter.setType(Collection.class.getName()); |
| xmlElement.setXmlJavaTypeAdapter(adapter); |
| |
| return objectFactory.createXmlElement(xmlElement); |
| } |
| |
| /** |
| * Create a JAXB property for given reference mapping. |
| */ |
| private JAXBElement<XmlElement> createProperty(ForeignReferenceMapping mapping, ObjectFactory objectFactory) { |
| final String referenceClassName = mapping.getReferenceClassName(); |
| |
| final XmlElement xmlElement = new XmlElement(); |
| xmlElement.setJavaAttribute(mapping.getAttributeName()); |
| xmlElement.setType(referenceClassName); |
| |
| final String adapterName = RestReferenceAdapterV2ClassWriter.getClassName(referenceClassName); |
| final XmlJavaTypeAdapter adapter = new XmlJavaTypeAdapter(); |
| adapter.setValue(adapterName); |
| adapter.setType(referenceClassName); |
| xmlElement.setXmlJavaTypeAdapter(adapter); |
| |
| return objectFactory.createXmlElement(xmlElement); |
| } |
| |
| @Override |
| public XmlBindings getXmlBindings(Map<String, ?> properties, ClassLoader classLoader) { |
| return this.xmlBindings; |
| } |
| |
| } |