001 // Copyright 2007, 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;
016
017 import org.tynamo.jpa.internal.CommitAfterWorker;
018 import org.tynamo.jpa.internal.EntityPersistentFieldStrategy;
019 import org.tynamo.jpa.internal.JPAEntityValueEncoder;
020 import org.apache.tapestry5.ValueEncoder;
021 import org.apache.tapestry5.ioc.Configuration;
022 import org.apache.tapestry5.ioc.LoggerSource;
023 import org.apache.tapestry5.ioc.MappedConfiguration;
024 import org.apache.tapestry5.ioc.OrderedConfiguration;
025 import org.apache.tapestry5.ioc.annotations.Symbol;
026 import org.apache.tapestry5.ioc.services.PropertyAccess;
027 import org.apache.tapestry5.ioc.services.TypeCoercer;
028 import org.apache.tapestry5.services.*;
029
030 import javax.persistence.EntityManager;
031 import javax.persistence.EntityManagerFactory;
032 import javax.persistence.metamodel.EntityType;
033 import javax.persistence.metamodel.Metamodel;
034
035 /**
036 * Supplements the services defined by {@link eu.cuetech.tapestry.jpa.JPACoreModule} with additional
037 * services and configuration specific to Tapestry web application.
038 */
039 @SuppressWarnings({"JavaDoc"})
040 public class JPAModule {
041 public static void contributeFactoryDefaults(MappedConfiguration<String, String> configuration) {
042 configuration.add(JPASymbols.PROVIDE_ENTITY_VALUE_ENCODERS, "true");
043 }
044
045 /**
046 * Contributes the package "<root>.entities" to the configuration, so that it will be
047 * scanned for annotated entity classes.
048 * <p/>
049 * public static void contributeHibernateEntityPackageManager(Configuration<String>
050 * configuration,
051 *
052 * @Inject
053 * @Symbol(InternalConstants.TAPESTRY_APP_PACKAGE_PARAM) String appRootPackage) {
054 * configuration.add(appRootPackage +
055 * ".entities"); }
056 */
057
058 public static void contributeAlias(Configuration<AliasContribution> configuration, @JPACore EntityManager em) {
059 configuration.add(AliasContribution.create(EntityManager.class, em));
060 }
061
062 /**
063 * Contributes the following:
064 * <dl>
065 * <dt>entity</dt>
066 * <dd>Stores the id of the entity and reloads from the {@link EntityManager}</dd>
067 * </dl>
068 */
069 public static void contributePersistentFieldManager(
070 MappedConfiguration<String, PersistentFieldStrategy> configuration) {
071 configuration.addInstance("entity", EntityPersistentFieldStrategy.class);
072 }
073
074 /**
075 * Adds the CommitAfter annotation work, to process the
076 * {@link eu.cuetech.tapestry.jpa.annotations.CommitAfter} annotation.
077 */
078 public static void contributeComponentClassTransformWorker(
079 OrderedConfiguration<ComponentClassTransformWorker> configuration) {
080 // If logging is enabled, we want logging to be the first advice, wrapping around the commit
081 // advice.
082
083 configuration.addInstance("CommitAfter", CommitAfterWorker.class, "after:Log");
084 }
085
086 /**
087 * Contribution to the {@link org.apache.tapestry5.services.ComponentClassResolver} service
088 * configuration.
089 */
090 public static void contributeComponentClassResolver(Configuration<LibraryMapping> configuration) {
091 configuration.add(new LibraryMapping("jpa", "org.tynamo.tapestry.jpa"));
092 }
093
094 /**
095 * Contributes {@link ValueEncoderFactory}s for all registered JPA entity classes. Encoding and
096 * decoding are based on the id property value of the entity using type coercion. Hence, if the
097 * id can be coerced to a String and back then the entity can be coerced.
098 */
099 @SuppressWarnings("unchecked")
100 public static void contributeValueEncoderSource(MappedConfiguration<Class, ValueEncoderFactory> configuration,
101 @Symbol(JPASymbols.PROVIDE_ENTITY_VALUE_ENCODERS) boolean provideEncoders,
102 final JPAEntityManagerSource ems, final EntityManager em, final TypeCoercer typeCoercer,
103 final PropertyAccess propertyAccess, final LoggerSource loggerSource) {
104 if (!provideEncoders)
105 return;
106
107 ems.create(); // create
108 EntityManagerFactory emf = ems.getEntityManagerFactory();
109 Metamodel metamodel = emf.getMetamodel();
110 for (EntityType<?> et : metamodel.getEntities()) {
111
112 final EntityType<?> etype = et;
113 ValueEncoderFactory factory = new ValueEncoderFactory() {
114 public ValueEncoder create(Class type) {
115 return new JPAEntityValueEncoder(etype.getJavaType(), em, propertyAccess, typeCoercer, loggerSource
116 .getLogger(etype.getJavaType()));
117 }
118 };
119
120 configuration.add(etype.getJavaType(), factory);
121 }
122
123 }
124
125 }