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.apache.tapestry5.hibernate;
016
017 import org.apache.tapestry5.ValueEncoder;
018 import org.apache.tapestry5.internal.InternalConstants;
019 import org.apache.tapestry5.internal.hibernate.CommitAfterWorker;
020 import org.apache.tapestry5.internal.hibernate.EntityPersistentFieldStrategy;
021 import org.apache.tapestry5.internal.hibernate.HibernateEntityValueEncoder;
022 import org.apache.tapestry5.ioc.Configuration;
023 import org.apache.tapestry5.ioc.LoggerSource;
024 import org.apache.tapestry5.ioc.MappedConfiguration;
025 import org.apache.tapestry5.ioc.OrderedConfiguration;
026 import org.apache.tapestry5.ioc.annotations.Inject;
027 import org.apache.tapestry5.ioc.annotations.Symbol;
028 import org.apache.tapestry5.ioc.services.PropertyAccess;
029 import org.apache.tapestry5.ioc.services.TypeCoercer;
030 import org.apache.tapestry5.services.AliasContribution;
031 import org.apache.tapestry5.services.ComponentClassTransformWorker;
032 import org.apache.tapestry5.services.LibraryMapping;
033 import org.apache.tapestry5.services.PersistentFieldStrategy;
034 import org.apache.tapestry5.services.ValueEncoderFactory;
035 import org.hibernate.Session;
036 import org.hibernate.mapping.PersistentClass;
037
038 import java.util.Iterator;
039
040 /**
041 * Supplements the services defined by {@link org.apache.tapestry5.hibernate.HibernateCoreModule} with additional
042 * services and configuration specific to Tapestry web application.
043 */
044 @SuppressWarnings({"JavaDoc"})
045 public class HibernateModule
046 {
047 public static void contributeFactoryDefaults(MappedConfiguration<String, String> configuration)
048 {
049 configuration.add(HibernateConstants.PROVIDE_ENTITY_VALUE_ENCODERS_SYMBOL, "true");
050 }
051
052 /**
053 * Contributes the package "<root>.entities" to the configuration, so that it will be scanned for annotated
054 * entity classes.
055 */
056 public static void contributeHibernateEntityPackageManager(Configuration<String> configuration,
057
058 @Inject
059 @Symbol(InternalConstants.TAPESTRY_APP_PACKAGE_PARAM)
060 String appRootPackage)
061 {
062 configuration.add(appRootPackage + ".entities");
063 }
064
065
066 public static void contributeAlias(Configuration<AliasContribution> configuration, @HibernateCore Session session)
067 {
068 configuration.add(AliasContribution.create(Session.class, session));
069 }
070
071
072 /**
073 * Contributes {@link ValueEncoderFactory}s for all registered Hibernate entity classes. Encoding and decoding are
074 * based on the id property value of the entity using type coercion. Hence, if the id can be coerced to a String and
075 * back then the entity can be coerced.
076 */
077 @SuppressWarnings("unchecked")
078 public static void contributeValueEncoderSource(MappedConfiguration<Class, ValueEncoderFactory> configuration,
079 @Symbol(HibernateConstants.PROVIDE_ENTITY_VALUE_ENCODERS_SYMBOL)
080 boolean provideEncoders,
081 final HibernateSessionSource sessionSource,
082 final Session session,
083 final TypeCoercer typeCoercer,
084 final PropertyAccess propertyAccess,
085 final LoggerSource loggerSource)
086 {
087 if (!provideEncoders) return;
088
089 org.hibernate.cfg.Configuration config = sessionSource.getConfiguration();
090 Iterator<PersistentClass> mappings = config.getClassMappings();
091 while (mappings.hasNext())
092 {
093 final PersistentClass persistentClass = mappings.next();
094 final Class entityClass = persistentClass.getMappedClass();
095
096 ValueEncoderFactory factory = new ValueEncoderFactory()
097 {
098 public ValueEncoder create(Class type)
099 {
100 return new HibernateEntityValueEncoder(entityClass, persistentClass, session, propertyAccess,
101 typeCoercer, loggerSource.getLogger(entityClass));
102 }
103 };
104
105 configuration.add(entityClass, factory);
106 }
107 }
108
109 /**
110 * Contributes the following: <dl> <dt>entity</dt> <dd>Stores the id of the entity and reloads from the {@link
111 * Session}</dd> </dl>
112 */
113 public static void contributePersistentFieldManager(
114 MappedConfiguration<String, PersistentFieldStrategy> configuration)
115 {
116 configuration.addInstance("entity", EntityPersistentFieldStrategy.class);
117 }
118
119 /**
120 * Adds the CommitAfter annotation work, to process the {@link org.apache.tapestry5.hibernate.annotations.CommitAfter}
121 * annotation.
122 */
123 public static void contributeComponentClassTransformWorker(
124 OrderedConfiguration<ComponentClassTransformWorker> configuration)
125 {
126 // If logging is enabled, we want logging to be the first advice, wrapping around the commit advice.
127
128 configuration.addInstance("CommitAfter", CommitAfterWorker.class, "after:Log");
129 }
130
131 /**
132 * Contribution to the {@link org.apache.tapestry5.services.ComponentClassResolver} service configuration.
133 */
134 public static void contributeComponentClassResolver(Configuration<LibraryMapping> configuration)
135 {
136 configuration.add(new LibraryMapping("hibernate", "org.apache.tapestry5.hibernate"));
137 }
138
139 }