blob: 11f635601ca2d893903a3689b694aca18268dc36 [file] [log] [blame]
/*
* Copyright (c) 2006, 2021 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Oracle - initial API and implementation
//
package org.eclipse.persistence.jpa.jpql.tools.resolver;
import org.eclipse.persistence.jpa.jpql.tools.spi.IManagedType;
import org.eclipse.persistence.jpa.jpql.tools.spi.IManagedTypeProvider;
import org.eclipse.persistence.jpa.jpql.tools.spi.IManagedTypeVisitor;
import org.eclipse.persistence.jpa.jpql.tools.spi.IMapping;
import org.eclipse.persistence.jpa.jpql.tools.spi.IType;
import org.eclipse.persistence.jpa.jpql.tools.spi.ITypeDeclaration;
import org.eclipse.persistence.jpa.jpql.tools.utility.iterable.EmptyIterable;
/**
* This {@link Resolver} is responsible to resolve the type of a collection-valued field.
*
* @version 2.5
* @since 2.3
* @author Pascal Filion
*/
public class CollectionValuedFieldResolver extends AbstractPathResolver {
/**
* Creates a new <code>CollectionValuedFieldResolver</code>.
*
* @param parent The parent {@link Resolver}, which is never <code>null</code>
* @param path A single segment of the collection-valued path expression
*/
public CollectionValuedFieldResolver(Resolver parent, String path) {
super(parent, path);
}
@Override
protected IType buildType() {
ITypeDeclaration typeDeclaration = getTypeDeclaration();
IType type = typeDeclaration.getType();
// For a collection type, return the first type parameter
if (getTypeHelper().isCollectionType(type)) {
ITypeDeclaration[] typeParameters = typeDeclaration.getTypeParameters();
if (typeParameters.length > 0) {
type = typeParameters[0].getType();
}
}
// For a map type, by default the value is the actual type to return
else if (getTypeHelper().isMapType(type)) {
ITypeDeclaration[] typeParameters = typeDeclaration.getTypeParameters();
if (typeParameters.length == 2) {
type = typeParameters[1].getType();
}
}
// A collection-valued path expression should not reference a primitive,
// however, in an invalid query, this could potentially happen and the API
// only deals with the primitive wrapper type
return getTypeHelper().convertPrimitive(type);
}
@Override
protected IManagedType resolveManagedType(IMapping mapping) {
ITypeDeclaration typeDeclaration = mapping.getTypeDeclaration();
IType type = typeDeclaration.getType();
// Collection type cannot be traversed
if (getTypeHelper().isCollectionType(type)) {
ITypeDeclaration[] typeParameters = typeDeclaration.getTypeParameters();
if (typeParameters.length == 0) {
return null;
}
type = typeParameters[0].getType();
}
// Wrap the Map into a virtual IManagedType so it can be returned and the
// IType for the Map can be used to retrieve the type of the key and value
else if (getTypeHelper().isMapType(type)) {
ITypeDeclaration[] typeParameters = typeDeclaration.getTypeParameters();
if (typeParameters.length != 2) {
return null;
}
type = typeParameters[1].getType();
}
// Retrieve the corresponding managed type for the mapping's type
return getProvider().getManagedType(type);
}
protected static class MapManagedType implements IManagedType {
protected final IType mapType;
protected final IManagedTypeProvider provider;
protected MapManagedType(IManagedTypeProvider provider, IType mapType) {
super();
this.provider = provider;
this.mapType = mapType;
}
@Override
public void accept(IManagedTypeVisitor visitor) {
}
@Override
public int compareTo(IManagedType managedType) {
return getType().getName().compareTo(managedType.getType().getName());
}
@Override
public IMapping getMappingNamed(String name) {
return null;
}
@Override
public IManagedTypeProvider getProvider() {
return provider;
}
@Override
public IType getType() {
return mapType;
}
@Override
public Iterable<IMapping> mappings() {
return EmptyIterable.instance();
}
@Override
public String toString() {
return getType().getName();
}
}
}