All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.data.cassandra.repository.query.CassandraQueryCreator Maven / Gradle / Ivy

There is a newer version: 4.3.2
Show newest version
/*
 * Copyright 2010-2013 the original author or authors.
 *
 * Licensed 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.springframework.data.cassandra.repository.query;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.domain.Sort;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.context.PersistentPropertyPath;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.data.repository.query.parser.Part;
import org.springframework.data.repository.query.parser.Part.IgnoreCaseType;
import org.springframework.data.repository.query.parser.Part.Type;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.util.Assert;

import com.datastax.driver.core.querybuilder.Clause;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;

/**
 * Custom query creator to create Cassandra criteria.
 */
class CassandraQueryCreator extends AbstractQueryCreator {

	private static final Logger LOG = LoggerFactory.getLogger(CassandraQueryCreator.class);
	private final CassandraParameterAccessor accessor;

	private final CassandraMappingContext context;

	/**
	 * Creates a new {@link CassandraQueryCreator} from the given {@link PartTree}, {@link ConvertingParameterAccessor}
	 * and {@link MappingContext}.
	 * 
	 * @param tree
	 * @param accessor
	 * @param context
	 */
	public CassandraQueryCreator(PartTree tree, CassandraParameterAccessor accessor, CassandraMappingContext context) {

		super(tree, accessor);

		Assert.notNull(context);

		this.accessor = accessor;
		this.context = context;
	}

	@Override
	protected Clause create(Part part, Iterator iterator) {

		PersistentPropertyPath path = context.getPersistentPropertyPath(part.getProperty());
		CassandraPersistentProperty property = path.getLeafProperty();
		Clause criteria = from(part, property,
				null /* TODO where(path.toDotPath(CassandraPersistentProperty.PropertyToFieldNameConverter.INSTANCE))*/,
				iterator);

		return criteria;
	}

	@Override
	protected Clause and(Part part, Clause base, Iterator iterator) {

		if (base == null) {
			return create(part, iterator);
		}

		PersistentPropertyPath path = context.getPersistentPropertyPath(part.getProperty());
		CassandraPersistentProperty property = path.getLeafProperty();

		return from(part, property,
				null /* TODO base.and(path.toDotPath(CassandraPersistentProperty.PropertyToFieldNameConverter.INSTANCE))*/,
				iterator);
	}

	@Override
	protected Clause or(Clause base, Clause criteria) {
		throw new InvalidDataAccessApiUsageException(String.format("Cassandra does not support an OR operator!"));
	}

	@Override
	protected Select complete(Clause criteria, Sort sort) {

		if (criteria == null) {
			return null;
		}

		Select select = QueryBuilder.select().all().from("TODO");
		select.where(criteria);

		if (LOG.isDebugEnabled()) {
			LOG.debug("Created query " + select.getQueryString());
		}

		return select;
	}

	private Clause from(Part part, CassandraPersistentProperty property, Clause criteria, Iterator parameters) {

		Type type = part.getType();

		switch (type) {
		// TODO
		// case AFTER:
		// case GREATER_THAN:
		// return criteria.gt(parameters.nextConverted(property));
		// case GREATER_THAN_EQUAL:
		// return criteria.gte(parameters.nextConverted(property));
		// case BEFORE:
		// case LESS_THAN:
		// return criteria.lt(parameters.nextConverted(property));
		// case LESS_THAN_EQUAL:
		// return criteria.lte(parameters.nextConverted(property));
		// case BETWEEN:
		// return criteria.gt(parameters.nextConverted(property)).lt(parameters.nextConverted(property));
		// case IS_NOT_NULL:
		// return criteria.ne(null);
		// case IS_NULL:
		// return criteria.is(null);
		// case NOT_IN:
		// return criteria.nin(nextAsArray(parameters, property));
		// case IN:
		// return criteria.in(nextAsArray(parameters, property));
		// case LIKE:
		// case STARTING_WITH:
		// case ENDING_WITH:
		// case CONTAINING:
		// return addAppropriateLikeRegexTo(criteria, part, parameters.next().toString());
		// case REGEX:
		// return criteria.regex(parameters.next().toString());
		// case EXISTS:
		// return criteria.exists((Boolean) parameters.next());
		// case TRUE:
		// return criteria.is(true);
		// case FALSE:
		// return criteria.is(false);
		// case WITHIN:
		//
		// Object parameter = parameters.next();
		// return criteria.within((Shape) parameter);
		// case SIMPLE_PROPERTY:
		//
		// return isSimpleComparisionPossible(part) ? criteria.is(parameters.nextConverted(property))
		// : createLikeRegexCriteriaOrThrow(part, property, criteria, parameters, false);
		//
		// case NEGATING_SIMPLE_PROPERTY:
		//
		// return isSimpleComparisionPossible(part) ? criteria.ne(parameters.nextConverted(property))
		// : createLikeRegexCriteriaOrThrow(part, property, criteria, parameters, true);
		default:
			throw new UnsupportedCassandraQueryOperatorException(String.format(""));
		}
	}

	private boolean isSimpleComparisionPossible(Part part) {

		switch (part.shouldIgnoreCase()) {
		case NEVER:
			return true;
		case WHEN_POSSIBLE:
			return part.getProperty().getType() != String.class;
		case ALWAYS:
			return false;
		default:
			return true;
		}
	}

	/**
	 * Returns the next element from the given {@link Iterator} expecting it to be of a certain type.
	 * 
	 * @param 
	 * @param iterator
	 * @param type
	 * @throws IllegalArgumentException in case the next element in the iterator is not of the given type.
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private  T nextAs(Iterator iterator, Class type) {
		Object parameter = iterator.next();
		if (parameter.getClass().isAssignableFrom(type)) {
			return (T) parameter;
		}

		throw new IllegalArgumentException(String.format("Expected parameter type of %s but got %s!", type,
				parameter.getClass()));
	}

	private Object[] nextAsArray(Iterator iterator, CassandraPersistentProperty property) {
		Object next = iterator.next(); // TODO nextConverted(property);

		if (next instanceof Collection) {
			return ((Collection) next).toArray();
		} else if (next.getClass().isArray()) {
			return (Object[]) next;
		}

		return new Object[] { next };
	}
}