openjpa-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Patrick Linskey" <plins...@gmail.com>
Subject Re: svn commit: r557437 - in /openjpa/trunk: openjpa-jdbc-5/src/main/java/org/apache/openjpa/jdbc/meta/ openjpa-jdbc-5/src/main/java/org/apache/openjpa/meta/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ openjpa-jdbc/src/main/java/o
Date Thu, 19 Jul 2007 23:49:09 GMT
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?

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

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


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?


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

-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

Mime
View raw message