You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2017/07/25 12:25:21 UTC
[06/16] cayenne git commit: CAY-2335: New XML loading/saving
mechanics with support of plugable handlers - new XML loader for DataMap -
new project version - updated test projects
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptor.java
index fe18894..335f109 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptor.java
@@ -42,6 +42,31 @@ public class QueryDescriptor implements Serializable, ConfigurationNode, XMLSeri
public static final String PROCEDURE_QUERY = "ProcedureQuery";
/**
+ * @since 4.1
+ */
+ public static final String OBJ_ENTITY_ROOT = "obj-entity";
+
+ /**
+ * @since 4.1
+ */
+ public static final String DB_ENTITY_ROOT = "db-entity";
+
+ /**
+ * @since 4.1
+ */
+ public static final String PROCEDURE_ROOT = "procedure";
+
+ /**
+ * @since 4.1
+ */
+ public static final String DATA_MAP_ROOT = "data-map";
+
+ /**
+ * @since 4.1
+ */
+ public static final String JAVA_CLASS_ROOT = "java-class";
+
+ /**
* Creates new SelectQuery query descriptor.
*/
public static SelectQueryDescriptor selectQueryDescriptor() {
@@ -189,47 +214,36 @@ public class QueryDescriptor implements Serializable, ConfigurationNode, XMLSeri
}
@Override
- public void encodeAsXML(XMLEncoder encoder) {
- encoder.print("<query name=\"");
- encoder.print(getName());
- encoder.print("\" type=\"");
- encoder.print(type);
+ public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+ encoder.start("query").attribute("name", getName()).attribute("type", type);
String rootString = null;
String rootType = null;
if (root instanceof String) {
- rootType = MapLoader.OBJ_ENTITY_ROOT;
+ rootType = OBJ_ENTITY_ROOT;
rootString = root.toString();
} else if (root instanceof ObjEntity) {
- rootType = MapLoader.OBJ_ENTITY_ROOT;
+ rootType = OBJ_ENTITY_ROOT;
rootString = ((ObjEntity) root).getName();
} else if (root instanceof DbEntity) {
- rootType = MapLoader.DB_ENTITY_ROOT;
+ rootType = DB_ENTITY_ROOT;
rootString = ((DbEntity) root).getName();
} else if (root instanceof Procedure) {
- rootType = MapLoader.PROCEDURE_ROOT;
+ rootType = PROCEDURE_ROOT;
rootString = ((Procedure) root).getName();
} else if (root instanceof Class<?>) {
- rootType = MapLoader.JAVA_CLASS_ROOT;
+ rootType = JAVA_CLASS_ROOT;
rootString = ((Class<?>) root).getName();
}
if (rootType != null) {
- encoder.print("\" root=\"");
- encoder.print(rootType);
- encoder.print("\" root-name=\"");
- encoder.print(rootString);
+ encoder.attribute("root", rootType).attribute("root-name", rootString);
}
-
- encoder.println("\">");
-
- encoder.indent(1);
-
encodeProperties(encoder);
- encoder.indent(-1);
- encoder.println("</query>");
+ delegate.visitQuery(this);
+ encoder.end();
}
void encodeProperties(XMLEncoder encoder) {
@@ -238,7 +252,7 @@ public class QueryDescriptor implements Serializable, ConfigurationNode, XMLSeri
if(value == null || value.isEmpty()) {
continue;
}
- encoder.printProperty(property.getKey(), value);
+ encoder.property(property.getKey(), value);
}
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java b/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java
index 10038cc..cd5235f 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/QueryDescriptorLoader.java
@@ -88,7 +88,7 @@ public class QueryDescriptorLoader {
return descriptor;
}
- void setName(String name) {
+ public void setName(String name) {
this.name = name;
}
@@ -98,7 +98,7 @@ public class QueryDescriptorLoader {
* and can't be changed without complete upgrade system rewrite
* @param factory old style query factory class
*/
- void setLegacyFactory(String factory) {
+ public void setLegacyFactory(String factory) {
switch (factory) {
case "org.apache.cayenne.map.SelectQueryBuilder":
queryType = QueryDescriptor.SELECT_QUERY;
@@ -117,7 +117,7 @@ public class QueryDescriptorLoader {
}
}
- void setQueryType(String queryType) {
+ public void setQueryType(String queryType) {
this.queryType = queryType;
}
@@ -132,20 +132,20 @@ public class QueryDescriptorLoader {
Object root = null;
if (rootType == null
- || MapLoader.DATA_MAP_ROOT.equals(rootType)
+ || QueryDescriptor.DATA_MAP_ROOT.equals(rootType)
|| rootName == null) {
root = dataMap;
}
- else if (MapLoader.OBJ_ENTITY_ROOT.equals(rootType)) {
+ else if (QueryDescriptor.OBJ_ENTITY_ROOT.equals(rootType)) {
root = dataMap.getObjEntity(rootName);
}
- else if (MapLoader.DB_ENTITY_ROOT.equals(rootType)) {
+ else if (QueryDescriptor.DB_ENTITY_ROOT.equals(rootType)) {
root = dataMap.getDbEntity(rootName);
}
- else if (MapLoader.PROCEDURE_ROOT.equals(rootType)) {
+ else if (QueryDescriptor.PROCEDURE_ROOT.equals(rootType)) {
root = dataMap.getProcedure(rootName);
}
- else if (MapLoader.JAVA_CLASS_ROOT.equals(rootType)) {
+ else if (QueryDescriptor.JAVA_CLASS_ROOT.equals(rootType)) {
// setting root to ObjEntity, since creating a Class requires
// the knowledge of the ClassLoader
root = dataMap.getObjEntityForJavaClass(rootName);
@@ -154,20 +154,20 @@ public class QueryDescriptorLoader {
return (root != null) ? root : dataMap;
}
- void setResultEntity(String resultEntity) {
+ public void setResultEntity(String resultEntity) {
this.resultEntity = resultEntity;
}
/**
* Sets the information pertaining to the root of the query.
*/
- void setRoot(DataMap dataMap, String rootType, String rootName) {
+ public void setRoot(DataMap dataMap, String rootType, String rootName) {
this.dataMap = dataMap;
this.rootType = rootType;
this.rootName = rootName;
}
- void setEjbql(String ejbql) {
+ public void setEjbql(String ejbql) {
this.ejbql = ejbql;
}
@@ -175,7 +175,7 @@ public class QueryDescriptorLoader {
* Adds raw sql. If adapterClass parameter is not null, sets the SQL string to be
* adapter-specific. Otherwise it is used as a default SQL string.
*/
- void addSql(String sql, String adapterClass) {
+ public void addSql(String sql, String adapterClass) {
if (adapterClass == null) {
this.sql = sql;
}
@@ -188,7 +188,7 @@ public class QueryDescriptorLoader {
}
}
- void setQualifier(String qualifier) {
+ public void setQualifier(String qualifier) {
if (qualifier == null || qualifier.trim().length() == 0) {
this.qualifier = null;
}
@@ -197,7 +197,7 @@ public class QueryDescriptorLoader {
}
}
- void addProperty(String name, String value) {
+ public void addProperty(String name, String value) {
if (properties == null) {
properties = new HashMap<>();
}
@@ -205,7 +205,7 @@ public class QueryDescriptorLoader {
properties.put(name, value);
}
- void addOrdering(String path, String descending, String ignoreCase) {
+ public void addOrdering(String path, String descending, String ignoreCase) {
if (orderings == null) {
orderings = new ArrayList<>();
}
@@ -232,7 +232,7 @@ public class QueryDescriptorLoader {
orderings.add(new Ordering(path, order));
}
- void addPrefetch(String path) {
+ public void addPrefetch(String path) {
if (path == null || (path != null && path.trim().length() == 0)) {
// throw??
return;
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
index f9b1ff0..e9c14f7 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/SQLTemplateDescriptor.java
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.cayenne.map;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
import org.apache.cayenne.query.SQLTemplate;
import org.apache.cayenne.util.XMLEncoder;
@@ -97,78 +98,64 @@ public class SQLTemplateDescriptor extends QueryDescriptor {
}
@Override
- public void encodeAsXML(XMLEncoder encoder) {
- encoder.print("<query name=\"");
- encoder.print(getName());
- encoder.print("\" type=\"");
- encoder.print(type);
+ public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+ encoder.start("query")
+ .attribute("name", getName())
+ .attribute("type", type);
String rootString = null;
String rootType = null;
if (root instanceof String) {
- rootType = MapLoader.OBJ_ENTITY_ROOT;
+ rootType = QueryDescriptor.OBJ_ENTITY_ROOT;
rootString = root.toString();
} else if (root instanceof ObjEntity) {
- rootType = MapLoader.OBJ_ENTITY_ROOT;
+ rootType = QueryDescriptor.OBJ_ENTITY_ROOT;
rootString = ((ObjEntity) root).getName();
} else if (root instanceof DbEntity) {
- rootType = MapLoader.DB_ENTITY_ROOT;
+ rootType = QueryDescriptor.DB_ENTITY_ROOT;
rootString = ((DbEntity) root).getName();
} else if (root instanceof Procedure) {
- rootType = MapLoader.PROCEDURE_ROOT;
+ rootType = QueryDescriptor.PROCEDURE_ROOT;
rootString = ((Procedure) root).getName();
} else if (root instanceof Class<?>) {
- rootType = MapLoader.JAVA_CLASS_ROOT;
+ rootType = QueryDescriptor.JAVA_CLASS_ROOT;
rootString = ((Class<?>) root).getName();
} else if (root instanceof DataMap) {
- rootType = MapLoader.DATA_MAP_ROOT;
+ rootType = QueryDescriptor.DATA_MAP_ROOT;
rootString = ((DataMap) root).getName();
}
if (rootType != null) {
- encoder.print("\" root=\"");
- encoder.print(rootType);
- encoder.print("\" root-name=\"");
- encoder.print(rootString);
+ encoder.attribute("root", rootType).attribute("root-name", rootString);
}
- encoder.println("\">");
-
- encoder.indent(1);
-
// print properties
encodeProperties(encoder);
-
// encode default SQL
if (sql != null) {
- encoder.print("<sql><![CDATA[");
- encoder.print(sql);
- encoder.println("]]></sql>");
+ encoder.start("sql").cdata(sql, true).end();
}
// encode adapter SQL
if (adapterSql != null && !adapterSql.isEmpty()) {
-
// sorting entries by adapter name
- TreeSet<String> keys = new TreeSet<String>(adapterSql.keySet());
+ TreeSet<String> keys = new TreeSet<>(adapterSql.keySet());
for (String key : keys) {
String value = adapterSql.get(key);
-
if (key != null && value != null) {
String sql = value.trim();
if (sql.length() > 0) {
- encoder.print("<sql adapter-class=\"");
- encoder.print(key);
- encoder.print("\"><![CDATA[");
- encoder.print(sql);
- encoder.println("]]></sql>");
+ encoder.start("sql")
+ .attribute("adapter-class", key)
+ .cdata(sql, true)
+ .end();
}
}
}
}
- encoder.indent(-1);
- encoder.println("</query>");
+ delegate.visitQuery(this);
+ encoder.end();
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/map/SelectQueryDescriptor.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/map/SelectQueryDescriptor.java b/cayenne-server/src/main/java/org/apache/cayenne/map/SelectQueryDescriptor.java
index e844b3e..7a677fb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/map/SelectQueryDescriptor.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/map/SelectQueryDescriptor.java
@@ -18,6 +18,7 @@
****************************************************************/
package org.apache.cayenne.map;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.query.Ordering;
import org.apache.cayenne.query.PrefetchTreeNode;
@@ -26,7 +27,6 @@ import org.apache.cayenne.util.XMLEncoder;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
/**
* @since 4.0
@@ -153,59 +153,45 @@ public class SelectQueryDescriptor extends QueryDescriptor {
}
@Override
- public void encodeAsXML(XMLEncoder encoder) {
- encoder.print("<query name=\"");
- encoder.print(getName());
- encoder.print("\" type=\"");
- encoder.print(type);
+ public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+ encoder.start("query")
+ .attribute("name", getName())
+ .attribute("type", type);
String rootString = null;
String rootType = null;
if (root instanceof String) {
- rootType = MapLoader.OBJ_ENTITY_ROOT;
+ rootType = QueryDescriptor.OBJ_ENTITY_ROOT;
rootString = root.toString();
} else if (root instanceof ObjEntity) {
- rootType = MapLoader.OBJ_ENTITY_ROOT;
+ rootType = QueryDescriptor.OBJ_ENTITY_ROOT;
rootString = ((ObjEntity) root).getName();
} else if (root instanceof DbEntity) {
- rootType = MapLoader.DB_ENTITY_ROOT;
+ rootType = QueryDescriptor.DB_ENTITY_ROOT;
rootString = ((DbEntity) root).getName();
} else if (root instanceof Procedure) {
- rootType = MapLoader.PROCEDURE_ROOT;
+ rootType = QueryDescriptor.PROCEDURE_ROOT;
rootString = ((Procedure) root).getName();
} else if (root instanceof Class<?>) {
- rootType = MapLoader.JAVA_CLASS_ROOT;
+ rootType = QueryDescriptor.JAVA_CLASS_ROOT;
rootString = ((Class<?>) root).getName();
}
if (rootType != null) {
- encoder.print("\" root=\"");
- encoder.print(rootType);
- encoder.print("\" root-name=\"");
- encoder.print(rootString);
+ encoder.attribute("root", rootType).attribute("root-name", rootString);
}
- encoder.println("\">");
-
- encoder.indent(1);
-
// print properties
encodeProperties(encoder);
// encode qualifier
if (qualifier != null) {
- encoder.print("<qualifier>");
- qualifier.encodeAsXML(encoder);
- encoder.println("</qualifier>");
+ encoder.start("qualifier").nested(qualifier, delegate).end();
}
// encode orderings
- if (orderings != null && !orderings.isEmpty()) {
- for (Ordering ordering : orderings) {
- ordering.encodeAsXML(encoder);
- }
- }
+ encoder.nested(orderings, delegate);
PrefetchTreeNode prefetchTree = new PrefetchTreeNode();
@@ -215,9 +201,9 @@ public class SelectQueryDescriptor extends QueryDescriptor {
node.setPhantom(false);
}
- prefetchTree.encodeAsXML(encoder);
+ encoder.nested(prefetchTree, delegate);
- encoder.indent(-1);
- encoder.println("</query>");
+ delegate.visitQuery(this);
+ encoder.end();
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java b/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java
index bc13719..a450b3b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/BaseQueryMetadata.java
@@ -27,6 +27,7 @@ import java.util.Map;
import java.util.StringTokenizer;
import org.apache.cayenne.Persistent;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.EntityResolver;
@@ -41,7 +42,7 @@ import org.apache.cayenne.util.XMLSerializable;
*
* @since 1.1
*/
-class BaseQueryMetadata implements QueryMetadata, XMLSerializable, Serializable {
+class BaseQueryMetadata implements QueryMetadata, Serializable {
private static final long serialVersionUID = 5129792493303459115L;
@@ -195,41 +196,6 @@ class BaseQueryMetadata implements QueryMetadata, XMLSerializable, Serializable
}
}
- public void encodeAsXML(XMLEncoder encoder) {
-
- if (fetchingDataRows != QueryMetadata.FETCHING_DATA_ROWS_DEFAULT) {
- encoder.printProperty(QueryMetadata.FETCHING_DATA_ROWS_PROPERTY, fetchingDataRows);
- }
-
- if (fetchOffset != QueryMetadata.FETCH_OFFSET_DEFAULT) {
- encoder.printProperty(QueryMetadata.FETCH_OFFSET_PROPERTY, fetchOffset);
- }
-
- if (fetchLimit != QueryMetadata.FETCH_LIMIT_DEFAULT) {
- encoder.printProperty(QueryMetadata.FETCH_LIMIT_PROPERTY, fetchLimit);
- }
-
- if (pageSize != QueryMetadata.PAGE_SIZE_DEFAULT) {
- encoder.printProperty(QueryMetadata.PAGE_SIZE_PROPERTY, pageSize);
- }
-
- if (cacheStrategy != null && QueryCacheStrategy.getDefaultStrategy() != cacheStrategy) {
- encoder.printProperty(QueryMetadata.CACHE_STRATEGY_PROPERTY, cacheStrategy.name());
- }
-
- if (statementFetchSize != QueryMetadata.STATEMENT_FETCH_SIZE_DEFAULT) {
- encoder.printProperty(QueryMetadata.STATEMENT_FETCH_SIZE_PROPERTY, statementFetchSize);
- }
-
- if (prefetchTree != null) {
- prefetchTree.encodeAsXML(encoder);
- }
-
- if (cacheGroup != null) {
- encoder.printProperty(QueryMetadata.CACHE_GROUPS_PROPERTY, cacheGroup);
- }
- }
-
/**
* @since 1.2
*/
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/EJBQLQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/EJBQLQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/query/EJBQLQuery.java
index 18732c7..7103562 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/EJBQLQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/EJBQLQuery.java
@@ -19,6 +19,7 @@
package org.apache.cayenne.query;
import org.apache.cayenne.CayenneRuntimeException;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
import org.apache.cayenne.ejbql.EJBQLCompiledExpression;
import org.apache.cayenne.ejbql.EJBQLException;
import org.apache.cayenne.ejbql.EJBQLParserFactory;
@@ -36,7 +37,7 @@ import java.util.Map;
*
* @since 3.0
*/
-public class EJBQLQuery extends CacheableQuery implements XMLSerializable {
+public class EJBQLQuery extends CacheableQuery {
@Deprecated
protected String name;
@@ -224,28 +225,6 @@ public class EJBQLQuery extends CacheableQuery implements XMLSerializable {
metadata.setFetchOffset(fetchOffset);
}
- public void encodeAsXML(XMLEncoder encoder) {
- encoder.print("<query name=\"");
- encoder.print(getName());
- encoder.print("\" factory=\"");
- encoder.print("org.apache.cayenne.map.EjbqlBuilder");
-
- encoder.println("\">");
-
- encoder.indent(1);
-
- metadata.encodeAsXML(encoder);
-
- if (ejbqlStatement != null) {
- encoder.print("<ejbql><![CDATA[");
- encoder.print(ejbqlStatement);
- encoder.println("]]></ejbql>");
- }
-
- encoder.indent(-1);
- encoder.println("</query>");
- }
-
public void setEjbqlStatement(String text) {
this.ejbqlStatement = text;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java b/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java
index 3625df6..38d6a2e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java
@@ -19,6 +19,8 @@
package org.apache.cayenne.query;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+import org.apache.cayenne.configuration.EmptyConfigurationNodeVisitor;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionException;
import org.apache.cayenne.exp.parser.ASTDbPath;
@@ -431,22 +433,12 @@ public class Ordering implements Comparator<Object>, Serializable, XMLSerializab
* @since 1.1
*/
@Override
- public void encodeAsXML(XMLEncoder encoder) {
- encoder.print("<ordering");
-
- if (isDescending()) {
- encoder.print(" descending=\"true\"");
- }
-
- if (isCaseInsensitive()) {
- encoder.print(" ignore-case=\"true\"");
- }
-
- encoder.print(">");
- if (getSortSpec() != null) {
- getSortSpec().encodeAsXML(encoder);
- }
- encoder.println("</ordering>");
+ public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
+ encoder.start("ordering")
+ .attribute("descending", isDescending())
+ .attribute("ignore-case", isCaseInsensitive())
+ .nested(getSortSpec(), delegate)
+ .end();
}
@Override
@@ -454,7 +446,7 @@ public class Ordering implements Comparator<Object>, Serializable, XMLSerializab
StringWriter buffer = new StringWriter();
PrintWriter pw = new PrintWriter(buffer);
XMLEncoder encoder = new XMLEncoder(pw);
- encodeAsXML(encoder);
+ encodeAsXML(encoder, new EmptyConfigurationNodeVisitor());
pw.close();
buffer.flush();
return buffer.toString();
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java b/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java
index a1d0fb6..2f72e4e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/PrefetchTreeNode.java
@@ -19,6 +19,7 @@
package org.apache.cayenne.query;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
import org.apache.cayenne.map.Entity;
import org.apache.cayenne.util.Util;
import org.apache.cayenne.util.XMLEncoder;
@@ -96,7 +97,8 @@ public class PrefetchTreeNode implements Serializable, XMLSerializable {
this.semantics = UNDEFINED_SEMANTICS;
}
- public void encodeAsXML(XMLEncoder encoder) {
+ @Override
+ public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
traverse(new XMLEncoderOperation(encoder));
}
@@ -218,7 +220,7 @@ public class PrefetchTreeNode implements Serializable, XMLSerializable {
*/
public void traverse(PrefetchProcessor processor) {
- boolean result = false;
+ boolean result;
if (isPhantom()) {
result = processor.startPhantomPrefetch(this);
@@ -500,31 +502,33 @@ public class PrefetchTreeNode implements Serializable, XMLSerializable {
}
public boolean startDisjointPrefetch(PrefetchTreeNode node) {
- encoder.print("<prefetch type=\"disjoint\">");
- encoder.print(node.getPath());
- encoder.println("</prefetch>");
+ encoder.start("prefetch")
+ .attribute("type", "disjoint")
+ .cdata(node.getPath(), true)
+ .end();
return true;
}
public boolean startDisjointByIdPrefetch(PrefetchTreeNode node) {
- encoder.print("<prefetch type=\"disjointById\">");
- encoder.print(node.getPath());
- encoder.println("</prefetch>");
+ encoder.start("prefetch")
+ .attribute("type", "disjointById")
+ .cdata(node.getPath(), true)
+ .end();
return true;
}
public boolean startJointPrefetch(PrefetchTreeNode node) {
- encoder.print("<prefetch type=\"joint\">");
- encoder.print(node.getPath());
- encoder.println("</prefetch>");
+ encoder.start("prefetch")
+ .attribute("type", "joint")
+ .cdata(node.getPath(), true)
+ .end();
return true;
}
public boolean startUnknownPrefetch(PrefetchTreeNode node) {
- encoder.print("<prefetch>");
- encoder.print(node.getPath());
- encoder.println("</prefetch>");
-
+ encoder.start("prefetch")
+ .cdata(node.getPath(), true)
+ .end();
return true;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/ProcedureQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/ProcedureQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/query/ProcedureQuery.java
index 12ac3c7..462bd8d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/ProcedureQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/ProcedureQuery.java
@@ -20,9 +20,10 @@
package org.apache.cayenne.query;
import org.apache.cayenne.access.jdbc.ColumnDescriptor;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.MapLoader;
import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.QueryDescriptor;
import org.apache.cayenne.util.XMLEncoder;
import org.apache.cayenne.util.XMLSerializable;
@@ -54,7 +55,7 @@ import java.util.Map;
* {@link org.apache.cayenne.access.DataContext#performGenericQuery(Query)}.
* </p>
*/
-public class ProcedureQuery extends AbstractQuery implements ParameterizedQuery, XMLSerializable {
+public class ProcedureQuery extends AbstractQuery implements ParameterizedQuery {
public static final String COLUMN_NAME_CAPITALIZATION_PROPERTY = "cayenne.ProcedureQuery.columnNameCapitalization";
@@ -226,53 +227,6 @@ public class ProcedureQuery extends AbstractQuery implements ParameterizedQuery,
}
/**
- * Prints itself as XML to the provided PrintWriter.
- *
- * @since 1.1
- */
- public void encodeAsXML(XMLEncoder encoder) {
- encoder.print("<query name=\"");
- encoder.print(getName());
- encoder.print("\" factory=\"");
- encoder.print("org.apache.cayenne.map.ProcedureQueryBuilder");
-
- encoder.print("\" root=\"");
- encoder.print(MapLoader.PROCEDURE_ROOT);
-
- String rootString = null;
-
- if (root instanceof String) {
- rootString = root.toString();
- }
- else if (root instanceof Procedure) {
- rootString = ((Procedure) root).getName();
- }
-
- if (rootString != null) {
- encoder.print("\" root-name=\"");
- encoder.print(rootString);
- }
-
- if (resultEntityName != null) {
- encoder.print("\" result-entity=\"");
- encoder.print(resultEntityName);
- }
-
- encoder.println("\">");
- encoder.indent(1);
-
- metaData.encodeAsXML(encoder);
- if (getColumnNamesCapitalization() != CapsStrategy.DEFAULT) {
- encoder.printProperty(
- COLUMN_NAME_CAPITALIZATION_PROPERTY,
- getColumnNamesCapitalization().name());
- }
-
- encoder.indent(-1);
- encoder.println("</query>");
- }
-
- /**
* Creates and returns a new ProcedureQuery built using this query as a prototype and
* substituting template parameters with the values from the map.
*
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
index 1fe3be2..554bb8b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SQLTemplate.java
@@ -20,12 +20,13 @@
package org.apache.cayenne.query;
import org.apache.cayenne.access.QueryEngine;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.MapLoader;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.QueryDescriptor;
import org.apache.cayenne.map.SQLResult;
import org.apache.cayenne.util.XMLEncoder;
import org.apache.cayenne.util.XMLSerializable;
@@ -69,7 +70,7 @@ import java.util.TreeSet;
*
* @since 1.1
*/
-public class SQLTemplate extends AbstractQuery implements ParameterizedQuery, XMLSerializable {
+public class SQLTemplate extends AbstractQuery implements ParameterizedQuery {
private static final long serialVersionUID = -3073521388289663641L;
@@ -198,92 +199,6 @@ public class SQLTemplate extends AbstractQuery implements ParameterizedQuery, XM
}
/**
- * Prints itself as XML to the provided PrintWriter.
- *
- * @since 1.1
- */
- @Override
- public void encodeAsXML(XMLEncoder encoder) {
- encoder.print("<query name=\"");
- encoder.print(getName());
- encoder.print("\" factory=\"");
- encoder.print("org.apache.cayenne.map.SQLTemplateBuilder");
-
- String rootString = null;
- String rootType = null;
-
- if (root instanceof String) {
- rootType = MapLoader.OBJ_ENTITY_ROOT;
- rootString = root.toString();
- } else if (root instanceof ObjEntity) {
- rootType = MapLoader.OBJ_ENTITY_ROOT;
- rootString = ((ObjEntity) root).getName();
- } else if (root instanceof DbEntity) {
- rootType = MapLoader.DB_ENTITY_ROOT;
- rootString = ((DbEntity) root).getName();
- } else if (root instanceof Procedure) {
- rootType = MapLoader.PROCEDURE_ROOT;
- rootString = ((Procedure) root).getName();
- } else if (root instanceof Class<?>) {
- rootType = MapLoader.JAVA_CLASS_ROOT;
- rootString = ((Class<?>) root).getName();
- } else if (root instanceof DataMap) {
- rootType = MapLoader.DATA_MAP_ROOT;
- rootString = ((DataMap) root).getName();
- }
-
- if (rootType != null) {
- encoder.print("\" root=\"");
- encoder.print(rootType);
- encoder.print("\" root-name=\"");
- encoder.print(rootString);
- }
-
- encoder.println("\">");
-
- encoder.indent(1);
-
- metaData.encodeAsXML(encoder);
-
- if (getColumnNamesCapitalization() != CapsStrategy.DEFAULT) {
- encoder.printProperty(COLUMN_NAME_CAPITALIZATION_PROPERTY, getColumnNamesCapitalization().name());
- }
-
- // encode default SQL
- if (defaultTemplate != null) {
- encoder.print("<sql><![CDATA[");
- encoder.print(defaultTemplate);
- encoder.println("]]></sql>");
- }
-
- // encode adapter SQL
- if (templates != null && !templates.isEmpty()) {
-
- // sorting entries by adapter name
- TreeSet<String> keys = new TreeSet<String>(templates.keySet());
- for (String key : keys) {
- String value = templates.get(key);
-
- if (key != null && value != null) {
- String sql = value.trim();
- if (sql.length() > 0) {
- encoder.print("<sql adapter-class=\"");
- encoder.print(key);
- encoder.print("\"><![CDATA[");
- encoder.print(sql);
- encoder.println("]]></sql>");
- }
- }
- }
- }
-
- // TODO: support parameter encoding
-
- encoder.indent(-1);
- encoder.println("</query>");
- }
-
- /**
* Initializes query parameters using a set of properties.
*
* @since 1.1
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
index ff9660e..b2d5bd1 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/SelectQuery.java
@@ -24,14 +24,15 @@ import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.ResultBatchIterator;
import org.apache.cayenne.ResultIterator;
import org.apache.cayenne.ResultIteratorCallback;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.exp.Property;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.EntityResolver;
-import org.apache.cayenne.map.MapLoader;
import org.apache.cayenne.map.ObjEntity;
import org.apache.cayenne.map.Procedure;
+import org.apache.cayenne.map.QueryDescriptor;
import org.apache.cayenne.util.XMLEncoder;
import org.apache.cayenne.util.XMLSerializable;
@@ -48,7 +49,7 @@ import java.util.Map;
* other parameters that serve as runtime hints to Cayenne on how to optimize
* the fetch and result processing.
*/
-public class SelectQuery<T> extends AbstractQuery implements ParameterizedQuery, XMLSerializable, Select<T> {
+public class SelectQuery<T> extends AbstractQuery implements ParameterizedQuery, Select<T> {
private static final long serialVersionUID = 5486418811888197559L;
@@ -434,73 +435,6 @@ public class SelectQuery<T> extends AbstractQuery implements ParameterizedQuery,
}
/**
- * Prints itself as XML to the provided PrintWriter.
- *
- * @since 1.1
- */
- public void encodeAsXML(XMLEncoder encoder) {
- encoder.print("<query name=\"");
- encoder.print(getName());
- encoder.print("\" factory=\"");
- encoder.print("org.apache.cayenne.map.SelectQueryBuilder");
-
- String rootString = null;
- String rootType = null;
-
- if (root instanceof String) {
- rootType = MapLoader.OBJ_ENTITY_ROOT;
- rootString = root.toString();
- } else if (root instanceof ObjEntity) {
- rootType = MapLoader.OBJ_ENTITY_ROOT;
- rootString = ((ObjEntity) root).getName();
- } else if (root instanceof DbEntity) {
- rootType = MapLoader.DB_ENTITY_ROOT;
- rootString = ((DbEntity) root).getName();
- } else if (root instanceof Procedure) {
- rootType = MapLoader.PROCEDURE_ROOT;
- rootString = ((Procedure) root).getName();
- } else if (root instanceof Class<?>) {
- rootType = MapLoader.JAVA_CLASS_ROOT;
- rootString = ((Class<?>) root).getName();
- }
-
- if (rootType != null) {
- encoder.print("\" root=\"");
- encoder.print(rootType);
- encoder.print("\" root-name=\"");
- encoder.print(rootString);
- }
-
- encoder.println("\">");
-
- encoder.indent(1);
-
- // print properties
- if (distinct != DISTINCT_DEFAULT) {
- encoder.printProperty(DISTINCT_PROPERTY, distinct);
- }
-
- metaData.encodeAsXML(encoder);
-
- // encode qualifier
- if (qualifier != null) {
- encoder.print("<qualifier>");
- qualifier.encodeAsXML(encoder);
- encoder.println("</qualifier>");
- }
-
- // encode orderings
- if (orderings != null && !orderings.isEmpty()) {
- for (Ordering ordering : orderings) {
- ordering.encodeAsXML(encoder);
- }
- }
-
- encoder.indent(-1);
- encoder.println("</query>");
- }
-
- /**
* A shortcut for {@link #queryWithParameters(Map, boolean)}that prunes
* parts of qualifier that have no parameter value set.
*/
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java b/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
index 429efdb..db596bb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/reflect/LifecycleCallbackEventHandler.java
@@ -35,26 +35,14 @@ import java.util.Map;
*/
class LifecycleCallbackEventHandler {
- private EntityResolver resolver;
private Map<String, Collection<AbstractCallback>> listeners;
private Collection<AbstractCallback> defaultListeners;
LifecycleCallbackEventHandler(EntityResolver resolver) {
- this.resolver = resolver;
this.listeners = new HashMap<>();
this.defaultListeners = new ArrayList<>();
}
- private boolean excludingDefaultListeners(String entityName) {
- ObjEntity entity = resolver.getObjEntity(entityName);
- return entity != null && entity.isExcludingDefaultListeners();
- }
-
- private boolean excludingSuperclassListeners(String entityName) {
- ObjEntity entity = resolver.getObjEntity(entityName);
- return entity != null && entity.isExcludingSuperclassListeners();
- }
-
boolean isEmpty() {
return listeners.isEmpty() && defaultListeners.isEmpty();
}
@@ -140,8 +128,7 @@ class LifecycleCallbackEventHandler {
void performCallbacks(Persistent object) {
// default listeners are invoked first
- if (!defaultListeners.isEmpty()
- && !excludingDefaultListeners(object.getObjectId().getEntityName())) {
+ if (!defaultListeners.isEmpty()) {
for (AbstractCallback listener : defaultListeners) {
listener.performCallback(object);
}
@@ -171,9 +158,7 @@ class LifecycleCallbackEventHandler {
}
// recursively perform super callbacks first
- if (!excludingSuperclassListeners(object.getObjectId().getEntityName())) {
- performCallbacks(object, callbackEntityClass.getSuperclass());
- }
+ performCallbacks(object, callbackEntityClass.getSuperclass());
// perform callbacks on provided class
String key = callbackEntityClass.getName();
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java b/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java
index d869d4c..7314488 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/remote/IncrementalSelectQuery.java
@@ -127,11 +127,6 @@ class IncrementalSelectQuery<T> extends SelectQuery<T> {
}
@Override
- public void encodeAsXML(XMLEncoder encoder) {
- query.encodeAsXML(encoder);
- }
-
- @Override
public boolean equals(Object obj) {
return query.equals(obj);
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/util/XMLEncoder.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/util/XMLEncoder.java b/cayenne-server/src/main/java/org/apache/cayenne/util/XMLEncoder.java
index 7551d99..039ca4d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/util/XMLEncoder.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/util/XMLEncoder.java
@@ -21,12 +21,26 @@ package org.apache.cayenne.util;
import java.io.PrintWriter;
import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedList;
import java.util.Map;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+
/**
+ * <p>
* A helper class to encode objects to XML.
- *
+ * </p>
+ * Usage: <pre>{@code
+ * XMLEncoder encoder = new XMLEncoder(writer);
+ * encoder
+ * .start("tag").attribute("name", "tag_name_attribute")
+ * .start("nested_tag").attribute("name", "nested_tag_name).cdata("tag text element").end()
+ * .end();
+ * }</pre>
+ *
* @since 1.1
+ * @since 4.1 API is greatly reworked to be more usable
*/
public class XMLEncoder {
@@ -37,6 +51,12 @@ public class XMLEncoder {
protected boolean indentLine;
protected int indentTimes;
+ protected boolean tagOpened;
+ protected boolean cdata;
+ protected int currentTagLevel;
+ protected int lastTagLevel;
+ protected Deque<String> openTags = new LinkedList<>();
+
public XMLEncoder(PrintWriter out) {
this(out, null, null);
}
@@ -54,163 +74,275 @@ public class XMLEncoder {
this.projectVersion = projectVersion;
}
- public PrintWriter getPrintWriter() {
- return out;
- }
-
- public void indent(int i) {
+ public XMLEncoder indent(int i) {
indentTimes += i;
if (indentTimes < 0) {
indentTimes = 0;
}
+ return this;
+ }
+
+ public XMLEncoder print(String text) {
+ printIndent();
+ out.print(text);
+ return this;
+ }
+
+ public XMLEncoder println(String text) {
+ printIndent();
+ out.println(text);
+ indentLine = true;
+ return this;
}
/**
- * Utility method that prints all map values, assuming they are XMLSerializable
- * objects.
+ * @since 3.1
*/
- public void print(Map<?, ? extends XMLSerializable> map) {
- for (XMLSerializable value : map.values()) {
- value.encodeAsXML(this);
+ public XMLEncoder println() {
+ out.println();
+ indentLine = true;
+ return this;
+ }
+
+ private XMLEncoder printIndent() {
+ if (indentLine) {
+ indentLine = false;
+
+ if (indentTimes > 0 && indent != null) {
+ for (int i = 0; i < indentTimes; i++) {
+ out.print(indent);
+ }
+ }
}
+ return this;
}
/**
- * Utility method that prints all map values, assuming they are XMLSerializable
- * objects.
+ * @since 4.1
+ * @param tag to start
+ * @return this
*/
- public void print(Collection<? extends XMLSerializable> c) {
- for (XMLSerializable value : c) {
- value.encodeAsXML(this);
+ public XMLEncoder start(String tag) {
+ if(tagOpened) {
+ println(">").indent(1);
}
+ printIndent().print("<").print(tag);
+
+ lastTagLevel = ++currentTagLevel;
+ tagOpened = true;
+ openTags.push(tag);
+ return this;
}
/**
- * Inserts an optional project version attribute in the output. If the project version
- * is not initialized for encoder, will do nothing.
- *
- * @since 3.1
+ * This method will track presence of nested tags and print closure accordingly
+ *
+ * @since 4.1
+ * @return this
*/
- public void printProjectVersion() {
- printAttribute("project-version", projectVersion);
+ public XMLEncoder end() {
+ tagOpened = false;
+ if(lastTagLevel == currentTagLevel-- && !cdata) {
+ openTags.pop();
+ println("/>");
+ } else {
+ if(!cdata) {
+ indent(-1).printIndent();
+ }
+ cdata = false;
+ print("</").print(openTags.pop()).println(">");
+ }
+ return this;
}
/**
- * Prints an XML attribute. The value is trimmed (so leading and following spaces are
- * lost) and then encoded to be a proper XML attribute value. E.g. "&" becomes
- * "&amp;", etc.
- *
- * @since 3.1
+ * @since 4.1
+ * @param name of the attribute
+ * @param value of the attribute
+ * @return this
*/
- public void printAttribute(String name, String value) {
- printAttribute(name, value, false);
+ public XMLEncoder attribute(String name, String value) {
+ return attribute(name, value, false);
}
/**
- * @since 3.1
+ * @since 4.1
+ * @param name of the attribute
+ * @param value of the attribute
+ * @param newLine should this attribute be printed on new line
+ * @return this
*/
- public void printlnAttribute(String name, String value) {
- printAttribute(name, value, true);
- }
-
- private void printAttribute(String name, String value, boolean lineBreak) {
- if (value == null) {
- return;
+ public XMLEncoder attribute(String name, String value, boolean newLine) {
+ if(Util.isEmptyString(value)) {
+ return this;
}
- value = value.trim();
- if (value.length() == 0) {
- return;
+ if(newLine) {
+ indent(1).println().printIndent();
}
-
- value = Util.encodeXmlAttribute(value);
-
- printIndent();
- out.print(' ');
- out.print(name);
- out.print("=\"");
- out.print(value);
- out.print("\"");
- if (lineBreak) {
- println();
+ print(" ").print(name).print("=\"").print(Util.encodeXmlAttribute(value)).print("\"");
+ if(newLine) {
+ indent(-1);
}
+ return this;
}
/**
- * Prints a common XML element - property with name and value.
+ * @since 4.1
+ * @param name of the attribute
+ * @param value of the attribute
+ * @return this
*/
- public void printProperty(String name, String value) {
- printIndent();
- out.print("<property");
- printAttribute("name", name);
- printAttribute("value", value);
- out.println("/>");
- indentLine = true;
+ public XMLEncoder attribute(String name, boolean value) {
+ if(!value) {
+ return this;
+ }
+ return attribute(name, "true");
}
/**
- * Prints a common XML element - property with name and value.
+ * @since 4.1
+ * @param name of the attribute
+ * @param value of the attribute
+ * @return this
*/
- public void printProperty(String name, boolean b) {
- printProperty(name, String.valueOf(b));
+ public XMLEncoder attribute(String name, int value) {
+ if(value == 0) {
+ return this;
+ }
+ return attribute(name, String.valueOf(value));
}
/**
- * Prints a common XML element - property with name and value.
+ * @since 4.1
+ * @param data char data
+ * @return this
*/
- public void printProperty(String name, int i) {
- printProperty(name, String.valueOf(i));
+ public XMLEncoder cdata(String data) {
+ return cdata(data, false);
}
- public void print(String text) {
- printIndent();
- out.print(text);
+ /**
+ * @since 4.1
+ * @param data char data
+ * @param escape does this data need to be enclosed into <![CDATA[ ... ]]>
+ * @return this
+ */
+ public XMLEncoder cdata(String data, boolean escape) {
+ if(tagOpened) {
+ print(">");
+ }
+ cdata = true;
+ if(escape) {
+ print("<![CDATA[");
+ }
+ print(data);
+ if(escape) {
+ print("]]>");
+ }
+ return this;
}
- public void print(char c) {
- printIndent();
- out.print(c);
+ /**
+ * @since 4.1
+ * @param object nested object to serialize
+ * @param delegate visitor
+ * @return this
+ */
+ public XMLEncoder nested(XMLSerializable object, ConfigurationNodeVisitor delegate) {
+ if(object == null) {
+ return this;
+ }
+ object.encodeAsXML(this, delegate);
+ return this;
}
- public void print(boolean b) {
- printIndent();
- out.print(b);
+ /**
+ * @since 4.1
+ * @param collection of nested objects
+ * @param delegate visitor
+ * @return this
+ */
+ public XMLEncoder nested(Collection<? extends XMLSerializable> collection, ConfigurationNodeVisitor delegate) {
+ if(collection == null) {
+ return this;
+ }
+ for (XMLSerializable value : collection) {
+ value.encodeAsXML(this, delegate);
+ }
+ return this;
}
- public void print(int i) {
- printIndent();
- out.print(i);
+ /**
+ * @since 4.1
+ * @param map of nested objects
+ * @param delegate visitor
+ * @return this
+ */
+ public XMLEncoder nested(Map<?, ? extends XMLSerializable> map, ConfigurationNodeVisitor delegate) {
+ if(map == null) {
+ return this;
+ }
+ for (XMLSerializable value : map.values()) {
+ value.encodeAsXML(this, delegate);
+ }
+ return this;
}
- public void println(String text) {
- printIndent();
- out.println(text);
+ /**
+ * Prints a common XML element - property with name and value.
+ * @since 4.1
+ */
+ public XMLEncoder property(String name, String value) {
+ if(Util.isEmptyString(value)) {
+ return this;
+ }
+ start("property").attribute("name", name).attribute("value", value).end();
indentLine = true;
+ return this;
}
/**
- * @since 3.1
+ * Prints a common XML element - property with name and value.
+ * @since 4.1
*/
- public void println() {
- out.println();
- indentLine = true;
+ public XMLEncoder property(String name, boolean b) {
+ if(!b) {
+ return this;
+ }
+ return property(name, "true");
}
- public void println(char c) {
- printIndent();
- out.println(c);
- indentLine = true;
+ /**
+ * Prints a common XML element - property with name and value.
+ * @since 4.1
+ */
+ public XMLEncoder property(String name, int i) {
+ if(i == 0) {
+ return this;
+ }
+ return property(name, String.valueOf(i));
}
- private void printIndent() {
- if (indentLine) {
- indentLine = false;
-
- if (indentTimes > 0 && indent != null) {
- for (int i = 0; i < indentTimes; i++) {
- out.print(indent);
- }
- }
+ /**
+ * Prints common XML element - tag with name and text value (<tag>value</tag>)
+ * If value is empty, nothing will be printed.
+ * @since 4.1
+ */
+ public XMLEncoder simpleTag(String tag, String value) {
+ if (!Util.isEmptyString(value)) {
+ start(tag).cdata(value).end();
}
+ return this;
+ }
+
+ /**
+ * Inserts an optional project version attribute in the output. If the project version
+ * is not initialized for encoder, will do nothing.
+ *
+ * @since 4.1
+ */
+ public XMLEncoder projectVersion() {
+ return attribute("project-version", projectVersion, true);
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/java/org/apache/cayenne/util/XMLSerializable.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/util/XMLSerializable.java b/cayenne-server/src/main/java/org/apache/cayenne/util/XMLSerializable.java
index 3c6cba0..2646785 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/util/XMLSerializable.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/util/XMLSerializable.java
@@ -19,6 +19,8 @@
package org.apache.cayenne.util;
+import org.apache.cayenne.configuration.ConfigurationNodeVisitor;
+
/**
* Interface for Cayenne objects that can be saved to XML.
*
@@ -30,5 +32,5 @@ public interface XMLSerializable {
*
* @since 1.1
*/
- public void encodeAsXML(XMLEncoder encoder);
+ void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate);
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/dbimport.xsd
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/dbimport.xsd b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/dbimport.xsd
new file mode 100644
index 0000000..a100799
--- /dev/null
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/dbimport.xsd
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<xs:schema targetNamespace="http://cayenne.apache.org/schema/10/dbimport"
+ xmlns:dbi="http://cayenne.apache.org/schema/10/dbimport"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="10">
+
+ <xs:element name="config">
+ <xs:complexType>
+ <xs:complexContent>
+ <xs:extension base="dbi:container">
+ <xs:sequence>
+ <xs:element name="catalog" minOccurs="0" maxOccurs="unbounded" type="dbi:catalog"/>
+ <xs:element name="schema" minOccurs="0" maxOccurs="unbounded" type="dbi:schema"/>
+ <xs:element name="tableType" minOccurs="0" maxOccurs="unbounded" type="dbi:db-type"/>
+
+ <xs:element name="defaultPackage" minOccurs="0" type="xs:string"/>
+ <xs:element name="forceDataMapCatalog" minOccurs="0" type="xs:boolean"/>
+ <xs:element name="forceDataMapSchema" minOccurs="0" type="xs:boolean"/>
+ <xs:element name="meaningfulPkTables" minOccurs="0" type="xs:string"/>
+ <xs:element name="namingStrategy" minOccurs="0" type="xs:string"/>
+ <xs:element name="skipPrimaryKeyLoading" minOccurs="0" type="xs:boolean"/>
+ <xs:element name="skipRelationshipsLoading" minOccurs="0" type="xs:boolean"/>
+ <xs:element name="stripFromTableNames" minOccurs="0" type="xs:string"/>
+ <xs:element name="useJava7Types" minOccurs="0" type="xs:boolean"/>
+ <xs:element name="usePrimitives" minOccurs="0" type="xs:boolean"/>
+
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:simpleType name="db-type">
+ <xs:restriction base="xs:string">
+ <xs:pattern value="[0-9a-zA-Z$_.]+"/>
+ </xs:restriction>
+ </xs:simpleType>
+
+ <xs:complexType name="includeTable" mixed="true">
+ <xs:sequence>
+ <xs:element name="name" minOccurs="0" type="dbi:db-type"/>
+ <xs:element name="includeColumn" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="excludeColumn" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="container" abstract="true">
+ <xs:sequence>
+ <xs:element name="includeTable" type="dbi:includeTable" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="excludeTable" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="includeColumn" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="excludeColumn" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="includeProcedure" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+ <xs:element name="excludeProcedure" type="dbi:db-type" minOccurs="0" maxOccurs="unbounded"/>
+
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+
+ <xs:complexType name="schema">
+ <xs:complexContent>
+ <xs:extension base="dbi:container">
+ <xs:sequence>
+ <xs:element name="name" type="dbi:db-type"/>
+
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+ <xs:complexType name="catalog">
+ <xs:complexContent>
+ <xs:extension base="dbi:container">
+ <xs:sequence>
+ <xs:element name="name" type="dbi:db-type"/>
+ <xs:element name="schema" type="dbi:schema" minOccurs="0" maxOccurs="unbounded"/>
+
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:extension>
+ </xs:complexContent>
+ </xs:complexType>
+
+</xs:schema>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/domain.xsd
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/domain.xsd b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/domain.xsd
new file mode 100644
index 0000000..40809d5
--- /dev/null
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/domain.xsd
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<xs:schema targetNamespace="http://cayenne.apache.org/schema/10/domain"
+ elementFormDefault="qualified" version="10"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:cay="http://cayenne.apache.org/schema/10/domain">
+
+ <xs:element name="domain">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:property"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:map"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:node"/>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="project-version" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="property">
+ <xs:annotation>
+ <xs:documentation>A generic property used by other elements.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="value" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="map">
+ <xs:annotation>
+ <xs:documentation>Link to an external file with data map.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="node">
+ <xs:annotation>
+ <xs:documentation>Data node description.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:map-ref"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:data-source"/>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="factory" use="required" type="xs:string"/>
+ <xs:attribute name="adapter" type="xs:string"/>
+ <xs:attribute name="schema-update-strategy" type="xs:string"/>
+ <xs:attribute name="parameters" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="map-ref">
+ <xs:annotation>
+ <xs:documentation>A reference to a map.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="data-source">
+ <xs:annotation>
+ <xs:documentation>Data source configuration.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="1" ref="cay:driver"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="cay:url"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="cay:connectionPool"/>
+ <xs:element minOccurs="0" maxOccurs="1" ref="cay:login"/>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="driver">
+ <xs:complexType>
+ <xs:attribute name="value" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="url">
+ <xs:complexType>
+ <xs:attribute name="value" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="connectionPool">
+ <xs:complexType>
+ <xs:attribute name="min" use="required" type="xs:int"/>
+ <xs:attribute name="max" use="required" type="xs:int"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="login">
+ <xs:complexType>
+ <xs:attribute name="userName" type="xs:string"/>
+ <xs:attribute name="password" type="xs:string"/>
+ <xs:attribute name="passwordLocation" type="xs:string"/>
+ <xs:attribute name="passwordSource" type="xs:string"/>
+ <xs:attribute name="encoderClass" type="xs:string"/>
+ <xs:attribute name="encoderKey" type="xs:string"/>
+ <xs:attribute name="encoderSalt" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+</xs:schema>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/info.xsd
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/info.xsd b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/info.xsd
new file mode 100644
index 0000000..480b24d
--- /dev/null
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/info.xsd
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<xs:schema targetNamespace="http://cayenne.apache.org/schema/10/info"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="10">
+ <xs:element name="property">
+ <xs:complexType>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="value" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c58b6f40/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/modelMap.xsd
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/modelMap.xsd b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/modelMap.xsd
new file mode 100644
index 0000000..7f36483
--- /dev/null
+++ b/cayenne-server/src/main/resources/org/apache/cayenne/schema/10/modelMap.xsd
@@ -0,0 +1,356 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-->
+
+<!--
+ Cayenne entity map schema
+ Defines format of Cayenne DataMap XML files (*.map.xml). DataMap files contain
+ the metadata needed for Cayenne object-relational features. Multiple DataMaps
+ are usually combined in one shared namespace, so the elements of the DataMap
+ may reference objects from other DataMaps.
+-->
+<xs:schema targetNamespace="http://cayenne.apache.org/schema/10/modelMap"
+ xmlns:cay="http://cayenne.apache.org/schema/10/modelMap"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="10">
+ <xs:element name="data-map">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:property"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:embeddable"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:procedure"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:db-entity"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:obj-entity"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:db-relationship"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:obj-relationship"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:query"/>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="project-version" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="db-entity">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element maxOccurs="unbounded" ref="cay:db-attribute"/>
+ <xs:element minOccurs="0" ref="cay:db-key-generator"/>
+
+ <!-- Qualifier for DB Entity -->
+ <xs:element minOccurs="0" ref="cay:qualifier"/>
+
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="schema" type="xs:string"/>
+ <xs:attribute name="catalog" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="db-attribute">
+ <xs:annotation>
+ <xs:documentation>A database column.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="isMandatory" type="xs:boolean"/>
+ <xs:attribute name="isPrimaryKey" type="xs:boolean">
+ <xs:annotation>
+ <xs:documentation>If true, the value of attribute is unique and used as a primary key identifier.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute name="isGenerated" type="xs:boolean"/>
+ <xs:attribute name="length" type="xs:integer"/>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="scale" type="xs:integer"/>
+ <xs:attribute name="type" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="obj-entity">
+ <xs:annotation>
+ <xs:documentation>A persistent Java class managed by Cayenne.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" ref="cay:qualifier"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:embedded-attribute"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:obj-attribute"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:attribute-override"/>
+
+ <!-- Callbacks -->
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:post-add"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:pre-persist"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:post-persist"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:pre-update"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:post-update"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:pre-remove"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:post-remove"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:post-load"/>
+
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="className" type="xs:string"/>
+ <xs:attribute name="abstract" type="xs:boolean"/>
+ <xs:attribute name="readOnly" type="xs:boolean"/>
+ <xs:attribute name="clientClassName" type="xs:string"/>
+ <xs:attribute name="clientSuperClassName" type="xs:string"/>
+ <xs:attribute name="dbEntityName" type="xs:string"/>
+ <xs:attribute name="lock-type" type="xs:string"/>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="superClassName" type="xs:string"/>
+ <xs:attribute name="superEntityName" type="xs:string"/>
+ <xs:attribute name="serverOnly" type="xs:boolean"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="qualifier" type="xs:string"/>
+
+ <xs:element name="obj-attribute">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="db-attribute-path" type="xs:string"/>
+ <xs:attribute name="lock" type="xs:boolean"/>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="type" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="attribute-override">
+ <xs:complexType>
+ <xs:attribute name="db-attribute-path" type="xs:string"/>
+ <xs:attribute name="lock" type="xs:boolean"/>
+ <xs:attribute name="name" type="xs:string"/>
+ <xs:attribute name="type" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="db-relationship">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="1" maxOccurs="unbounded" ref="cay:db-attribute-pair"/>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="source" use="required" type="xs:string"/>
+ <xs:attribute name="target" use="required" type="xs:string"/>
+ <xs:attribute name="toDependentPK" type="xs:boolean"/>
+ <xs:attribute name="toMany" type="xs:boolean"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="db-attribute-pair">
+ <xs:complexType>
+ <xs:attribute name="source" use="required" type="xs:string"/>
+ <xs:attribute name="target" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="obj-relationship">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="db-relationship-path" use="required" type="xs:string"/>
+ <xs:attribute name="deleteRule" type="xs:string"/>
+ <xs:attribute name="lock" type="xs:boolean"/>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="source" use="required" type="xs:string"/>
+ <xs:attribute name="target" use="required" type="xs:string"/>
+ <xs:attribute name="collection-type" type="xs:string"/>
+ <xs:attribute name="map-key" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="query">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:property"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:sql"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:ejbql"/>
+ <xs:element name="qualifier" minOccurs="0" maxOccurs="unbounded" type="xs:string"/>
+ <xs:element minOccurs="0" maxOccurs="unbounded" ref="cay:ordering"/>
+ <xs:element name="prefetch" minOccurs="0" maxOccurs="unbounded" type="xs:string"/>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="type" use="required" type="xs:string"/>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="root" type="xs:string"/>
+ <xs:attribute name="root-name" type="xs:string"/>
+ <xs:attribute name="result-entity" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ordering">
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="descending" type="xs:boolean"/>
+ <xs:attribute name="ignore-case" type="xs:boolean"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="sql">
+ <xs:annotation>
+ <xs:documentation>Defines arbitrary SQL statement. Note that SQL statement can be customized for different SQL dialects per DbAdapter class. If no adapter-specific statement is found, the one with no adapter label is used by default.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:simpleContent>
+ <xs:extension base="xs:string">
+ <xs:attribute name="adapter-class" type="xs:string"/>
+ </xs:extension>
+ </xs:simpleContent>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="ejbql" type="xs:string"/>
+
+ <xs:element name="property">
+ <xs:annotation>
+ <xs:documentation>A generic property used by other elements.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="value" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="embeddable">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="embeddable-attribute" minOccurs="0" maxOccurs="unbounded">
+ <xs:complexType>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="type" use="required" type="xs:string"/>
+ <xs:attribute name="db-attribute-name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="className" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="embedded-attribute">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded"
+ ref="cay:embeddable-attribute-override"/>
+ </xs:sequence>
+ <xs:attribute name="type" use="required" type="xs:string"/>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="embeddable-attribute-override">
+ <xs:complexType>
+ <xs:attribute name="db-attribute-path" use="required" type="xs:string"/>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="procedure">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element minOccurs="0" maxOccurs="unbounded" name="procedure-parameter">
+ <xs:complexType>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="type" use="required" type="xs:string"/>
+ <xs:attribute name="length" type="xs:integer"/>
+ <xs:attribute name="direction" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other" processContents="lax"/>
+ </xs:sequence>
+ <xs:attribute name="name" use="required" type="xs:string"/>
+ <xs:attribute name="schema" type="xs:string"/>
+ <xs:attribute name="catalog" type="xs:string"/>
+ <xs:attribute name="returningValue" type="xs:boolean"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pre-update">
+ <xs:complexType>
+ <xs:attribute name="method-name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="post-persist">
+ <xs:complexType>
+ <xs:attribute name="method-name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="post-update">
+ <xs:complexType>
+ <xs:attribute name="method-name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="post-add">
+ <xs:complexType>
+ <xs:attribute name="method-name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pre-persist">
+ <xs:complexType>
+ <xs:attribute name="method-name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="post-remove">
+ <xs:complexType>
+ <xs:attribute name="method-name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="post-load">
+ <xs:complexType>
+ <xs:attribute name="method-name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pre-remove">
+ <xs:complexType>
+ <xs:attribute name="method-name" use="required" type="xs:string"/>
+ </xs:complexType>
+ </xs:element>
+
+ <xs:element name="db-key-generator">
+ <xs:annotation>
+ <xs:documentation>Used to install the Automatic Sequence/Key Generation facility for db-entity. This feature is intended for use with simple (non-compound) integral primary keys.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="db-generator-type" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>Specifies the Key Generation Method that will be employed
+ 'ORACLE' - use Oracle's SEQUENCE
+ 'NAMED_SEQUENCE_TABLE' - use USER designated SEQUENCE TABLE. User specifies the name of a DBMS Table with the schema (sequence INT) which will be used to hold sequence values (not supported yet)</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element minOccurs="0" name="db-generator-name" type="xs:string">
+ <xs:annotation>
+ <xs:documentation>For db-generator-type ORACLE this is the name of the ORACLE SEQUENCE to use. The SEQUENCE is assumed to already exist in the Database.
+If this is db-generator-type NAMED_SEQUENCE_TABLE Key Generation, this specifies the name of the SEQUENCE TABLE to use. The NAMED_SEQUENCE_TABLE is assumed to already exist in the database.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <xs:element minOccurs="0" name="db-key-cache-size" type="xs:integer">
+ <xs:annotation>
+ <xs:documentation>Size of key cache. For db-generator-type ORACLE , this value MUST match the Oracle SEQUENCE INCREMENT value. If there is a mismatch between this value and the Oracle SEQUENCE INCREMENT value, then there will likely be duplicate key problems.
+For db-generator-type NAMED_SEQUENCE_TABLE , this tells how many keys the Container will fetch in a single DBMS call.</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>