/******************************************************************************* * Copyright (c) 2006, 2015 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * 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 javax.persistence.Access; import javax.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); } /** * {@inheritDoc} */ 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(); } /** * {@inheritDoc} */ public IMapping getMappingNamed(String name) { initializeMappings(); return mappings.get(name); } /** * {@inheritDoc} */ public IManagedTypeProvider getProvider() { return provider; } /** * {@inheritDoc} */ public JavaType getType() { return type; } protected void initializeMappings() { if (mappings == null) { mappings = new HashMap<String, IMapping>(); 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)); } /** * {@inheritDoc} */ public final Iterable<IMapping> mappings() { initializeMappings(); return new SnapshotCloneIterable<IMapping>(mappings.values()); } }