/*
 * 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.procedure.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import javax.persistence.Parameter;

import org.hibernate.procedure.internal.ProcedureCallImpl;
import org.hibernate.procedure.spi.ParameterRegistrationImplementor;
import org.hibernate.procedure.spi.ParameterStrategy;
import org.hibernate.query.ParameterMetadata;
import org.hibernate.query.QueryParameter;
import org.hibernate.query.procedure.ProcedureParameter;
import org.hibernate.query.procedure.spi.ProcedureParameterImplementor;

Author:Steve Ebersole
/** * @author Steve Ebersole */
public class ProcedureParameterMetadata implements ParameterMetadata { private final ProcedureCallImpl procedureCall; private ParameterStrategy parameterStrategy = ParameterStrategy.UNKNOWN; private List<ProcedureParameterImplementor> parameters = new ArrayList<>(); public ProcedureParameterMetadata(ProcedureCallImpl procedureCall) { this.procedureCall = procedureCall; } public void registerParameter(ProcedureParameterImplementor parameter) { if ( parameter.getName() != null ) { if ( parameterStrategy == ParameterStrategy.POSITIONAL ) { throw new IllegalArgumentException( "Cannot mix named parameter with positional parameter registrations" ); } parameterStrategy = ParameterStrategy.NAMED; } else if ( parameter.getPosition() != null ) { if ( parameterStrategy == ParameterStrategy.NAMED ) { throw new IllegalArgumentException( "Cannot mix positional parameter with named parameter registrations" ); } this.parameterStrategy = ParameterStrategy.POSITIONAL; } else { throw new IllegalArgumentException( "Unrecognized parameter type : " + parameter ); } if ( parameters == null ) { parameters = new ArrayList<>(); } parameters.add( parameter ); } @Override public boolean hasNamedParameters() { return parameterStrategy == ParameterStrategy.NAMED; } @Override public boolean hasPositionalParameters() { return parameterStrategy == ParameterStrategy.POSITIONAL; } @Override public Set<QueryParameter<?>> collectAllParameters() { final Set<QueryParameter<?>> rtn = new LinkedHashSet<>(); for ( ProcedureParameter parameter : parameters ) { rtn.add( parameter ); } return rtn; } @Override public Set<Parameter<?>> collectAllParametersJpa() { final Set<Parameter<?>> rtn = new LinkedHashSet<>(); for ( ProcedureParameter parameter : parameters ) { rtn.add( parameter ); } return rtn; } @Override public Set<String> getNamedParameterNames() { if ( !hasNamedParameters() ) { return Collections.emptySet(); } final Set<String> rtn = new HashSet<>(); for ( ProcedureParameter parameter : parameters ) { if ( parameter.getName() != null ) { rtn.add( parameter.getName() ); } } return rtn; } @Override public int getPositionalParameterCount() { return hasPositionalParameters() ? parameters.size() : 0; } @Override @SuppressWarnings("unchecked") public <T> ParameterRegistrationImplementor<T> getQueryParameter(String name) { assert name != null; if ( hasNamedParameters() ) { for ( ParameterRegistrationImplementor parameter : parameters ) { if ( name.equals( parameter.getName() ) ) { return parameter; } } } throw new IllegalArgumentException( "Named parameter [" + name + "] is not registered with this procedure call" ); } @Override @SuppressWarnings("unchecked") public <T> ParameterRegistrationImplementor<T> getQueryParameter(Integer position) { assert position != null; if ( hasPositionalParameters() ) { for ( ParameterRegistrationImplementor parameter : parameters ) { if ( parameter.getPosition() != null && position.intValue() == parameter.getPosition() ) { return parameter; } } } throw new IllegalArgumentException( "Positional parameter [" + position + "] is not registered with this procedure call" ); } @Override @SuppressWarnings("unchecked") public <T> ProcedureParameterImplementor<T> resolve(Parameter<T> param) { if ( ProcedureParameterImplementor.class.isInstance( param ) ) { for ( ProcedureParameterImplementor parameter : parameters ) { if ( parameter == param ) { return parameter; } } } throw new IllegalArgumentException( "Could not resolve javax.persistence.Parameter to org.hibernate.query.QueryParameter" ); } @Override public Collection<QueryParameter> getPositionalParameters() { return parameters.stream().filter( p -> p.getPosition() != null ).collect( Collectors.toList() ); } @Override public Collection<QueryParameter> getNamedParameters() { return parameters.stream().filter( p -> p.getPosition() == null ).collect( Collectors.toList() ); } @Override public int getParameterCount() { return parameters.size(); } @Override @SuppressWarnings("SuspiciousMethodCalls") public boolean containsReference(QueryParameter parameter) { return parameters.contains( parameter ); } public ParameterStrategy getParameterStrategy() { return parameterStrategy; } @Override public void visitRegistrations(Consumer<QueryParameter> action) { for ( ProcedureParameterImplementor parameter : parameters ) { action.accept( parameter ); } } }