blob: 4c2b1acfe37309ed66b50180efe731c3d9d967e0 [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.tests.jpql.tools.spi.java;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import jakarta.persistence.Access;
import jakarta.persistence.AccessType;
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.IMapping;
import org.eclipse.persistence.jpa.jpql.tools.spi.IMappingBuilder;
import org.eclipse.persistence.jpa.jpql.tools.utility.iterable.SnapshotCloneIterable;
/**
* The abstract definition of {@link IManagedType} defined for wrapping the runtime mapped class object.
*
* @version 2.5
* @since 2.3
* @author Pascal Filion
*/
@SuppressWarnings("nls")
public abstract class JavaManagedType implements IManagedType {
/**
* The builder that is responsible to create the {@link IMapping} wrapping a persistent attribute
* or property.
*/
private IMappingBuilder<Member> mappingBuilder;
/**
* The cached {@link IMapping mappings} wrapping the persistent attributes and properties.
*/
private Map<String, IMapping> mappings;
/**
* The provider of JPA managed types.
*/
private final IManagedTypeProvider provider;
/**
* The cached {@link JavaType} representing the managed type.
*/
private final JavaType type;
/**
* Creates a new <code>JavaManagedType</code>.
*
* @param provider The provider of JPA managed types
* @param type The {@link org.eclipse.persistence.jpa.jpql.tools.spi.IType IType} wrapping the Java type
* @param mappingBuilder The builder that is responsible to create the {@link IMapping} wrapping
* a persistent attribute or property
*/
public JavaManagedType(IManagedTypeProvider provider,
JavaType type,
IMappingBuilder<Member> mappingBuilder) {
super();
this.type = type;
this.provider = provider;
this.mappingBuilder = mappingBuilder;
}
protected IMapping buildMapping(Member member) {
return mappingBuilder.buildMapping(this, member);
}
@Override
public int compareTo(IManagedType managedType) {
return getType().getName().compareTo(managedType.getType().getName());
}
protected AccessType getAccessType() {
Access accessType = type.getType().getAnnotation(Access.class);
if (accessType == null) {
return AccessType.FIELD;
}
return accessType.value();
}
@Override
public IMapping getMappingNamed(String name) {
initializeMappings();
return mappings.get(name);
}
@Override
public IManagedTypeProvider getProvider() {
return provider;
}
@Override
public JavaType getType() {
return type;
}
protected void initializeMappings() {
if (mappings == null) {
mappings = new HashMap<>();
initializeMappings(type.getType(), getAccessType());
}
}
protected void initializeMappings(Class<?> type, AccessType accessType) {
if (type == Object.class) {
return;
}
if (accessType == AccessType.FIELD) {
for (Field field : type.getDeclaredFields()) {
if (isPersistentAttribute(field)) {
mappings.put(field.getName(), buildMapping(field));
}
}
}
else {
for (Method method : type.getDeclaredMethods()) {
if (isProperty(method)) {
mappings.put(method.getName(), buildMapping(method));
}
}
}
initializeMappings(type.getSuperclass(), accessType);
}
protected boolean isPersistentAttribute(Field field) {
int modifiers = field.getModifiers();
return !Modifier.isStatic(modifiers) &&
!Modifier.isPublic(modifiers);
}
protected boolean isProperty(Method method) {
int modifiers = method.getModifiers();
String name = method.getName();
return // Name convention
(name.startsWith("get") ||
name.startsWith("is")) &&
// Return type and parameter
method.getReturnType() != Void.class &&
method.getParameterTypes().length == 0 &&
// Modifiers
!Modifier.isStatic(modifiers) &&
!Modifier.isNative(modifiers) &&
(Modifier.isPublic(modifiers) ||
Modifier.isProtected(modifiers));
}
@Override
public final Iterable<IMapping> mappings() {
initializeMappings();
return new SnapshotCloneIterable<>(mappings.values());
}
}