001/* 002 * (C) Copyright 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019 020package org.nuxeo.ecm.core.query.sql.model; 021 022import java.util.ArrayList; 023import java.util.Iterator; 024import java.util.List; 025 026/** 027 * An expression for an single operator with an arbitrary number of operands. 028 * <p> 029 * It extends {@link Predicate} but it's really not a real Predicate (some users of Predicate expect it to have lvalue 030 * and rvalue fields, which are null in this class). 031 * 032 * @author Florent Guillaume 033 */ 034public class MultiExpression extends Predicate { 035 036 private static final long serialVersionUID = 1L; 037 038 public final List<Predicate> predicates; 039 040 public MultiExpression(Operator operator, List<Predicate> predicates) { 041 super(null, operator, null); 042 this.predicates = predicates; 043 } 044 045 /** 046 * Copy constructor. 047 * 048 * @since 10.3 049 */ 050 public MultiExpression(MultiExpression other) { 051 this(other.operator, new ArrayList<>(other.predicates)); 052 } 053 054 @Override 055 public void accept(IVisitor visitor) { 056 visitor.visitMultiExpression(this); 057 } 058 059 @Override 060 public String toString() { 061 if (predicates.isEmpty()) { 062 StringBuilder sb = new StringBuilder(); 063 // this is not really valid NXQL but sufficient for debugging 064 sb.append(operator); 065 sb.append("()"); 066 return sb.toString(); 067 } 068 if (predicates.size() == 1) { 069 // here debugging loses the operator, but this shouldn't be an issue for semantics 070 return predicates.get(0).toString(); 071 } 072 StringBuilder sb = new StringBuilder(); 073 sb.append('('); 074 for (Iterator<Predicate> it = predicates.iterator(); it.hasNext();) { 075 Predicate predicate = it.next(); 076 sb.append(predicate.toString()); 077 if (it.hasNext()) { 078 sb.append(' '); 079 sb.append(operator); 080 sb.append(' '); 081 } 082 } 083 sb.append(')'); 084 return sb.toString(); 085 } 086 087 @Override 088 public boolean equals(Object other) { 089 if (other == this) { 090 return true; 091 } 092 if (other instanceof MultiExpression) { 093 return equals((MultiExpression) other); 094 } 095 return false; 096 } 097 098 protected boolean equals(MultiExpression other) { 099 return predicates.equals(other.predicates) && super.equals(other); 100 } 101 102 @Override 103 public int hashCode() { 104 return predicates.hashCode() + super.hashCode(); 105 } 106 107}