Hi, Patrick,
Thanks for the comments.
My comments in *BLUE*.
Catalina
On 7/19/07, Patrick Linskey <plinskey@gmail.com> wrote:
>
> Hi,
>
> I'll be reviewing this code piecemeal. Here are some initial comments:
>
> >
> openjpa/trunk/openjpa-jdbc-5/src/main/java/org/apache/openjpa/meta/XMLClassMetaData.java
> >
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLMapping.java
> >
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLMetaData.java
>
> Why aren't these in the same place? It looks like XMLClassMetaData
> relies on XMLMapping and XMLMetaData, and that those dependencies are
> basically useless without XMLClassMetaData. Should we just move them
> to be near each other?
XMLClassMetaData.java placed in openjpa-jdbc-5 is mainly due to JAXB
dependency.
I can move XMLMapping.java and XMLMetaData.java to openjpa-jdbc-5 if we want
to keep them near by.
> 3. if no objection, make XMLMappingRepository as the default metadata
> repository
> > (string set in JDBCConfigurationImpl.java)
>
> I think that we should just move the code in XMLMappingRepository into
> MappingRepository. Refactoring tools should be able to do so
> trivially.
I can merge the funcitons implemented in XMLMappingRepository into
MappingRepository and get rid of XMLMappingRepository.
> 4. when defecting a field having XML bindings, set default strategy to
> > XMLValueHandler without requiring explicit @Strategy annotation in the
> entities
>
> How do you detect this? If it's reliable, then I definitely agree that
> we shouldn't require the @Strategy.
This was a comment from Abe when XMLValueHandler was first introduced.
I don't know how to do this part yet. Need some help on this one.
I noticed that XMLClassMetaData does a lot of annotation-parsing. This
> will mean that we can't allow configuration of this data in an XML
> format (once we have one) (obviously, unless we change things). Is it
> desirable to support XML-based configuration of domain model or not?
Currently the the XMLMapping support is enabled by annotations.
This could be a discussion topic at the face-to-face meeting.
>From a naming standpoint, I'd prefer if XMLMetaData was renamed to
> XMLFieldMetaData and XMLMapping was renamed to XMLMetaData. I prefer
> this because it is more in line with how we do other metadata naming.
> Again, this can be done trivially by an IDE; I can help out if you
> don't use one.
yes. will do the renaming as recommended.
-Patrick
>
> On 7/18/07, wisneskid@apache.org <wisneskid@apache.org> wrote:
> > Author: wisneskid
> > Date: Wed Jul 18 17:45:51 2007
> > New Revision: 557437
> >
> > URL: http://svn.apache.org/viewvc?view=rev&rev=557437
> > Log:
> > OPENJPA-240 XMLMapping Query support for persistent field maps to XML
> column.
> >
> > Added:
> >
> openjpa/trunk/openjpa-jdbc-5/src/main/java/org/apache/openjpa/jdbc/meta/XMLMappingRepository.java
> > openjpa/trunk/openjpa-jdbc-5/src/main/java/org/apache/openjpa/meta/
> >
> openjpa/trunk/openjpa-jdbc-5/src/main/java/org/apache/openjpa/meta/XMLClassMetaData.java
> >
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLMapping.java
> >
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLMetaData.java
> > Modified:
> >
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
> >
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ConstPath.java
> >
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EndsWithExpression.java
> >
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/FilterValue.java
> >
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/FilterValueImpl.java
> >
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
> >
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StartsWithExpression.java
> >
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
> >
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
> >
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java
> >
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java
> >
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java
> >
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CandidatePath.java
> >
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Path.java
> >
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java
> >
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java
> >
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
> >
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java
> >
> > Added:
> openjpa/trunk/openjpa-jdbc-5/src/main/java/org/apache/openjpa/jdbc/meta/XMLMappingRepository.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc-5/src/main/java/org/apache/openjpa/jdbc/meta/XMLMappingRepository.java?view=auto&rev=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc-5/src/main/java/org/apache/openjpa/jdbc/meta/XMLMappingRepository.java
> (added)
> > +++
> openjpa/trunk/openjpa-jdbc-5/src/main/java/org/apache/openjpa/jdbc/meta/XMLMappingRepository.java
> Wed Jul 18 17:45:51 2007
> > @@ -0,0 +1,82 @@
> > +/*
> > + * 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.XMLMapping;
> > +
> > +/**
> > + * 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 XMLMapping[] 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 XMLMapping getXMLClassMetaData(Class cls) {
> > + synchronized(_xmlmetas) {
> > + if (_xmlmetas.isEmpty())
> > + return null;
> > + else
> > + return (XMLClassMetaData) _xmlmetas.get(cls);
> > + }
> > + }
> > +
> > + public XMLMapping getXMLMetaData(FieldMetaData fmd) {
> > + XMLMapping 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, XMLMapping
> meta) {
> > + _xmlmetas.put(cls, meta);
> > + }
> > +
> > + protected XMLClassMetaData newXMLClassMetaData(FieldMetaData fmd,
> String name) {
> > + return new XMLClassMetaData(fmd.getDeclaredType(), name, this);
> > + }
> > +
> > + protected XMLMapping[] newXMLClassMetaDataArray(int length) {
> > + return new XMLClassMetaData[length];
> > + }
> > +}
> >
> > Added:
> openjpa/trunk/openjpa-jdbc-5/src/main/java/org/apache/openjpa/meta/XMLClassMetaData.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc-5/src/main/java/org/apache/openjpa/meta/XMLClassMetaData.java?view=auto&rev=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc-5/src/main/java/org/apache/openjpa/meta/XMLClassMetaData.java
> (added)
> > +++
> openjpa/trunk/openjpa-jdbc-5/src/main/java/org/apache/openjpa/meta/XMLClassMetaData.java
> Wed Jul 18 17:45:51 2007
> > @@ -0,0 +1,227 @@
> > +/*
> > + * 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.XMLMapping;
> > +import org.apache.openjpa.meta.XMLMetaData;
> > +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 XMLMapping
> > +{
> > + 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 XMLMapping getFieldMapping(String name) {
> > + return (XMLMapping) _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;
> > + 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;
> > + XMLMapping 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 XMLMetaData();
> > + field.setXmltype(ELEMENT);
> > + field.setXmlname(xmlname);
> > + field.setXmlnamespace(el.getAnnotation(
> XmlElement.class)
> > + .namespace());
> > + }
> > + }
> > + else if (el.getAnnotation(XmlAttribute.class) != null) {
> > + field = new XMLMetaData();
> > + field.setXmltype(XMLMetaData.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);
> > + }
> > + }
> > +}
> >
> > Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
> (original)
> > +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/AbstractVal.java
> Wed Jul 18 17:45:51 2007
> > @@ -41,6 +41,10 @@
> > return false;
> > }
> >
> > + public boolean isXPath() {
> > + return false;
> > + }
> > +
> > public Object toDataStoreValue(Select sel, ExpContext ctx, ExpState
> state,
> > Object val) {
> > return val;
> >
> > Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ConstPath.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ConstPath.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ConstPath.java
> (original)
> > +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ConstPath.java
> Wed Jul 18 17:45:51 2007
> > @@ -31,6 +31,7 @@
> > import org.apache.openjpa.kernel.exps.ExpressionVisitor;
> > import org.apache.openjpa.meta.ClassMetaData;
> > import org.apache.openjpa.meta.FieldMetaData;
> > +import org.apache.openjpa.meta.XMLMapping;
> > import org.apache.openjpa.util.InternalException;
> >
> > /**
> > @@ -203,5 +204,15 @@
> > public ConstPathExpState(ExpState constantState) {
> > this.constantState = constantState;
> > }
> > + }
> > +
> > + public void get(FieldMetaData fmd, XMLMapping meta) {
> > + }
> > +
> > + public void get(XMLMapping meta, String name) {
> > + }
> > +
> > + public XMLMapping getXmlMapping() {
> > + return null;
> > }
> > }
> >
> > Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EndsWithExpression.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EndsWithExpression.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EndsWithExpression.java
> (original)
> > +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/EndsWithExpression.java
> Wed Jul 18 17:45:51 2007
> > @@ -28,6 +28,7 @@
> > import org.apache.openjpa.jdbc.sql.SQLBuffer;
> > import org.apache.openjpa.jdbc.sql.Select;
> > import org.apache.openjpa.kernel.exps.ExpressionVisitor;
> > +import org.apache.openjpa.meta.XMLMapping;
> >
> > /**
> > * Test if one string ends with another.
> > @@ -192,6 +193,14 @@
> > }
> >
> > public FieldMapping getFieldMapping() {
> > + return null;
> > + }
> > +
> > + public PCPath getXPath() {
> > + return null;
> > + }
> > +
> > + public XMLMapping getXmlMapping() {
> > return null;
> > }
> > }
> >
> > Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/FilterValue.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/FilterValue.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/FilterValue.java
> (original)
> > +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/FilterValue.java
> Wed Jul 18 17:45:51 2007
> > @@ -23,6 +23,7 @@
> > import org.apache.openjpa.jdbc.schema.Column;
> > import org.apache.openjpa.jdbc.schema.Table;
> > import org.apache.openjpa.jdbc.sql.SQLBuffer;
> > +import org.apache.openjpa.meta.XMLMapping;
> >
> > /**
> > * The simplified public view of any non-operator in a query filter,
> > @@ -103,4 +104,16 @@
> > * return null.
> > */
> > public FieldMapping getFieldMapping();
> > +
> > + /**
> > + * If this is an XPath, return it,
> > + * else return null;
> > + */
> > + public PCPath getXPath();
> > +
> > + /**
> > + * If this is an XPath, return XML mapping metadata,
> > + * else return null;
> > + */
> > + public XMLMapping getXmlMapping();
> > }
> >
> > Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/FilterValueImpl.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/FilterValueImpl.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/FilterValueImpl.java
> (original)
> > +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/FilterValueImpl.java
> Wed Jul 18 17:45:51 2007
> > @@ -24,6 +24,7 @@
> > import org.apache.openjpa.jdbc.schema.Table;
> > import org.apache.openjpa.jdbc.sql.SQLBuffer;
> > import org.apache.openjpa.jdbc.sql.Select;
> > +import org.apache.openjpa.meta.XMLMapping;
> >
> > /**
> > * Implementation of {@link FilterValue} that wraps a {@link Val}.
> > @@ -97,5 +98,16 @@
> >
> > public FieldMapping getFieldMapping() {
> > return (isPath()) ? ((PCPath) _val).getFieldMapping(_state) :
> null;
> > + }
> > +
> > + public PCPath getXPath() {
> > + if (isPath() && ((PCPath) _val).isXPath())
> > + return (PCPath) _val;
> > + else
> > + return null;
> > + }
> > +
> > + public XMLMapping getXmlMapping() {
> > + return (getXPath() == null) ? null :
> getXPath().getXmlMapping();
> > }
> > }
> >
> > Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
> (original)
> > +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/PCPath.java
> Wed Jul 18 17:45:51 2007
> > @@ -40,6 +40,7 @@
> > import org.apache.openjpa.meta.ClassMetaData;
> > import org.apache.openjpa.meta.FieldMetaData;
> > import org.apache.openjpa.meta.JavaTypes;
> > +import org.apache.openjpa.meta.XMLMapping;
> > import org.apache.openjpa.util.UserException;
> >
> > /**
> > @@ -55,6 +56,7 @@
> > private static final int BOUND_VAR = 1;
> > private static final int UNBOUND_VAR = 2;
> > private static final int UNACCESSED_VAR = 3;
> > + private static final int XPATH = 4;
> >
> > private static final Localizer _loc = Localizer.forPackage(
> PCPath.class);
> >
> > @@ -66,6 +68,7 @@
> > private String _varName = null;
> > private Class _cast = null;
> > private boolean _cid = false;
> > + private FieldMetaData _xmlfield = null;
> >
> > /**
> > * Return a path starting with the 'this' ptr.
> > @@ -168,7 +171,40 @@
> > public boolean isKey() {
> > return _key;
> > }
> > -
> > +
> > + public boolean isXPath() {
> > + return _type == XPATH;
> > + }
> > +
> > + public String getXPath() {
> > + StringBuffer xpath = new StringBuffer();
> > + Action action;
> > + Iterator itr = _actions.iterator();
> > +
> > + // Skip variable actions since they are not part of the xpath
> > + // until we reach the first xpath action.
> > + // The first xpath action maps to the root of an xml document.
> > + do
> > + action = (Action) itr.next();
> > + while (action.op != Action.GET_XPATH);
> > +
> > + // Skip XmlRootElement:
> > + // We can't rely on the accuracy of the name of the root
> element,
> > + // because it could be set to some default by JAXB XML Binding.
> > + // The caller(DBDictionary) should start with "/*" or "/*/",
> > + // we build the remaining xpath that follows the root element.
> > + while (itr.hasNext()) {
> > + action = (Action) itr.next();
> > + if (((XMLMapping) action.data).getXmlname() != null)
> > + xpath.append(((XMLMapping) action.data).getXmlname());
> > + else
> > + xpath.append("*");
> > + if (itr.hasNext())
> > + xpath.append("/");
> > + }
> > + return xpath.toString();
> > + }
> > +
> > public String getPath() {
> > if (_actions == null)
> > return (_varName == null) ? "" : _varName + ".";
> > @@ -274,6 +310,36 @@
> > _cast = null;
> > _key = false;
> > }
> > +
> > + public void get(FieldMetaData fmd, XMLMapping meta) {
> > + if (_actions == null)
> > + _actions = new LinkedList();
> > + Action action = new Action();
> > + action.op = Action.GET_XPATH;
> > + action.data = meta;
> > + _actions.add(action);
> > + _cast = null;
> > + _key = false;;
> > + _type = XPATH;
> > + _xmlfield = fmd;
> > + }
> > +
> > + public void get(XMLMapping meta, String name) {
> > + Action action = new Action();
> > + action.op = Action.GET_XPATH;
> > + action.data = meta.getFieldMapping(name);
> > + _actions.add(action);
> > + _cast = null;
> > + _key = false;;
> > + _type = XPATH;
> > + }
> > +
> > + public XMLMapping getXmlMapping() {
> > + Action act = (Action) _actions.getLast();
> > + if (act != null)
> > + return (XMLMapping) act.data;
> > + return null;
> > + }
> >
> > public synchronized void getKey() {
> > if (_cid)
> > @@ -288,7 +354,8 @@
> >
> > public FieldMetaData last() {
> > Action act = lastFieldAction();
> > - return (act == null) ? null : (FieldMetaData) act.data;
> > + return (act == null) ? null : isXPath() ? _xmlfield :
> > + (FieldMetaData) act.data;
> > }
> >
> > /**
> > @@ -298,6 +365,9 @@
> > if (_actions == null)
> > return null;
> >
> > + if (isXPath())
> > + return (Action) _actions.getLast();
> > +
> > ListIterator itr = _actions.listIterator(_actions.size());
> > Action prev;
> > while (itr.hasPrevious()) {
> > @@ -313,6 +383,9 @@
> > if (_cast != null)
> > return _cast;
> > Action act = lastFieldAction();
> > + if (act != null && act.op == Action.GET_XPATH)
> > + return ((XMLMapping) act.data).getType();
> > +
> > FieldMetaData fld = (act == null) ? null : (FieldMetaData)
> act.data;
> > boolean key = act != null && act.op == Action.GET_KEY;
> > if (fld != null) {
> > @@ -373,7 +446,8 @@
> > rel.getTable());
> > } else {
> > // move past the previous field, if any
> > - field = (FieldMapping) action.data;
> > + field = (action.op == Action.GET_XPATH) ?
> (FieldMapping) _xmlfield :
> > + (FieldMapping) action.data;
> > if (pstate.field != null) {
> > // if this is the second-to-last field and the last
> is
> > // the related field this field joins to, no need
> to
> > @@ -416,6 +490,9 @@
> > from = from.getJoinablePCSuperclassMapping())
> > pstate.joins = from.joinSuperclass(pstate.joins,
> false);
> > }
> > + // nothing more to do from here on as we encountered an
> xpath action
> > + if (action.op == Action.GET_XPATH)
> > + break;
> > }
> > }
> > if (_varName != null)
> > @@ -534,6 +611,8 @@
> > PathExpState pstate = (PathExpState) state;
> > FieldMapping field = (pstate.cmpfield != null) ?
> pstate.cmpfield
> > : pstate.field;
> > + if (isXPath())
> > + return val;
> > if (field != null) {
> > if (_key)
> > return field.toKeyDataStoreValue(val, ctx.store);
> > @@ -639,6 +718,9 @@
> > // (e.g., during a bulk update)
> > if (sel == null)
> > sql.append(col.getName());
> > + else if (_type == XPATH)
> > + // if this is an xpath, append xpath string
> > + sql.append(getXPath());
> > else
> > sql.append(sel.getColumnAlias(col, state.joins));
> > }
> > @@ -716,6 +798,7 @@
> > public static final int SUBQUERY = 4;
> > public static final int UNBOUND_VAR = 5;
> > public static final int CAST = 6;
> > + public static final int GET_XPATH = 7;
> >
> > public int op = -1;
> > public Object data = null;
> >
> > Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StartsWithExpression.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StartsWithExpression.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StartsWithExpression.java
> (original)
> > +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/StartsWithExpression.java
> Wed Jul 18 17:45:51 2007
> > @@ -28,6 +28,7 @@
> > import org.apache.openjpa.jdbc.sql.SQLBuffer;
> > import org.apache.openjpa.jdbc.sql.Select;
> > import org.apache.openjpa.kernel.exps.ExpressionVisitor;
> > +import org.apache.openjpa.meta.XMLMapping;
> > import serp.util.Numbers;
> >
> > /**
> > @@ -184,6 +185,15 @@
> > public FieldMapping getFieldMapping() {
> > return null;
> > }
> > +
> > + public PCPath getXPath() {
> > + return null;
> > + }
> > +
> > + public XMLMapping getXmlMapping() {
> > + return null;
> > + }
> > +
> > }
> >
> > /**
> > @@ -258,6 +268,14 @@
> > }
> >
> > public FieldMapping getFieldMapping() {
> > + return null;
> > + }
> > +
> > + public PCPath getXPath() {
> > + return null;
> > + }
> > +
> > + public XMLMapping getXmlMapping() {
> > return null;
> > }
> > }
> >
> > Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
> (original)
> > +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
> Wed Jul 18 17:45:51 2007
> > @@ -22,13 +22,17 @@
> > import java.sql.Connection;
> > import java.sql.DatabaseMetaData;
> > import java.sql.SQLException;
> > +import java.sql.Types;
> > import java.util.Arrays;
> > import java.util.StringTokenizer;
> > import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
> > import org.apache.openjpa.jdbc.schema.Sequence;
> > import org.apache.openjpa.lib.util.Localizer;
> > +import org.apache.openjpa.meta.JavaTypes;
> > import org.apache.openjpa.util.OpenJPAException;
> > import org.apache.openjpa.util.UnsupportedException;
> > +import org.apache.openjpa.kernel.Filters;
> > +import org.apache.openjpa.jdbc.kernel.exps.FilterValue;
> >
> > /**
> > * Dictionary for IBM DB2 database.
> > @@ -491,5 +495,121 @@
> >
> > public int getDb2ServerType() {
> > return db2ServerType;
> > + }
> > +
> > + protected void appendLength(SQLBuffer buf, int type) {
> > + if (type == Types.VARCHAR)
> > + buf.append("(").append(Integer.toString
> (characterColumnSize)).
> > + append(")");
> > + }
> > +
> > + /**
> > + * If this dictionary supports XML type,
> > + * use this method to append xml predicate.
> > + *
> > + * @param buf the SQL buffer to write the comparison
> > + * @param op the comparison operation to perform
> > + * @param lhs the left hand side of the comparison
> > + * @param rhs the right hand side of the comparison
> > + * @param lhsxml indicates whether the left operand maps to xml
> > + * @param rhsxml indicates whether the right operand maps to xml
> > + */
> > + public void appendXmlComparison(SQLBuffer buf, String op,
> FilterValue lhs,
> > + FilterValue rhs, boolean lhsxml, boolean rhsxml) {
> > + super.appendXmlComparison(buf, op, lhs, rhs, lhsxml, rhsxml);
> > + if (lhsxml && rhsxml)
> > + appendXmlComparison2(buf, op, lhs, rhs);
> > + else if (lhsxml)
> > + appendXmlComparison1(buf, op, lhs, rhs);
> > + else
> > + appendXmlComparison1(buf, op, rhs, lhs);
> > + }
> > +
> > + /**
> > + * Append an xml comparison predicate.
> > + *
> > + * @param buf the SQL buffer to write the comparison
> > + * @param op the comparison operation to perform
> > + * @param lhs the left hand side of the comparison (maps to xml
> column)
> > + * @param rhs the right hand side of the comparison
> > + */
> > + private void appendXmlComparison1(SQLBuffer buf, String op,
> > + FilterValue lhs, FilterValue rhs) {
> > + boolean castrhs = false;
> > + Class rc = Filters.wrap(rhs.getType());
> > + int type = 0;
> > + if (rhs.isConstant()) {
> > + type = getJDBCType(JavaTypes.getTypeCode(rc), false);
> > + castrhs = true;
> > + }
> > +
> > + appendXmlExists(buf, lhs);
> > +
> > + buf.append(" ").append(op).append(" ");
> > +
> > + buf.append("$");
> > + if (castrhs)
> > + buf.append("Parm");
> > + else
> > + rhs.appendTo(buf);
> > +
> > + buf.append("]' PASSING ");
> > + appendXmlVar(buf, lhs);
> > + buf.append(", ");
> > +
> > + if (castrhs)
> > + appendCast(buf, rhs, type);
> > + else
> > + rhs.appendTo(buf);
> > +
> > + buf.append(" AS \"");
> > + if (castrhs)
> > + buf.append("Parm");
> > + else
> > + rhs.appendTo(buf);
> > + buf.append("\")");
> > + }
> > +
> > + /**
> > + * Append an xml comparison predicate. (both operands map to xml
> column)
> > + *
> > + * @param buf the SQL buffer to write the comparison
> > + * @param op the comparison operation to perform
> > + * @param lhs the left hand side of the comparison (maps to xml
> column)
> > + * @param rhs the right hand side of the comparison (maps to xml
> column)
> > + */
> > + private void appendXmlComparison2(SQLBuffer buf, String op,
> > + FilterValue lhs, FilterValue rhs) {
> > + appendXmlExists(buf, lhs);
> > +
> > + buf.append(" ").append(op).append(" ");
> > +
> > + buf.append("$").append(rhs.getColumnAlias(
> > + rhs.getFieldMapping().getColumns()[0])).
> > + append("/*/");
> > + rhs.appendTo(buf);
> > +
> > + buf.append("]' PASSING ");
> > + appendXmlVar(buf, lhs);
> > + buf.append(", ");
> > + appendXmlVar(buf, rhs);
> > + buf.append(")");
> > + }
> > +
> > + private void appendXmlVar(SQLBuffer buf, FilterValue val) {
> > + buf.append(val.getColumnAlias(
> > + val.getFieldMapping().getColumns()[0])).
> > + append(" AS ").
> > + append("\"").append(val.getColumnAlias(
> > + val.getFieldMapping().getColumns()[0])).
> > + append("\"");
> > + }
> > +
> > + private void appendXmlExists(SQLBuffer buf, FilterValue val) {
> > + buf.append("XMLEXISTS('");
> > + buf.append("$").append(val.getColumnAlias(
> > + val.getFieldMapping().getColumns()[0])).
> > + append("/*[");
> > + val.appendTo(buf);
> > }
> > }
> >
> > Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
> (original)
> > +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
> Wed Jul 18 17:45:51 2007
> > @@ -84,6 +84,7 @@
> > import org.apache.openjpa.jdbc.schema.Table;
> > import org.apache.openjpa.jdbc.schema.Unique;
> > import org.apache.openjpa.kernel.Filters;
> > +import org.apache.openjpa.kernel.exps.Path;
> > import org.apache.openjpa.lib.conf.Configurable;
> > import org.apache.openjpa.lib.conf.Configuration;
> > import org.apache.openjpa.lib.jdbc.ConnectionDecorator;
> > @@ -2456,6 +2457,12 @@
> > */
> > public void comparison(SQLBuffer buf, String op, FilterValue lhs,
> > FilterValue rhs) {
> > + boolean lhsxml = lhs.getXPath() != null;
> > + boolean rhsxml = rhs.getXPath() != null;
> > + if (lhsxml || rhsxml) {
> > + appendXmlComparison(buf, op, lhs, rhs, lhsxml, rhsxml);
> > + return;
> > + }
> > boolean castlhs = false;
> > boolean castrhs = false;
> > Class lc = Filters.wrap(lhs.getType());
> > @@ -2485,6 +2492,15 @@
> > }
> >
> > /**
> > + * If this dictionary supports XML type,
> > + * use this method to append xml predicate.
> > + */
> > + public void appendXmlComparison(SQLBuffer buf, String op,
> FilterValue lhs,
> > + FilterValue rhs, boolean lhsxml, boolean rhsxml) {
> > + assertSupport(supportsXMLColumn, "SupportsXMLColumn");
> > + }
> > +
> > + /**
> > * Append SQL for the given numeric value to the buffer, casting as
> needed.
> > */
> > protected void appendNumericCast(SQLBuffer buf, FilterValue val) {
> > @@ -2518,9 +2534,13 @@
> > val.appendTo(buf);
> > buf.append(mid);
> > buf.append(getTypeName(type));
> > + appendLength(buf, type);
> > buf.append(post);
> > }
> >
> > + protected void appendLength(SQLBuffer buf, int type) {
> > + }
> > +
> > ///////////
> > // DDL SQL
> > ///////////
> >
> > Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java
> (original)
> > +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/OracleDictionary.java
> Wed Jul 18 17:45:51 2007
> > @@ -1038,4 +1038,63 @@
> > return false;
> > }
> > }
> > +
> > + /**
> > + * If this dictionary supports XML type,
> > + * use this method to append xml predicate.
> > + *
> > + * @param buf the SQL buffer to write the comparison
> > + * @param op the comparison operation to perform
> > + * @param lhs the left hand side of the comparison
> > + * @param rhs the right hand side of the comparison
> > + */
> > + public void appendXmlComparison(SQLBuffer buf, String op,
> FilterValue lhs,
> > + FilterValue rhs, boolean lhsxml, boolean rhsxml) {
> > + super.appendXmlComparison(buf, op, lhs, rhs, lhsxml, rhsxml);
> > + if (lhsxml && rhsxml)
> > + appendXmlComparison2(buf, op, lhs, rhs);
> > + else if (lhsxml)
> > + appendXmlComparison1(buf, op, lhs, rhs);
> > + else
> > + appendXmlComparison1(buf, op, rhs, lhs);
> > + }
> > +
> > + /**
> > + * Append an xml comparison predicate
> > + *
> > + * @param buf the SQL buffer to write the comparison
> > + * @param op the comparison operation to perform
> > + * @param lhs the left hand side of the comparison (maps to xml
> column)
> > + * @param rhs the right hand side of the comparison
> > + */
> > + private void appendXmlComparison1(SQLBuffer buf, String op,
> > + FilterValue lhs, FilterValue rhs) {
> > + appendXmlExtractValue(buf, lhs);
> > + buf.append(" ").append(op).append(" ");
> > + rhs.appendTo(buf);
> > + }
> > +
> > + /**
> > + * Append an xml comparison predicate (both operands map to xml
> column)
> > + *
> > + * @param buf the SQL buffer to write the comparison
> > + * @param op the comparison operation to perform
> > + * @param lhs the left hand side of the comparison (maps to xml
> column)
> > + * @param rhs the right hand side of the comparison (maps to xml
> column)
> > + */
> > + private void appendXmlComparison2(SQLBuffer buf, String op,
> > + FilterValue lhs, FilterValue rhs) {
> > + appendXmlExtractValue(buf, lhs);
> > + buf.append(" ").append(op).append(" ");
> > + appendXmlExtractValue(buf, rhs);
> > + }
> > +
> > + private void appendXmlExtractValue(SQLBuffer buf, FilterValue val)
> {
> > + buf.append("extractValue(").
> > + append(val.getColumnAlias(
> > + val.getFieldMapping().getColumns()[0])).
> > + append(",'/*/");
> > + val.appendTo(buf);
> > + buf.append("')");
> > + }
> > }
> >
> > Modified:
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java
> (original)
> > +++
> openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java
> Wed Jul 18 17:45:51 2007
> > @@ -23,8 +23,11 @@
> > import java.sql.SQLException;
> > import java.sql.Types;
> >
> > +import org.apache.openjpa.jdbc.kernel.exps.FilterValue;
> > +import org.apache.openjpa.kernel.Filters;
> > import org.apache.openjpa.jdbc.schema.Column;
> > import org.apache.openjpa.lib.util.Localizer;
> > +import org.apache.openjpa.meta.JavaTypes;
> >
> > /**
> > * Dictionary for MS SQLServer.
> > @@ -133,5 +136,98 @@
> > cols[i].setType(Types.CLOB);
> > }
> > return cols;
> > + }
> > +
> > + protected void appendLength(SQLBuffer buf, int type) {
> > + if (type == Types.VARCHAR)
> > + buf.append("(").append(Integer.toString
> (characterColumnSize)).append(")");
> > + }
> > +
> > + /**
> > + * If this dictionary supports XML type,
> > + * use this method to append xml predicate.
> > + *
> > + * @param buf the SQL buffer to write the comparison
> > + * @param op the comparison operation to perform
> > + * @param lhs the left hand side of the comparison
> > + * @param rhs the right hand side of the comparison
> > + * @param lhsxml indicates whether the left operand maps to xml
> > + * @param rhsxml indicates whether the right operand maps to xml
> > + */
> > + public void appendXmlComparison(SQLBuffer buf, String op,
> FilterValue lhs,
> > + FilterValue rhs, boolean lhsxml, boolean rhsxml) {
> > + super.appendXmlComparison(buf, op, lhs, rhs, lhsxml, rhsxml);
> > + if (lhsxml && rhsxml)
> > + appendXmlComparison2(buf, op, lhs, rhs);
> > + else if (lhsxml)
> > + appendXmlComparison1(buf, op, lhs, rhs);
> > + else
> > + appendXmlComparison1(buf, op, rhs, lhs);
> > + }
> > + /**
> > + * Append an xml comparison predicate
> > + *
> > + * @param buf the SQL buffer to write the comparison
> > + * @param op the comparison operation to perform
> > + * @param lhs the left hand side of the comparison (maps to xml
> column)
> > + * @param rhs the right hand side of the comparison
> > + */
> > + private void appendXmlComparison1(SQLBuffer buf, String op,
> > + FilterValue lhs, FilterValue rhs) {
> > + boolean castrhs = rhs.isConstant();
> > + if (castrhs)
> > + appendXmlValue(buf, lhs);
> > + else
> > + appendXmlExist(buf, lhs);
> > + buf.append(" ").append(op).append(" ");
> > + if (castrhs)
> > + rhs.appendTo(buf);
> > + else {
> > + buf.append("sql:column(\"");
> > + rhs.appendTo(buf);
> > + buf.append("\")").
> > + append("]') = 1");
> > + }
> > + }
> > +
> > + private void appendXmlExist(SQLBuffer buf, FilterValue lhs) {
> > + buf.append(lhs.getColumnAlias(
> > + lhs.getFieldMapping().getColumns()[0])).
> > + append(".exist('").
> > + append("/*[");
> > + lhs.appendTo(buf);
> > + }
> > +
> > + /**
> > + * Append an xml comparison predicate (both operands map to xml
> column)
> > + *
> > + * @param buf the SQL buffer to write the comparison
> > + * @param op the comparison operation to perform
> > + * @param lhs the left hand side of the comparison (maps to xml
> column)
> > + * @param rhs the right hand side of the comparison (maps to xml
> column)
> > + */
> > + private void appendXmlComparison2(SQLBuffer buf, String op,
> > + FilterValue lhs, FilterValue rhs) {
> > + appendXmlValue(buf, lhs);
> > + buf.append(" ").append(op).append(" ");
> > + appendXmlValue(buf, rhs);
> > + }
> > +
> > + private void appendXmlValue(SQLBuffer buf, FilterValue val) {
> > + Class rc = Filters.wrap(val.getType());
> > + int type = getJDBCType(JavaTypes.getTypeCode(rc), false);
> > + boolean isXmlAttribute = (val.getXmlMapping() == null) ? false
> > + : val.getXmlMapping().isXmlAttribute();
> > + buf.append(val.getColumnAlias(
> > + val.getFieldMapping().getColumns()[0])).
> > + append(".value(").
> > + append("'(/*/");
> > + val.appendTo(buf);
> > + if (!isXmlAttribute)
> > + buf.append("/text()");
> > + buf.append(")[1]','").
> > + append(getTypeName(type));
> > + appendLength(buf, type);
> > + buf.append("')");
> > }
> > }
> >
> > Modified:
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java
> (original)
> > +++
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/AbstractExpressionBuilder.java
> Wed Jul 18 17:45:51 2007
> > @@ -30,6 +30,8 @@
> > import org.apache.openjpa.lib.util.Localizer.Message;
> > import org.apache.openjpa.meta.ClassMetaData;
> > import org.apache.openjpa.meta.FieldMetaData;
> > +import org.apache.openjpa.meta.JavaTypes;
> > +import org.apache.openjpa.meta.XMLMapping;
> > import org.apache.openjpa.util.InternalException;
> > import org.apache.openjpa.util.OpenJPAException;
> > import org.apache.openjpa.util.UnsupportedException;
> > @@ -243,6 +245,27 @@
> > protected Value traversePath(Path path, String field) {
> > return traversePath(path, field, false, false);
> > }
> > +
> > + protected Value traverseXPath(Path path, String field) {
> > + XMLMapping meta = path.getXmlMapping();
> > + if (meta.getFieldMapping(field) == null) {
> > + throw parseException(EX_USER, "no-field",
> > + new Object[]{ meta.getType(), field }, null);
> > + }
> > + else {
> > + // collection-valued xpath is not allowed
> > + int type = meta.getFieldMapping(field).getTypeCode();
> > + switch (type) {
> > + case JavaTypes.ARRAY:
> > + case JavaTypes.COLLECTION:
> > + case JavaTypes.MAP:
> > + throw new
> UserException(_loc.get("collection-valued-path",
> > + field));
> > + }
> > + }
> > + path.get(meta, field);
> > + return path;
> > + }
> >
> > /**
> > * Traverse the given field in the given path.
> > @@ -272,6 +295,14 @@
> > addAccessPath(meta);
> > path.setMetaData(meta);
> > }
> > + else {
> > + // xmlsupport xpath
> > + XMLMapping xmlmeta = fmd.getRepository
> ().getXMLMetaData(fmd);
> > + if (xmlmeta != null) {
> > + path.get(fmd, xmlmeta);
> > + return path;
> > + }
> > + }
> >
> > if (meta != null || !pcOnly)
> > path.get(fmd, allowNull);
> > @@ -309,11 +340,11 @@
> >
> > if (o1 && !o2) {
> > val1.setImplicitType(c2);
> > - if (val1.getMetaData() == null)
> > + if (val1.getMetaData() == null && !val1.isXPath())
> > val1.setMetaData(val2.getMetaData());
> > } else if (!o1 && o2) {
> > val2.setImplicitType(c1);
> > - if (val2.getMetaData() == null)
> > + if (val2.getMetaData() == null && !val1.isXPath())
> > val2.setMetaData(val1.getMetaData());
> > } else if (o1 && o2 && expected != null) {
> > // we never expect a pc type, so don't bother with metadata
> >
> > Modified:
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CandidatePath.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CandidatePath.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CandidatePath.java
> (original)
> > +++
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/CandidatePath.java
> Wed Jul 18 17:45:51 2007
> > @@ -30,6 +30,7 @@
> > import org.apache.openjpa.kernel.StoreContext;
> > import org.apache.openjpa.meta.ClassMetaData;
> > import org.apache.openjpa.meta.FieldMetaData;
> > +import org.apache.openjpa.meta.XMLMapping;
> >
> > /**
> > * A path represents a traversal into fields of a candidate object.
> > @@ -184,4 +185,14 @@
> > return ((Traversal) other).field.equals(field);
> > }
> > }
> > +
> > + public void get(FieldMetaData fmd, XMLMapping meta) {
> > + }
> > +
> > + public void get(XMLMapping meta, String name) {
> > + }
> > +
> > + public XMLMapping getXmlMapping() {
> > + return null;
> > + }
> > }
> >
> > Modified:
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Path.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Path.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Path.java
> (original)
> > +++
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Path.java
> Wed Jul 18 17:45:51 2007
> > @@ -19,6 +19,7 @@
> > package org.apache.openjpa.kernel.exps;
> >
> > import org.apache.openjpa.meta.FieldMetaData;
> > +import org.apache.openjpa.meta.XMLMapping;
> >
> > /**
> > * A path represents a traversal into fields of a candidate object.
> > @@ -42,4 +43,28 @@
> > * not contain a final field.
> > */
> > public FieldMetaData last();
> > +
> > + /**
> > + * Traverse into the given field that maps to xml column, and
> update
> > + * the current object to that field value.
> > + *
> > + * @param fmd field maps to xml column
> > + * @param meta associated xml mapping
> > + */
> > + public void get(FieldMetaData fmd, XMLMapping meta);
> > +
> > + /**
> > + * Traverse into the gevin xpath name of the current object, and
> update
> > + * the current object to that xpath field.
> > + *
> > + * @param meta
> > + * @param name
> > + */
> > + public void get(XMLMapping meta, String name);
> > +
> > + /**
> > + * Return the current XPath's xmlmapping metadata.
> > + * @return Return xmlmapping
> > + */
> > + public XMLMapping getXmlMapping();
> > }
> >
> > Modified:
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java
> (original)
> > +++
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Val.java
> Wed Jul 18 17:45:51 2007
> > @@ -109,6 +109,10 @@
> > public boolean isAggregate() {
> > return false;
> > }
> > +
> > + public boolean isXPath() {
> > + return false;
> > + }
> >
> > public void acceptVisit(ExpressionVisitor visitor) {
> > visitor.enter(this);
> >
> > Modified:
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java
> (original)
> > +++
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/exps/Value.java
> Wed Jul 18 17:45:51 2007
> > @@ -52,6 +52,11 @@
> > public boolean isAggregate();
> >
> > /**
> > + * Return true if this value is an XML Path.
> > + */
> > + public boolean isXPath();
> > +
> > + /**
> > * Return any associated persistent type.
> > */
> > public ClassMetaData getMetaData();
> >
> > Modified:
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
> (original)
> > +++
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/jpql/JPQLExpressionBuilder.java
> Wed Jul 18 17:45:51 2007
> > @@ -1088,7 +1088,7 @@
> > if (fmd == null)
> > return;
> >
> > - Class type = fmd.getType();
> > + Class type = path.isXPath() ? path.getType() : fmd.getType();
> > if (type == null)
> > return;
> >
> > @@ -1298,6 +1298,11 @@
> > // walk through the children and assemble the path
> > boolean allowNull = !inner;
> > for (int i = 1; i < node.children.length; i++) {
> > + if (path.isXPath()) {
> > + for (int j = i; j <node.children.length; j++)
> > + path = (Path) traverseXPath(path, node.children
> [j].text);
> > + return path;
> > + }
> > path = (Path) traversePath(path, node.children[i].text,
> pcOnly,
> > allowNull);
> >
> >
> > Modified:
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java?view=diff&rev=557437&r1=557436&r2=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java
> (original)
> > +++
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/MetaDataRepository.java
> Wed Jul 18 17:45:51 2007
> > @@ -1850,4 +1850,13 @@
> > && StringUtils.equals (name, qk.name);
> > }
> > }
> > +
> > + /**
> > + * Return XML metadata for a given field metadata
> > + * @param fmd
> > + * @return null
> > + */
> > + public XMLMapping getXMLMetaData(FieldMetaData fmd) {
> > + return null;
> > + }
> > }
> >
> > Added:
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLMapping.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLMapping.java?view=auto&rev=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLMapping.java
> (added)
> > +++
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLMapping.java
> Wed Jul 18 17:45:51 2007
> > @@ -0,0 +1,119 @@
> > +/*
> > + * 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.io.Serializable;
> > +
> > +/**
> > + * Describe metadata about an xml type.
> > + *
> > + * @author Catalina Wei
> > + * @since 1.0.0
> > + */
> > +public interface XMLMapping extends Serializable {
> > + /**
> > + * JAXB XML binding default name
> > + */
> > + public static final String defaultName = "##default";
> > + public static final int XMLTYPE = 0;
> > + public static final int ELEMENT = 1;
> > + public static final int ATTRIBUTE = 2;
> > +
> > + /**
> > + * Return true if mapping on an XmlRootElement.
> > + */
> > + public boolean isXmlRootElement();
> > +
> > + /**
> > + * Return true if mapping on an XmlElement.
> > + */
> > + public boolean isXmlElement();
> > +
> > + /**
> > + * Return true if mapping on an XmlAttribute.
> > + */
> > + public boolean isXmlAttribute();
> > +
> > + /**
> > + * Return XMLMapping for a given field.
> > + * @param name the field name.
> > + * @return XMLMapping.
> > + */
> > + public XMLMapping getFieldMapping(String name);
> > +
> > + /**
> > + * Set type.
> > + */
> > + public void setType(Class type);
> > +
> > + /**
> > + * Return type.
> > + */
> > + public Class getType();
> > +
> > + /**
> > + * Return type code.
> > + */
> > + public int getTypeCode();
> > +
> > + /**
> > + * Return the mapping name.
> > + */
> > + public String getName();
> > +
> > + /**
> > + * Return xml element tag name or xml attribute name.
> > + */
> > + public String getXmlname();
> > +
> > + /**
> > + * Return xml namespace.
> > + */
> > + public String getXmlnamespace();
> > +
> > + /**
> > + * Set field name.
> > + * @param name the field name.
> > + */
> > + public void setName(String name);
> > +
> > + /**
> > + * Set xml element or attribute name.
> > + * @param name the element name or attribute name
> > + */
> > + public void setXmlname(String name);
> > +
> > + /**
> > + * Set namespace.
> > + * @param namespace
> > + */
> > + public void setXmlnamespace(String namespace);
> > +
> > + /**
> > + * Set xmltype
> > + * @param type XMLTYPE, ELEMENT, or ATTRIBUTE
> > + */
> > + public void setXmltype(int type);
> > +
> > + /**
> > + * Return xmltype
> > + * @return xmltype
> > + */
> > + public int getXmltype();
> > +}
> >
> > Added:
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLMetaData.java
> > URL:
> http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLMetaData.java?view=auto&rev=557437
> >
> ==============================================================================
> > ---
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLMetaData.java
> (added)
> > +++
> openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/meta/XMLMetaData.java
> Wed Jul 18 17:45:51 2007
> > @@ -0,0 +1,111 @@
> > +/*
> > + * 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 org.apache.commons.lang.StringUtils;
> > +
> > +/**
> > + * Contains metadata about an xml element or attribute
> > + *
> > + * @author Catalina Wei
> > + * @since 1.0.0
> > + */
> > +public class XMLMetaData implements XMLMapping {
> > +
> > + private String _name;
> > + private String _xmlname = null;
> > + private String _xmlnamespace = null;
> > + private Class _decType = Object.class;
> > + private int _decCode = JavaTypes.OBJECT;
> > + private Class _type = Object.class;
> > + private int _code = JavaTypes.OBJECT;
> > + private int _xmltype;
> > +
> > + public XMLMetaData() {
> > + }
> > +
> > + public Class getType() {
> > + return (_type == null) ? _decType : _type;
> > + }
> > +
> > + public void setType(Class type) {
> > + _type = type;
> > + if (type != null)
> > + setTypeCode(JavaTypes.getTypeCode(type));
> > + }
> > +
> > + public int getTypeCode() {
> > + return (_type == null) ? _decCode : _code;
> > + }
> > +
> > + // set JavaTypes code
> > + public void setTypeCode(int code) {
> > + _code = code;
> > + }
> > +
> > + public void setName(String name) {
> > + _name = name;
> > + }
> > +
> > + public String getName() {
> > + return _name;
> > + }
> > +
> > + public void setXmlname(String name) {
> > + _xmlname = name;
> > + }
> > +
> > + public String getXmlname() {
> > + return _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 setXmltype(int type) {
> > + _xmltype = type;
> > + }
> > +
> > + public int getXmltype() {
> > + return _xmltype;
> > + }
> > +
> > + public boolean isXmlRootElement() {
> > + return false;
> > + }
> > +
> > + public boolean isXmlElement() {
> > + return _xmltype == ELEMENT;
> > + }
> > +
> > + public boolean isXmlAttribute() {
> > + return _xmltype == ATTRIBUTE;
> > + }
> > +
> > + public XMLMapping getFieldMapping(String name) {
> > + return null;
> > + }
> > +}
> >
> >
> >
>
>
> --
> Patrick Linskey
> 202 669 5907
>
|