001 // Copyright 2011 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.tapestry5.internal.jpa; 016 017 import org.apache.tapestry5.ValueEncoder; 018 import org.apache.tapestry5.ioc.internal.util.InternalUtils; 019 import org.apache.tapestry5.ioc.services.PropertyAccess; 020 import org.apache.tapestry5.ioc.services.PropertyAdapter; 021 import org.apache.tapestry5.ioc.services.TypeCoercer; 022 import org.apache.tapestry5.jpa.EntityManagerManager; 023 import org.slf4j.Logger; 024 025 import javax.persistence.EntityManager; 026 import javax.persistence.metamodel.EntityType; 027 import javax.persistence.metamodel.SingularAttribute; 028 import javax.persistence.metamodel.Type; 029 030 public class JpaValueEncoder<E> implements ValueEncoder<E> 031 { 032 private final EntityType<E> entity; 033 private final EntityManagerManager entityManagerManager; 034 private final String persistenceUnitName; 035 private final TypeCoercer typeCoercer; 036 private final Logger logger; 037 private final String idPropertyName; 038 private final PropertyAdapter propertyAdapter; 039 040 public JpaValueEncoder(final EntityType<E> entity, 041 final EntityManagerManager entityManagerManager, final String persistenceUnitName, 042 final PropertyAccess propertyAccess, final TypeCoercer typeCoercer, final Logger logger) 043 { 044 super(); 045 this.entity = entity; 046 this.entityManagerManager = entityManagerManager; 047 this.persistenceUnitName = persistenceUnitName; 048 this.typeCoercer = typeCoercer; 049 this.logger = logger; 050 051 final Type<?> idType = this.entity.getIdType(); 052 053 final SingularAttribute<? super E, ?> idAttribute = this.entity.getId(idType.getJavaType()); 054 055 idPropertyName = idAttribute.getName(); 056 057 propertyAdapter = propertyAccess.getAdapter(entity.getJavaType()).getPropertyAdapter( 058 idPropertyName); 059 060 } 061 062 /** 063 * {@inheritDoc} 064 */ 065 public String toClient(final E value) 066 { 067 if (value == null) 068 return null; 069 070 final Object id = propertyAdapter.get(value); 071 072 if (id == null) 073 { 074 return null; 075 } 076 077 return typeCoercer.coerce(id, String.class); 078 } 079 080 /** 081 * {@inheritDoc} 082 */ 083 public E toValue(final String clientValue) 084 { 085 if (InternalUtils.isBlank(clientValue)) 086 return null; 087 088 Object id = null; 089 final Class<E> entityClass = entity.getJavaType(); 090 091 try 092 { 093 094 id = typeCoercer.coerce(clientValue, propertyAdapter.getType()); 095 } 096 catch (final Exception ex) 097 { 098 throw new RuntimeException(String.format( 099 "Exception converting '%s' to instance of %s (id type for entity %s): %s", 100 clientValue, propertyAdapter.getType().getName(), entityClass.getName(), 101 InternalUtils.toMessage(ex)), ex); 102 } 103 104 final EntityManager em = entityManagerManager.getEntityManager(persistenceUnitName); 105 106 final E result = em.find(entityClass, id); 107 108 if (result == null) 109 { 110 // We don't identify the entity type in the message because the logger is based on the 111 // entity type. 112 logger.error(String.format( 113 "Unable to convert client value '%s' into an entity instance.", clientValue)); 114 } 115 116 return result; 117 } 118 }