/*
* 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.apache.jackrabbit.test.api.query.qom;
import org.apache.jackrabbit.test.NotExecutableException;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import javax.jcr.PropertyType;
import javax.jcr.Binary;
import javax.jcr.query.QueryResult;
import javax.jcr.query.InvalidQueryException;
import javax.jcr.query.Query;
import javax.jcr.query.qom.QueryObjectModelConstants;
import javax.jcr.query.qom.QueryObjectModel;
import java.io.ByteArrayInputStream;
import java.util.Calendar;
import java.math.BigDecimal;
/**
* <code>LengthTest</code> performs tests with the Query Object Model length
* operand.
*/
public class LengthTest extends AbstractQOMTest {
private Node node;
protected void setUp() throws Exception {
super.setUp();
node = testRootNode.addNode(nodeName1, testNodeType);
superuser.save();
}
protected void tearDown() throws Exception {
node = null;
super.tearDown();
}
public void testStringLength() throws RepositoryException {
node.setProperty(propertyName1, "abc");
superuser.save();
checkOperators(propertyName1, node.getProperty(propertyName1).getLength());
}
public void testBinaryLength() throws RepositoryException {
byte[] data = "abc".getBytes();
Binary b = vf.createBinary(new ByteArrayInputStream(data));
try {
node.setProperty(propertyName1, b);
} finally {
b.dispose();
}
superuser.save();
checkOperators(propertyName1, node.getProperty(propertyName1).getLength());
}
public void testLongLength() throws RepositoryException {
node.setProperty(propertyName1, 123);
superuser.save();
checkOperators(propertyName1, node.getProperty(propertyName1).getLength());
}
public void testDoubleLength() throws RepositoryException {
node.setProperty(propertyName1, Math.PI);
superuser.save();
checkOperators(propertyName1, node.getProperty(propertyName1).getLength());
}
public void testDateLength() throws RepositoryException {
node.setProperty(propertyName1, Calendar.getInstance());
superuser.save();
checkOperators(propertyName1, node.getProperty(propertyName1).getLength());
}
public void testBooleanLength() throws RepositoryException {
node.setProperty(propertyName1, false);
superuser.save();
checkOperators(propertyName1, node.getProperty(propertyName1).getLength());
}
public void testNameLength() throws RepositoryException {
node.setProperty(propertyName1, vf.createValue(node.getName(), PropertyType.NAME));
superuser.save();
checkOperators(propertyName1, node.getProperty(propertyName1).getLength());
}
public void testPathLength() throws RepositoryException {
node.setProperty(propertyName1, vf.createValue(node.getPath(), PropertyType.PATH));
superuser.save();
checkOperators(propertyName1, node.getProperty(propertyName1).getLength());
}
public void testReferenceLength() throws RepositoryException, NotExecutableException {
ensureMixinType(node, mixReferenceable);
superuser.save();
node.setProperty(propertyName1, node);
superuser.save();
checkOperators(propertyName1, node.getProperty(propertyName1).getLength());
}
public void testWeakReferenceLength()
throws RepositoryException, NotExecutableException {
ensureMixinType(node, mixReferenceable);
superuser.save();
node.setProperty(propertyName1, vf.createValue(node, true));
superuser.save();
checkOperators(propertyName1, node.getProperty(propertyName1).getLength());
}
public void testURILength() throws RepositoryException {
node.setProperty(propertyName1, vf.createValue("http://example.com", PropertyType.URI));
superuser.save();
checkOperators(propertyName1, node.getProperty(propertyName1).getLength());
}
public void testDecimalLength() throws RepositoryException {
node.setProperty(propertyName1, new BigDecimal(123));
superuser.save();
checkOperators(propertyName1, node.getProperty(propertyName1).getLength());
}
//------------------------< conversion tests >------------------------------
public void testLengthStringLiteral() throws RepositoryException {
node.setProperty(propertyName1, "abc");
superuser.save();
String length = String.valueOf(node.getProperty(propertyName1).getLength());
executeQueries(propertyName1, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, vf.createValue(length));
}
public void testLengthBinaryLiteral() throws RepositoryException {
node.setProperty(propertyName1, "abc");
superuser.save();
String length = String.valueOf(node.getProperty(propertyName1).getLength());
Binary b = vf.createBinary(new ByteArrayInputStream(length.getBytes()));
try {
executeQueries(propertyName1, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO,
vf.createValue(b));
} finally {
b.dispose();
}
}
public void testLengthDoubleLiteral() throws RepositoryException {
node.setProperty(propertyName1, "abc");
superuser.save();
double length = node.getProperty(propertyName1).getLength();
executeQueries(propertyName1, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, vf.createValue(length));
}
public void testLengthDateLiteral() throws RepositoryException {
node.setProperty(propertyName1, "abc");
superuser.save();
Calendar length = Calendar.getInstance();
length.setTimeInMillis(node.getProperty(propertyName1).getLength());
executeQueries(propertyName1, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, vf.createValue(length));
}
public void testLengthBooleanLiteral() throws RepositoryException {
try {
executeQueries(propertyName1, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, vf.createValue(false));
fail("Boolean literal cannot be converted to long");
} catch (InvalidQueryException e) {
// expected
}
}
public void testLengthNameLiteral() throws RepositoryException {
try {
executeQueries(propertyName1, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, vf.createValue(
propertyName1, PropertyType.NAME));
fail("Name literal cannot be converted to long");
} catch (InvalidQueryException e) {
// expected
}
}
public void testLengthPathLiteral() throws RepositoryException {
try {
executeQueries(propertyName1, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, vf.createValue(
node.getPath(), PropertyType.PATH));
fail("Path literal cannot be converted to long");
} catch (InvalidQueryException e) {
// expected
}
}
public void testLengthReferenceLiteral() throws RepositoryException, NotExecutableException {
ensureMixinType(node, mixReferenceable);
superuser.save();
try {
executeQueries(propertyName1, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, vf.createValue(node));
fail("Reference literal cannot be converted to long");
} catch (InvalidQueryException e) {
// expected
}
}
public void testLengthWeakReferenceLiteral() throws RepositoryException, NotExecutableException {
ensureMixinType(node, mixReferenceable);
superuser.save();
try {
executeQueries(propertyName1, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, vf.createValue(node, true));
fail("Reference literal cannot be converted to long");
} catch (InvalidQueryException e) {
// expected
}
}
public void testLengthURILiteral() throws RepositoryException {
try {
executeQueries(propertyName1, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO,
vf.createValue(node.getPath(), PropertyType.URI));
fail("URI literal cannot be converted to long");
} catch (InvalidQueryException e) {
// expected
}
}
public void testLengthDecimalLiteral() throws RepositoryException {
node.setProperty(propertyName1, "abc");
superuser.save();
BigDecimal length = new BigDecimal(node.getProperty(propertyName1).getLength());
executeQueries(propertyName1, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, vf.createValue(length));
}
//------------------------< internal helpers >------------------------------
private void checkOperators(String propertyName,
long length) throws RepositoryException {
checkLength(propertyName, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, length, true);
checkLength(propertyName, QueryObjectModelConstants.JCR_OPERATOR_EQUAL_TO, length - 1, false);
checkLength(propertyName, QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN, length - 1, true);
checkLength(propertyName, QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN, length, false);
checkLength(propertyName, QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO, length, true);
checkLength(propertyName, QueryObjectModelConstants.JCR_OPERATOR_GREATER_THAN_OR_EQUAL_TO, length + 1, false);
checkLength(propertyName, QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN, length + 1, true);
checkLength(propertyName, QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN, length, false);
checkLength(propertyName, QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO, length, true);
checkLength(propertyName, QueryObjectModelConstants.JCR_OPERATOR_LESS_THAN_OR_EQUAL_TO, length - 1, false);
checkLength(propertyName, QueryObjectModelConstants.JCR_OPERATOR_NOT_EQUAL_TO, length - 1, true);
checkLength(propertyName, QueryObjectModelConstants.JCR_OPERATOR_NOT_EQUAL_TO, length, false);
}
private void checkLength(String propertyName,
String operator,
long length,
boolean matches) throws RepositoryException {
Node[] expected;
if (matches) {
expected = new Node[]{node};
} else {
expected = new Node[0];
}
QueryResult[] results = executeQueries(propertyName, operator, length);
for (int i = 0; i < results.length; i++) {
checkResult(results[i], expected);
}
}
private QueryResult[] executeQueries(String propertyName,
String operator,
long length)
throws RepositoryException {
Value v = vf.createValue(length);
return executeQueries(propertyName, operator, v);
}
private QueryResult[] executeQueries(String propertyName,
String operator,
Value length)
throws RepositoryException {
QueryObjectModel qom = qf.createQuery(
qf.selector(testNodeType, "s"),
qf.and(
qf.childNode("s", testRoot),
qf.comparison(
qf.length(
qf.propertyValue(
"s", propertyName)),
operator,
qf.literal(length))
), null, null);
QueryResult[] results = new QueryResult[2];
results[0] = qom.execute();
results[1] = qm.createQuery(qom.getStatement(), Query.JCR_SQL2).execute();
return results;
}
}