mirror of https://github.com/apache/openjpa.git
OPENJPA-240 XMLMapping Query support for persistent field maps to XML column.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@557437 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
25fbdab82b
commit
a275b7aefb
|
@ -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];
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,6 +41,10 @@ abstract class AbstractVal
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isXPath() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public Object toDataStoreValue(Select sel, ExpContext ctx, ExpState state,
|
public Object toDataStoreValue(Select sel, ExpContext ctx, ExpState state,
|
||||||
Object val) {
|
Object val) {
|
||||||
return val;
|
return val;
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.apache.openjpa.kernel.OpenJPAStateManager;
|
||||||
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
|
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
|
||||||
import org.apache.openjpa.meta.ClassMetaData;
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
import org.apache.openjpa.meta.FieldMetaData;
|
import org.apache.openjpa.meta.FieldMetaData;
|
||||||
|
import org.apache.openjpa.meta.XMLMapping;
|
||||||
import org.apache.openjpa.util.InternalException;
|
import org.apache.openjpa.util.InternalException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -204,4 +205,14 @@ class ConstPath
|
||||||
this.constantState = constantState;
|
this.constantState = constantState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void get(FieldMetaData fmd, XMLMapping meta) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void get(XMLMapping meta, String name) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMLMapping getXmlMapping() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.apache.openjpa.jdbc.sql.DBDictionary;
|
||||||
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
||||||
import org.apache.openjpa.jdbc.sql.Select;
|
import org.apache.openjpa.jdbc.sql.Select;
|
||||||
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
|
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
|
||||||
|
import org.apache.openjpa.meta.XMLMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if one string ends with another.
|
* Test if one string ends with another.
|
||||||
|
@ -194,5 +195,13 @@ class EndsWithExpression
|
||||||
public FieldMapping getFieldMapping() {
|
public FieldMapping getFieldMapping() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PCPath getXPath() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMLMapping getXmlMapping() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.apache.openjpa.jdbc.meta.FieldMapping;
|
||||||
import org.apache.openjpa.jdbc.schema.Column;
|
import org.apache.openjpa.jdbc.schema.Column;
|
||||||
import org.apache.openjpa.jdbc.schema.Table;
|
import org.apache.openjpa.jdbc.schema.Table;
|
||||||
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
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,
|
* The simplified public view of any non-operator in a query filter,
|
||||||
|
@ -103,4 +104,16 @@ public interface FilterValue {
|
||||||
* return null.
|
* return null.
|
||||||
*/
|
*/
|
||||||
public FieldMapping getFieldMapping();
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.openjpa.jdbc.schema.Column;
|
||||||
import org.apache.openjpa.jdbc.schema.Table;
|
import org.apache.openjpa.jdbc.schema.Table;
|
||||||
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
||||||
import org.apache.openjpa.jdbc.sql.Select;
|
import org.apache.openjpa.jdbc.sql.Select;
|
||||||
|
import org.apache.openjpa.meta.XMLMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link FilterValue} that wraps a {@link Val}.
|
* Implementation of {@link FilterValue} that wraps a {@link Val}.
|
||||||
|
@ -98,4 +99,15 @@ class FilterValueImpl
|
||||||
public FieldMapping getFieldMapping() {
|
public FieldMapping getFieldMapping() {
|
||||||
return (isPath()) ? ((PCPath) _val).getFieldMapping(_state) : null;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.apache.openjpa.lib.util.Localizer;
|
||||||
import org.apache.openjpa.meta.ClassMetaData;
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
import org.apache.openjpa.meta.FieldMetaData;
|
import org.apache.openjpa.meta.FieldMetaData;
|
||||||
import org.apache.openjpa.meta.JavaTypes;
|
import org.apache.openjpa.meta.JavaTypes;
|
||||||
|
import org.apache.openjpa.meta.XMLMapping;
|
||||||
import org.apache.openjpa.util.UserException;
|
import org.apache.openjpa.util.UserException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,6 +56,7 @@ class PCPath
|
||||||
private static final int BOUND_VAR = 1;
|
private static final int BOUND_VAR = 1;
|
||||||
private static final int UNBOUND_VAR = 2;
|
private static final int UNBOUND_VAR = 2;
|
||||||
private static final int UNACCESSED_VAR = 3;
|
private static final int UNACCESSED_VAR = 3;
|
||||||
|
private static final int XPATH = 4;
|
||||||
|
|
||||||
private static final Localizer _loc = Localizer.forPackage(PCPath.class);
|
private static final Localizer _loc = Localizer.forPackage(PCPath.class);
|
||||||
|
|
||||||
|
@ -66,6 +68,7 @@ class PCPath
|
||||||
private String _varName = null;
|
private String _varName = null;
|
||||||
private Class _cast = null;
|
private Class _cast = null;
|
||||||
private boolean _cid = false;
|
private boolean _cid = false;
|
||||||
|
private FieldMetaData _xmlfield = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a path starting with the 'this' ptr.
|
* Return a path starting with the 'this' ptr.
|
||||||
|
@ -168,7 +171,40 @@ class PCPath
|
||||||
public boolean isKey() {
|
public boolean isKey() {
|
||||||
return _key;
|
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() {
|
public String getPath() {
|
||||||
if (_actions == null)
|
if (_actions == null)
|
||||||
return (_varName == null) ? "" : _varName + ".";
|
return (_varName == null) ? "" : _varName + ".";
|
||||||
|
@ -274,6 +310,36 @@ class PCPath
|
||||||
_cast = null;
|
_cast = null;
|
||||||
_key = false;
|
_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() {
|
public synchronized void getKey() {
|
||||||
if (_cid)
|
if (_cid)
|
||||||
|
@ -288,7 +354,8 @@ class PCPath
|
||||||
|
|
||||||
public FieldMetaData last() {
|
public FieldMetaData last() {
|
||||||
Action act = lastFieldAction();
|
Action act = lastFieldAction();
|
||||||
return (act == null) ? null : (FieldMetaData) act.data;
|
return (act == null) ? null : isXPath() ? _xmlfield :
|
||||||
|
(FieldMetaData) act.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -298,6 +365,9 @@ class PCPath
|
||||||
if (_actions == null)
|
if (_actions == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
if (isXPath())
|
||||||
|
return (Action) _actions.getLast();
|
||||||
|
|
||||||
ListIterator itr = _actions.listIterator(_actions.size());
|
ListIterator itr = _actions.listIterator(_actions.size());
|
||||||
Action prev;
|
Action prev;
|
||||||
while (itr.hasPrevious()) {
|
while (itr.hasPrevious()) {
|
||||||
|
@ -313,6 +383,9 @@ class PCPath
|
||||||
if (_cast != null)
|
if (_cast != null)
|
||||||
return _cast;
|
return _cast;
|
||||||
Action act = lastFieldAction();
|
Action act = lastFieldAction();
|
||||||
|
if (act != null && act.op == Action.GET_XPATH)
|
||||||
|
return ((XMLMapping) act.data).getType();
|
||||||
|
|
||||||
FieldMetaData fld = (act == null) ? null : (FieldMetaData) act.data;
|
FieldMetaData fld = (act == null) ? null : (FieldMetaData) act.data;
|
||||||
boolean key = act != null && act.op == Action.GET_KEY;
|
boolean key = act != null && act.op == Action.GET_KEY;
|
||||||
if (fld != null) {
|
if (fld != null) {
|
||||||
|
@ -373,7 +446,8 @@ class PCPath
|
||||||
rel.getTable());
|
rel.getTable());
|
||||||
} else {
|
} else {
|
||||||
// move past the previous field, if any
|
// 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 (pstate.field != null) {
|
||||||
// if this is the second-to-last field and the last is
|
// if this is the second-to-last field and the last is
|
||||||
// the related field this field joins to, no need to
|
// the related field this field joins to, no need to
|
||||||
|
@ -416,6 +490,9 @@ class PCPath
|
||||||
from = from.getJoinablePCSuperclassMapping())
|
from = from.getJoinablePCSuperclassMapping())
|
||||||
pstate.joins = from.joinSuperclass(pstate.joins, false);
|
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)
|
if (_varName != null)
|
||||||
|
@ -534,6 +611,8 @@ class PCPath
|
||||||
PathExpState pstate = (PathExpState) state;
|
PathExpState pstate = (PathExpState) state;
|
||||||
FieldMapping field = (pstate.cmpfield != null) ? pstate.cmpfield
|
FieldMapping field = (pstate.cmpfield != null) ? pstate.cmpfield
|
||||||
: pstate.field;
|
: pstate.field;
|
||||||
|
if (isXPath())
|
||||||
|
return val;
|
||||||
if (field != null) {
|
if (field != null) {
|
||||||
if (_key)
|
if (_key)
|
||||||
return field.toKeyDataStoreValue(val, ctx.store);
|
return field.toKeyDataStoreValue(val, ctx.store);
|
||||||
|
@ -639,6 +718,9 @@ class PCPath
|
||||||
// (e.g., during a bulk update)
|
// (e.g., during a bulk update)
|
||||||
if (sel == null)
|
if (sel == null)
|
||||||
sql.append(col.getName());
|
sql.append(col.getName());
|
||||||
|
else if (_type == XPATH)
|
||||||
|
// if this is an xpath, append xpath string
|
||||||
|
sql.append(getXPath());
|
||||||
else
|
else
|
||||||
sql.append(sel.getColumnAlias(col, state.joins));
|
sql.append(sel.getColumnAlias(col, state.joins));
|
||||||
}
|
}
|
||||||
|
@ -716,6 +798,7 @@ class PCPath
|
||||||
public static final int SUBQUERY = 4;
|
public static final int SUBQUERY = 4;
|
||||||
public static final int UNBOUND_VAR = 5;
|
public static final int UNBOUND_VAR = 5;
|
||||||
public static final int CAST = 6;
|
public static final int CAST = 6;
|
||||||
|
public static final int GET_XPATH = 7;
|
||||||
|
|
||||||
public int op = -1;
|
public int op = -1;
|
||||||
public Object data = null;
|
public Object data = null;
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.apache.openjpa.jdbc.sql.DBDictionary;
|
||||||
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
import org.apache.openjpa.jdbc.sql.SQLBuffer;
|
||||||
import org.apache.openjpa.jdbc.sql.Select;
|
import org.apache.openjpa.jdbc.sql.Select;
|
||||||
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
|
import org.apache.openjpa.kernel.exps.ExpressionVisitor;
|
||||||
|
import org.apache.openjpa.meta.XMLMapping;
|
||||||
import serp.util.Numbers;
|
import serp.util.Numbers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -184,6 +185,15 @@ class StartsWithExpression
|
||||||
public FieldMapping getFieldMapping() {
|
public FieldMapping getFieldMapping() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PCPath getXPath() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMLMapping getXmlMapping() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -260,5 +270,13 @@ class StartsWithExpression
|
||||||
public FieldMapping getFieldMapping() {
|
public FieldMapping getFieldMapping() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PCPath getXPath() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMLMapping getXmlMapping() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,17 @@ import java.lang.reflect.Method;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DatabaseMetaData;
|
import java.sql.DatabaseMetaData;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Types;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
|
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
|
||||||
import org.apache.openjpa.jdbc.schema.Sequence;
|
import org.apache.openjpa.jdbc.schema.Sequence;
|
||||||
import org.apache.openjpa.lib.util.Localizer;
|
import org.apache.openjpa.lib.util.Localizer;
|
||||||
|
import org.apache.openjpa.meta.JavaTypes;
|
||||||
import org.apache.openjpa.util.OpenJPAException;
|
import org.apache.openjpa.util.OpenJPAException;
|
||||||
import org.apache.openjpa.util.UnsupportedException;
|
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.
|
* Dictionary for IBM DB2 database.
|
||||||
|
@ -492,4 +496,120 @@ public class DB2Dictionary
|
||||||
public int getDb2ServerType() {
|
public int getDb2ServerType() {
|
||||||
return db2ServerType;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,6 +84,7 @@ import org.apache.openjpa.jdbc.schema.Sequence;
|
||||||
import org.apache.openjpa.jdbc.schema.Table;
|
import org.apache.openjpa.jdbc.schema.Table;
|
||||||
import org.apache.openjpa.jdbc.schema.Unique;
|
import org.apache.openjpa.jdbc.schema.Unique;
|
||||||
import org.apache.openjpa.kernel.Filters;
|
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.Configurable;
|
||||||
import org.apache.openjpa.lib.conf.Configuration;
|
import org.apache.openjpa.lib.conf.Configuration;
|
||||||
import org.apache.openjpa.lib.jdbc.ConnectionDecorator;
|
import org.apache.openjpa.lib.jdbc.ConnectionDecorator;
|
||||||
|
@ -2456,6 +2457,12 @@ public class DBDictionary
|
||||||
*/
|
*/
|
||||||
public void comparison(SQLBuffer buf, String op, FilterValue lhs,
|
public void comparison(SQLBuffer buf, String op, FilterValue lhs,
|
||||||
FilterValue rhs) {
|
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 castlhs = false;
|
||||||
boolean castrhs = false;
|
boolean castrhs = false;
|
||||||
Class lc = Filters.wrap(lhs.getType());
|
Class lc = Filters.wrap(lhs.getType());
|
||||||
|
@ -2484,6 +2491,15 @@ public class DBDictionary
|
||||||
rhs.appendTo(buf);
|
rhs.appendTo(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Append SQL for the given numeric value to the buffer, casting as needed.
|
||||||
*/
|
*/
|
||||||
|
@ -2518,9 +2534,13 @@ public class DBDictionary
|
||||||
val.appendTo(buf);
|
val.appendTo(buf);
|
||||||
buf.append(mid);
|
buf.append(mid);
|
||||||
buf.append(getTypeName(type));
|
buf.append(getTypeName(type));
|
||||||
|
appendLength(buf, type);
|
||||||
buf.append(post);
|
buf.append(post);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void appendLength(SQLBuffer buf, int type) {
|
||||||
|
}
|
||||||
|
|
||||||
///////////
|
///////////
|
||||||
// DDL SQL
|
// DDL SQL
|
||||||
///////////
|
///////////
|
||||||
|
|
|
@ -1038,4 +1038,63 @@ public class OracleDictionary
|
||||||
return false;
|
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("')");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,11 @@ import java.sql.DatabaseMetaData;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.sql.Types;
|
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.jdbc.schema.Column;
|
||||||
import org.apache.openjpa.lib.util.Localizer;
|
import org.apache.openjpa.lib.util.Localizer;
|
||||||
|
import org.apache.openjpa.meta.JavaTypes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dictionary for MS SQLServer.
|
* Dictionary for MS SQLServer.
|
||||||
|
@ -134,4 +137,97 @@ public class SQLServerDictionary
|
||||||
}
|
}
|
||||||
return cols;
|
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("')");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,6 +30,8 @@ import org.apache.openjpa.lib.util.Localizer;
|
||||||
import org.apache.openjpa.lib.util.Localizer.Message;
|
import org.apache.openjpa.lib.util.Localizer.Message;
|
||||||
import org.apache.openjpa.meta.ClassMetaData;
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
import org.apache.openjpa.meta.FieldMetaData;
|
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.InternalException;
|
||||||
import org.apache.openjpa.util.OpenJPAException;
|
import org.apache.openjpa.util.OpenJPAException;
|
||||||
import org.apache.openjpa.util.UnsupportedException;
|
import org.apache.openjpa.util.UnsupportedException;
|
||||||
|
@ -243,6 +245,27 @@ public abstract class AbstractExpressionBuilder {
|
||||||
protected Value traversePath(Path path, String field) {
|
protected Value traversePath(Path path, String field) {
|
||||||
return traversePath(path, field, false, false);
|
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.
|
* Traverse the given field in the given path.
|
||||||
|
@ -272,6 +295,14 @@ public abstract class AbstractExpressionBuilder {
|
||||||
addAccessPath(meta);
|
addAccessPath(meta);
|
||||||
path.setMetaData(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)
|
if (meta != null || !pcOnly)
|
||||||
path.get(fmd, allowNull);
|
path.get(fmd, allowNull);
|
||||||
|
@ -309,11 +340,11 @@ public abstract class AbstractExpressionBuilder {
|
||||||
|
|
||||||
if (o1 && !o2) {
|
if (o1 && !o2) {
|
||||||
val1.setImplicitType(c2);
|
val1.setImplicitType(c2);
|
||||||
if (val1.getMetaData() == null)
|
if (val1.getMetaData() == null && !val1.isXPath())
|
||||||
val1.setMetaData(val2.getMetaData());
|
val1.setMetaData(val2.getMetaData());
|
||||||
} else if (!o1 && o2) {
|
} else if (!o1 && o2) {
|
||||||
val2.setImplicitType(c1);
|
val2.setImplicitType(c1);
|
||||||
if (val2.getMetaData() == null)
|
if (val2.getMetaData() == null && !val1.isXPath())
|
||||||
val2.setMetaData(val1.getMetaData());
|
val2.setMetaData(val1.getMetaData());
|
||||||
} else if (o1 && o2 && expected != null) {
|
} else if (o1 && o2 && expected != null) {
|
||||||
// we never expect a pc type, so don't bother with metadata
|
// we never expect a pc type, so don't bother with metadata
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.apache.openjpa.kernel.OpenJPAStateManager;
|
||||||
import org.apache.openjpa.kernel.StoreContext;
|
import org.apache.openjpa.kernel.StoreContext;
|
||||||
import org.apache.openjpa.meta.ClassMetaData;
|
import org.apache.openjpa.meta.ClassMetaData;
|
||||||
import org.apache.openjpa.meta.FieldMetaData;
|
import org.apache.openjpa.meta.FieldMetaData;
|
||||||
|
import org.apache.openjpa.meta.XMLMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A path represents a traversal into fields of a candidate object.
|
* A path represents a traversal into fields of a candidate object.
|
||||||
|
@ -184,4 +185,14 @@ class CandidatePath
|
||||||
return ((Traversal) other).field.equals(field);
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package org.apache.openjpa.kernel.exps;
|
package org.apache.openjpa.kernel.exps;
|
||||||
|
|
||||||
import org.apache.openjpa.meta.FieldMetaData;
|
import org.apache.openjpa.meta.FieldMetaData;
|
||||||
|
import org.apache.openjpa.meta.XMLMapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A path represents a traversal into fields of a candidate object.
|
* A path represents a traversal into fields of a candidate object.
|
||||||
|
@ -42,4 +43,28 @@ public interface Path
|
||||||
* not contain a final field.
|
* not contain a final field.
|
||||||
*/
|
*/
|
||||||
public FieldMetaData last();
|
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,6 +109,10 @@ public abstract class Val
|
||||||
public boolean isAggregate() {
|
public boolean isAggregate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isXPath() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void acceptVisit(ExpressionVisitor visitor) {
|
public void acceptVisit(ExpressionVisitor visitor) {
|
||||||
visitor.enter(this);
|
visitor.enter(this);
|
||||||
|
|
|
@ -51,6 +51,11 @@ public interface Value {
|
||||||
*/
|
*/
|
||||||
public boolean isAggregate();
|
public boolean isAggregate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if this value is an XML Path.
|
||||||
|
*/
|
||||||
|
public boolean isXPath();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return any associated persistent type.
|
* Return any associated persistent type.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1088,7 +1088,7 @@ public class JPQLExpressionBuilder
|
||||||
if (fmd == null)
|
if (fmd == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Class type = fmd.getType();
|
Class type = path.isXPath() ? path.getType() : fmd.getType();
|
||||||
if (type == null)
|
if (type == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -1298,6 +1298,11 @@ public class JPQLExpressionBuilder
|
||||||
// walk through the children and assemble the path
|
// walk through the children and assemble the path
|
||||||
boolean allowNull = !inner;
|
boolean allowNull = !inner;
|
||||||
for (int i = 1; i < node.children.length; i++) {
|
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,
|
path = (Path) traversePath(path, node.children[i].text, pcOnly,
|
||||||
allowNull);
|
allowNull);
|
||||||
|
|
||||||
|
|
|
@ -1850,4 +1850,13 @@ public class MetaDataRepository
|
||||||
&& StringUtils.equals (name, qk.name);
|
&& StringUtils.equals (name, qk.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return XML metadata for a given field metadata
|
||||||
|
* @param fmd
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public XMLMapping getXMLMetaData(FieldMetaData fmd) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue