1 /* 2 * ModeShape (http://www.modeshape.org) 3 * See the COPYRIGHT.txt file distributed with this work for information 4 * regarding copyright ownership. Some portions may be licensed 5 * to Red Hat, Inc. under one or more contributor license agreements. 6 * See the AUTHORS.txt file in the distribution for a full listing of 7 * individual contributors. 8 * 9 * ModeShape is free software. Unless otherwise indicated, all code in ModeShape 10 * is licensed to you under the terms of the GNU Lesser General Public License as 11 * published by the Free Software Foundation; either version 2.1 of 12 * the License, or (at your option) any later version. 13 * 14 * ModeShape is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 * Lesser General Public License for more details. 18 * 19 * You should have received a copy of the GNU Lesser General Public 20 * License along with this software; if not, write to the Free 21 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 22 * 02110-1301 USA, or see the FSF site: http://www.fsf.org. 23 */ 24 package org.modeshape.graph.query.model; 25 26 import net.jcip.annotations.Immutable; 27 import org.modeshape.common.util.CheckArg; 28 import org.modeshape.common.util.HashCode; 29 30 /** 31 * A join condition that tests whether a property on a node is equal to a property on another node. A node-tuple satisfies the 32 * constraint only if: 33 * <ul> 34 * <li>the {@code selector1Name} node has a property named {@code property1Name}, and</li> 35 * <li>the {@code selector2Name} node has a property named {@code property2Name}, and</li> 36 * <li>the value of property {@code property1Name} is equal to the value of property {@code property2Name}</li> 37 * </ul> 38 */ 39 @Immutable 40 public class EquiJoinCondition implements JoinCondition { 41 private static final long serialVersionUID = 1L; 42 43 private final SelectorName selector1Name; 44 private final String property1Name; 45 private final SelectorName selector2Name; 46 private final String property2Name; 47 private final int hc; 48 49 /** 50 * Create an equi-join condition, given the names of the selector and property for the left- and right-hand-side of the join. 51 * 52 * @param selector1Name the selector name appearing on the left-side of the join; never null 53 * @param property1Name the property name for the left-side of the join; never null 54 * @param selector2Name the selector name appearing on the right-side of the join; never null 55 * @param property2Name the property name for the right-side of the join; never null 56 */ 57 public EquiJoinCondition( SelectorName selector1Name, 58 String property1Name, 59 SelectorName selector2Name, 60 String property2Name ) { 61 CheckArg.isNotNull(selector1Name, "selector1Name"); 62 CheckArg.isNotNull(property1Name, "property1Name"); 63 CheckArg.isNotNull(selector2Name, "selector2Name"); 64 CheckArg.isNotNull(property2Name, "property2Name"); 65 this.selector1Name = selector1Name; 66 this.property1Name = property1Name; 67 this.selector2Name = selector2Name; 68 this.property2Name = property2Name; 69 this.hc = HashCode.compute(this.selector1Name, this.property1Name, this.selector2Name, this.property2Name); 70 } 71 72 /** 73 * Create an equi-join condition, given the columns. 74 * 75 * @param column1 the column for the left-side of the join; never null 76 * @param column2 the column for the right-side of the join; never null 77 */ 78 public EquiJoinCondition( Column column1, 79 Column column2 ) { 80 this(column1.selectorName(), column1.propertyName(), column2.selectorName(), column2.propertyName()); 81 } 82 83 /** 84 * Get the name of the selector that appears on the left-side of the join. 85 * 86 * @return the selector name appearing on the left-side of the join; never null 87 */ 88 public final SelectorName selector1Name() { 89 return selector1Name; 90 } 91 92 /** 93 * Get the name of the property that appears on the left-side of the join. 94 * 95 * @return the property name for the left-side of the join; never null 96 */ 97 public final String property1Name() { 98 return property1Name; 99 } 100 101 /** 102 * Get the name of the selector that appears on the right-side of the join. 103 * 104 * @return the selector name appearing on the right-side of the join; never null 105 */ 106 public final SelectorName selector2Name() { 107 return selector2Name; 108 } 109 110 /** 111 * Get the name of the property that appears on the left-side of the join. 112 * 113 * @return the property name for the left-side of the join; never null 114 */ 115 public final String property2Name() { 116 return property2Name; 117 } 118 119 /** 120 * {@inheritDoc} 121 * 122 * @see java.lang.Object#toString() 123 */ 124 @Override 125 public String toString() { 126 return Visitors.readable(this); 127 } 128 129 /** 130 * {@inheritDoc} 131 * 132 * @see java.lang.Object#hashCode() 133 */ 134 @Override 135 public int hashCode() { 136 return hc; 137 } 138 139 /** 140 * {@inheritDoc} 141 * 142 * @see java.lang.Object#equals(java.lang.Object) 143 */ 144 @Override 145 public boolean equals( Object obj ) { 146 if (obj == this) return true; 147 if (obj instanceof EquiJoinCondition) { 148 EquiJoinCondition that = (EquiJoinCondition)obj; 149 if (this.hc != that.hc) return false; 150 if (!this.selector1Name.equals(that.selector1Name)) return false; 151 if (!this.selector2Name.equals(that.selector2Name)) return false; 152 if (!this.property1Name.equals(that.property1Name)) return false; 153 if (!this.property2Name.equals(that.property2Name)) return false; 154 return true; 155 } 156 return false; 157 } 158 159 /** 160 * {@inheritDoc} 161 * 162 * @see org.modeshape.graph.query.model.Visitable#accept(org.modeshape.graph.query.model.Visitor) 163 */ 164 public void accept( Visitor visitor ) { 165 visitor.visit(this); 166 } 167 }