You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2006/07/19 23:35:07 UTC
svn commit: r423615 [10/44] - in /incubator/openjpa/trunk: ./
openjpa-jdbc-5/ openjpa-jdbc-5/src/ openjpa-jdbc-5/src/main/
openjpa-jdbc-5/src/main/java/ openjpa-jdbc-5/src/main/java/org/
openjpa-jdbc-5/src/main/java/org/apache/ openjpa-jdbc-5/src/main/...
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ToLowerCase.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ToLowerCase.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ToLowerCase.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ToLowerCase.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.kernel.exps;
+
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.Select;
+
+/**
+ * Lower-cases a string.
+ *
+ * @author Abe White
+ */
+class ToLowerCase
+ extends StringFunction {
+
+ /**
+ * Constructor. Provide the string to operate on.
+ */
+ public ToLowerCase(Val val) {
+ super(val);
+ }
+
+ public void initialize(Select sel, JDBCStore store, boolean nullTest) {
+ _val.initialize(sel, store, false);
+
+ DBDictionary dict = store.getDBDictionary();
+ String func = dict.toLowerCaseFunction;
+ dict.assertSupport(func != null, "ToLowerCaseFunction");
+
+ int idx = func.indexOf("{0}");
+ _pre = func.substring(0, idx);
+ _post = func.substring(idx + 3);
+ }
+}
+
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ToLowerCase.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ToUpperCase.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ToUpperCase.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ToUpperCase.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ToUpperCase.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.kernel.exps;
+
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.Select;
+
+/**
+ * Upper-cases a string.
+ *
+ * @author Abe White
+ */
+class ToUpperCase
+ extends StringFunction {
+
+ /**
+ * Constructor. Provide the string to operate on.
+ */
+ public ToUpperCase(Val val) {
+ super(val);
+ }
+
+ public void initialize(Select sel, JDBCStore store, boolean nullTest) {
+ _val.initialize(sel, store, false);
+
+ DBDictionary dict = store.getDBDictionary();
+ String func = dict.toUpperCaseFunction;
+ dict.assertSupport(func != null, "ToUpperCaseFunction");
+
+ int idx = func.indexOf("{0}");
+ _pre = func.substring(0, idx);
+ _post = func.substring(idx + 3);
+ }
+}
+
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/ToUpperCase.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Trim.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Trim.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Trim.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Trim.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,196 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.kernel.exps;
+
+import java.lang.Math;
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.Filters;
+import org.apache.openjpa.kernel.exps.Literal;
+import org.apache.openjpa.meta.ClassMetaData;
+
+/**
+ * Returns the number of characters in a string.
+ *
+ * @author Marc Prud'hommeaux
+ */
+class Trim
+ extends AbstractVal
+ implements Val {
+
+ private final Val _val;
+ private final Val _trimChar;
+ private final Boolean _where;
+ private ClassMetaData _meta = null;
+ private String _func = null;
+
+ /**
+ * Constructor. Provide the string to operate on.
+ */
+ public Trim(Val val, Val trimChar, Boolean where) {
+ _val = val;
+ _trimChar = trimChar;
+ _where = where;
+ }
+
+ public ClassMetaData getMetaData() {
+ return _meta;
+ }
+
+ public void setMetaData(ClassMetaData meta) {
+ _meta = meta;
+ }
+
+ public boolean isVariable() {
+ return false;
+ }
+
+ public Class getType() {
+ return String.class;
+ }
+
+ public void setImplicitType(Class type) {
+ }
+
+ public void initialize(Select sel, JDBCStore store, boolean nullTest) {
+ _val.initialize(sel, store, false);
+
+ DBDictionary dict = store.getDBDictionary();
+ if (_where == null) {
+ _func = dict.trimBothFunction;
+ dict.assertSupport(_func != null, "TrimBothFunction");
+ } else if (_where.equals(Boolean.TRUE)) {
+ _func = dict.trimLeadingFunction;
+ dict.assertSupport(_func != null, "TrimLeadingFunction");
+ } else if (_where.equals(Boolean.FALSE)) {
+ _func = dict.trimTrailingFunction;
+ dict.assertSupport(_func != null, "TrimTrailingFunction");
+ }
+ }
+
+ public Joins getJoins() {
+ return _val.getJoins();
+ }
+
+ public Object toDataStoreValue(Object val, JDBCStore store) {
+ return val;
+ }
+
+ public void select(Select sel, JDBCStore store, Object[] params,
+ boolean pks, JDBCFetchState fetchState) {
+ sel.select(newSQLBuffer(sel, store, params, fetchState), this);
+ }
+
+ public void selectColumns(Select sel, JDBCStore store,
+ Object[] params, boolean pks, JDBCFetchState fetchState) {
+ _val.selectColumns(sel, store, params, true, fetchState);
+ }
+
+ public void groupBy(Select sel, JDBCStore store, Object[] params,
+ JDBCFetchState fetchState) {
+ sel.groupBy(newSQLBuffer(sel, store, params, fetchState), false);
+ }
+
+ public void orderBy(Select sel, JDBCStore store, Object[] params,
+ boolean asc, JDBCFetchState fetchState) {
+ sel.orderBy(newSQLBuffer(sel, store, params, fetchState), asc, false);
+ }
+
+ private SQLBuffer newSQLBuffer(Select sel, JDBCStore store,
+ Object[] params, JDBCFetchState fetchState) {
+ calculateValue(sel, store, params, null, fetchState);
+ SQLBuffer buf = new SQLBuffer(store.getDBDictionary());
+ appendTo(buf, 0, sel, store, params, fetchState);
+ clearParameters();
+ return buf;
+ }
+
+ public Object load(Result res, JDBCStore store,
+ JDBCFetchState fetchState)
+ throws SQLException {
+ return Filters.convert(res.getObject(this,
+ JavaSQLTypes.JDBC_DEFAULT, null), getType());
+ }
+
+ public boolean hasVariable(Variable var) {
+ return _val.hasVariable(var);
+ }
+
+ public void calculateValue(Select sel, JDBCStore store,
+ Object[] params, Val other, JDBCFetchState fetchState) {
+ _val.calculateValue(sel, store, params, null, fetchState);
+ }
+
+ public void clearParameters() {
+ _val.clearParameters();
+ }
+
+ public int length() {
+ return 1;
+ }
+
+ public void appendTo(SQLBuffer sql, int index, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+ _val.calculateValue(sel, store, params, _trimChar, fetchState);
+ _trimChar.calculateValue(sel, store, params, _val, fetchState);
+
+ int fromPart = _func.indexOf("{0}");
+ int charPart = _func.indexOf("{1}");
+
+ if (charPart == -1)
+ charPart = _func.length();
+
+ String part1 = _func.substring(0, Math.min(fromPart, charPart));
+
+ String part2 = _func.substring(Math.min(fromPart, charPart) + 3,
+ Math.max(fromPart, charPart));
+
+ String part3 = null;
+ if (charPart != _func.length())
+ part3 = _func.substring(Math.max(fromPart, charPart) + 3);
+
+ sql.append(part1);
+ (fromPart < charPart ? _val : _trimChar).
+ appendTo(sql, 0, sel, store, params, fetchState);
+ sql.append(part2);
+
+ if (charPart != _func.length()) {
+ (fromPart > charPart ? _val : _trimChar).
+ appendTo(sql, 0, sel, store, params, fetchState);
+ sql.append(part3);
+ } else {
+ // since the trim statement did not specify the token for
+ // where to specify the trim char (denoted by "{1}"),
+ // we do not have the ability to trim off non-whitespace
+ // characters; throw an exception when we attempt to do so
+ if (!(_trimChar instanceof Literal)
+ || String.valueOf(((Literal) _trimChar).getValue()).
+ trim().length() != 0) {
+ store.getDBDictionary().assertSupport(false,
+ "TrimNonWhitespaceCharacters");
+ }
+ }
+ }
+}
+
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Trim.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/UnaryOp.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/UnaryOp.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/UnaryOp.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/UnaryOp.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.kernel.exps;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.JavaSQLTypes;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.Filters;
+import org.apache.openjpa.meta.ClassMetaData;
+
+/**
+ * Value produced by a unary operation on a value.
+ *
+ * @author Abe White
+ */
+abstract class UnaryOp
+ extends AbstractVal
+ implements Val {
+
+ private final Val _val;
+ private ClassMetaData _meta = null;
+ private Class _cast = null;
+
+ /**
+ * Constructor. Provide the value to operate on.
+ */
+ public UnaryOp(Val val) {
+ _val = val;
+ }
+
+ protected Val getVal() {
+ return _val;
+ }
+
+ public ClassMetaData getMetaData() {
+ return _meta;
+ }
+
+ public void setMetaData(ClassMetaData meta) {
+ _meta = meta;
+ }
+
+ public boolean isVariable() {
+ return false;
+ }
+
+ public Class getType() {
+ if (_cast != null)
+ return _cast;
+ return getType(_val.getType());
+ }
+
+ public void setImplicitType(Class type) {
+ _cast = type;
+ }
+
+ public void initialize(Select sel, JDBCStore store, boolean nullTest) {
+ _val.initialize(sel, store, false);
+ }
+
+ public Joins getJoins() {
+ return _val.getJoins();
+ }
+
+ public Object toDataStoreValue(Object val, JDBCStore store) {
+ return val;
+ }
+
+ public void select(Select sel, JDBCStore store, Object[] params,
+ boolean pks, JDBCFetchState fetchState) {
+ sel.select(newSQLBuffer(sel, store, params, fetchState), this);
+ if (isAggregate())
+ sel.setAggregate(true);
+ }
+
+ public void selectColumns(Select sel, JDBCStore store,
+ Object[] params, boolean pks, JDBCFetchState fetchState) {
+ _val.selectColumns(sel, store, params, true, fetchState);
+ }
+
+ public void groupBy(Select sel, JDBCStore store, Object[] params,
+ JDBCFetchState fetchState) {
+ sel.groupBy(newSQLBuffer(sel, store, params, fetchState), false);
+ }
+
+ public void orderBy(Select sel, JDBCStore store, Object[] params,
+ boolean asc, JDBCFetchState fetchState) {
+ sel.orderBy(newSQLBuffer(sel, store, params, fetchState), asc, false);
+ }
+
+ private SQLBuffer newSQLBuffer(Select sel, JDBCStore store,
+ Object[] params, JDBCFetchState fetchState) {
+ calculateValue(sel, store, params, null, fetchState);
+ SQLBuffer buf = new SQLBuffer(store.getDBDictionary());
+ appendTo(buf, 0, sel, store, params, fetchState);
+ clearParameters();
+ return buf;
+ }
+
+ public Object load(Result res, JDBCStore store,
+ JDBCFetchState fetchState)
+ throws SQLException {
+ return Filters.convert(res.getObject(this,
+ JavaSQLTypes.JDBC_DEFAULT, null), getType());
+ }
+
+ public boolean hasVariable(Variable var) {
+ return _val.hasVariable(var);
+ }
+
+ public void calculateValue(Select sel, JDBCStore store,
+ Object[] params, Val other, JDBCFetchState fetchState) {
+ _val.calculateValue(sel, store, params, null, fetchState);
+ }
+
+ public void clearParameters() {
+ _val.clearParameters();
+ }
+
+ public int length() {
+ return 1;
+ }
+
+ public void appendTo(SQLBuffer sql, int index, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+ sql.append(getOperator());
+ sql.append("(");
+ _val.appendTo(sql, 0, sel, store, params, fetchState);
+ sql.append(")");
+ }
+
+ /**
+ * Return whether this operator is an aggregate.
+ */
+ protected boolean isAggregate() {
+ return false;
+ }
+
+ /**
+ * Return the type of this value based on the argument type. Returns
+ * the argument type by default.
+ */
+ protected Class getType(Class c) {
+ return c;
+ }
+
+ /**
+ * Return the name of this operator.
+ */
+ protected abstract String getOperator();
+}
+
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/UnaryOp.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.kernel.exps;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.exps.Value;
+
+/**
+ * A Value represents any non-operator in a query filter, including
+ * constants, variables, and object fields.
+ *
+ * @author Abe White
+ * @nojavadoc
+ */
+public interface Val
+ extends Value {
+
+ /**
+ * Initialize the value. This method should recursively initialize any
+ * sub-values. It should also cache the {@link Joins} instance
+ * containing the joins for this value. No additional joins should be
+ * made after this call. The parent expression might modify these joins
+ * during its own initialization so that common joins are moved up the
+ * expression tree. These joins should not be included in the SQL
+ * appended through any of the <code>append</code> methods.
+ *
+ * @param sel used to create {@link Joins} instances
+ * @param store the store manager for the query
+ * @param nullTest if true, then this value will be compared
+ * to null or tested for emptiness
+ */
+ public void initialize(Select sel, JDBCStore store, boolean nullTest);
+
+ /**
+ * Return the joins for this value. These joins should be created
+ * and cached during the {@link #initialize} method. The parent
+ * expression might modify these joins during its own initialization so
+ * that common joins are moved up the expression tree.
+ */
+ public Joins getJoins();
+
+ /**
+ * Return the datastore value of the given object in the context of this
+ * value.
+ */
+ public Object toDataStoreValue(Object val, JDBCStore store);
+
+ /**
+ * Select the data for this value.
+ */
+ public void select(Select sel, JDBCStore store, Object[] params,
+ boolean pks, JDBCFetchState fetchState);
+
+ /**
+ * Select just the columns for this value.
+ */
+ public void selectColumns(Select sel, JDBCStore store, Object[] params,
+ boolean pks, JDBCFetchState fetchState);
+
+ /**
+ * Group by this value.
+ */
+ public void groupBy(Select sel, JDBCStore store, Object[] params,
+ JDBCFetchState fetchState);
+
+ /**
+ * Order by this value.
+ */
+ public void orderBy(Select sel, JDBCStore store, Object[] params,
+ boolean asc, JDBCFetchState fetchState);
+
+ /**
+ * Load the data for this value.
+ */
+ public Object load(Result res, JDBCStore store,
+ JDBCFetchState fetchState)
+ throws SQLException;
+
+ /**
+ * Return true if this value uses the given variable.
+ */
+ public boolean hasVariable(Variable var);
+
+ /**
+ * Calculate and cache the SQL for this value. This method is called
+ * before <code>length</code> or any <code>append</code> methods.
+ *
+ * @param other the value being compared to, or null if not a comparison
+ */
+ public void calculateValue(Select sel, JDBCStore store,
+ Object[] params, Val other, JDBCFetchState fetchState);
+
+ /**
+ * Clear parameter values held by this value or its subcomponents.
+ * This method is called sometime after <code>calculateValue</code>.
+ */
+ public void clearParameters();
+
+ /**
+ * Return the number of SQL elements in this value.
+ */
+ public int length();
+
+ /**
+ * Append the <code>index</code>th SQL element to the given buffer.
+ */
+ public void appendTo(SQLBuffer sql, int index, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState);
+
+ /**
+ * Append the SQL testing whether this value is empty to the given buffer.
+ */
+ public void appendIsEmpty(SQLBuffer sql, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState);
+
+ /**
+ * Append the SQL testing whether this value is not empty to
+ * the given buffer.
+ */
+ public void appendIsNotEmpty(SQLBuffer sql, Select sel, JDBCStore store,
+ Object[] params, JDBCFetchState fetchState);
+
+ /**
+ * Append the SQL checking the size of this value.
+ */
+ public void appendSize(SQLBuffer sql, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState);
+
+ /**
+ * Append the SQL testing whether this value is null to the given buffer.
+ */
+ public void appendIsNull(SQLBuffer sql, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState);
+
+ /**
+ * Append the SQL testing whether this value is not null to the given
+ * buffer.
+ */
+ public void appendIsNotNull(SQLBuffer sql, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState);
+}
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Val.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Variable.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Variable.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Variable.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Variable.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.kernel.exps;
+
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchState;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.SQLBuffer;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.meta.ClassMetaData;
+
+/**
+ * A variable in a filter. Typically, the {@link #initialize} and
+ * {@link #getJoins} methods of this value are not called. They are
+ * only called if the variable is bound but otherwise unused in the filter,
+ * in which case we must at least make the joins to the variable because the
+ * act of binding a variable should at least guarantee that an instance
+ * represting the variable could exist (i.e. the binding collection is not
+ * empty).
+ *
+ * @author Abe White
+ */
+class Variable
+ implements Val {
+
+ private final String _name;
+ private final Class _type;
+ private ClassMetaData _meta;
+ private PCPath _path = null;
+ private Class _cast = null;
+
+ /**
+ * Constructor. Supply variable name and type.
+ */
+ public Variable(String name, Class type) {
+ _name = name;
+ _type = type;
+ }
+
+ /**
+ * Return the variable name.
+ */
+ public String getName() {
+ return _name;
+ }
+
+ /**
+ * Return true if the variable is bound.
+ */
+ public boolean isBound() {
+ return _path != null;
+ }
+
+ /**
+ * Return the path this variable is aliased to.
+ */
+ public PCPath getPCPath() {
+ return _path;
+ }
+
+ /**
+ * Set the path this variable is aliased to.
+ */
+ public void setPCPath(PCPath path) {
+ _path = path;
+ }
+
+ public ClassMetaData getMetaData() {
+ return _meta;
+ }
+
+ public void setMetaData(ClassMetaData meta) {
+ _meta = meta;
+ }
+
+ public boolean isVariable() {
+ return true;
+ }
+
+ public Class getType() {
+ if (_cast != null)
+ return _cast;
+ return _type;
+ }
+
+ public void setImplicitType(Class type) {
+ _cast = type;
+ if (_path != null)
+ _path.setImplicitType(type);
+ }
+
+ public void initialize(Select sel, JDBCStore store, boolean nullTest) {
+ if (_path != null) {
+ _path.addVariableAction(this);
+ _path.initialize(sel, store, nullTest);
+ _path.joinRelation();
+ }
+ }
+
+ public Joins getJoins() {
+ return (_path == null) ? null : _path.getJoins();
+ }
+
+ public Object toDataStoreValue(Object val, JDBCStore store) {
+ return val;
+ }
+
+ public void select(Select sel, JDBCStore store, Object[] params,
+ boolean pks, JDBCFetchState fetchState) {
+ }
+
+ public void selectColumns(Select sel, JDBCStore store,
+ Object[] params, boolean pks, JDBCFetchState fetchState) {
+ }
+
+ public void groupBy(Select sel, JDBCStore store, Object[] params,
+ JDBCFetchState fetchState) {
+ }
+
+ public void orderBy(Select sel, JDBCStore store, Object[] params,
+ boolean asc, JDBCFetchState fetchState) {
+ }
+
+ public Object load(Result res, JDBCStore store,
+ JDBCFetchState fetchState)
+ throws SQLException {
+ return null;
+ }
+
+ public boolean hasVariable(Variable var) {
+ return this == var;
+ }
+
+ public void calculateValue(Select sel, JDBCStore store,
+ Object[] params, Val other, JDBCFetchState fetchState) {
+ if (_path != null)
+ _path.calculateValue(sel, store, params, other, fetchState);
+ }
+
+ public void clearParameters() {
+ if (_path != null)
+ _path.clearParameters();
+ }
+
+ public int length() {
+ return 0;
+ }
+
+ public void appendTo(SQLBuffer sql, int index, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+ }
+
+ public void appendIsEmpty(SQLBuffer sql, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+ }
+
+ public void appendIsNotEmpty(SQLBuffer sql, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+ }
+
+ public void appendSize(SQLBuffer sql, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+ }
+
+ public void appendIsNull(SQLBuffer sql, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+ }
+
+ public void appendIsNotNull(SQLBuffer sql, Select sel,
+ JDBCStore store, Object[] params, JDBCFetchState fetchState) {
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/Variable.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/package.html
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/package.html?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/package.html (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/package.html Wed Jul 19 14:34:44 2006
@@ -0,0 +1,5 @@
+<html>
+<body>
+<p><strong>OpenJPA-JDBC Expression Tree</strong></p>
+</body>
+</html>
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/package.html
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/package.html
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/package.html?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/package.html (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/package.html Wed Jul 19 14:34:44 2006
@@ -0,0 +1,9 @@
+<html>
+<body>
+<p><strong>OpenJPA-JDBC Runtime Kernel</strong></p>
+
+<p>
+ Runtime services for the JDBC OpenJPA implementation.
+</p>
+</body>
+</html>
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/package.html
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,957 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.set.ListOrderedSet;
+import org.apache.openjpa.enhance.PersistenceCapable;
+import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.meta.strats.NoneClassStrategy;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ColumnIO;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+import org.apache.openjpa.jdbc.schema.Schemas;
+import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.RowManager;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.FetchConfiguration;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.kernel.PCState;
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.rop.ResultObjectProvider;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.meta.ClassMetaData;
+import org.apache.openjpa.meta.ValueMetaData;
+import org.apache.openjpa.util.ApplicationIds;
+import org.apache.openjpa.util.InternalException;
+import org.apache.openjpa.util.MetaDataException;
+import org.apache.openjpa.util.OpenJPAId;
+
+/**
+ * Specialization of metadata for relational databases.
+ *
+ * @author Abe White
+ */
+public class ClassMapping
+ extends ClassMetaData
+ implements ClassStrategy {
+
+ public static final ClassMapping[] EMPTY_MAPPINGS = new ClassMapping[0];
+
+ private static final Localizer _loc = Localizer.forPackage
+ (ClassMapping.class);
+
+ private final ClassMappingInfo _info;
+ private final Discriminator _discrim;
+ private final Version _version;
+ private ClassStrategy _strategy = null;
+
+ private Table _table = null;
+ private ColumnIO _io = null;
+ private Column[] _cols = Schemas.EMPTY_COLUMNS;
+ private ForeignKey _fk = null;
+ private int _subclassMode = Integer.MAX_VALUE;
+
+ private ClassMapping[] _joinSubMaps = null;
+ private ClassMapping[] _assignMaps = null;
+
+ // maps columns to joinables
+ private final Map _joinables = Collections.synchronizedMap(new HashMap());
+
+ /**
+ * Constructor. Supply described type and owning repository.
+ */
+ protected ClassMapping(Class type, MappingRepository repos) {
+ super(type, repos);
+ _discrim = repos.newDiscriminator(this);
+ _version = repos.newVersion(this);
+ _info = repos.newMappingInfo(this);
+ }
+
+ /**
+ * Embedded constructor. Supply embedding value and owning repository.
+ */
+ protected ClassMapping(ValueMetaData vmd) {
+ super(vmd);
+ _discrim = getMappingRepository().newDiscriminator(this);
+ _version = getMappingRepository().newVersion(this);
+ _info = getMappingRepository().newMappingInfo(this);
+ }
+
+ /**
+ * The class discriminator.
+ */
+ public Discriminator getDiscriminator() {
+ return _discrim;
+ }
+
+ /**
+ * The version indicator.
+ */
+ public Version getVersion() {
+ return _version;
+ }
+
+ ///////////
+ // Runtime
+ ///////////
+
+ /**
+ * Return the oid value stored in the result. This implementation will
+ * recurse until it finds an ancestor class who uses oid values for its
+ * primary key.
+ *
+ * @param fk if non-null, use the local columns of the given foreign
+ * key in place of this class' primary key columns
+ * @see #isPrimaryKeyObjectId
+ */
+ public Object getObjectId(JDBCStore store, Result res, ForeignKey fk,
+ boolean subs, Joins joins)
+ throws SQLException {
+ ValueMapping embed = getEmbeddingMapping();
+ if (embed != null)
+ return embed.getFieldMapping().getDefiningMapping().
+ getObjectId(store, res, fk, subs, joins);
+
+ return getObjectId(this, store, res, fk, subs, joins);
+ }
+
+ /**
+ * Recursive helper for public <code>getObjectId</code> method.
+ */
+ private Object getObjectId(ClassMapping cls, JDBCStore store, Result res,
+ ForeignKey fk, boolean subs, Joins joins)
+ throws SQLException {
+ if (!isPrimaryKeyObjectId(true))
+ return getPCSuperclassMapping().getObjectId(cls, store, res, fk,
+ subs, joins);
+ if (getIdentityType() == ID_UNKNOWN)
+ throw new InternalException();
+
+ Column[] pks = getPrimaryKeyColumns();
+ if (getIdentityType() == ID_DATASTORE) {
+ Column col = (fk == null) ? pks[0] : fk.getColumn(pks[0]);
+ long id = res.getLong(col, joins);
+ return (id == 0 && res.wasNull()) ? null
+ : store.newDataStoreId(id, cls, subs);
+ }
+
+ // application identity
+ Object[] vals = new Object[getPrimaryKeyFields().length];
+ FieldMapping fm;
+ Joinable join;
+ int pkIdx;
+ for (int i = 0; i < pks.length; i++) {
+ // we know that all pk column join mappings use primary key fields,
+ // cause this mapping uses the oid as its primary key (we recursed
+ // at the beginning of the method to ensure this)
+ join = assertJoinable(pks[i]);
+ fm = getFieldMapping(join.getFieldIndex());
+ pkIdx = fm.getPrimaryKeyIndex();
+
+ // could have already set value with previous multi-column joinable
+ if (vals[pkIdx] == null) {
+ res.startDataRequest(fm);
+ vals[pkIdx] = join.getPrimaryKeyValue(res, join.getColumns(),
+ fk, joins);
+ res.endDataRequest();
+ if (vals[pkIdx] == null)
+ return null;
+ }
+ }
+ Object oid = ApplicationIds.fromPKValues(vals, cls);
+ if (!subs && oid instanceof OpenJPAId)
+ ((OpenJPAId) oid).setManagedInstanceType(cls.getDescribedType());
+ return oid;
+ }
+
+ /**
+ * Return the given column value(s) for the given object. The given
+ * columns will be primary key columns of this mapping, but may be in
+ * any order. If there is only one column, return its value. If there
+ * are multiple columns, return an object array of their values, in the
+ * same order the columns are given.
+ */
+ public Object toDataStoreValue(Object obj, Column[] cols, JDBCStore store) {
+ Object ret = (cols.length == 1) ? null : new Object[cols.length];
+
+ // in the past we've been lenient about being able to translate objects
+ // from other persistence contexts, so try to get sm directly from
+ // instance before asking our context
+ OpenJPAStateManager sm;
+ if (obj instanceof PersistenceCapable)
+ sm = (OpenJPAStateManager) ((PersistenceCapable) obj).
+ pcGetStateManager();
+ else
+ sm = store.getContext().getStateManager(obj);
+ if (sm == null)
+ return ret;
+
+ Object val;
+ for (int i = 0; i < cols.length; i++) {
+ val = assertJoinable(cols[i]).getJoinValue(sm, cols[i], store);
+ if (cols.length == 1)
+ ret = val;
+ else
+ ((Object[]) ret)[i] = val;
+ }
+ return ret;
+ }
+
+ /**
+ * Return the joinable for the given column, or throw an exception if
+ * none is available.
+ */
+ public Joinable assertJoinable(Column col) {
+ Joinable join = getJoinable(col);
+ if (join == null)
+ throw new MetaDataException(_loc.get("no-joinable",
+ col.getFullName()));
+ return join;
+ }
+
+ /**
+ * Return the {@link Joinable} for the given column. Any column that
+ * another mapping joins to must be controlled by a joinable.
+ */
+ public Joinable getJoinable(Column col) {
+ Joinable join;
+ if (getEmbeddingMetaData() != null) {
+ join = getEmbeddingMapping().getFieldMapping().
+ getDefiningMapping().getJoinable(col);
+ if (join != null)
+ return join;
+ }
+ ClassMapping sup = getJoinablePCSuperclassMapping();
+ if (sup != null) {
+ join = sup.getJoinable(col);
+ if (join != null)
+ return join;
+ }
+ return (Joinable) _joinables.get(col);
+ }
+
+ /**
+ * Add the given column-to-joinable mapping.
+ */
+ public void setJoinable(Column col, Joinable joinable) {
+ // don't let non-pk override pk
+ Joinable join = (Joinable) _joinables.get(col);
+ if (join == null || (join.getFieldIndex() != -1
+ && getField(join.getFieldIndex()).getPrimaryKeyIndex() == -1))
+ _joinables.put(col, joinable);
+ }
+
+ /**
+ * Return whether the columns of the given foreign key to this mapping
+ * can be used to construct an object id for this type. This is a
+ * relatively expensive operation; its results should be cached.
+ *
+ * @return {@link Boolean#TRUE} if the foreign key contains all oid
+ * columns, <code>null</code> if it contains only some columns,
+ * or {@link Boolean#FALSE} if it contains non-oid columns
+ */
+ public Boolean isForeignKeyObjectId(ForeignKey fk) {
+ // if this mapping's primary key can't construct an oid, then no way
+ // foreign key can
+ if (getIdentityType() == ID_UNKNOWN || !isPrimaryKeyObjectId(false))
+ return Boolean.FALSE;
+
+ // with datastore identity, it's all or nothing
+ Column[] cols = fk.getPrimaryKeyColumns();
+ if (getIdentityType() == ID_DATASTORE) {
+ if (cols.length != 1 || cols[0] != getPrimaryKeyColumns()[0])
+ return Boolean.FALSE;
+ return Boolean.TRUE;
+ }
+
+ // check the join mapping for each pk column to see if it links up to
+ // a primary key field
+ Joinable join;
+ for (int i = 0; i < cols.length; i++) {
+ join = assertJoinable(cols[i]);
+ if (join.getFieldIndex() != -1
+ && getField(join.getFieldIndex()).getPrimaryKeyIndex() == -1)
+ return Boolean.FALSE;
+ }
+
+ // if all primary key links, see whether we join to all pks
+ if (isPrimaryKeyObjectId(true)
+ && cols.length == getPrimaryKeyColumns().length)
+ return Boolean.TRUE;
+ return null;
+ }
+
+ ///////
+ // ORM
+ ///////
+
+ /**
+ * Raw mapping data.
+ */
+ public ClassMappingInfo getMappingInfo() {
+ return _info;
+ }
+
+ /**
+ * The strategy used to map this mapping.
+ */
+ public ClassStrategy getStrategy() {
+ return _strategy;
+ }
+
+ /**
+ * The strategy used to map this mapping. The <code>adapt</code>
+ * parameter determines whether to adapt when mapping the strategy;
+ * use null if the strategy should not be mapped.
+ */
+ public void setStrategy(ClassStrategy strategy, Boolean adapt) {
+ // set strategy first so we can access it during mapping
+ ClassStrategy orig = _strategy;
+ _strategy = strategy;
+ if (strategy != null) {
+ try {
+ strategy.setClassMapping(this);
+ if (adapt != null)
+ strategy.map(adapt.booleanValue());
+ } catch (RuntimeException re) {
+ // reset strategy
+ _strategy = orig;
+ throw re;
+ }
+ }
+ }
+
+ /**
+ * The mapping's primary table.
+ */
+ public Table getTable() {
+ return _table;
+ }
+
+ /**
+ * The mapping's primary table.
+ */
+ public void setTable(Table table) {
+ _table = table;
+ }
+
+ /**
+ * The columns this mapping uses to uniquely identify an object.
+ * These will typically be the primary key columns or the columns this
+ * class uses to link to its superclass table.
+ */
+ public Column[] getPrimaryKeyColumns() {
+ if (_cols.length == 0 && getIdentityType() == ID_APPLICATION
+ && isMapped()) {
+ FieldMapping[] pks = getPrimaryKeyFieldMappings();
+ Collection cols = new ArrayList(pks.length);
+ Column[] fieldCols;
+ for (int i = 0; i < pks.length; i++) {
+ fieldCols = pks[i].getColumns();
+ for (int j = 0; j < fieldCols.length; j++)
+ cols.add(fieldCols[j]);
+ }
+ _cols = (Column[]) cols.toArray(new Column[cols.size()]);
+ }
+ return _cols;
+ }
+
+ /**
+ * The columns this mapping uses to uniquely identify an object.
+ * These will typically be the primary key columns or the columns this
+ * class uses to link to its superclass table.
+ */
+ public void setPrimaryKeyColumns(Column[] cols) {
+ if (cols == null)
+ cols = Schemas.EMPTY_COLUMNS;
+ _cols = cols;
+ }
+
+ /**
+ * I/O information on the key columns / join key.
+ */
+ public ColumnIO getColumnIO() {
+ return (_io == null) ? ColumnIO.UNRESTRICTED : _io;
+ }
+
+ /**
+ * I/O information on the key columns / join key.
+ */
+ public void setColumnIO(ColumnIO io) {
+ _io = io;
+ }
+
+ /**
+ * Foreign key linking the primary key columns to the superclass table,
+ * or null if none.
+ */
+ public ForeignKey getJoinForeignKey() {
+ return _fk;
+ }
+
+ /**
+ * Foreign key linking the primary key columns to the superclass table,
+ * or null if none.
+ */
+ public void setJoinForeignKey(ForeignKey fk) {
+ _fk = fk;
+ }
+
+ public void refSchemaComponents() {
+ if (getEmbeddingMetaData() == null) {
+ if (_table != null && _table.getPrimaryKey() != null)
+ _table.getPrimaryKey().ref();
+ if (_fk != null)
+ _fk.ref();
+ Column[] pks = getPrimaryKeyColumns();
+ for (int i = 0; i < pks.length; i++)
+ pks[i].ref();
+ } else {
+ FieldMapping[] fields = getFieldMappings();
+ for (int i = 0; i < fields.length; i++)
+ fields[i].refSchemaComponents();
+ }
+ }
+
+ /**
+ * Clear mapping information, including strategy.
+ */
+ public void clearMapping() {
+ _strategy = null;
+ _cols = Schemas.EMPTY_COLUMNS;
+ _fk = null;
+ _table = null;
+ _info.clear();
+ setResolve(MODE_MAPPING | MODE_MAPPING_INIT, false);
+ }
+
+ /**
+ * Update {@link MappingInfo} with our current mapping information.
+ */
+ public void syncMappingInfo() {
+ if (getEmbeddingMetaData() == null)
+ _info.syncWith(this);
+ else {
+ _info.clear();
+ FieldMapping[] fields = getFieldMappings();
+ for (int i = 0; i < fields.length; i++)
+ fields[i].syncMappingInfo();
+ }
+ }
+
+ //////////////////////
+ // MetaData interface
+ //////////////////////
+
+ protected void setDescribedType(Class type) {
+ super.setDescribedType(type);
+ // this method called from superclass constructor, so _info not yet
+ // initialized
+ if (_info != null)
+ _info.setClassName(type.getName());
+ }
+
+ /**
+ * The subclass fetch mode, as one of the eager constants in
+ * {@link JDBCFetchConfiguration}.
+ */
+ public int getSubclassFetchMode() {
+ if (_subclassMode == Integer.MAX_VALUE) {
+ if (getPCSuperclass() != null)
+ _subclassMode = getPCSuperclassMapping().
+ getSubclassFetchMode();
+ else
+ _subclassMode = FetchConfiguration.DEFAULT;
+ }
+ return _subclassMode;
+ }
+
+ /**
+ * The subclass fetch mode, as one of the eager constants in
+ * {@link JDBCFetchConfiguration}.
+ */
+ public void setSubclassFetchMode(int mode) {
+ _subclassMode = mode;
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getRepository}.
+ */
+ public MappingRepository getMappingRepository() {
+ return (MappingRepository) getRepository();
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getEmbeddingMetaData}
+ */
+ public ValueMapping getEmbeddingMapping() {
+ return (ValueMapping) getEmbeddingMetaData();
+ }
+
+ /**
+ * Returns true if this class does not use the "none" strategy (including
+ * if it has a null strategy, and therefore is probably in the process of
+ * being mapped).
+ */
+ public boolean isMapped() {
+ if (!super.isMapped())
+ return false;
+ if (_strategy != null)
+ return _strategy != NoneClassStrategy.getInstance();
+ return !NoneClassStrategy.ALIAS.equals(_info.getStrategy());
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getPCSuperclassMetaData}.
+ */
+ public ClassMapping getPCSuperclassMapping() {
+ return (ClassMapping) getPCSuperclassMetaData();
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getMappedPCSuperclassMetaData}.
+ */
+ public ClassMapping getMappedPCSuperclassMapping() {
+ return (ClassMapping) getMappedPCSuperclassMetaData();
+ }
+
+ /**
+ * Return the nearest mapped superclass that can join to this class.
+ */
+ public ClassMapping getJoinablePCSuperclassMapping() {
+ ClassMapping sup = getMappedPCSuperclassMapping();
+ if (sup == null)
+ return null;
+ if (_fk != null || _table == null || _table.equals(sup.getTable()))
+ return sup;
+ return null;
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getPCSubclassMetaDatas}.
+ */
+ public ClassMapping[] getPCSubclassMappings() {
+ return (ClassMapping[]) getPCSubclassMetaDatas();
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getMappedPCSubclassMetaDatas}.
+ */
+ public ClassMapping[] getMappedPCSubclassMappings() {
+ return (ClassMapping[]) getMappedPCSubclassMetaDatas();
+ }
+
+ /**
+ * Return mapped subclasses that are reachable via joins.
+ */
+ public ClassMapping[] getJoinablePCSubclassMappings() {
+ ClassMapping[] subs = getMappedPCSubclassMappings(); // checks for new
+ if (_joinSubMaps == null) {
+ if (subs.length == 0)
+ _joinSubMaps = subs;
+ else {
+ List joinable = new ArrayList(subs.length);
+ for (int i = 0; i < subs.length; i++)
+ if (isSubJoinable(subs[i]))
+ joinable.add(subs[i]);
+ _joinSubMaps = (ClassMapping[]) joinable.toArray
+ (new ClassMapping[joinable.size()]);
+ }
+ }
+ return _joinSubMaps;
+ }
+
+ /**
+ * Return whether we can reach the given subclass via joins.
+ */
+ private boolean isSubJoinable(ClassMapping sub) {
+ if (sub == null)
+ return false;
+ if (sub == this)
+ return true;
+ return isSubJoinable(sub.getJoinablePCSuperclassMapping());
+ }
+
+ /**
+ * Returns the closest-derived list of non-inter-joinable mapped types
+ * assignable to this type. May return this mapping.
+ */
+ public ClassMapping[] getIndependentAssignableMappings() {
+ ClassMapping[] subs = getMappedPCSubclassMappings(); // checks for new
+ if (_assignMaps == null) {
+ // remove unmapped subs
+ if (subs.length == 0) {
+ if (isMapped())
+ _assignMaps = new ClassMapping[]{ this };
+ else
+ _assignMaps = subs;
+ } else {
+ int size = (int) (subs.length * 1.33 + 2);
+ Set independent = ListOrderedSet.decorate(new HashSet(size),
+ new ArrayList(subs.length + 1));
+ if (isMapped())
+ independent.add(this);
+ independent.addAll(Arrays.asList(subs));
+
+ // remove all mappings that have a superclass mapping in the set
+ ClassMapping map, sup;
+ List clear = null;
+ for (Iterator itr = independent.iterator(); itr.hasNext();) {
+ map = (ClassMapping) itr.next();
+ sup = map.getJoinablePCSuperclassMapping();
+ if (sup != null && independent.contains(sup)) {
+ if (clear == null)
+ clear = new ArrayList(independent.size() - 1);
+ clear.add(map);
+ }
+ }
+ if (clear != null)
+ independent.removeAll(clear);
+
+ _assignMaps = (ClassMapping[]) independent.toArray
+ (new ClassMapping[independent.size()]);
+ }
+ }
+ return _assignMaps;
+ }
+
+ /**
+ * Convenience method to perform cast from {@link ClassMetaData#getFields}.
+ */
+ public FieldMapping[] getFieldMappings() {
+ return (FieldMapping[]) getFields();
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getDeclaredFields}.
+ */
+ public FieldMapping[] getDeclaredFieldMappings() {
+ return (FieldMapping[]) getDeclaredFields();
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getPrimaryKeyFields}.
+ */
+ public FieldMapping[] getPrimaryKeyFieldMappings() {
+ return (FieldMapping[]) getPrimaryKeyFields();
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getVersionField}.
+ */
+ public FieldMapping getVersionFieldMapping() {
+ return (FieldMapping) getVersionField();
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getDefaultFetchGroupFields}.
+ */
+ public FieldMapping[] getDefaultFetchGroupFieldMappings() {
+ return (FieldMapping[]) getDefaultFetchGroupFields();
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getDefinedFields}.
+ */
+ public FieldMapping[] getDefinedFieldMappings() {
+ return (FieldMapping[]) getDefinedFields();
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getFieldsInListingOrder}.
+ */
+ public FieldMapping[] getFieldMappingsInListingOrder() {
+ return (FieldMapping[]) getFieldsInListingOrder();
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getDefinedFieldsInListingOrder}.
+ */
+ public FieldMapping[] getDefinedFieldMappingsInListingOrder() {
+ return (FieldMapping[]) getDefinedFieldsInListingOrder();
+ }
+
+ /**
+ * Convenience method to perform cast from {@link ClassMetaData#getField}.
+ */
+ public FieldMapping getFieldMapping(int index) {
+ return (FieldMapping) getField(index);
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getDeclaredField}.
+ */
+ public FieldMapping getDeclaredFieldMapping(int index) {
+ return (FieldMapping) getDeclaredField(index);
+ }
+
+ /**
+ * Convenience method to perform cast from {@link ClassMetaData#getField}.
+ */
+ public FieldMapping getFieldMapping(String name) {
+ return (FieldMapping) getField(name);
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getDeclaredField}.
+ */
+ public FieldMapping getDeclaredFieldMapping(String name) {
+ return (FieldMapping) getDeclaredField(name);
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#getDeclaredUnmanagedFields}.
+ */
+ public FieldMapping[] getDeclaredUnmanagedFieldMappings() {
+ return (FieldMapping[]) getDeclaredUnmanagedFields();
+ }
+
+ /**
+ * Convenience method to perform cast from
+ * {@link ClassMetaData#addDeclaredField}.
+ */
+ public FieldMapping addDeclaredFieldMapping(String name, Class type) {
+ return (FieldMapping) addDeclaredField(name, type);
+ }
+
+ protected void resolveMapping(boolean runtime) {
+ super.resolveMapping(runtime);
+
+ // map class strategy; it may already be mapped by the repository before
+ // the resolve process begins
+ MappingRepository repos = getMappingRepository();
+ if (_strategy == null)
+ repos.getStrategyInstaller().installStrategy(this);
+ Log log = getRepository().getLog();
+ if (log.isTraceEnabled())
+ log.trace(_loc.get("strategy", this, _strategy.getAlias()));
+
+ // make sure unmapped superclass fields are defined if we're mapped;
+ // also may have been done by repository already
+ defineSuperclassFields(getJoinablePCSuperclassMapping() == null);
+
+ // resolve everything that doesn't rely on any relations to avoid
+ // recursion, then resolve all fields
+ resolveNonRelationMappings();
+ FieldMapping[] fms = getFieldMappings();
+ for (int i = 0; i < fms.length; i++)
+ if (fms[i].getDefiningMetaData() == this)
+ fms[i].resolve(MODE_MAPPING);
+ fms = getDeclaredUnmanagedFieldMappings();
+ for (int i = 0; i < fms.length; i++)
+ fms[i].resolve(MODE_MAPPING);
+
+ // mark mapped columns
+ if (_cols != null) {
+ ColumnIO io = getColumnIO();
+ for (int i = 0; i < _cols.length; i++) {
+ if (io.isInsertable(i, false))
+ _cols[i].setFlag(Column.FLAG_DIRECT_INSERT, true);
+ if (io.isUpdatable(i, false))
+ _cols[i].setFlag(Column.FLAG_DIRECT_UPDATE, true);
+ }
+ }
+ }
+
+ /**
+ * Resolve non-relation field mappings so that when we do relation
+ * mappings they can rely on them for joins.
+ */
+ void resolveNonRelationMappings() {
+ // make sure primary key fields are resolved first because other
+ // fields might rely on them
+ FieldMapping[] fms = getPrimaryKeyFieldMappings();
+ for (int i = 0; i < fms.length; i++)
+ fms[i].resolve(MODE_MAPPING);
+
+ // resolve defined fields that are safe; that don't rely on other types
+ // also being resolved. don't use getDefinedFields b/c it relies on
+ // whether fields are mapped, which isn't known yet
+ fms = getFieldMappings();
+ for (int i = 0; i < fms.length; i++)
+ if (fms[i].getDefiningMetaData() == this
+ && !fms[i].isTypePC() && !fms[i].getKey().isTypePC()
+ && !fms[i].getElement().isTypePC())
+ fms[i].resolve(MODE_MAPPING);
+
+ _discrim.resolve(MODE_MAPPING);
+ _version.resolve(MODE_MAPPING);
+ }
+
+ protected void initializeMapping() {
+ super.initializeMapping();
+
+ FieldMapping[] fields = getDefinedFieldMappings();
+ for (int i = 0; i < fields.length; i++)
+ fields[i].resolve(MODE_MAPPING_INIT);
+ _discrim.resolve(MODE_MAPPING_INIT);
+ _version.resolve(MODE_MAPPING_INIT);
+ _strategy.initialize();
+ }
+
+ protected void clearDefinedFieldCache() {
+ // just make this method available to other classes in this package
+ super.clearDefinedFieldCache();
+ }
+
+ protected void clearSubclassCache() {
+ super.clearSubclassCache();
+ _joinSubMaps = null;
+ _assignMaps = null;
+ }
+
+ public void copy(ClassMetaData cls) {
+ super.copy(cls);
+ if (_subclassMode == Integer.MAX_VALUE)
+ _subclassMode = ((ClassMapping) cls).getSubclassFetchMode();
+ }
+
+ protected boolean validateDataStoreExtensionPrefix(String prefix) {
+ return "jdbc-".equals(prefix);
+ }
+
+ ////////////////////////////////
+ // ClassStrategy implementation
+ ////////////////////////////////
+
+ public String getAlias() {
+ return assertStrategy().getAlias();
+ }
+
+ public void map(boolean adapt) {
+ assertStrategy().map(adapt);
+ }
+
+ public void initialize() {
+ assertStrategy().initialize();
+ }
+
+ public void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+ throws SQLException {
+ assertStrategy().insert(sm, store, rm);
+ }
+
+ public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+ throws SQLException {
+ assertStrategy().update(sm, store, rm);
+ }
+
+ public void delete(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
+ throws SQLException {
+ assertStrategy().delete(sm, store, rm);
+ }
+
+ public Boolean isCustomInsert(OpenJPAStateManager sm, JDBCStore store) {
+ return assertStrategy().isCustomInsert(sm, store);
+ }
+
+ public Boolean isCustomUpdate(OpenJPAStateManager sm, JDBCStore store) {
+ return assertStrategy().isCustomUpdate(sm, store);
+ }
+
+ public Boolean isCustomDelete(OpenJPAStateManager sm, JDBCStore store) {
+ return assertStrategy().isCustomDelete(sm, store);
+ }
+
+ public void customInsert(OpenJPAStateManager sm, JDBCStore store)
+ throws SQLException {
+ assertStrategy().customInsert(sm, store);
+ }
+
+ public void customUpdate(OpenJPAStateManager sm, JDBCStore store)
+ throws SQLException {
+ assertStrategy().customUpdate(sm, store);
+ }
+
+ public void customDelete(OpenJPAStateManager sm, JDBCStore store)
+ throws SQLException {
+ assertStrategy().customDelete(sm, store);
+ }
+
+ public void setClassMapping(ClassMapping owner) {
+ assertStrategy().setClassMapping(owner);
+ }
+
+ public boolean isPrimaryKeyObjectId(boolean hasAll) {
+ return assertStrategy().isPrimaryKeyObjectId(hasAll);
+ }
+
+ public Joins joinSuperclass(Joins joins, boolean toThis) {
+ return assertStrategy().joinSuperclass(joins, toThis);
+ }
+
+ public boolean supportsEagerSelect(Select sel, OpenJPAStateManager sm,
+ JDBCStore store, ClassMapping base, JDBCFetchConfiguration fetch) {
+ return assertStrategy().supportsEagerSelect(sel, sm, store, base,
+ fetch);
+ }
+
+ public ResultObjectProvider customLoad(JDBCStore store, boolean subclasses,
+ JDBCFetchConfiguration fetch, long startIdx, long endIdx)
+ throws SQLException {
+ return assertStrategy().customLoad(store, subclasses, fetch,
+ startIdx, endIdx);
+ }
+
+ public boolean customLoad(OpenJPAStateManager sm, JDBCStore store,
+ PCState state, JDBCFetchConfiguration fetch)
+ throws SQLException, ClassNotFoundException {
+ return assertStrategy().customLoad(sm, store, state, fetch);
+ }
+
+ public boolean customLoad(OpenJPAStateManager sm, JDBCStore store,
+ JDBCFetchConfiguration fetch, Result result)
+ throws SQLException {
+ return assertStrategy().customLoad(sm, store, fetch, result);
+ }
+
+ private ClassStrategy assertStrategy() {
+ if (_strategy == null)
+ throw new InternalException();
+ return _strategy;
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMapping.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMappingInfo.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMappingInfo.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMappingInfo.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMappingInfo.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,341 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.io.File;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.openjpa.jdbc.meta.strats.FullClassStrategy;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+import org.apache.openjpa.jdbc.schema.Schema;
+import org.apache.openjpa.jdbc.schema.SchemaGroup;
+import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.lib.meta.SourceTracker;
+import org.apache.openjpa.lib.xml.Commentable;
+
+/**
+ * Information about the mapping from a class to the schema, in raw form.
+ * The columns and tables used in mapping info will not be part of the
+ * {@link SchemaGroup} used at runtime. Rather, they will be structs
+ * with the relevant pieces of information filled in.
+ *
+ * @author Abe White
+ */
+public class ClassMappingInfo
+ extends MappingInfo
+ implements SourceTracker, Commentable {
+
+ private String _className = Object.class.getName();
+ private String _tableName = null;
+ private boolean _joined = false;
+ private Map _seconds = null;
+ private String _subStrat = null;
+ private File _file = null;
+ private int _srcType = SRC_OTHER;
+ private String[] _comments = null;
+
+ /**
+ * The described class name.
+ */
+ public String getClassName() {
+ return _className;
+ }
+
+ /**
+ * The described class name.
+ */
+ public void setClassName(String name) {
+ _className = name;
+ }
+
+ /**
+ * The default strategy for subclasses in this hierarchy.
+ */
+ public String getHierarchyStrategy() {
+ return _subStrat;
+ }
+
+ /**
+ * The default strategy for subclasses in this hierarchy.
+ */
+ public void setHierarchyStrategy(String strategy) {
+ _subStrat = strategy;
+ }
+
+ /**
+ * The given table name.
+ */
+ public String getTableName() {
+ return _tableName;
+ }
+
+ /**
+ * The given table name.
+ */
+ public void setTableName(String table) {
+ _tableName = table;
+ }
+
+ /**
+ * Whether there is a join to the superclass table.
+ */
+ public boolean isJoinedSubclass() {
+ return _joined;
+ }
+
+ /**
+ * Whether there is a join to the superclass table.
+ */
+ public void setJoinedSubclass(boolean joined) {
+ _joined = joined;
+ }
+
+ /**
+ * Return the class-level joined tables.
+ */
+ public String[] getSecondaryTableNames() {
+ if (_seconds == null)
+ return new String[0];
+ return (String[]) _seconds.keySet().toArray(new String[]{ });
+ }
+
+ /**
+ * We allow fields to reference class-level joins using just the table
+ * name, whereas the class join might have schema, etc information.
+ * This method returns the name of the given table as listed in a
+ * class-level join, or the given name if no join exists.
+ */
+ public String getSecondaryTableName(String tableName) {
+ // if no secondary table joins, bad table name, exact match,
+ // or an already-qualified table name, nothing to do
+ if (_seconds == null || tableName == null
+ || _seconds.containsKey(tableName)
+ || tableName.indexOf('.') != -1)
+ return tableName;
+
+ // decide which class-level join table is best match
+ String best = tableName;
+ int pts = 0;
+ String fullJoin;
+ String join;
+ int idx;
+ for (Iterator itr = _seconds.keySet().iterator(); itr.hasNext();) {
+ // award a caseless match without schema 2 points
+ fullJoin = (String) itr.next();
+ idx = fullJoin.lastIndexOf('.');
+ if (idx == -1 && pts < 2 && fullJoin.equalsIgnoreCase(tableName)) {
+ best = fullJoin;
+ pts = 2;
+ } else if (idx == -1)
+ continue;
+
+ // immediately return an exact match with schema
+ join = fullJoin.substring(idx + 1);
+ if (join.equals(tableName))
+ return join;
+
+ // caseless match with schema worth 1 point
+ if (pts < 1 && join.equalsIgnoreCase(tableName)) {
+ best = fullJoin;
+ pts = 1;
+ }
+ }
+ return best;
+ }
+
+ /**
+ * Return any columns defined for the given class level join, or empty
+ * list if none.
+ */
+ public List getSecondaryTableJoinColumns(String tableName) {
+ if (_seconds == null || tableName == null)
+ return Collections.EMPTY_LIST;
+
+ // get the columns for the join with the best match for table name
+ List cols = (List) _seconds.get(getSecondaryTableName(tableName));
+ if (cols == null) {
+ // possible that given table has extra info the join table
+ // doesn't have; strip it
+ int idx = tableName.lastIndexOf('.');
+ if (idx != -1) {
+ tableName = tableName.substring(idx + 1);
+ cols = (List) _seconds.get(getSecondaryTableName(tableName));
+ }
+ }
+ return (cols == null) ? Collections.EMPTY_LIST : cols;
+ }
+
+ /**
+ * Declare the given class-level join.
+ */
+ public void setSecondaryTableJoinColumns(String tableName, List cols) {
+ if (cols == null)
+ cols = Collections.EMPTY_LIST;
+ if (_seconds == null)
+ _seconds = new HashMap();
+ _seconds.put(tableName, cols);
+ }
+
+ /**
+ * Return the table for the given class.
+ */
+ public Table getTable(final ClassMapping cls, boolean adapt) {
+ return createTable(cls, new TableDefaults() {
+ public String get(Schema schema) {
+ // delay this so that we don't do schema reflection for unique
+ // table name unless necessary
+ return cls.getMappingRepository().getMappingDefaults().
+ getTableName(cls, schema);
+ }
+ }, null, _tableName, adapt);
+ }
+
+ /**
+ * Return the datastore identity columns for the given class, based on the
+ * given templates.
+ */
+ public Column[] getDataStoreIdColumns(ClassMapping cls, Column[] tmplates,
+ Table table, boolean adapt) {
+ cls.getMappingRepository().getMappingDefaults().
+ populateDataStoreIdColumns(cls, table, tmplates);
+ return createColumns(cls, "datastoreid", tmplates, table, adapt);
+ }
+
+ /**
+ * Return the join from this class to its superclass. The table for
+ * this class must be set.
+ */
+ public ForeignKey getSuperclassJoin(final ClassMapping cls, Table table,
+ boolean adapt) {
+ ClassMapping sup = cls.getJoinablePCSuperclassMapping();
+ if (sup == null)
+ return null;
+
+ ForeignKeyDefaults def = new ForeignKeyDefaults() {
+ public ForeignKey get(Table local, Table foreign, boolean inverse) {
+ return cls.getMappingRepository().getMappingDefaults().
+ getJoinForeignKey(cls, local, foreign);
+ }
+
+ public void populate(Table local, Table foreign, Column col,
+ Object target, boolean inverse, int pos, int cols) {
+ cls.getMappingRepository().getMappingDefaults().
+ populateJoinColumn(cls, local, foreign, col, target,
+ pos, cols);
+ }
+ };
+ return createForeignKey(cls, "superclass", getColumns(), def, table,
+ cls, sup, false, adapt);
+ }
+
+ /**
+ * Synchronize internal information with the mapping data for the given
+ * class.
+ */
+ public void syncWith(ClassMapping cls) {
+ clear(false);
+
+ ClassMapping sup = cls.getMappedPCSuperclassMapping();
+ if (cls.getTable() != null && (sup == null
+ || sup.getTable() != cls.getTable()))
+ _tableName = cls.getMappingRepository().getDBDictionary().
+ getFullName(cls.getTable(), true);
+
+ // set io before syncing cols
+ setColumnIO(cls.getColumnIO());
+ if (cls.getJoinForeignKey() != null && sup != null
+ && sup.getTable() != null)
+ syncForeignKey(cls, cls.getJoinForeignKey(), cls.getTable(),
+ sup.getTable());
+ else if (cls.getIdentityType() == ClassMapping.ID_DATASTORE)
+ syncColumns(cls, cls.getPrimaryKeyColumns(), false);
+
+ // record inheritance strategy if class does not use default strategy
+ // for base classes, and for all subclasses so we can be sure subsequent
+ // mapping runs don't think subclass is unmapped
+ String strat = (cls.getStrategy() == null) ? null
+ : cls.getStrategy().getAlias();
+ if (strat != null && (cls.getPCSuperclass() != null
+ || !FullClassStrategy.ALIAS.equals(strat)))
+ setStrategy(strat);
+ }
+
+ public boolean hasSchemaComponents() {
+ return super.hasSchemaComponents() || _tableName != null;
+ }
+
+ protected void clear(boolean canFlags) {
+ super.clear(canFlags);
+ _tableName = null;
+ }
+
+ public void copy(MappingInfo info) {
+ super.copy(info);
+ if (!(info instanceof ClassMappingInfo))
+ return;
+
+ ClassMappingInfo cinfo = (ClassMappingInfo) info;
+ if (_tableName == null)
+ _tableName = cinfo.getTableName();
+ if (_subStrat == null)
+ _subStrat = cinfo.getHierarchyStrategy();
+ if (cinfo._seconds != null) {
+ if (_seconds == null)
+ _seconds = new HashMap();
+ Object key;
+ for (Iterator itr = cinfo._seconds.keySet().iterator();
+ itr.hasNext();) {
+ key = itr.next();
+ if (!_seconds.containsKey(key))
+ _seconds.put(key, cinfo._seconds.get(key));
+ }
+ }
+ }
+
+ public File getSourceFile() {
+ return _file;
+ }
+
+ public Object getSourceScope() {
+ return null;
+ }
+
+ public int getSourceType() {
+ return _srcType;
+ }
+
+ public void setSource(File file, int srcType) {
+ _file = file;
+ _srcType = srcType;
+ }
+
+ public String getResourceName() {
+ return _className;
+ }
+
+ public String[] getComments() {
+ return (_comments == null) ? EMPTY_COMMENTS : _comments;
+ }
+
+ public void setComments(String[] comments) {
+ _comments = comments;
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassMappingInfo.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassStrategy.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassStrategy.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassStrategy.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassStrategy.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.jdbc.sql.Select;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.kernel.PCState;
+import org.apache.openjpa.lib.rop.ResultObjectProvider;
+
+/**
+ * Mapping from a class to a relational schema.
+ *
+ * @author Abe White
+ * @since 4.0
+ */
+public interface ClassStrategy
+ extends Strategy {
+
+ /**
+ * Set the class mapping using this strategy. This will be called before
+ * use.
+ */
+ public void setClassMapping(ClassMapping owner);
+
+ /**
+ * Return true if the this class' primary key columns correspond to the
+ * base class' primary key columns used to construct oid values. Base
+ * classes always return true. Classes that join to the base class table,
+ * though, may not always join using the same columns the base class
+ * uses for oid values, or may not use all the columns. When performing a
+ * select, we will join down to the most-derived class that is identified
+ * by oid values. We cannot use non-primary key field values for joining
+ * during selects, because the field values to join on might be the ones
+ * we're trying to select! Similarly, we can only reconstruct oid values
+ * for selected objects using classes whose primary keys store oid values.
+ *
+ * @param hasAll if true, there must be a primary key column for every
+ * base class primary key column; if false the primary key
+ * must only match a subset of the base class primary key columns
+ */
+ public boolean isPrimaryKeyObjectId(boolean hasAll);
+
+ /**
+ * Join the mapping and its superclass.
+ *
+ * @param toThis if false, inner join to the superclass table; if
+ * true, outer join from the superclass table to this table
+ */
+ public Joins joinSuperclass(Joins joins, boolean toThis);
+
+ /**
+ * Return true if this strategy can perform the given select from
+ * the given <code>base</code> mapping.
+ * The given state manager may be null if selecting multiple instances.
+ */
+ public boolean supportsEagerSelect(Select sel, OpenJPAStateManager sm,
+ JDBCStore store, ClassMapping base, JDBCFetchConfiguration fetch);
+
+ /**
+ * Implement this method to customize obtaining a result containing all
+ * instances of this class. Return null for standard loading.
+ */
+ public ResultObjectProvider customLoad(JDBCStore store, boolean subclasses,
+ JDBCFetchConfiguration fetch, long startIdx, long endIdx)
+ throws SQLException;
+
+ /**
+ * Implement this method to load the state of a given object, without
+ * a previous {@link Result}. Return true if this method handles the
+ * load. If the object does not exist in the data store, simply take no
+ * action on it (but still return true). Return false to use default
+ * loading.
+ *
+ * @param state if non-null, then you must initialize the state
+ * and persistent object of the given state manager
+ * (after determining the actual class of the object
+ * from the database, if there are possible persistent
+ * subclasses); initialization looks like this: <code>
+ * sm.initialize (pcClass, state)</code>
+ */
+ public boolean customLoad(OpenJPAStateManager sm, JDBCStore store,
+ PCState state, JDBCFetchConfiguration fetch)
+ throws SQLException, ClassNotFoundException;
+
+ /**
+ * Implement this method to customize loading from a {@link Result}
+ * into an instance. Return true if this mapping handles the
+ * load; false if normal loading should procede after calling this method.
+ */
+ public boolean customLoad(OpenJPAStateManager sm, JDBCStore store,
+ JDBCFetchConfiguration fetch, Result result)
+ throws SQLException;
+}
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ClassStrategy.java
------------------------------------------------------------------------------
svn:executable = *
Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/DelegatingJoinable.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/DelegatingJoinable.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/DelegatingJoinable.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/DelegatingJoinable.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.sql.SQLException;
+
+import org.apache.openjpa.jdbc.kernel.JDBCStore;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+import org.apache.openjpa.jdbc.sql.Joins;
+import org.apache.openjpa.jdbc.sql.Result;
+import org.apache.openjpa.kernel.OpenJPAStateManager;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.MetaDataException;
+
+/**
+ * Delegates to another {@link Joinable} after doing column
+ * translation. Useful for joins that are not managed by any fields on
+ * the joined-from side. For example, a vertical class mapping manages
+ * foreign key columns linking to the superclass table. It needs to use
+ * the joinables of the superclass to actually extract the column values
+ * from field values and so forth, but in order for other mappings to join
+ * to its foreign key columns it needs joinables of its own. So it creates
+ * delegating joinables.
+ *
+ * @author Abe White
+ */
+public class DelegatingJoinable
+ implements Joinable {
+
+ private static final Localizer _loc = Localizer.forPackage
+ (DelegatingJoinable.class);
+
+ private final Joinable _join;
+ private final ForeignKey _fk;
+ private final Column[] _cols;
+
+ /**
+ * Constructor.
+ *
+ * @param join the mapping to delegate to
+ * @param fk the foreign key to use to translate any given columns
+ * to the given delegate's columns
+ */
+ public DelegatingJoinable(Joinable join, ForeignKey fk) {
+ _join = join;
+ _fk = fk;
+
+ Column[] pks = join.getColumns();
+ _cols = new Column[pks.length];
+ for (int i = 0; i < pks.length; i++) {
+ _cols[i] = fk.getColumn(pks[i]);
+ if (_cols[i] == null)
+ throw new MetaDataException(_loc.get("incomplete-join",
+ pks[i].getFullName()));
+ }
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param join the mapping to delegate to
+ * @param cols translated columns
+ */
+ public DelegatingJoinable(Joinable join, Column[] cols) {
+ _join = join;
+ _fk = null;
+ _cols = cols;
+ if (cols.length != join.getColumns().length)
+ throw new MetaDataException(_loc.get("bad-remap",
+ join.getColumns()[0].getFullName()));
+ }
+
+ public int getFieldIndex() {
+ return _join.getFieldIndex();
+ }
+
+ public Object getPrimaryKeyValue(Result res, Column[] cols, ForeignKey fk,
+ Joins joins)
+ throws SQLException {
+ return _join.getPrimaryKeyValue(res, cols, fk, joins);
+ }
+
+ public Column[] getColumns() {
+ return _cols;
+ }
+
+ public Object getJoinValue(Object val, Column col, JDBCStore store) {
+ return _join.getJoinValue(val, translate(col), store);
+ }
+
+ public Object getJoinValue(OpenJPAStateManager sm, Column col,
+ JDBCStore store) {
+ return _join.getJoinValue(sm, translate(col), store);
+ }
+
+ public void setAutoAssignedValue(OpenJPAStateManager sm, JDBCStore store,
+ Column col, Object autogen) {
+ _join.setAutoAssignedValue(sm, store, translate(col), autogen);
+ }
+
+ private Column translate(Column col) {
+ if (_fk != null)
+ return _fk.getPrimaryKeyColumn(col);
+
+ Column[] cols = _join.getColumns();
+ for (int i = 0; i < cols.length; i++)
+ if (col == cols[i])
+ return _cols[i];
+ return null;
+ }
+}
Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/DelegatingJoinable.java
------------------------------------------------------------------------------
svn:executable = *