You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2008/05/06 12:55:05 UTC

svn commit: r653743 - in /cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans: JoinProcessor.java JoinTreeNode.java

Author: aadamchik
Date: Tue May  6 03:55:04 2008
New Revision: 653743

URL: http://svn.apache.org/viewvc?rev=653743&view=rev
Log:
CAY-802  Split Expressions
(standalone class for merging expressions into joins)

Added:
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinProcessor.java
    cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinProcessor.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinProcessor.java?rev=653743&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinProcessor.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinProcessor.java Tue May  6 03:55:04 2008
@@ -0,0 +1,116 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.access.trans;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbJoin;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.JoinType;
+
+/**
+ * Encapsulates join reuse/split logic used in SelectQuery processing. All expression
+ * path's that exist in the query (in the qualifier, etc.) are processed to produce a
+ * combined join tree.
+ * 
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+class JoinProcessor {
+
+    private JoinTreeNode root;
+    private JoinTreeNode topNode;
+
+    JoinProcessor(SelectTranslator tableAliasSource) {
+        String rootAlias = tableAliasSource.aliasForTable(tableAliasSource
+                .getRootDbEntity());
+        this.root = new JoinTreeNode(tableAliasSource);
+        this.root.setTargetTableAlias(rootAlias);
+        resetStack();
+    }
+
+    /**
+     * Appends all configured joins to the provided output object.
+     */
+    void appendJoins(Appendable out) throws IOException {
+        appendJoinSubtree(out, root);
+    }
+
+    private void appendJoinSubtree(Appendable out, JoinTreeNode node) throws IOException {
+
+        DbRelationship relationship = node.getRelationship();
+
+        DbEntity targetEntity = (DbEntity) relationship.getTargetEntity();
+        String srcAlias = node.getSourceTableAlias();
+        String targetAlias = node.getTargetTableAlias();
+
+        switch (node.getJoinType()) {
+            case INNER:
+                out.append(" JOIN");
+                break;
+            case LEFT_OUTER:
+                out.append(" LEFT JOIN");
+                break;
+            default:
+                throw new IllegalArgumentException("Unsupported join type: "
+                        + node.getJoinType());
+        }
+
+        out.append(' ').append(targetEntity.getFullyQualifiedName()).append(' ').append(
+                targetAlias).append(" ON (");
+
+        List<DbJoin> joins = relationship.getJoins();
+        int len = joins.size();
+        for (int i = 0; i < len; i++) {
+            DbJoin join = joins.get(i);
+
+            if (i > 0) {
+                out.append(" AND ");
+            }
+
+            out
+                    .append(srcAlias)
+                    .append('.')
+                    .append(join.getSourceName())
+                    .append(" = ")
+                    .append(targetAlias)
+                    .append('.')
+                    .append(join.getTargetName());
+        }
+
+        out.append(')');
+    }
+
+    /**
+     * Pops the stack all the way to the root node.
+     */
+    void resetStack() {
+        topNode = root;
+    }
+
+    /**
+     * Finds or creates a JoinTreeNode for the given arguments and sets it as the next
+     * current join.
+     */
+    void pushJoin(DbRelationship relationship, JoinType joinType, String alias) {
+        topNode = topNode.findOrCreateChild(relationship, joinType, alias);
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java?rev=653743&view=auto
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java (added)
+++ cayenne/main/trunk/framework/cayenne-jdk1.5-unpublished/src/main/java/org/apache/cayenne/access/trans/JoinTreeNode.java Tue May  6 03:55:04 2008
@@ -0,0 +1,122 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.access.trans;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.apache.cayenne.map.DbEntity;
+import org.apache.cayenne.map.DbRelationship;
+import org.apache.cayenne.map.JoinType;
+import org.apache.cayenne.util.Util;
+
+/**
+ * @since 3.0
+ * @author Andrus Adamchik
+ */
+final class JoinTreeNode {
+
+    private String targetTableAlias;
+    private String sourceTableAlias;
+    private DbRelationship relationship;
+    private String alias;
+    private JoinType joinType;
+    private Collection<JoinTreeNode> children;
+    private SelectTranslator tableAliasSource;
+
+    JoinTreeNode(SelectTranslator tableAliasSource) {
+        this.tableAliasSource = tableAliasSource;
+    }
+
+    JoinTreeNode(SelectTranslator tableAliasSource, DbRelationship relationship,
+            JoinType joinType, String alias) {
+        this(tableAliasSource);
+        this.relationship = relationship;
+        this.alias = alias;
+        this.joinType = joinType;
+    }
+
+    Collection<JoinTreeNode> getChildren() {
+        return children != null ? children : Collections.<JoinTreeNode> emptyList();
+    }
+
+    JoinTreeNode findOrCreateChild(
+            DbRelationship relationship,
+            JoinType joinType,
+            String alias) {
+
+        if (children == null) {
+            children = new ArrayList<JoinTreeNode>(4);
+        }
+        else {
+            for (JoinTreeNode child : children) {
+
+                if (child.equals(relationship, joinType, alias)) {
+                    return child;
+                }
+            }
+        }
+
+        JoinTreeNode child = new JoinTreeNode(
+                tableAliasSource,
+                relationship,
+                joinType,
+                alias);
+        child.setSourceTableAlias(this.targetTableAlias);
+        child.setTargetTableAlias(tableAliasSource
+                .newAliasForTable((DbEntity) relationship.getTargetEntity()));
+        children.add(child);
+        return child;
+    }
+
+    private boolean equals(DbRelationship relationship, JoinType joinType, String alias) {
+        return this.relationship == relationship
+                && this.joinType == joinType
+                && Util.nullSafeEquals(this.alias, alias);
+    }
+
+    String getTargetTableAlias() {
+        return targetTableAlias;
+    }
+
+    void setTargetTableAlias(String targetTableAlias) {
+        this.targetTableAlias = targetTableAlias;
+    }
+
+    String getSourceTableAlias() {
+        return sourceTableAlias;
+    }
+
+    void setSourceTableAlias(String sourceTableAlias) {
+        this.sourceTableAlias = sourceTableAlias;
+    }
+
+    DbRelationship getRelationship() {
+        return relationship;
+    }
+
+    String getAlias() {
+        return alias;
+    }
+
+    JoinType getJoinType() {
+        return joinType;
+    }
+}
\ No newline at end of file