| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.apache.openjpa.persistence; |
| |
| import java.lang.reflect.Modifier; |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.util.Arrays; |
| import java.util.Collection; |
| |
| import javax.persistence.EntityManager; |
| import javax.persistence.EntityManagerFactory; |
| |
| import org.apache.openjpa.enhance.PCRegistry; |
| import org.apache.openjpa.kernel.Broker; |
| import org.apache.openjpa.kernel.BrokerFactory; |
| import org.apache.openjpa.kernel.BrokerImpl.StateManagerId; |
| import org.apache.openjpa.lib.util.Localizer; |
| import org.apache.openjpa.meta.ClassMetaData; |
| import org.apache.openjpa.meta.FieldMetaData; |
| import org.apache.openjpa.util.ApplicationIds; |
| import org.apache.openjpa.util.BigDecimalId; |
| import org.apache.openjpa.util.BigIntegerId; |
| import org.apache.openjpa.util.ByteId; |
| import org.apache.openjpa.util.CharId; |
| import org.apache.openjpa.util.DoubleId; |
| import org.apache.openjpa.util.FloatId; |
| import org.apache.openjpa.util.Id; |
| import org.apache.openjpa.util.ImplHelper; |
| import org.apache.openjpa.util.IntId; |
| import org.apache.openjpa.util.LongId; |
| import org.apache.openjpa.util.ObjectId; |
| import org.apache.openjpa.util.OpenJPAId; |
| import org.apache.openjpa.util.ShortId; |
| import org.apache.openjpa.util.StringId; |
| import org.apache.openjpa.util.UserException; |
| |
| /** |
| * Helper class for switching between OpenJPA's JPA facade and the underlying |
| * Broker kernel. |
| * |
| * @since 1.0.0 |
| */ |
| public class JPAFacadeHelper { |
| |
| public static final String EM_KEY = |
| "org.apache.openjpa.persistence.EntityManager"; |
| public static final String EMF_KEY = |
| "org.apache.openjpa.persistence.EntityManagerFactory"; |
| |
| private static final Localizer _loc = |
| Localizer.forPackage(JPAFacadeHelper.class); |
| |
| public static OpenJPAEntityManagerFactory toEntityManagerFactory( |
| BrokerFactory factory) { |
| if (factory == null) |
| return null; |
| |
| factory.lock(); |
| try { |
| OpenJPAEntityManagerFactory emf = (OpenJPAEntityManagerFactory) |
| factory.getUserObject(EMF_KEY); |
| if (emf == null) { |
| emf = EntityManagerFactoryValue.newFactory(factory); |
| factory.putUserObject(EMF_KEY, emf); |
| } |
| return emf; |
| } catch (Exception e) { |
| throw PersistenceExceptions.toPersistenceException(e); |
| } finally { |
| factory.unlock(); |
| } |
| } |
| |
| /** |
| * Return the underlying broker factory for the given persistence manager |
| * factory facade. |
| */ |
| public static BrokerFactory toBrokerFactory(EntityManagerFactory emf) { |
| if (emf == null) |
| return null; |
| if (!(emf instanceof EntityManagerFactoryImpl)) { |
| Class c = emf.getClass(); |
| try { |
| // either cast here may fail |
| emf = (EntityManagerFactoryImpl) ((OpenJPAEntityManagerFactory) |
| emf).getUserObject(EMF_KEY); |
| } catch (ClassCastException cce) { |
| throw new ArgumentException(_loc.get( |
| "cant-convert-brokerfactory", c), null, null, false); |
| } |
| } |
| return ((EntityManagerFactoryImpl) emf).getBrokerFactory(); |
| } |
| |
| /** |
| * Return a persistence manager facade to the given broker retaining |
| * previously associated persistence context type. |
| */ |
| public static OpenJPAEntityManager toEntityManager(Broker broker) { |
| if (broker == null) |
| return null; |
| |
| broker.lock(); |
| try { |
| OpenJPAEntityManager em = (OpenJPAEntityManager) |
| broker.getUserObject(EM_KEY); |
| if (em == null) { |
| EntityManagerFactoryImpl emf = (EntityManagerFactoryImpl) |
| toEntityManagerFactory(broker.getBrokerFactory()); |
| em = emf.newEntityManagerImpl(broker); |
| broker.putUserObject(EM_KEY, em); |
| } |
| return em; |
| } catch (Exception e) { |
| throw PersistenceExceptions.toPersistenceException(e); |
| } finally { |
| broker.unlock(); |
| } |
| } |
| |
| /** |
| * Return the underlying broker for the given entity manager facade. |
| */ |
| public static Broker toBroker(EntityManager em) { |
| if (em == null) |
| return null; |
| if (!(em instanceof EntityManagerImpl)) { |
| Class c = em.getClass(); |
| try { |
| // either cast here may fail |
| em = (EntityManagerImpl) ((OpenJPAEntityManager) em). |
| getUserObject(EM_KEY); |
| } catch (ClassCastException cce) { |
| throw new ArgumentException(_loc.get("cant-convert-broker", c), |
| new Throwable[] { cce }, null, false); |
| } |
| } |
| return ((EntityManagerImpl) em).getBroker(); |
| } |
| |
| /** |
| * Returns the {@link org.apache.openjpa.meta.ClassMetaData} associated with |
| * the persistent object <code>o</code>. |
| */ |
| public static ClassMetaData getMetaData(Object o) { |
| if (o == null) |
| return null; |
| EntityManager em = OpenJPAPersistence.getEntityManager(o); |
| return (em == null) ? null : getMetaData(em, |
| ImplHelper.getManagedInstance(o).getClass()); |
| } |
| |
| /** |
| * Returns the {@link org.apache.openjpa.meta.ClassMetaData} associated |
| * with the persistent type <code>cls</code>. |
| */ |
| public static ClassMetaData getMetaData(EntityManager em, Class cls) { |
| if (em == null) |
| throw new NullPointerException("em == null"); |
| |
| OpenJPAEntityManagerSPI kem = (OpenJPAEntityManagerSPI) |
| OpenJPAPersistence.cast(em); |
| try { |
| return kem.getConfiguration().getMetaDataRepositoryInstance(). |
| getMetaData(cls, kem.getClassLoader(), false); |
| } catch (Exception e) { |
| throw PersistenceExceptions.toPersistenceException(e); |
| } |
| } |
| |
| /** |
| * Returns the {@link org.apache.openjpa.meta.ClassMetaData} associated |
| * with the persistent type <code>cls</code>. |
| */ |
| public static ClassMetaData getMetaData(EntityManagerFactory emf, |
| Class cls) { |
| if (emf == null) |
| throw new NullPointerException("emf == null"); |
| |
| OpenJPAEntityManagerFactorySPI emfSPI = |
| (OpenJPAEntityManagerFactorySPI) OpenJPAPersistence.cast(emf); |
| try { |
| return emfSPI.getConfiguration().getMetaDataRepositoryInstance(). |
| getMetaData(cls, null, false); |
| } catch (Exception e) { |
| throw PersistenceExceptions.toPersistenceException(e); |
| } |
| } |
| |
| /** |
| * Translate from a OpenJPA identity object to a Persistence one. |
| */ |
| public static Object fromOpenJPAObjectId(Object oid) { |
| if (oid instanceof OpenJPAId) |
| return ((OpenJPAId) oid).getIdObject(); |
| return oid; |
| } |
| |
| /** |
| * Translate from a Persistence identity object to a OpenJPA one. If the provided oid isn't of the expected type |
| * a UserException will be thrown. |
| */ |
| public static Object toOpenJPAObjectId(ClassMetaData meta, Object oid) { |
| if (oid == null || meta == null) |
| return null; |
| if (oid instanceof OpenJPAId) { |
| return oid; |
| } |
| |
| Class<?> cls = meta.getDescribedType(); |
| FieldMetaData[] pks = meta.getPrimaryKeyFields(); |
| |
| Object expected = meta.getObjectIdType(); |
| try { |
| switch (meta.getIdentityType()) { |
| case ClassMetaData.ID_DATASTORE: |
| if (oid instanceof String && ((String) oid).startsWith(StateManagerId.STRING_PREFIX)) |
| return new StateManagerId((String) oid); |
| return new Id(cls, ((Number) oid).longValue()); |
| case ClassMetaData.ID_APPLICATION: |
| if (ImplHelper.isAssignable(meta.getObjectIdType(), oid.getClass())) { |
| if (!meta.isOpenJPAIdentity() && meta.isObjectIdTypeShared()) |
| return new ObjectId(cls, oid); |
| return oid; |
| } |
| |
| if (meta.getIdClass() == null) { |
| expected = pks[0].getDeclaredType(); |
| } else { |
| expected = meta.getIdClass(); |
| } |
| // stringified app id? |
| if (oid instanceof String |
| && !meta.getRepository().getConfiguration().getCompatibilityInstance().getStrictIdentityValues() |
| && !Modifier.isAbstract(cls.getModifiers())) |
| return PCRegistry.newObjectId(cls, (String) oid); |
| |
| Object[] arr = (oid instanceof Object[]) ? (Object[]) oid : new Object[] { oid }; |
| Object rtrn = ApplicationIds.fromPKValues(arr, meta); |
| if (rtrn != null && meta.getObjectIdType() != null) { |
| if (rtrn instanceof ObjectId) { |
| // embedded id and composite id with a derived id that |
| // uses an embedded id |
| if (pks.length > 0 && (pks[0].isEmbedded() || pks[0].isTypePC())) { |
| Class idClass = meta.getIdClass(); |
| if (pks[0].getDeclaredType().equals(oid.getClass()) || idClass != null |
| && idClass.equals(oid.getClass())) { |
| return rtrn; |
| } |
| } |
| } else { |
| if (!(rtrn instanceof StringId) || rtrn instanceof StringId && oid instanceof String) { |
| return rtrn; |
| } |
| } |
| } |
| default: |
| throw new UserException(_loc.get("invalid-oid", new Object[] { expected, oid.getClass() })); |
| } |
| } catch (RuntimeException re) { |
| if (expected == null) |
| throw new UserException(_loc.get("invalid-oid", new Object[] { Number.class, oid.getClass() })); |
| throw new UserException(_loc.get("invalid-oid", new Object[] { expected, oid.getClass() })); |
| } |
| } |
| |
| /** |
| * Return an array of OpenJPA oids for the given native oid array. |
| */ |
| public static Object[] toOpenJPAObjectIds(ClassMetaData meta, |
| Object... oids) { |
| if (oids == null || oids.length == 0) |
| return oids; |
| |
| // since the class if fixed for all oids, we can tell if we have to |
| // translate the array based on whether the first oid needs translating |
| Object oid = toOpenJPAObjectId(meta, oids[0]); |
| if (oid == oids[0]) |
| return oids; |
| |
| Object[] copy = new Object[oids.length]; |
| copy[0] = oid; |
| for (int i = 1; i < oids.length; i++) |
| copy[i] = toOpenJPAObjectId(meta, oids[i]); |
| return copy; |
| } |
| |
| /** |
| * Return a collection of OpenJPA oids for the given native oid collection. |
| */ |
| public static Collection<Object> toOpenJPAObjectIds(ClassMetaData meta, Collection<Object> oids) { |
| if (oids == null || oids.size() == 0) { |
| return oids; |
| } |
| return Arrays.asList(toOpenJPAObjectIds(meta, oids.toArray())); |
| } |
| |
| |
| /** |
| * Translate from a OpenJPA identity class to a native one. |
| */ |
| public static Class fromOpenJPAObjectIdClass(Class oidClass) { |
| if (oidClass == null) |
| return null; |
| if (oidClass == Id.class) |
| return Long.class; |
| if (oidClass == ByteId.class) |
| return Byte.class; |
| if (oidClass == CharId.class) |
| return Character.class; |
| if (oidClass == DoubleId.class) |
| return Double.class; |
| if (oidClass == FloatId.class) |
| return Float.class; |
| if (oidClass == IntId.class) |
| return Integer.class; |
| if (oidClass == LongId.class) |
| return Long.class; |
| if (oidClass == ShortId.class) |
| return Short.class; |
| if (oidClass == StringId.class) |
| return String.class; |
| if (oidClass == BigDecimalId.class) |
| return BigDecimal.class; |
| if (oidClass == BigIntegerId.class) |
| return BigInteger.class; |
| return oidClass; |
| } |
| } |