001    // Copyright 2008 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.tynamo.jpa.internal;
016    
017    import java.io.Serializable;
018    
019    import javax.persistence.EntityManager;
020    import javax.persistence.PersistenceUnitUtil;
021    import javax.persistence.metamodel.EntityType;
022    
023    import org.apache.tapestry5.ValueEncoder;
024    import org.apache.tapestry5.ioc.internal.util.Defense;
025    import org.apache.tapestry5.ioc.internal.util.InternalUtils;
026    import org.apache.tapestry5.ioc.services.PropertyAccess;
027    import org.apache.tapestry5.ioc.services.TypeCoercer;
028    import org.slf4j.Logger;
029    
030    public final class JPAEntityValueEncoder<E> implements ValueEncoder<E>
031    {
032            private final EntityType<E> entityType;
033    
034            private final EntityManager em;
035    
036            private final TypeCoercer typeCoercer;
037    
038            private final Logger logger;
039    
040            private final Class idClass;
041    
042            private final PersistenceUnitUtil puu;
043    
044            public JPAEntityValueEncoder(Class<E> entityClass, EntityManager em, PropertyAccess propertyAccess,
045                    TypeCoercer typeCoercer, Logger logger)
046            {
047                    this.em = em;
048                    this.entityType = em.getMetamodel().entity(entityClass);
049                    this.typeCoercer = typeCoercer;
050                    this.logger = logger;
051                    puu = em.getEntityManagerFactory().getPersistenceUnitUtil();
052    
053                    idClass = entityType.getIdType().getJavaType();
054            }
055    
056            public String toClient(E value)
057            {
058                    if (value == null)
059                    {
060                            return null;
061                    }
062    
063                    Object id = puu.getIdentifier(value);
064    
065                    if (id == null)
066                    {
067                            throw new IllegalStateException(String.format(
068                                    "Entity %s has an id of null; this probably means that it has not been persisted yet.", value));
069                    }
070                    // this.idClass=id.getClass();
071    
072                    return this.typeCoercer.coerce(id, String.class);
073            }
074    
075            @SuppressWarnings("unchecked")
076            public E toValue(String clientValue)
077            {
078                    if (InternalUtils.isBlank(clientValue))
079                    {
080                            return null;
081                    }
082    
083                    Object id = this.typeCoercer.coerce(clientValue, this.idClass);
084    
085                    Serializable ser = Defense.cast(id, Serializable.class, "id");
086    
087                    E result = this.em.find(this.entityType.getJavaType(), ser);
088    
089                    if (result == null)
090                    {
091                            // We don't identify the entity type in the message because the logger is based on the
092                            // entity type.
093                            this.logger.error(String
094                                    .format("Unable to convert client value '%s' into an entity instance.", clientValue));
095                    }
096    
097                    return result;
098            }
099    
100    }