/* * JBoss, Home of Professional Open Source. * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. Some portions may be licensed * to Red Hat, Inc. under one or more contributor license agreements. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301 USA. */ package org.teiid.query.sql.lang; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.teiid.core.util.EquivalenceUtil; import org.teiid.core.util.HashCodeUtil; import org.teiid.query.sql.LanguageVisitor; import org.teiid.query.sql.symbol.GroupSymbol; /** * Represents a subpart of the FROM clause specifying a join within the FROM. It may * optionally specify criteria for the join, depending on the join type. For example, * these are some representations of JoinPredicates: * <OL> * <LI>GroupA CROSS JOIN GroupB</LI> * <LI>GroupA JOIN GroupB ON GroupA.E1=GroupB.E1 AND GroupA.E2=GroupB.E2</LI> * <LI>GroupA RIGHT OUTER JOIN (GroupB JOIN GroupC ON GroupB.E1=GroupC.E1) ON GroupA.E1=GroupB.E1</LI> * </OL> */ public class JoinPredicate extends FromClause { private FromClause leftClause; private FromClause rightClause; private JoinType joinType = JoinType.JOIN_INNER; private List joinCriteria; /** * Construct a JoinPredicate */ public JoinPredicate() { this.joinCriteria = new ArrayList(); } /** * Construct a JoinPredicate between two clauses of the specified type. * @param leftClause Left from clause * @param rightClause Right from clause * @param type Type of join */ public JoinPredicate(FromClause leftClause, FromClause rightClause, JoinType type) { this.leftClause = leftClause; this.rightClause = rightClause; this.joinType = type; this.joinCriteria = new ArrayList(); } /** * Construct a JoinPredicate between two clauses of the specified type. * @param leftClause Left from clause * @param rightClause Right from clause * @param type Type of join * @param criteria List of Criteria for this join predicate */ public JoinPredicate(FromClause leftClause, FromClause rightClause, JoinType type, List criteria) { this.leftClause = leftClause; this.rightClause = rightClause; this.joinType = type; this.joinCriteria = criteria; } /** * Construct a JoinPredicate between two clauses of the specified type. * @param leftClause Left from clause * @param rightClause Right from clause * @param type Type of join * @param criteria List of Criteria for this join predicate */ public JoinPredicate(FromClause leftClause, FromClause rightClause, JoinType type, Criteria criteria) { this.leftClause = leftClause; this.rightClause = rightClause; this.joinType = type; this.joinCriteria = Criteria.separateCriteriaByAnd(criteria); } /** * Set left clause * @param predicate Left clause to set */ public void setLeftClause(FromClause predicate) { this.leftClause = predicate; } /** * Get left clause * @return Left clause */ public FromClause getLeftClause() { return this.leftClause; } /** * Set right clause * @param predicate Right clause to set */ public void setRightClause(FromClause predicate) { this.rightClause = predicate; } /** * Get right clause * @return Right clause */ public FromClause getRightClause() { return this.rightClause; } /** * Set join type for this predicate * @param type Type of join */ public void setJoinType(JoinType type) { this.joinType = type; } /** * Get join type for this predicate * @return Type of join */ public JoinType getJoinType() { return this.joinType; } /** * Set join criteria for this predicate * @param criteria List of {@link Criteria} set on this predicate */ public void setJoinCriteria(List criteria) { this.joinCriteria = criteria; } /** * Get join criteria for this predicate * @return List of {@link Criteria} */ public List getJoinCriteria() { return this.joinCriteria; } /** * Collect all GroupSymbols for this from clause. * @param groups Groups to add to */ public void collectGroups(Collection<GroupSymbol> groups) { if(this.leftClause != null) { this.leftClause.collectGroups(groups); } if(this.rightClause != null) { this.rightClause.collectGroups(groups); } } public void acceptVisitor(LanguageVisitor visitor) { visitor.visit(this); } /** * Compare this object to another * @param obj Other object * @return True if equal */ public boolean equals(Object obj) { if (!super.equals(obj)) { return false; } if(!(obj instanceof JoinPredicate)) { return false; } JoinPredicate other = (JoinPredicate) obj; List thisCrit = this.getJoinCriteria(); if(thisCrit != null && thisCrit.size() == 0) { thisCrit = null; } List otherCrit = other.getJoinCriteria(); if(otherCrit != null && otherCrit.size() == 0) { otherCrit = null; } return EquivalenceUtil.areEqual(other.getJoinType(), this.getJoinType()) && EquivalenceUtil.areEqual(other.getLeftClause(), this.getLeftClause()) && EquivalenceUtil.areEqual(other.getRightClause(), this.getRightClause()) && EquivalenceUtil.areEqual(otherCrit, thisCrit); } /** * Get hash code for object * @return Hash code */ public int hashCode() { int hash = HashCodeUtil.hashCode(0, getLeftClause()); hash = HashCodeUtil.hashCode(hash, getJoinType().getTypeCode()); hash = HashCodeUtil.hashCode(hash, getRightClause()); return hash; } /** * Return deep clone for object * @return Deep clone */ protected FromClause cloneDirect() { FromClause copyLeft = null; if(this.leftClause != null) { copyLeft = this.leftClause.clone(); } FromClause copyRight = null; if(this.rightClause != null) { copyRight = this.rightClause.clone(); } List copyCrits = null; if(this.joinCriteria != null) { copyCrits = new ArrayList(joinCriteria.size()); Iterator iter = this.joinCriteria.iterator(); while(iter.hasNext()) { Criteria crit = (Criteria) iter.next(); copyCrits.add(crit.clone()); } } JoinPredicate clonedJoinPredicate = new JoinPredicate(copyLeft, copyRight, this.joinType, copyCrits); return clonedJoinPredicate; } }