/*
* 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.exoplatform.services.jcr.impl.core.query;
import org.exoplatform.services.jcr.datamodel.InternalQName;
import org.exoplatform.services.jcr.datamodel.QPath;
import org.exoplatform.services.jcr.datamodel.QPathEntry;
import org.exoplatform.services.jcr.impl.Constants;
import java.util.Date;
import javax.jcr.RepositoryException;
/**
* Implements a query node that defines property value relation.
*/
public class RelationQueryNode extends NAryQueryNode implements QueryConstants {
/**
* Acts as an syntetic placeholder for a location step that matches any
* name. This is required becase a JCR path does not allow a Name with
* a single '*' (star) character.
*/
public static final InternalQName STAR_NAME_TEST = new InternalQName(Constants.NS_REP_URI, "__star__");
/**
* The relative path to the property.
*/
private QPath relPath;
/**
* If <code>true</code> this relation query node contains a value preceded
* with an unary minus.
*/
private boolean unaryMinus;
/**
* The <code>long</code> value of the relation if this is a query is of type
* <code>long</code>
*/
private long valueLong;
/**
* The <code>int</code> value of the position index.
*/
private int valuePosition;
/**
* The <code>double</code> value of the relation if this is a query is of
* type <code>double</code>
*/
private double valueDouble;
/**
* The <code>String</code> value of the relation if this is a query is of
* type <code>String</code>
*/
private String valueString;
/**
* The <code>Date</code> value of the relation if this is a query is of type
* <code>Date</code>
*/
private Date valueDate;
/**
* The operation type of this relation. One of the operation values defined
* in {@link QueryConstants}.
*/
private final int operation;
/**
* The value type of this relation. One of {@link #TYPE_DATE}, {@link
* #TYPE_DOUBLE}, {@link #TYPE_LONG}, {@link #TYPE_STRING}, {@link #TYPE_POSITION}.
*/
private int type;
/**
* Creates a new <code>RelationQueryNode</code> without a type nor value
* assigned.
*
* @param parent the parent node for this query node.
*/
protected RelationQueryNode(QueryNode parent, int operation) {
super(parent);
this.operation = operation;
}
/**
* {@inheritDoc}
* @throws RepositoryException
*/
public Object accept(QueryNodeVisitor visitor, Object data) throws RepositoryException {
return visitor.visit(this, data);
}
/**
* Returns the type of this node.
*
* @return the type of this node.
*/
public int getType() {
return QueryNode.TYPE_RELATION;
}
/**
* If <code>b</code> is <code>true</code> then the value in this relation
* node contains a receding unary minus.
*
* @param b <code>true</code> if this relation contains a unary minus.
*/
public void setUnaryMinus(boolean b) {
unaryMinus = b;
}
/**
* Returns the type of the value.
*
* @return the type of the value.
*/
public int getValueType() {
return type;
}
/**
* @return the relative path that references the property in this relation.
*/
public QPath getRelativePath() {
return relPath;
}
/**
* Sets the relative path to the property in this relation.
*
* @param relPath the relative path to a property.
* @throws IllegalArgumentException if <code>relPath</code> is absolute.
*/
public void setRelativePath(QPath relPath) {
if (relPath != null && relPath.isAbsolute()) {
throw new IllegalArgumentException("relPath must be relative");
}
this.relPath = relPath;
}
/**
* Adds a path element to the existing relative path. To add a path element
* which matches all node names use {@link #STAR_NAME_TEST}.
*
* @param element the path element to append.
*/
public void addPathElement(QPathEntry element) {
if (relPath == null)
this.relPath = new QPath(new QPathEntry[]{element});
else
this.relPath = QPath.makeChildPath(relPath, element, element.getIndex());
}
/**
* Returns the <code>long</code> value if this relation if of type
* {@link #TYPE_LONG}.
*
* @return the <code>long</code> value.
*/
public long getLongValue() {
return valueLong;
}
/**
* Sets a new value of type <code>long</code>.
*
* @param value the new value.
*/
public void setLongValue(long value) {
valueLong = unaryMinus ? -value : value;
type = TYPE_LONG;
}
/**
* Returns the <code>int</code> position index value if this relation is
* of type {@link #TYPE_POSITION}.
* @return the position index value.
*/
public int getPositionValue() {
return valuePosition;
}
/**
* Sets a new value for the position index.
*
* @param value the new value.
*/
public void setPositionValue(int value) {
valuePosition = value;
type = TYPE_POSITION;
}
/**
* Returns the <code>double</code> value if this relation if of type
* {@link #TYPE_DOUBLE}.
*
* @return the <code>double</code> value.
*/
public double getDoubleValue() {
return valueDouble;
}
/**
* Sets a new value of type <code>double</code>.
*
* @param value the new value.
*/
public void setDoubleValue(double value) {
valueDouble = unaryMinus ? -value : value;
type = TYPE_DOUBLE;
}
/**
* Returns the <code>String</code> value if this relation if of type
* {@link #TYPE_STRING}.
*
* @return the <code>String</code> value.
*/
public String getStringValue() {
return valueString;
}
/**
* Sets a new value of type <code>String</code>.
*
* @param value the new value.
*/
public void setStringValue(String value) {
valueString = value;
type = TYPE_STRING;
}
/**
* Returns the <code>Date</code> value if this relation if of type
* {@link #TYPE_DATE}.
*
* @return the <code>Date</code> value.
*/
public Date getDateValue() {
return valueDate;
}
/**
* Sets a new value of type <code>Date</code>.
*
* @param value the new value.
*/
public void setDateValue(Date value) {
valueDate = value;
type = TYPE_DATE;
}
/**
* Returns the operation type.
*
* @return the operation type.
*/
public int getOperation() {
return operation;
}
/**
* {@inheritDoc}
*/
public boolean equals(Object obj) {
if (obj instanceof RelationQueryNode) {
RelationQueryNode other = (RelationQueryNode) obj;
return type == other.type
&& (valueDate == null ? other.valueDate == null : valueDate.equals(other.valueDate))
&& valueDouble == other.valueDouble
&& valueLong == other.valueLong
&& valuePosition == other.valuePosition
&& (valueString == null ? other.valueString == null : valueString.equals(other.valueString))
&& (relPath == null ? other.relPath == null : relPath.equals(other.relPath));
}
return false;
}
}