/* * 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 http://www.gnu.org/licenses/lgpl-2.1.html */ package org.hibernate.query.sqm.tree.internal; import java.util.Arrays; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.hibernate.query.sqm.tree.SqmParameter; import org.hibernate.query.sqm.tree.SqmStatement; import org.hibernate.query.sqm.tree.expression.NamedParameterSqmExpression; import org.hibernate.query.sqm.tree.expression.PositionalParameterSqmExpression; import org.hibernate.query.sqm.SemanticException; /** * @author Steve Ebersole */ public abstract class AbstractSqmStatement implements SqmStatement, ParameterCollector { private Map<String,NamedParameterSqmExpression> namedQueryParameters; private Map<Integer,PositionalParameterSqmExpression> positionalQueryParameters; @Override public void addParameter(NamedParameterSqmExpression parameter) { assert parameter.getName() != null; assert parameter.getPosition() == null; if ( namedQueryParameters == null ) { namedQueryParameters = new ConcurrentHashMap<>(); } namedQueryParameters.put( parameter.getName(), parameter ); } @Override public void addParameter(PositionalParameterSqmExpression parameter) { assert parameter.getPosition() != null; assert parameter.getName() == null; if ( positionalQueryParameters == null ) { positionalQueryParameters = new ConcurrentHashMap<>(); } positionalQueryParameters.put( parameter.getPosition(), parameter ); } public void wrapUp() { validateParameters(); } private void validateParameters() { if ( positionalQueryParameters == null ) { return; } // validate the positions. JPA says that these should start with 1 and // increment contiguously (no gaps) int[] positionsArray = positionalQueryParameters.keySet().stream().mapToInt( Integer::intValue ).toArray(); Arrays.sort( positionsArray ); int previous = 0; for ( Integer position : positionsArray ) { if ( position != previous + 1 ) { if ( previous == 0 ) { throw new SemanticException( "Positional parameters did not start with 1 : " + position ); } else { throw new SemanticException( "Gap in positional parameter positions; skipped " + (previous+1) ); } } previous = position; } } @Override public Set<SqmParameter> getQueryParameters() { Set<SqmParameter> parameters = new HashSet<>(); if ( namedQueryParameters != null ) { parameters.addAll( namedQueryParameters.values() ); } if ( positionalQueryParameters != null ) { parameters.addAll( positionalQueryParameters.values() ); } return parameters; } }