/* * Copyright (C) 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jboss.errai.jpa.client.local; import java.util.Set; import javax.persistence.metamodel.EmbeddableType; import javax.persistence.metamodel.EntityType; import javax.persistence.metamodel.ManagedType; import javax.persistence.metamodel.Metamodel; import com.google.common.collect.ImmutableBiMap; import com.google.common.collect.ImmutableBiMap.Builder; /** * Trivial implementation of the JPA Metamodel class. This class is normally * instantiated and populated by generated code in ErraiEntityManager. * <p> * Instances of this class have two distinct lifecycle phases: when first * constructed, the package-private methods {@link #addEntityType(EntityType)} * and friends may be called to add new entity types. This is normally done from * generated code, but test code can also do this manually. Once * {@link #freeze()} has been called, the instance is "frozen." When frozen, all * the Metamodel interface methods operate properly, but the addXXX() methods * throw exceptions when called. * * @author Jonathan Fuerth <jfuerth@gmail.com> */ public class ErraiMetamodel implements Metamodel { // these are populated by a call to freeze() private ImmutableBiMap<String, EntityType<?>> entityTypes; private ImmutableBiMap<Class<?>, ManagedType<?>> managedTypes; private ImmutableBiMap<Class<?>, EmbeddableType<?>> embeddableTypes; // these are set to null when freeze() is called private Builder<String, EntityType<?>> entityTypeBuilder = ImmutableBiMap.builder(); private Builder<Class<?>, ManagedType<?>> managedTypeBuilder = ImmutableBiMap.builder(); private Builder<Class<?>, EmbeddableType<?>> embeddableTypeBuilder = ImmutableBiMap.builder(); <X> void addEntityType(EntityType<X> e) { entityTypeBuilder.put(e.getJavaType().getName(), e); managedTypeBuilder.put(e.getJavaType(), e); } <X> void addManagedType(ManagedType<X> e) { managedTypeBuilder.put(e.getJavaType(), e); } <X> void addEmbeddableType(EmbeddableType<X> e) { embeddableTypeBuilder.put(e.getJavaType(), e); managedTypeBuilder.put(e.getJavaType(), e); } /** * Freezes the definition of this metamodel. Once frozen, no more entity * metadata can be added, and the collections returned by * {@link #getEntities()} and friends are immutable. */ void freeze() { entityTypes = entityTypeBuilder.build(); entityTypeBuilder = null; managedTypes = managedTypeBuilder.build(); managedTypeBuilder = null; embeddableTypes = embeddableTypeBuilder.build(); embeddableTypeBuilder = null; } /** * Returns true iff this instance is frozen. See the class-level documentation * for a description of the implications. */ boolean isFrozen() { return entityTypeBuilder == null; } /** * Works like {@link #entity(String)} but * * @param className * The fully-qualified class name of the entity type to retrieve (as * returned by {@code Class.getName()}). Null not permitted. * @param failIfNotFound * does not throw an exception if the entity type does not exist. * @return the ErraiEntityType associated with the named class, or null if * {@code failIfNotFound} is true and no such entity exists. */ @SuppressWarnings("unchecked") <X> ErraiEntityType<X> entity(String className, boolean failIfNotFound) { ErraiEntityType<X> et = (ErraiEntityType<X>) entityTypes.get(className); if (failIfNotFound && et == null) { throw new IllegalArgumentException(className + " is not a known entity type"); } return et; } /** * Retrieves an ErraiEntityType by name rather than class reference. * * @param className * The fully-qualified class name of the entity type to retrieve (as * returned by {@code Class.getName()}). Null not permitted. * @return the ErraiEntityType associated with the named class. * @throws IllegalArgumentException * if the given class name is not an known entity type. */ public <X> ErraiEntityType<X> entity(String className) { return entity(className, true); } @Override public <X> ErraiEntityType<X> entity(Class<X> cls) { return entity(cls.getName()); } @Override @SuppressWarnings("unchecked") public <X> ManagedType<X> managedType(Class<X> cls) { return (ManagedType<X>) managedTypes.get(cls); } @Override @SuppressWarnings("unchecked") public <X> EmbeddableType<X> embeddable(Class<X> cls) { return (EmbeddableType<X>) embeddableTypes.get(cls); } @Override public Set<ManagedType<?>> getManagedTypes() { return managedTypes.values(); } @Override public Set<EntityType<?>> getEntities() { return entityTypes.values(); } @Override public Set<EmbeddableType<?>> getEmbeddables() { return embeddableTypes.values(); } }