public static Join create()

in jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/join/Join.java [121:251]


    public static Join create(final MultiColumnQueryHits left,
                              final MultiColumnQueryHits right,
                              final JoinType joinType,
                              final JoinConditionImpl condition,
                              final IndexReader reader,
                              final HierarchyResolver resolver,
                              final NamespaceMappings nsMappings,
                              final HierarchyManager hmgr)
            throws IOException {
        try {
            return (Join) condition.accept(new DefaultQOMTreeVisitor() {

                private boolean isInner = JoinType.INNER == joinType;
                private MultiColumnQueryHits outer;
                private int outerIdx;

                public Object visit(DescendantNodeJoinConditionImpl node, Object data)
                        throws Exception {
                    MultiColumnQueryHits ancestor = getSourceWithName(node.getAncestorSelectorQName(), left, right);
                    MultiColumnQueryHits descendant = getSourceWithName(node.getDescendantSelectorQName(), left, right);
                    Condition c;
                    if (isInner
                            || descendant == left && JoinType.LEFT == joinType
                            || descendant == right && JoinType.RIGHT == joinType) {
                        // also applies to inner join
                        // assumption: DescendantNodeJoin is more
                        // efficient than AncestorNodeJoin, TODO: verify
                        outer = descendant;
                        outerIdx = getIndex(outer, node.getDescendantSelectorQName());
                        c = new DescendantNodeJoin(ancestor, node.getAncestorSelectorQName(), reader, resolver);
                    } else {
                        // left == ancestor
                        outer = ancestor;
                        outerIdx = getIndex(outer, node.getAncestorSelectorQName());
                        c = new AncestorNodeJoin(descendant, node.getDescendantSelectorQName(), reader, resolver);
                    }
                    return new Join(outer, outerIdx, isInner, c);
                }

                public Object visit(EquiJoinConditionImpl node, Object data)
                        throws Exception {
                    MultiColumnQueryHits src1 = getSourceWithName(node.getSelector1QName(), left, right);
                    MultiColumnQueryHits src2 = getSourceWithName(node.getSelector2QName(), left, right);
                    MultiColumnQueryHits inner;
                    Name innerName;
                    Name innerPropName;
                    Name outerPropName;
                    if (isInner
                            || src1 == left && JoinType.LEFT == joinType
                            || src1 == right && JoinType.RIGHT == joinType) {
                        outer = src1;
                        outerIdx = getIndex(outer, node.getSelector1QName());
                        inner = src2;
                        innerName = node.getSelector2QName();
                        innerPropName = node.getProperty2QName();
                        outerPropName = node.getProperty1QName();
                    } else {
                        outer = src2;
                        outerIdx = getIndex(outer, node.getSelector2QName());
                        inner = src1;
                        innerName = node.getSelector1QName();
                        innerPropName = node.getProperty1QName();
                        outerPropName = node.getProperty2QName();
                    }

                    Condition c = new EquiJoin(
                            inner, getIndex(inner, innerName), nsMappings,
                            reader, innerPropName, outerPropName);
                    return new Join(outer, outerIdx, isInner, c);
                }

                public Object visit(ChildNodeJoinConditionImpl node, Object data)
                        throws Exception {
                    MultiColumnQueryHits child = getSourceWithName(node.getChildSelectorQName(), left, right);
                    MultiColumnQueryHits parent = getSourceWithName(node.getParentSelectorQName(), left, right);
                    Condition c;
                    if (child == left && JoinType.LEFT == joinType
                            || child == right && JoinType.RIGHT == joinType) {
                        outer = child;
                        outerIdx = getIndex(outer, node.getChildSelectorQName());
                        c = new ChildNodeJoin(parent, reader, resolver, node);
                    } else {
                        // also applies to inner joins
                        // assumption: ParentNodeJoin is more efficient than
                        // ChildNodeJoin, TODO: verify
                        outer = parent;
                        outerIdx = getIndex(outer, node.getParentSelectorQName());
                        c = new ParentNodeJoin(child, reader, resolver, node);
                    }
                    return new Join(outer, outerIdx, isInner, c);
                }

                public Object visit(SameNodeJoinConditionImpl node, Object data)
                        throws Exception {
                    MultiColumnQueryHits src1 = getSourceWithName(node.getSelector1QName(), left, right);
                    MultiColumnQueryHits src2 = getSourceWithName(node.getSelector2QName(), left, right);
                    Condition c;
                    if (isInner
                            || src1 == left && JoinType.LEFT == joinType
                            || src1 == right && JoinType.RIGHT == joinType) {
                        outer = src1;
                        outerIdx = getIndex(outer, node.getSelector1QName());
                        Path selector2Path = node.getSelector2QPath();
                        if (selector2Path == null || (selector2Path.getLength() == 1 && selector2Path.denotesCurrent())) {
                            c = new SameNodeJoin(src2, node.getSelector2QName(), reader);
                        } else {
                            c = new DescendantPathNodeJoin(src2, node.getSelector2QName(),
                                    node.getSelector2QPath(), hmgr);
                        }
                    } else {
                        outer = src2;
                        outerIdx = getIndex(outer, node.getSelector2QName());
                        Path selector2Path = node.getSelector2QPath();
                        if (selector2Path == null || (selector2Path.getLength() == 1 && selector2Path.denotesCurrent())) {
                            c = new SameNodeJoin(src1, node.getSelector1QName(), reader);
                        } else {
                            c = new AncestorPathNodeJoin(src1, node.getSelector1QName(),
                                    node.getSelector2QPath(), hmgr);
                        }
                    }
                    return new Join(outer, outerIdx, isInner, c);
                }
            }, null);
        } catch (IOException e) {
            throw e;
        } catch (Exception e) {
            IOException ex = new IOException(e.getMessage());
            ex.initCause(e);
            throw ex;
        }
    }