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 }