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

org.hibernate.query.internal.ParameterMetadataImpl Maven / Gradle / Ivy

There is a newer version: 7.0.0.Beta1
Show newest version
/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * License: GNU Lesser General Public License (LGPL), version 2.1 or later.
 * See the lgpl.txt file in the root directory or .
 */
package org.hibernate.query.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Predicate;
import javax.persistence.Parameter;

import org.hibernate.QueryException;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.internal.util.collections.IdentitySet;
import org.hibernate.internal.util.compare.ComparableComparator;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.spi.ParameterMetadataImplementor;
import org.hibernate.query.spi.QueryParameterImplementor;

/**
 * Encapsulates metadata about parameters encountered within a query.
 *
 * @author Steve Ebersole
 */
public class ParameterMetadataImpl implements ParameterMetadataImplementor {
	/**
	 * Singleton access
	 */
	public static final ParameterMetadataImpl EMPTY = new ParameterMetadataImpl();

	private final Set> queryParameters;

	private final Set names;
	private final Set labels;


	private ParameterMetadataImpl() {
		this.queryParameters = Collections.emptySet();
		this.names = Collections.emptySet();
		this.labels = Collections.emptySet();
	}

	public ParameterMetadataImpl(Set> queryParameters) {
		this.queryParameters = queryParameters;

		// if we have any ordinal parameters, make sure the numbers
		// start with 1 and are contiguous

		Set names = null;
		Set labels = null;

		for ( QueryParameterImplementor queryParameter : queryParameters ) {
			if ( queryParameter.getPosition() != null ) {
				if ( labels == null ) {
					labels = new HashSet<>();
				}
				labels.add( queryParameter.getPosition() );
			}
			else if ( queryParameter.getName() != null ) {
				if ( names == null ) {
					names = new HashSet<>();
				}
				names.add( queryParameter.getName() );
			}
		}

		this.labels = labels == null
				? Collections.emptySet()
				: labels;

		this.names = names == null
				? Collections.emptySet()
				: names;

		verifyOrdinalParamLabels( labels );
	}

	public ParameterMetadataImpl(
			Map> positionalQueryParameters,
			Map> namedQueryParameters) {
		if ( CollectionHelper.isEmpty( positionalQueryParameters )
				&& CollectionHelper.isEmpty( namedQueryParameters ) ) {
			// no parameters
			this.queryParameters = Collections.emptySet();
			this.names = Collections.emptySet();
			this.labels = Collections.emptySet();
		}
		else {
			this.queryParameters = new IdentitySet<>();
			this.queryParameters.addAll( positionalQueryParameters.values() );
			this.queryParameters.addAll( namedQueryParameters.values() );

			this.names = namedQueryParameters.keySet();
			this.labels = positionalQueryParameters.keySet();

			verifyOrdinalParamLabels( labels );
		}

	}

	private static void verifyOrdinalParamLabels(Set labels) {
		if ( CollectionHelper.isEmpty( labels ) ) {
			return;
		}

		final List sortedLabels = new ArrayList<>( labels );
		sortedLabels.sort( ComparableComparator.instance() );

		int lastPosition = -1;
		for ( Integer sortedPosition : sortedLabels ) {
			if ( lastPosition == -1 ) {
				if ( sortedPosition != 1 ) {
					throw new QueryException(
							String.format(
									Locale.ROOT,
									"Expected ordinal parameter labels to start with 1, but found - %s",
									sortedPosition
							)
					);
				}

				lastPosition = sortedPosition;
				continue;
			}

			if ( sortedPosition != lastPosition + 1 ) {
				throw new QueryException(
						String.format(
								Locale.ROOT,
								"Unexpected gap in ordinal parameter labels [%s -> %s] : [%s]",
								lastPosition,
								sortedPosition,
								StringHelper.join( ",", sortedLabels.iterator() )
						)
				);
			}

			lastPosition = sortedPosition;
		}
	}

	@Override
	public int getParameterCount() {
		return queryParameters.size();
	}

	@Override
	public boolean containsReference(QueryParameter parameter) {
		//noinspection SuspiciousMethodCalls
		return queryParameters.contains( parameter );
	}

	@Override
	public void visitParameters(Consumer> consumer) {
		queryParameters.forEach( consumer );
	}

	@Override
	public Set> getRegistrations() {
		return Collections.unmodifiableSet( queryParameters );
	}

	@Override
	public boolean hasAnyMatching(Predicate> filter) {
		for ( QueryParameterImplementor queryParameter : queryParameters ) {
			if ( filter.test( queryParameter ) ) {
				return true;
			}
		}

		return false;
	}

	@Override
	public QueryParameterImplementor resolve(Parameter param) {
		if ( param instanceof QueryParameterImplementor ) {
			return (QueryParameterImplementor) param;
		}

		throw new IllegalArgumentException( "Could not resolve javax.persistence.Parameter to org.hibernate.query.QueryParameter" );
	}


	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Named parameter handling

	@Override
	public boolean hasNamedParameters() {
		return ! names.isEmpty();
	}

	@Override
	public Set getNamedParameterNames() {
		return  names;
	}

	@Override
	public QueryParameterImplementor getQueryParameter(String name) {
		for ( QueryParameterImplementor queryParameter : queryParameters ) {
			if ( name.equals( queryParameter.getName() ) ) {
				return queryParameter;
			}
		}

		return null;
	}



	// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Positional parameter handling

	@Override
	public boolean hasPositionalParameters() {
		return ! labels.isEmpty();
	}

	public Set getOrdinalParameterLabels() {
		return labels;
	}

	@Override
	public QueryParameterImplementor getQueryParameter(int positionLabel) {
		for ( QueryParameterImplementor queryParameter : queryParameters ) {
			if ( queryParameter.getPosition() != null && queryParameter.getPosition() == positionLabel ) {
				return queryParameter;
			}
		}

		return null;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy