You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by Patrick Linskey <pl...@gmail.com> on 2007/07/20 00:06:28 UTC

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

Hi,

Is this Catalina's code also? I think that it'd be helpful if we call
out in the commit message when we're committing code from someone
else.

-Patrick

On 7/18/07, wisneskid@apache.org <wi...@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

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

Posted by Craig L Russell <Cr...@Sun.COM>.
For an example, please see:
>
> Author: clr
> Date: Tue Jul 17 16:56:45 2007
> New Revision: 557089
>
> URL: http://svn.apache.org/viewvc?view=rev&rev=557089
> Log:
> OPENJPA-235 break-nullable-patch contributed by Markus Fuchs
>
On Jul 19, 2007, at 3:06 PM, Patrick Linskey wrote:

> Hi,
>
> Is this Catalina's code also? I think that it'd be helpful if we call
> out in the commit message when we're committing code from someone
> else.
>
> -Patrick
>
> On 7/18/07, wisneskid@apache.org <wi...@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.
>>
Note that the patch was uploaded by Catalina to the JIRA and the  
author tag (which as a project we discourage) identifies Catalina as  
well. So there is no issue of code provenance. It's really a matter  
of what we as a group want to see as a process.

Craig


Craig Russell
Architect, Sun Java Enterprise System http://java.sun.com/products/jdo
408 276-5638 mailto:Craig.Russell@sun.com
P.S. A good JDO? O, Gasp!