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:
David J. Wisneski 2007-07-31 16:19:24 +00:00
parent 872d00888d
commit 7ca46cf69d
13 changed files with 505 additions and 324 deletions

View File

@ -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];
}
}

View File

@ -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);
}
}
}

View File

@ -122,4 +122,8 @@ public class DelegatingMetaDataFactory
public void addFieldExtensionKeys(Collection exts) {
_delegate.addFieldExtensionKeys(exts);
}
public void loadXMLMetaData(FieldMetaData fmd) {
_delegate.loadXMLMetaData(fmd);
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -134,4 +134,7 @@ public class NoneMetaDataFactory
public Class getUnimplementedExceptionType() {
return null;
}
public void loadXMLMetaData(FieldMetaData fmd) {
}
}

View File

@ -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);
}
}

View File

@ -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) {
}
}

View File

@ -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);
}

View File

@ -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"
);
}

View File

@ -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>

View File

@ -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);
}
}
}

View File

@ -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);
}
}