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 throw new IllegalStateException(
074 String.format(
075 "Entity %s has an %s property of null; this probably means that it has not been persisted yet.",
076 value, idPropertyName));
077
078 return typeCoercer.coerce(id, String.class);
079 }
080
081 /**
082 * {@inheritDoc}
083 */
084 public E toValue(final String clientValue)
085 {
086 if (InternalUtils.isBlank(clientValue))
087 return null;
088
089 Object id = null;
090 final Class<E> entityClass = entity.getJavaType();
091
092 try
093 {
094
095 id = typeCoercer.coerce(clientValue, propertyAdapter.getType());
096 }
097 catch (final Exception ex)
098 {
099 throw new RuntimeException(String.format(
100 "Exception converting '%s' to instance of %s (id type for entity %s): %s",
101 clientValue, propertyAdapter.getType().getName(), entityClass.getName(),
102 InternalUtils.toMessage(ex)), ex);
103 }
104
105 final EntityManager em = entityManagerManager.getEntityManager(persistenceUnitName);
106
107 final E result = em.find(entityClass, id);
108
109 if (result == null)
110 {
111 // We don't identify the entity type in the message because the logger is based on the
112 // entity type.
113 logger.error(String.format(
114 "Unable to convert client value '%s' into an entity instance.", clientValue));
115 }
116
117 return result;
118 }
119 }