001// Copyright 2011-2013 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 015package org.apache.tapestry5.internal.jpa; 016 017import org.apache.tapestry5.ValueEncoder; 018import org.apache.tapestry5.ioc.internal.util.InternalUtils; 019import org.apache.tapestry5.ioc.services.PropertyAccess; 020import org.apache.tapestry5.ioc.services.PropertyAdapter; 021import org.apache.tapestry5.ioc.services.TypeCoercer; 022import org.apache.tapestry5.ioc.util.ExceptionUtils; 023import org.apache.tapestry5.jpa.EntityManagerManager; 024import org.slf4j.Logger; 025 026import javax.persistence.EntityManager; 027import javax.persistence.metamodel.EntityType; 028import javax.persistence.metamodel.SingularAttribute; 029import javax.persistence.metamodel.Type; 030 031public class JpaValueEncoder<E> implements ValueEncoder<E> 032{ 033 private final EntityType<E> entity; 034 private final EntityManagerManager entityManagerManager; 035 private final String persistenceUnitName; 036 private final TypeCoercer typeCoercer; 037 private final Logger logger; 038 private final String idPropertyName; 039 private final PropertyAdapter propertyAdapter; 040 041 public JpaValueEncoder(final EntityType<E> entity, 042 final EntityManagerManager entityManagerManager, final String persistenceUnitName, 043 final PropertyAccess propertyAccess, final TypeCoercer typeCoercer, final Logger logger) 044 { 045 super(); 046 this.entity = entity; 047 this.entityManagerManager = entityManagerManager; 048 this.persistenceUnitName = persistenceUnitName; 049 this.typeCoercer = typeCoercer; 050 this.logger = logger; 051 052 final Type<?> idType = this.entity.getIdType(); 053 054 final SingularAttribute<? super E, ?> idAttribute = this.entity.getId(idType.getJavaType()); 055 056 idPropertyName = idAttribute.getName(); 057 058 propertyAdapter = propertyAccess.getAdapter(entity.getJavaType()).getPropertyAdapter( 059 idPropertyName); 060 061 } 062 063 /** 064 * {@inheritDoc} 065 */ 066 @Override 067 public String toClient(final E value) 068 { 069 if (value == null) 070 return null; 071 072 final Object id = propertyAdapter.get(value); 073 074 if (id == null) 075 { 076 return null; 077 } 078 079 return typeCoercer.coerce(id, String.class); 080 } 081 082 /** 083 * {@inheritDoc} 084 */ 085 @Override 086 public E toValue(final String clientValue) 087 { 088 if (InternalUtils.isBlank(clientValue)) 089 return null; 090 091 Object id = null; 092 final Class<E> entityClass = entity.getJavaType(); 093 094 try 095 { 096 097 id = typeCoercer.coerce(clientValue, propertyAdapter.getType()); 098 } 099 catch (final Exception ex) 100 { 101 throw new RuntimeException(String.format( 102 "Exception converting '%s' to instance of %s (id type for entity %s): %s", 103 clientValue, propertyAdapter.getType().getName(), entityClass.getName(), 104 ExceptionUtils.toMessage(ex)), ex); 105 } 106 107 final EntityManager em = entityManagerManager.getEntityManager(persistenceUnitName); 108 109 final E result = em.find(entityClass, id); 110 111 if (result == null) 112 { 113 // We don't identify the entity type in the message because the logger is based on the 114 // entity type. 115 logger.error(String.format( 116 "Unable to convert client value '%s' into an entity instance.", clientValue)); 117 } 118 119 return result; 120 } 121}