mirror of https://github.com/apache/openjpa.git
OPENJPA-240 XMLMapping Query - refactoring JAXB XML annotaion parser
Help Catalina committing OPENJPA-240.r560665.patch for refactoring JAXB XML annotation parser. git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@561376 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
872d00888d
commit
7ca46cf69d
|
@ -1,82 +0,0 @@
|
|||
/*
|
||||
* 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.openjpa.jdbc.meta;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.openjpa.meta.FieldMetaData;
|
||||
import org.apache.openjpa.meta.XMLClassMetaData;
|
||||
import org.apache.openjpa.meta.XMLMetaData;
|
||||
|
||||
/**
|
||||
* Repository of object/relational mapping information.
|
||||
* (extended to include XML mapping metadata for XML columns)
|
||||
*
|
||||
* @author Catalina Wei
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class XMLMappingRepository extends MappingRepository {
|
||||
// xml mapping
|
||||
protected final XMLMetaData[] EMPTY_XMLMETAS;
|
||||
private final Map _xmlmetas = new HashMap();
|
||||
|
||||
public XMLMappingRepository() {
|
||||
super();
|
||||
EMPTY_XMLMETAS = newXMLClassMetaDataArray(0);
|
||||
}
|
||||
|
||||
public synchronized XMLClassMetaData addXMLClassMetaData(FieldMetaData fmd,
|
||||
String name) {
|
||||
XMLClassMetaData meta = newXMLClassMetaData(fmd, name);
|
||||
addXMLClassMetaData(fmd.getDeclaredType(), meta);
|
||||
return meta;
|
||||
}
|
||||
|
||||
public XMLMetaData getXMLClassMetaData(Class cls) {
|
||||
synchronized(_xmlmetas) {
|
||||
if (_xmlmetas.isEmpty())
|
||||
return null;
|
||||
else
|
||||
return (XMLClassMetaData) _xmlmetas.get(cls);
|
||||
}
|
||||
}
|
||||
|
||||
public XMLMetaData getXMLMetaData(FieldMetaData fmd) {
|
||||
XMLMetaData xmlmeta = null;
|
||||
if (XMLClassMetaData.isXMLMapping(fmd.getDeclaredType())) {
|
||||
xmlmeta = getXMLClassMetaData(fmd.getDeclaredType());
|
||||
if (xmlmeta == null)
|
||||
xmlmeta = addXMLClassMetaData(fmd, fmd.getName());
|
||||
}
|
||||
return xmlmeta;
|
||||
}
|
||||
|
||||
public synchronized void addXMLClassMetaData(Class cls, XMLMetaData meta) {
|
||||
_xmlmetas.put(cls, meta);
|
||||
}
|
||||
|
||||
protected XMLClassMetaData newXMLClassMetaData(FieldMetaData fmd, String name) {
|
||||
return new XMLClassMetaData(fmd.getDeclaredType(), name, this);
|
||||
}
|
||||
|
||||
protected XMLMetaData[] newXMLClassMetaDataArray(int length) {
|
||||
return new XMLClassMetaData[length];
|
||||
}
|
||||
}
|
|
@ -1,233 +0,0 @@
|
|||
/*
|
||||
* 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.openjpa.meta;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.HashMap;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
import org.apache.openjpa.jdbc.meta.XMLMappingRepository;
|
||||
import org.apache.openjpa.meta.JavaTypes;
|
||||
import org.apache.openjpa.meta.XMLMetaData;
|
||||
import org.apache.openjpa.meta.XMLFieldMetaData;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
/**
|
||||
* Contains metadata about a persistent field that maps to an xml column.
|
||||
* This metadata is loaded at runtime when query involves predicates
|
||||
* that navigate through xpath.
|
||||
*
|
||||
* @author Catalina Wei
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public class XMLClassMetaData implements XMLMetaData
|
||||
{
|
||||
private Class _type;
|
||||
private int _code = JavaTypes.OBJECT;
|
||||
private int _xmltype = XMLTYPE;
|
||||
private String _name = null;
|
||||
private String _xmlname = null;
|
||||
private String _xmlnamespace = null;
|
||||
private boolean _isXMLRootElement = false;
|
||||
private HashMap _fieldMap = new HashMap();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param type the class that contains XmlType annotation.
|
||||
* @name the persistent field name that maps to xml column
|
||||
* @param repo the meta repository.
|
||||
*/
|
||||
public XMLClassMetaData(Class type, String name, XMLMappingRepository repos) {
|
||||
_type = type;
|
||||
_isXMLRootElement = _type.getAnnotation(XmlRootElement.class) != null;
|
||||
if (_isXMLRootElement) {
|
||||
_xmlname = ((XmlRootElement) _type.getAnnotation
|
||||
(XmlRootElement.class)).name();
|
||||
_xmlnamespace = ((XmlRootElement) _type.getAnnotation
|
||||
(XmlRootElement.class)).namespace();
|
||||
}
|
||||
else {
|
||||
_xmlname = ((XmlType) _type.getAnnotation
|
||||
(XmlType.class)).name();
|
||||
_xmlnamespace = ((XmlType) _type.getAnnotation
|
||||
(XmlType.class)).namespace();
|
||||
_name = name;
|
||||
}
|
||||
populateFromReflection(_type, repos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Supply described type and repository.
|
||||
*
|
||||
* @param type the class that contains XmlType annotation.
|
||||
* @param repo the meta repository.
|
||||
*/
|
||||
protected XMLClassMetaData(Class type, XMLMappingRepository repos) {
|
||||
_type = type;
|
||||
_isXMLRootElement = _type.getAnnotation(XmlRootElement.class) != null;
|
||||
if (_isXMLRootElement) {
|
||||
_xmlname = ((XmlRootElement) _type.getAnnotation
|
||||
(XmlRootElement.class)).name();
|
||||
_xmlnamespace = ((XmlRootElement) _type.getAnnotation
|
||||
(XmlRootElement.class)).namespace();
|
||||
}
|
||||
else {
|
||||
_xmlname = ((XmlType) _type.getAnnotation
|
||||
(XmlType.class)).name();
|
||||
_xmlnamespace = ((XmlType) _type.getAnnotation
|
||||
(XmlType.class)).namespace();
|
||||
}
|
||||
populateFromReflection(_type, repos);
|
||||
repos.addXMLClassMetaData(type, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a class type return true if XmlType annotation exists
|
||||
* @param type
|
||||
* @return true if XmlType annotation is present else false.
|
||||
*/
|
||||
public static boolean isXMLMapping(Class type) {
|
||||
return type.isAnnotationPresent(XmlType.class);
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
public void setXmlname(String name) {
|
||||
_xmlname = name;
|
||||
}
|
||||
|
||||
public String getXmlname() {
|
||||
return _isXMLRootElement ? null : _xmlname;
|
||||
}
|
||||
|
||||
public void setXmlnamespace(String name) {
|
||||
// avoid JAXB XML bind default name
|
||||
if (!StringUtils.equals(defaultName, name))
|
||||
_xmlnamespace = name;
|
||||
}
|
||||
|
||||
public String getXmlnamespace() {
|
||||
return _xmlnamespace;
|
||||
}
|
||||
|
||||
public boolean isXmlRootElement() {
|
||||
return _isXMLRootElement;
|
||||
}
|
||||
|
||||
public boolean isXmlElement() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isXmlAttribute() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public XMLMetaData getFieldMapping(String name) {
|
||||
return (XMLMetaData) _fieldMap.get(name);
|
||||
}
|
||||
|
||||
public void setType(Class type) {
|
||||
_type = type;
|
||||
}
|
||||
|
||||
public Class getType() {
|
||||
return _type;
|
||||
}
|
||||
|
||||
public int getTypeCode() {
|
||||
return _code;
|
||||
}
|
||||
|
||||
public void setXmltype(int type) {
|
||||
_xmltype = type;
|
||||
}
|
||||
public int getXmltype() {
|
||||
return _xmltype;
|
||||
}
|
||||
|
||||
private synchronized void populateFromReflection(Class cls,
|
||||
XMLMappingRepository repos) {
|
||||
Member[] members;
|
||||
Class superclass = cls.getSuperclass();
|
||||
|
||||
// handle inheritance at sub-element level
|
||||
if (superclass.isAnnotationPresent(XmlType.class))
|
||||
populateFromReflection(superclass, repos);
|
||||
|
||||
if (((XmlAccessorType) cls.getAnnotation(XmlAccessorType.class)).value()
|
||||
== XmlAccessType.FIELD)
|
||||
members = cls.getDeclaredFields();
|
||||
else
|
||||
members = cls.getDeclaredMethods();
|
||||
for (int i = 0; i < members.length; i++) {
|
||||
Member member = members[i];
|
||||
AnnotatedElement el = (AnnotatedElement) member;
|
||||
XMLMetaData field = null;
|
||||
if (el.getAnnotation(XmlElement.class) != null) {
|
||||
String xmlname = el.getAnnotation(XmlElement.class).name();
|
||||
// avoid JAXB XML bind default name
|
||||
if (StringUtils.equals(defaultName, xmlname))
|
||||
xmlname = member.getName();
|
||||
if (((Field) member).getType().
|
||||
isAnnotationPresent(XmlType.class)) {
|
||||
field = new XMLClassMetaData(((Field) member).getType(),
|
||||
repos);
|
||||
field.setXmltype(XMLTYPE);
|
||||
field.setXmlname(xmlname);
|
||||
}
|
||||
else {
|
||||
field = new XMLFieldMetaData();
|
||||
field.setXmltype(ELEMENT);
|
||||
field.setXmlname(xmlname);
|
||||
field.setXmlnamespace(el.getAnnotation(XmlElement.class)
|
||||
.namespace());
|
||||
}
|
||||
}
|
||||
else if (el.getAnnotation(XmlAttribute.class) != null) {
|
||||
field = new XMLFieldMetaData();
|
||||
field.setXmltype(XMLFieldMetaData.ATTRIBUTE);
|
||||
String xmlname = el.getAnnotation(XmlAttribute.class).name();
|
||||
// avoid JAXB XML bind default name
|
||||
if (StringUtils.equals(defaultName, xmlname))
|
||||
xmlname = member.getName();
|
||||
field.setXmlname("@"+xmlname);
|
||||
field.setXmlnamespace(el.getAnnotation(XmlAttribute.class)
|
||||
.namespace());
|
||||
}
|
||||
field.setName(member.getName());
|
||||
field.setType(((Field) member).getType());
|
||||
_fieldMap.put(member.getName(), field);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -122,4 +122,8 @@ public class DelegatingMetaDataFactory
|
|||
public void addFieldExtensionKeys(Collection exts) {
|
||||
_delegate.addFieldExtensionKeys(exts);
|
||||
}
|
||||
|
||||
public void loadXMLMetaData(FieldMetaData fmd) {
|
||||
_delegate.loadXMLMetaData(fmd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,4 +144,10 @@ public interface MetaDataFactory
|
|||
* Add any extension keys used by this instance to the given set.
|
||||
*/
|
||||
public void addFieldExtensionKeys (Collection exts);
|
||||
|
||||
/**
|
||||
* Load XMLClassMetadata for the given class. Loaded
|
||||
* metadata should be added directly to the repository.
|
||||
*/
|
||||
public void loadXMLMetaData(FieldMetaData fmd);
|
||||
}
|
||||
|
|
|
@ -117,6 +117,10 @@ public class MetaDataRepository
|
|||
// map of classes to lists of their subclasses
|
||||
private final Map _subs = Collections.synchronizedMap(new HashMap());
|
||||
|
||||
// xml mapping
|
||||
protected final XMLMetaData[] EMPTY_XMLMETAS;
|
||||
private final Map _xmlmetas = new HashMap();
|
||||
|
||||
private transient OpenJPAConfiguration _conf = null;
|
||||
private transient Log _log = null;
|
||||
private transient InterfaceImplGenerator _implGen = null;
|
||||
|
@ -148,6 +152,7 @@ public class MetaDataRepository
|
|||
EMPTY_METAS = newClassMetaDataArray(0);
|
||||
EMPTY_FIELDS = newFieldMetaDataArray(0);
|
||||
EMPTY_ORDERS = newOrderArray(0);
|
||||
EMPTY_XMLMETAS = newXMLClassMetaDataArray(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -785,6 +790,13 @@ public class MetaDataRepository
|
|||
return new FieldMetaData[length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new array of the proper xml class metadata subclass.
|
||||
*/
|
||||
protected XMLMetaData[] newXMLClassMetaDataArray(int length) {
|
||||
return new XMLClassMetaData[length];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new embedded class metadata instance.
|
||||
*/
|
||||
|
@ -1861,9 +1873,67 @@ public class MetaDataRepository
|
|||
/**
|
||||
* Return XML metadata for a given field metadata
|
||||
* @param fmd
|
||||
* @return null
|
||||
* @return XML metadata
|
||||
*/
|
||||
public XMLMetaData getXMLMetaData(FieldMetaData fmd) {
|
||||
return null;
|
||||
public synchronized XMLMetaData getXMLMetaData(FieldMetaData fmd) {
|
||||
Class cls = fmd.getDeclaredType();
|
||||
// check if cached before
|
||||
XMLMetaData xmlmeta = (XMLClassMetaData) _xmlmetas.get(cls);
|
||||
if (xmlmeta != null)
|
||||
return xmlmeta;
|
||||
|
||||
// load JAXB XML metadata
|
||||
_factory.loadXMLMetaData(fmd);
|
||||
|
||||
xmlmeta = (XMLClassMetaData) _xmlmetas.get(cls);
|
||||
|
||||
return xmlmeta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new metadata, populate it with default information, add it to
|
||||
* the repository, and return it.
|
||||
*
|
||||
* @param access the access type to use in populating metadata
|
||||
*/
|
||||
public XMLClassMetaData addXMLMetaData(Class type, String name) {
|
||||
XMLClassMetaData meta = newXMLClassMetaData(type, name);
|
||||
|
||||
// synchronize on this rather than the map, because all other methods
|
||||
// that access _xmlmetas are synchronized on this
|
||||
synchronized (this) {
|
||||
_xmlmetas.put(type, meta);
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the cached XMLClassMetaData for the given class
|
||||
* Return null if none.
|
||||
*/
|
||||
public XMLMetaData getCachedXMLMetaData(Class cls) {
|
||||
return (XMLMetaData) _xmlmetas.get(cls);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new xml class metadata
|
||||
* @param type
|
||||
* @param name
|
||||
* @return a XMLClassMetaData
|
||||
*/
|
||||
protected XMLClassMetaData newXMLClassMetaData(Class type, String name) {
|
||||
return new XMLClassMetaData(type, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new xml field meta, add it to the fieldMap in the given
|
||||
* xml class metadata
|
||||
* @param type
|
||||
* @param name
|
||||
* @param meta
|
||||
* @return a XMLFieldMetaData
|
||||
*/
|
||||
public XMLFieldMetaData newXMLFieldMetaData(Class type, String name) {
|
||||
return new XMLFieldMetaData(type, name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,4 +134,7 @@ public class NoneMetaDataFactory
|
|||
public Class getUnimplementedExceptionType() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void loadXMLMetaData(FieldMetaData fmd) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* 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.openjpa.meta;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
public class XMLClassMetaData implements XMLMetaData
|
||||
{
|
||||
private Class _type;
|
||||
private int _code = JavaTypes.OBJECT;
|
||||
private int _xmltype = XMLTYPE;
|
||||
private String _name = null;
|
||||
private String _xmlname = null;
|
||||
private String _xmlnamespace = null;
|
||||
private boolean _isXMLRootElement = false;
|
||||
private HashMap _fieldMap = new HashMap();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param type the class that contains XmlType annotation.
|
||||
* @name the persistent field name that maps to xml column
|
||||
*/
|
||||
public XMLClassMetaData(Class type, String name) {
|
||||
_type = type;
|
||||
_name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param type the class that contains XmlType annotation.
|
||||
*/
|
||||
public XMLClassMetaData(Class type) {
|
||||
_type = type;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
public void setXmlname(String name) {
|
||||
_xmlname = name;
|
||||
}
|
||||
|
||||
public String getXmlname() {
|
||||
return _isXMLRootElement ? null : _xmlname;
|
||||
}
|
||||
|
||||
public void setXmlnamespace(String name) {
|
||||
// avoid JAXB XML bind default name
|
||||
if (!StringUtils.equals(defaultName, name))
|
||||
_xmlnamespace = name;
|
||||
}
|
||||
|
||||
public String getXmlnamespace() {
|
||||
return _xmlnamespace;
|
||||
}
|
||||
|
||||
public void setXmlRootElement(boolean isXMLRootElement) {
|
||||
_isXMLRootElement = isXMLRootElement;
|
||||
}
|
||||
|
||||
public boolean isXmlRootElement() {
|
||||
return _isXMLRootElement;
|
||||
}
|
||||
|
||||
public boolean isXmlElement() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isXmlAttribute() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public XMLMetaData getFieldMapping(String name) {
|
||||
return (XMLMetaData) _fieldMap.get(name);
|
||||
}
|
||||
|
||||
public void setType(Class type) {
|
||||
_type = type;
|
||||
}
|
||||
|
||||
public Class getType() {
|
||||
return _type;
|
||||
}
|
||||
|
||||
public int getTypeCode() {
|
||||
return _code;
|
||||
}
|
||||
|
||||
public void setXmltype(int type) {
|
||||
_xmltype = type;
|
||||
}
|
||||
|
||||
public int getXmltype() {
|
||||
return _xmltype;
|
||||
}
|
||||
|
||||
public void addField(String name, XMLMetaData field) {
|
||||
_fieldMap.put(name, field);
|
||||
}
|
||||
}
|
|
@ -40,6 +40,11 @@ public class XMLFieldMetaData implements XMLMetaData {
|
|||
public XMLFieldMetaData() {
|
||||
}
|
||||
|
||||
public XMLFieldMetaData(Class type, String name) {
|
||||
setType(type);
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public Class getType() {
|
||||
return (_type == null) ? _decType : _type;
|
||||
}
|
||||
|
@ -108,4 +113,10 @@ public class XMLFieldMetaData implements XMLMetaData {
|
|||
public XMLMetaData getFieldMapping(String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setXmlRootElement(boolean isXmlRootElement) {
|
||||
}
|
||||
|
||||
public void addField(String name, XMLMetaData field) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,4 +116,8 @@ public interface XMLMetaData extends Serializable {
|
|||
* @return xmltype
|
||||
*/
|
||||
public int getXmltype();
|
||||
|
||||
public void setXmlRootElement(boolean isXmlRootElement);
|
||||
|
||||
public void addField(String name, XMLMetaData field);
|
||||
}
|
||||
|
|
|
@ -54,12 +54,6 @@ public class TestXMLCustomerOrder
|
|||
.CustomerKey.class
|
||||
, org.apache.openjpa.persistence.xmlmapping.entities.Order.class
|
||||
, org.apache.openjpa.persistence.xmlmapping.entities.EAddress.class
|
||||
, "openjpa.MetaDataRepository"
|
||||
, "org.apache.openjpa.jdbc.meta.XMLMappingRepository"
|
||||
// , "openjpa.ConnectionDriverName"
|
||||
// , "org.apache.commons.dbcp.BasicDataSource"
|
||||
// , "openjpa.ConnectionProperties"
|
||||
// , "DriverClassName=com.ibm.db2.jcc.DB2Driver,Url=jdbc:db2:testdb"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,11 @@
|
|||
<version>1.0</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
<version>2.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
|
|
@ -0,0 +1,234 @@
|
|||
/*
|
||||
* 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.openjpa.persistence;
|
||||
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Member;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlAttribute;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.openjpa.conf.OpenJPAConfiguration;
|
||||
import org.apache.openjpa.lib.log.Log;
|
||||
import org.apache.openjpa.lib.util.Localizer;
|
||||
import org.apache.openjpa.meta.DelegatingMetaDataFactory;
|
||||
import org.apache.openjpa.meta.FieldMetaData;
|
||||
import org.apache.openjpa.meta.MetaDataFactory;
|
||||
import org.apache.openjpa.meta.MetaDataRepository;
|
||||
import org.apache.openjpa.meta.XMLFieldMetaData;
|
||||
import org.apache.openjpa.meta.XMLMetaData;
|
||||
|
||||
/**
|
||||
* JAXB xml annotation metadata parser.
|
||||
*
|
||||
* @author Catalina Wei
|
||||
* @nojavadoc
|
||||
*/
|
||||
public class AnnotationPersistenceXMLMetaDataParser {
|
||||
|
||||
private static final Localizer _loc = Localizer.forPackage
|
||||
(AnnotationPersistenceXMLMetaDataParser.class);
|
||||
|
||||
private final OpenJPAConfiguration _conf;
|
||||
private final Log _log;
|
||||
private MetaDataRepository _repos = null;
|
||||
|
||||
// the class we were invoked to parse
|
||||
private Class _cls = null;
|
||||
private FieldMetaData _fmd = null;
|
||||
|
||||
/**
|
||||
* Constructor; supply configuration.
|
||||
*/
|
||||
public AnnotationPersistenceXMLMetaDataParser(OpenJPAConfiguration conf) {
|
||||
_conf = conf;
|
||||
_log = conf.getLog(OpenJPAConfiguration.LOG_METADATA);
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration supplied on construction.
|
||||
*/
|
||||
public OpenJPAConfiguration getConfiguration() {
|
||||
return _conf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Metadata log.
|
||||
*/
|
||||
public Log getLog() {
|
||||
return _log;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the repository for this parser. If none has been set,
|
||||
* create a new repository and sets it.
|
||||
*/
|
||||
public MetaDataRepository getRepository() {
|
||||
if (_repos == null) {
|
||||
MetaDataRepository repos = _conf.newMetaDataRepositoryInstance();
|
||||
MetaDataFactory mdf = repos.getMetaDataFactory();
|
||||
if (mdf instanceof DelegatingMetaDataFactory)
|
||||
mdf = ((DelegatingMetaDataFactory) mdf).getInnermostDelegate();
|
||||
if (mdf instanceof PersistenceMetaDataFactory)
|
||||
((PersistenceMetaDataFactory) mdf).setXMLAnnotationParser(this);
|
||||
_repos = repos;
|
||||
}
|
||||
return _repos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the metadata repository for this parser.
|
||||
*/
|
||||
public void setRepository(MetaDataRepository repos) {
|
||||
_repos = repos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear caches.
|
||||
*/
|
||||
public void clear() {
|
||||
_cls = null;
|
||||
_fmd = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse persistence metadata for the given field metadata.
|
||||
*/
|
||||
public void parse(FieldMetaData fmd) {
|
||||
_fmd = fmd;
|
||||
_cls = fmd.getDeclaredType();
|
||||
if (_log.isTraceEnabled())
|
||||
_log.trace(_loc.get("parse-class", _cls.getName()));
|
||||
|
||||
try {
|
||||
parseXMLClassAnnotations();
|
||||
} finally {
|
||||
_cls = null;
|
||||
_fmd = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read annotations for the current type.
|
||||
*/
|
||||
private XMLMetaData parseXMLClassAnnotations() {
|
||||
// check immediately whether the class has JAXB XML annotations
|
||||
if (!_cls.isAnnotationPresent(XmlType.class))
|
||||
return null;
|
||||
|
||||
// find / create metadata
|
||||
XMLMetaData meta = getXMLMetaData();
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find or create xml metadata for the current type.
|
||||
*/
|
||||
private synchronized XMLMetaData getXMLMetaData() {
|
||||
XMLMetaData meta = getRepository().getCachedXMLMetaData(_cls);
|
||||
if (meta == null) {
|
||||
// if not in cache, create metadata
|
||||
meta = getRepository().addXMLMetaData(_cls, _fmd.getName());
|
||||
parseXmlRootElement(_cls, meta);
|
||||
populateFromReflection(_cls, meta);
|
||||
}
|
||||
return meta;
|
||||
}
|
||||
|
||||
private void parseXmlRootElement(Class type, XMLMetaData meta) {
|
||||
if (type.getAnnotation(XmlRootElement.class) != null) {
|
||||
meta.setXmlRootElement(true);
|
||||
meta.setXmlname(((XmlRootElement) type.getAnnotation
|
||||
(XmlRootElement.class)).name());
|
||||
meta.setXmlnamespace(((XmlRootElement) type.getAnnotation
|
||||
(XmlRootElement.class)).namespace());
|
||||
}
|
||||
else {
|
||||
meta.setXmlname(((XmlType) type.getAnnotation
|
||||
(XmlType.class)).name());
|
||||
meta.setXmlnamespace(((XmlType) type.getAnnotation
|
||||
(XmlType.class)).namespace());
|
||||
}
|
||||
}
|
||||
|
||||
private void populateFromReflection(Class cls, XMLMetaData meta) {
|
||||
Member[] members;
|
||||
|
||||
Class superclass = cls.getSuperclass();
|
||||
|
||||
// handle inheritance at sub-element level
|
||||
if (superclass.isAnnotationPresent(XmlType.class))
|
||||
populateFromReflection(superclass, meta);
|
||||
|
||||
if (((XmlAccessorType) cls.getAnnotation(XmlAccessorType.class)).value()
|
||||
== XmlAccessType.FIELD)
|
||||
members = cls.getDeclaredFields();
|
||||
else
|
||||
members = cls.getDeclaredMethods();
|
||||
|
||||
for (int i = 0; i < members.length; i++) {
|
||||
Member member = members[i];
|
||||
AnnotatedElement el = (AnnotatedElement) member;
|
||||
XMLMetaData field = null;
|
||||
if (el.getAnnotation(XmlElement.class) != null) {
|
||||
String xmlname = el.getAnnotation(XmlElement.class).name();
|
||||
// avoid JAXB XML bind default name
|
||||
if (StringUtils.equals(XMLMetaData.defaultName, xmlname))
|
||||
xmlname = member.getName();
|
||||
if (((Field) member).getType()
|
||||
.isAnnotationPresent(XmlType.class)) {
|
||||
field = _repos.addXMLMetaData(((Field) member).getType()
|
||||
, member.getName());
|
||||
parseXmlRootElement(((Field) member).getType(), field);
|
||||
populateFromReflection(((Field) member).getType(), field);
|
||||
field.setXmltype(XMLMetaData.XMLTYPE);
|
||||
field.setXmlname(xmlname);
|
||||
}
|
||||
else {
|
||||
field = _repos.newXMLFieldMetaData(((Field) member)
|
||||
.getType(), member.getName());
|
||||
field.setXmltype(XMLMetaData.ELEMENT);
|
||||
field.setXmlname(xmlname);
|
||||
field.setXmlnamespace(el.getAnnotation(XmlElement.class)
|
||||
.namespace());
|
||||
}
|
||||
}
|
||||
else if (el.getAnnotation(XmlAttribute.class) != null) {
|
||||
field = _repos.newXMLFieldMetaData(((Field) member).getType()
|
||||
, member.getName());
|
||||
field.setXmltype(XMLFieldMetaData.ATTRIBUTE);
|
||||
String xmlname = el.getAnnotation(XmlAttribute.class).name();
|
||||
// avoid JAXB XML bind default name
|
||||
if (StringUtils.equals(XMLMetaData.defaultName, xmlname))
|
||||
xmlname = member.getName();
|
||||
field.setXmlname("@"+xmlname);
|
||||
field.setXmlnamespace(el.getAnnotation(XmlAttribute.class)
|
||||
.namespace());
|
||||
}
|
||||
meta.addField(member.getName(), field);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -56,6 +56,7 @@ import org.apache.openjpa.meta.MetaDataDefaults;
|
|||
import org.apache.openjpa.meta.MetaDataFactory;
|
||||
import org.apache.openjpa.meta.QueryMetaData;
|
||||
import org.apache.openjpa.meta.SequenceMetaData;
|
||||
import org.apache.openjpa.meta.XMLMetaData;
|
||||
import org.apache.openjpa.util.GeneralException;
|
||||
import org.apache.openjpa.util.MetaDataException;
|
||||
|
||||
|
@ -75,6 +76,7 @@ public class PersistenceMetaDataFactory
|
|||
private final PersistenceMetaDataDefaults _def =
|
||||
new PersistenceMetaDataDefaults();
|
||||
private AnnotationPersistenceMetaDataParser _annoParser = null;
|
||||
private AnnotationPersistenceXMLMetaDataParser _annoXMLParser = null;
|
||||
private XMLPersistenceMetaDataParser _xmlParser = null;
|
||||
private Map<URL, Set> _xml = null; // xml rsrc -> class names
|
||||
private Set<URL> _unparsed = null; // xml rsrc
|
||||
|
@ -467,4 +469,42 @@ public class PersistenceMetaDataFactory
|
|||
public void setInto(Options opts) {
|
||||
opts.keySet().retainAll(opts.setInto(_def).keySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return JAXB XML annotation parser,
|
||||
* creating it if it does not already exist.
|
||||
*/
|
||||
public AnnotationPersistenceXMLMetaDataParser getXMLAnnotationParser() {
|
||||
if (_annoXMLParser == null) {
|
||||
_annoXMLParser = newXMLAnnotationParser();
|
||||
_annoXMLParser.setRepository(repos);
|
||||
}
|
||||
return _annoXMLParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JAXB XML annotation parser.
|
||||
*/
|
||||
public void setXMLAnnotationParser(
|
||||
AnnotationPersistenceXMLMetaDataParser parser) {
|
||||
if (_annoXMLParser != null)
|
||||
_annoXMLParser.setRepository(null);
|
||||
if (parser != null)
|
||||
parser.setRepository(repos);
|
||||
_annoXMLParser = parser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JAXB XML annotation parser.
|
||||
*/
|
||||
protected AnnotationPersistenceXMLMetaDataParser newXMLAnnotationParser() {
|
||||
return new AnnotationPersistenceXMLMetaDataParser
|
||||
(repos.getConfiguration());
|
||||
}
|
||||
|
||||
public void loadXMLMetaData(FieldMetaData fmd) {
|
||||
AnnotationPersistenceXMLMetaDataParser parser
|
||||
= getXMLAnnotationParser();
|
||||
parser.parse(fmd);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue