<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC 
	"-//SPRING//DTD BEAN//EN" 
	"http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

	<bean id="propertyConfigurer" 
		class="magoffin.matt.xweb.util.XwebParamPropertiesPlaceholderConfigurer">
		<property name="order" value="1"/>
		<property name="locations">
			<list>
				<value>classpath:/env.properties</value>
			</list>
		</property>
		<property name="settingDao" ref="parameterDaoEnvironment"/>
	</bean>
	
	<bean id="messageSource" class="magoffin.matt.xweb.util.JdbcMessagesSource">
		<property name="jdbcTemplate" ref="myJdbcTemplate"/>
		<property name="parentMessageSource">
			<bean class="magoffin.matt.xweb.util.ResourceBundleMessagesSource">
				<property name="basenames">
					<list>
						<value>messages</value>
						<value>domain-messages</value>
					</list>
				</property>
			</bean>
		</property>
	</bean>
	
	<!-- 
		transformerFactory: a default JAXP TranformerFactory
	-->
	<bean id="transformerFactory" class="javax.xml.transform.TransformerFactory"
		factory-method="newInstance">
		<!--  set any desired features or attributes here -->
	</bean>
	
	<!-- 
	 cacheManager: the EHCache CacheManager to enable injecting caches into beans
	 -->
	<bean id="cacheManager" class="net.sf.ehcache.CacheManager" factory-method="create"/>
	
	<bean id="myJdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<constructor-arg index="0"><ref bean="myDataSource"/></constructor-arg>
	</bean>
	
	<bean id="myTransactionInterceptor" 
		class="org.springframework.transaction.interceptor.TransactionInterceptor">
		<property name="transactionManager">
			<ref bean="transactionManager"/>
		</property>
		<property name="transactionAttributeSource">
			<value>
				magoffin.matt.ieat.biz.RecipeBiz.add*=PROPAGATION_REQUIRED
				magoffin.matt.ieat.biz.RecipeBiz.remove*=PROPAGATION_REQUIRED
				magoffin.matt.ieat.biz.RecipeBiz.store*=PROPAGATION_REQUIRED
				magoffin.matt.ieat.biz.RecipeBiz.*ById=PROPAGATION_REQUIRED
				magoffin.matt.ieat.biz.UserBiz.forgot*=PROPAGATION_REQUIRED
				magoffin.matt.ieat.biz.UserBiz.store*=PROPAGATION_REQUIRED
				magoffin.matt.ieat.biz.UserBiz.confirm*=PROPAGATION_REQUIRED
				magoffin.matt.ieat.biz.UserBiz.register*=PROPAGATION_REQUIRED
				magoffin.matt.ieat.biz.UserBiz.logon*=PROPAGATION_REQUIRED
			</value>
		</property>
	</bean>
	
	<bean id="recipeBizTarget" class="magoffin.matt.ieat.biz.impl.RecipeBizImpl" 
		init-method="init">
		<property name="baseDao"><ref local="baseDao"/></property>
		<property name="courseDao"><ref local="courseDao"/></property>
		<property name="difficultyDao"><ref local="difficultyDao"/></property>
		<property name="ethnicityDao"><ref local="ethnicityDao"/></property>
		<property name="ingredientDao"><ref local="ingredientDao"/></property>
		<property name="mealDao"><ref local="mealDao"/></property>
		<property name="prepTimeDao"><ref local="prepTimeDao"/></property>
		<property name="recipeDao"><ref local="recipeDao"/></property>
		<property name="systemDao" ref="systemDao"/>
		<property name="unitDao"><ref local="unitDao"/></property>
		<property name="recipeValidator"><ref local="recipeValidator"/></property>
		<property name="domainObjectFactory"><ref bean="domainObjectFactory"/></property>
		<property name="imageBasePath">
			<value>${recipe.image.base.path}</value>
		</property>
		<property name="imageSupportedExtensions">
			<set>
				<value>gif</value>
				<value>jpg</value>
				<value>png</value>
			</set>
		</property>
	</bean>
		
	<bean id="recipeSecurityAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.RecipeSecurityInterceptor">
				<property name="recipeDao"><ref local="recipeDao"/></property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>removeRecipe</value>
				<value>setRecipeImage</value>
				<value>storeRecipe</value>
			</list>
		</property>
	</bean>
	
	<bean id="featureCommentsSecurityAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.FeatureSecurityInterceptor">
				<property name="feature" value="feature.comments"/>
				<property name="featureEnabled" value="${feature.comments}"/>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>addCommentToRecipe</value>
			</list>
		</property>
	</bean>
	
	<bean id="featureRecipeImagesSecurityAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.FeatureSecurityInterceptor">
				<property name="feature" value="feature.recipeimages"/>
				<property name="featureEnabled" value="${feature.recipeimages}"/>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>storeRecipeImage</value>
			</list>
		</property>
	</bean>
	
	<bean id="featureRegistrationSecurityAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.FeatureSecurityInterceptor">
				<property name="feature" value="feature.registration"/>
				<property name="featureEnabled" value="${feature.registration}"/>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>confirmRegisteredUser</value>
				<value>registerUser</value>
			</list>
		</property>
	</bean>
	
	<bean id="mealSecurityAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.MealSecurityInterceptor">
				<property name="mealDao"><ref local="mealDao"/></property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>getMealById</value>
				<value>removeMeal</value>
				<value>storeMeal</value>
			</list>
		</property>
	</bean>
	
	<!-- Ingredient search indexing support -->
	<bean id="recipeBizIngredientIndexAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.IngredientIndexInterceptor">
				<property name="recipeSearchIndexBiz"><ref local="recipeSearchIndexBiz"/></property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>storeIngredient</value>
			</list>
		</property>
	</bean>
	
	<!-- Recipe search indexing support -->
	<bean id="recipeBizRecipeIndexAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.RecipeIndexInterceptor">
				<property name="recipeSearchIndexBiz"><ref local="recipeSearchIndexBiz"/></property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>storeRecipe</value>
				<value>storeRecipeRating</value>
			</list>
		</property>
	</bean>
	<bean id="recipeBizRecipeIndexDeleteAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.RecipeIndexDeleteInterceptor">
				<property name="recipeSearchIndexBiz"><ref local="recipeSearchIndexBiz"/></property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>removeRecipe</value>
			</list>
		</property>
	</bean>

	<bean id="recipeBiz" class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="target"><ref local="recipeBizTarget"/></property>
		<property name="proxyInterfaces">
			<list>
				<value>magoffin.matt.ieat.biz.RecipeBiz</value>
			</list>
		</property>
		<property name="interceptorNames">
			<list>
				<value>recipeSecurityAdvisor</value>
				<value>featureCommentsSecurityAdvisor</value>
				<value>featureRecipeImagesSecurityAdvisor</value>
				<value>mealSecurityAdvisor</value>
				<value>recipeBizIngredientIndexAdvisor</value>
				<value>recipeBizRecipeIndexAdvisor</value>
				<value>recipeBizRecipeIndexDeleteAdvisor</value>
				<value>myTransactionInterceptor</value>
			</list>
		</property>
	</bean>
	
	<bean id="encryptor" class="magoffin.matt.util.DataEncryption">
		<constructor-arg index="0"><value>${crypto.provider}</value></constructor-arg>
		<constructor-arg index="1"><value>${crypto.key.type}</value></constructor-arg>
		<constructor-arg index="2"><value>${crypto.cipher.type}</value></constructor-arg>
		<constructor-arg index="3"><value>${crypto.key}</value></constructor-arg>
		<constructor-arg index="4"><value>${crypto.pbe.salt}</value></constructor-arg>
	</bean>
	
	<bean id="userBizTarget" class="magoffin.matt.ieat.biz.impl.UserBizImpl" init-method="init">
		<property name="salt"><value>${crypto.salt}</value></property>
		<property name="userDao"><ref local="userDao"/></property>
		<property name="encryptor"><ref local="encryptor"/></property>
		<property name="userValidator"><ref local="userValidator"/></property>
	</bean>
		
	<bean id="registrationEmailAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.UserEmailInterceptor">
				<property name="mailMergeSupport">
					<bean class="magoffin.matt.ieat.util.MailMergeSupport">
						<property name="templatePath"><value>magoffin/matt/ieat/mailtemplates</value></property>
						<property name="templateName"><value>registration.txt</value></property>
						<property name="mailSender"><ref bean="mailSender"/></property>
						<property name="messageTemplate"><ref local="mailMessage"/></property>
						<property name="messageSource"><ref local="messageSource"/></property>
						<property name="subjectMessageKey"><value>registration-complete.mail.subject</value></property>
					</bean>
				</property>
				<property name="confirmUrl"><value>${url.registration.confirm}</value></property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>registerUser</value>
			</list>
		</property>
	</bean>

	<bean id="welcomeEmailAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.UserEmailInterceptor">
				<property name="mailMergeSupport">
					<bean class="magoffin.matt.ieat.util.MailMergeSupport">
						<property name="templatePath"><value>magoffin/matt/ieat/mailtemplates</value></property>
						<property name="templateName"><value>welcome.txt</value></property>
						<property name="mailSender"><ref bean="mailSender"/></property>
						<property name="messageTemplate"><ref local="mailMessage"/></property>
						<property name="messageSource"><ref local="messageSource"/></property>
						<property name="subjectMessageKey"><value>welcome.mail.subject</value></property>
					</bean>
				</property>
				<property name="confirmUrl"><value>${url.welcome}</value></property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>confirmRegisteredUser</value>
			</list>
		</property>
	</bean>
	
	<bean id="forgotPasswordEmailAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.UserLoginEmailInterceptor">
				<property name="mailMergeSupport">
					<bean class="magoffin.matt.ieat.util.MailMergeSupport">
						<property name="templatePath"><value>magoffin/matt/ieat/mailtemplates</value></property>
						<property name="templateName"><value>forgot-password.txt</value></property>
						<property name="mailSender"><ref bean="mailSender"/></property>
						<property name="messageTemplate"><ref local="mailMessage"/></property>
						<property name="messageSource"><ref local="messageSource"/></property>
						<property name="subjectMessageKey"><value>forgot-password.mail.subject</value></property>
					</bean>
				</property>
				<property name="userDao"><ref bean="userDao"/></property>
				<property name="confirmUrl"><value>${url.forgot-password.confirm}</value></property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>forgotPassword</value>
			</list>
		</property>
	</bean>

	<bean id="userRegistrationIndexAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.UserArgumentIndexInterceptor">
				<property name="recipeSearchIndexBiz"><ref local="recipeSearchIndexBiz"/></property>
				<property name="userDao"><ref local="userDao"/></property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>registerUser</value>
			</list>
		</property>
	</bean>
	<bean id="userIndexAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.UserIndexInterceptor">
				<property name="recipeSearchIndexBiz"><ref local="recipeSearchIndexBiz"/></property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>storeUser</value>
			</list>
		</property>
	</bean>
	<bean id="userIndexDeleteAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.UserIndexDeleteInterceptor">
				<property name="recipeSearchIndexBiz"><ref local="recipeSearchIndexBiz"/></property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>removeUser</value>
			</list>
		</property>
	</bean>

	<bean id="userBiz" class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="target"><ref local="userBizTarget"/></property>
		<property name="proxyInterfaces">
			<list>
				<value>magoffin.matt.ieat.biz.UserBiz</value>
			</list>
		</property>
		<property name="interceptorNames">
			<list>
				<value>featureRegistrationSecurityAdvisor</value>
				<value>forgotPasswordEmailAdvisor</value>
				<value>userRegistrationIndexAdvisor</value>
				<value>userIndexAdvisor</value>
				<value>userIndexDeleteAdvisor</value>
				<value>myTransactionInterceptor</value>
				<value>registrationEmailAdvisor</value>
				<value>welcomeEmailAdvisor</value>
			</list>
		</property>
	</bean>
	
	<bean id="recipeSearchIndexBizTarget" 
		class="magoffin.matt.ieat.biz.impl.lucene.RecipeSearchBizLuceneImpl" 
		init-method="init">
		<property name="lucene" ref="luceneService"/>
		<property name="domainObjectFactory" ref="domainObjectFactory"/>
	</bean>
	
	<bean id="luceneService" class="magoffin.matt.lucene.LuceneSearchService" 
		init-method="initialize" destroy-method="finish">
		<property name="baseIndexDirectoryPath" value="${lucene.index.base.path}"/>
		<property name="optimizeTriggerCount" value="${lucene.index.optimize.trigger}"/>
		<property name="updateBufferSize" value="${lucene.update.buffer.size}"/>
		<property name="updateBufferFlushMs" value="${lucene.update.buffer.flush}"/>
		<property name="discardedIndexReaderMinCloseTime" value="60000"/>
		<property name="discardedIndexReaderProcessorMs" value="120000"/>
		<property name="neverOptimize" value="${lucene.index.optimize.never}"/>
		<property name="indexTimeZone" ref="indexTimeZone"/>
		<property name="plugins">
			<list>
				<ref local="ingredientLucenePlugin"/>
				<ref local="recipeLucenePlugin"/>
				<ref local="unitLucenePlugin"/>
				<ref local="userLucenePlugin"/>
			</list>
		</property>
	</bean>
	<bean id="ingredientLucenePlugin" 
		class="magoffin.matt.ieat.biz.impl.lucene.IngredientLucenePlugin">
		<property name="config">
			<bean class="magoffin.matt.lucene.BasicIndexConfig"/>
		</property>
		<property name="analyzer" ref="standardAnalyzer"/>
		<property name="domainObjectFactory" ref="domainObjectFactory"/>
		<property name="messages" ref="messageSource"/>
		<property name="ingredientDao" ref="ingredientDao"/>
	</bean>
	<bean id="recipeLucenePlugin" 
		class="magoffin.matt.ieat.biz.impl.lucene.RecipeLucenePlugin">
		<property name="config">
			<bean class="magoffin.matt.lucene.BasicIndexConfig"/>
		</property>
		<property name="analyzer" ref="standardAnalyzer"/>
		<property name="domainObjectFactory" ref="domainObjectFactory"/>
		<property name="messages" ref="messageSource"/>
		<property name="recipeDao" ref="recipeDao"/>
		<property name="userDao" ref="userDao"/>
		<property name="averageRatingNumberFormat">
			<bean class="java.text.NumberFormat" factory-method="getInstance">
				<property name="maximumFractionDigits" value="0"/>
			</bean>
		</property>
	</bean>
	<bean id="unitLucenePlugin" 
		class="magoffin.matt.ieat.biz.impl.lucene.UnitLucenePlugin">
		<property name="config">
			<bean class="magoffin.matt.lucene.BasicIndexConfig"/>
		</property>
		<property name="analyzer" ref="standardAnalyzer"/>
		<property name="domainObjectFactory" ref="domainObjectFactory"/>
		<property name="messages" ref="messageSource"/>
		<property name="unitDao" ref="unitDao"/>
	</bean>
	<bean id="userLucenePlugin" 
		class="magoffin.matt.ieat.biz.impl.lucene.UserLucenePlugin">
		<property name="config">
			<bean class="magoffin.matt.lucene.BasicIndexConfig"/>
		</property>
		<property name="analyzer" ref="standardAnalyzer"/>
		<property name="domainObjectFactory" ref="domainObjectFactory"/>
		<property name="messages" ref="messageSource"/>
		<property name="userDao" ref="userDao"/>
	</bean>
	<bean id="standardAnalyzer" 
		class="magoffin.matt.ieat.biz.impl.lucene.StandardEatAnalyzer">
		<property name="snowballStemmerName" value="${lucene.snowball.stemmer.name}"/>
		<property name="indexKeyLength" value="1"/>
	</bean>
	<bean id="indexTimeZone" class="java.util.TimeZone" factory-method="getTimeZone">
		<constructor-arg index="0" type="java.lang.String" value="${index.timezone.java}"/>
	</bean>

	<bean  id="recipeSearchIndexBiz" name="recipeSearchBiz" 
		class="org.springframework.aop.framework.ProxyFactoryBean">
		<property name="target"><ref local="recipeSearchIndexBizTarget"/></property>
		<property name="proxyInterfaces">
			<list>
				<value>magoffin.matt.ieat.biz.RecipeSearchBiz</value>
				<value>magoffin.matt.ieat.biz.RecipeSearchIndexBiz</value>
			</list>
		</property>
		<property name="interceptorNames">
			<list>
				<value>recipeIndexCacheAdvisor</value>
				<value>userIndexCacheAdvisor</value>
			</list>
		</property>
	</bean>
	
	<bean id="recipeIndexCacheAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.IndexSearchResultsCacheInterceptor">
				<property name="cache">
					<bean class="net.sf.ehcache.constructs.blocking.BlockingCache">
						<constructor-arg index="0">
							<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean"> 
								<property name="cacheManager" ref="cacheManager"/> 
								<property name="cacheName" value="magoffin.matt.ieat.recipe_index_cache"/> 
							</bean>
						</constructor-arg>
						<property name="timeoutMillis" value="5000"/>
					</bean>
				</property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>findRecipesForIndex</value>
			</list>
		</property>
	</bean>
		
	<bean id="userIndexCacheAdvisor"
		class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
		<property name="advice">
			<bean class="magoffin.matt.ieat.aop.IndexSearchResultsCacheInterceptor">
				<property name="cache">
					<bean class="net.sf.ehcache.constructs.blocking.BlockingCache">
						<constructor-arg index="0">
							<bean class="org.springframework.cache.ehcache.EhCacheFactoryBean"> 
								<property name="cacheManager" ref="cacheManager"/> 
								<property name="cacheName" value="magoffin.matt.ieat.user_index_cache"/> 
							</bean>
						</constructor-arg>
						<property name="timeoutMillis" value="5000"/>
					</bean>
				</property>
			</bean>
		</property>
		<property name="mappedNames">
			<list>
				<value>findUsersForIndex</value>
			</list>
		</property>
	</bean>
	
	<bean id="mailMessage" class="org.springframework.mail.SimpleMailMessage">
		<property name="from"><value>${mail.from}</value></property>
	</bean>
	
	<bean id="alterRecipeSizeValidator" class="magoffin.matt.ieat.validation.AlterRecipeSizeValidator"/>
	<bean id="emailRecipeValidator" class="magoffin.matt.ieat.validation.EmailRecipeValidator"/>
	<bean id="ingredientValidator" class="magoffin.matt.ieat.validation.IngredientValidator"/>
	<bean id="logonValidator" class="magoffin.matt.ieat.validation.LogonValidator"/>
	<bean id="mealValidator" class="magoffin.matt.ieat.validation.MealValidator"/>
	<bean id="mealRecipeValidator" class="magoffin.matt.ieat.validation.MealRecipeValidator"/>
	<bean id="recipeCommentsValidator" class="magoffin.matt.ieat.validation.RecipeCommentsValidator"/>
	<bean id="recipeValidator" class="magoffin.matt.ieat.validation.RecipeValidator"/>
	<bean id="recipeMLImportValidator" class="magoffin.matt.ieat.validation.RecipeImportValidator">
		<property name="rioBiz" ref="recipeIOBiz"/>
		<property name="recipeSearchBiz" ref="recipeSearchBiz"/>
		<property name="ingredientDao" ref="ingredientDao"/>
		<property name="unitDao" ref="unitDao"/>
		<property name="systemDao" ref="systemDao"/>
		<property name="domainObjectFactory" ref="domainObjectFactory"/>
		<property name="importType" value="1"/>
	</bean>
	<bean id="recipeSearchValidator" class="magoffin.matt.ieat.validation.RecipeSearchValidator"/>
	<bean id="userValidator" class="magoffin.matt.ieat.validation.UserValidator"/>

	<!-- Job (periodic task) configuration -->
	
	<!-- 
		Job: cleanStaleRegistrationsJob
		
		Delete users that have registered but not confirmed that registration
		after a number of days. This is to clean out users that are not using 
		the application.
	-->
	<bean id="cleanStaleRegistrationsJob"
		class="org.springframework.scheduling.quartz.JobDetailBean">
		<property name="jobClass">
			<value>magoffin.matt.ieat.task.RemoveStaleUserRegistrations</value>
		</property>
		<property name="jobDataAsMap">
			<map>
				<entry key="userDao"><ref bean="userDao"/></entry>
				<entry key="numDaysCutoff"><value>14</value></entry>
			</map>
		</property>
	</bean>

	<!-- 
		Trigger: cleanStaleRegistrationsTrigger
		
		Run the cleanStaleRegistrationsJob job every day early in the morning.
	-->
	<bean id="cleanStaleRegistrationsTrigger" 
		class="org.springframework.scheduling.quartz.CronTriggerBean">
		<property name="jobDetail">
			<ref bean="cleanStaleRegistrationsJob"/>
		</property>
		<property name="cronExpression">
			<!-- run every morning at 2 AM -->
			<value>0 0 2 * * ?</value>
		</property>
	</bean>
	
	<!-- The job scheduler -->
	<bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
		<property name="triggers">
			<list>
				<ref local="cleanStaleRegistrationsTrigger"/>
			</list>
		</property>
	</bean>
	
	<!-- RecipeIOBiz -->
	<bean id="recipeIOBiz" class="magoffin.matt.ieat.biz.impl.RecipeIOBizImpl" init-method="init">
		<property name="jaxbContext"><value>magoffin.matt.ieat.domain</value></property>
		<property name="domainObjectFactory"><ref bean="domainObjectFactory"/></property>
		<property name="messagesSource"><ref local="messageSource"/></property>
		<property name="cacheXslt"><value>${xslt.cache}</value></property>
		<property name="recipeMl2ieatStylesheet">
			<value>magoffin/matt/ieat/biz/impl/recipeml-to-ieat.xsl</value>
		</property>
		<property name="ieat2RecipeMlStylesheet">
			<value>magoffin/matt/ieat/biz/impl/ieat-to-recipeml.xsl</value>
		</property>
		<property name="ieat2TextStylesheet">
			<value>magoffin/matt/ieat/biz/impl/ieat-to-text.xsl</value>
		</property>
		<property name="emailRecipeMailMergeSupport">
			<bean class="magoffin.matt.ieat.util.MailMergeSupport">
				<property name="templatePath"><value>magoffin/matt/ieat/mailtemplates</value></property>
				<property name="templateName"><value>recipe.txt</value></property>
				<property name="mailSender"><ref bean="mailSender"/></property>
				<property name="messageTemplate"><ref local="mailMessage"/></property>
				<property name="messageSource"><ref local="messageSource"/></property>
				<property name="subjectMessageKey"><value>email-recipe.mail.subject</value></property>
			</bean>
		</property>
	</bean>
	
	<!-- DAO configuration elements -->
	
	<bean id="abstractHibernateDao" abstract="true">
		<property name="sessionFactory"><ref bean="mySessionFactory"/></property>
	</bean>

	<bean id="baseDao" class="magoffin.matt.ieat.dao.hbm.BaseDaoImpl" 
		parent="abstractHibernateDao"/>

	<bean id="courseDao" class="magoffin.matt.ieat.dao.hbm.CourseDaoImpl" 
		parent="abstractHibernateDao"/>

	<bean id="difficultyDao" class="magoffin.matt.ieat.dao.hbm.DifficultyDaoImpl" 
		parent="abstractHibernateDao"/>

	<bean id="ethnicityDao" class="magoffin.matt.ieat.dao.hbm.EthnicityDaoImpl" 
		parent="abstractHibernateDao"/>

	<bean id="ingredientDao" class="magoffin.matt.ieat.dao.hbm.IngredientDaoImpl" init-method="init" 
		parent="abstractHibernateDao">
		<property name="jdbcTemplate"><ref bean="myJdbcTemplate"/></property>
		 <property name="sqlIndexAll">
			<value>select ingredientid, ingr_name from ingredient order by ingredientid</value>
		</property>
	</bean>

	<bean id="mealDao" class="magoffin.matt.ieat.dao.hbm.MealDaoImpl" 
		parent="abstractHibernateDao"/>

	<bean id="prepTimeDao" class="magoffin.matt.ieat.dao.hbm.PrepTimeDaoImpl" 
		parent="abstractHibernateDao"/>

	<bean id="recipeDao" class="magoffin.matt.ieat.dao.hbm.RecipeDaoImpl" init-method="init" 
		parent="abstractHibernateDao">
		<property name="jdbcTemplate"><ref bean="myJdbcTemplate"/></property>
		<property name="domainObjectFactory">
			<ref bean="domainObjectFactory"/>
		</property>
		<property name="sqlIndexAll">
		 	<!--
		 		SQL to index recipe data. This may produce duplicate rows, but must be 
		 		in recipe ID order; must result in the following columns:
		 		
		 		1: recipeId
		 		2: name
		 		3: excerpt
		 		4: directions
		 		5: step value (multi)
		 		6: ingredient id (multi)
		 		7: rating user id (multi)
		 		8: rating (multi)
		 		9: owner id
		 	-->
			<value>select r.recipeid, r.recipe_name, r.excerpt, r.directions, s.value_,
				i.ingredientid, rr.userid, rr.rating, r.ownerid from recipe r 
				left outer join recipestep s on r.recipeid = s.recipeid 
				left outer join recipeingredient i on r.recipeid = i.recipeid
				left outer join reciperating rr on r.recipeid = rr.recipeid
				order by r.recipeid, s.pos, i.pos</value>
		</property>
		<property name="sqlReassignBase">
			<!-- 
				SQL to reassign the base for a set of recipes.
				
				1: new baseId
				2: old baseId
			-->
			<value>update recipe set baseid = ? where baseid = ?</value>
		</property>
		<property name="sqlReassignCourse">
			<!-- 
				SQL to reassign the course for a set of recipes.
				
				1: new courseId
				2: old courseId
			-->
			<value>update recipe set courseid = ? where courseid = ?</value>
		</property>
		<property name="sqlReassignDifficulty">
			<!-- 
				SQL to reassign the difficulty for a set of recipes.
				
				1: new difficultyId
				2: old difficultyId
			-->
			<value>update recipe set difficultyid = ? where difficultyid = ?</value>
		</property>
		<property name="sqlReassignEthnicity">
			<!-- 
				SQL to reassign the ethnicity for a set of recipes.
				
				1: new ethnicityId
				2: old ethnicityId
			-->
			<value>update recipe set ethnicityid = ? where ethnicityid = ?</value>
		</property>
		<property name="sqlReassignIngredient">
			<!-- 
				SQL to reassign the ingredient for a set of recipes.
				
				1: new ingredientId
				2: old ingredientId
			-->
			<value>update recipeingredient set ingredientid = ? where ingredientid = ?</value>
		</property>
		<property name="sqlReassignPrepTime">
			<!-- 
				SQL to reassign the prepTime for a set of recipes.
				
				1: new prepTimeId
				2: old prepTimeId
			-->
			<value>update recipe set preptimeid = ? where preptimeid = ?</value>
		</property>
  	</bean>

	<bean id="systemDao" class="magoffin.matt.ieat.dao.hbm.SystemDaoImpl" 
		parent="abstractHibernateDao"/>
	
	<bean id="parameterDaoEnvironment" 
		class="magoffin.matt.xweb.util.XwebJdbcParamDao">
		<property name="jdbcTemplate" ref="myJdbcTemplate"/>
		<property name="keyPrefix" value="env:"/>
	</bean>

	<bean id="unitDao" class="magoffin.matt.ieat.dao.hbm.UnitDaoImpl" 
		parent="abstractHibernateDao">
		<property name="jdbcTemplate" ref="myJdbcTemplate"/>
		<property name="sqlIndexAll">
			<!-- 
				SQL to index unit table, must result in following columns:
					1: unitId, 
					2: name (value)
					3: abbreviation
			-->
			<value>select unitid, value_, abbreviation from unit order by unitid</value>
		</property>
  	</bean>

	<bean id="userDao" class="magoffin.matt.ieat.dao.hbm.UserDaoImpl" 
		parent="abstractHibernateDao">
		<property name="jdbcTemplate" ref="myJdbcTemplate"/>
		<property name="sqlIndexAll">
			<!-- 
				SQL to index user table, must result in following columns:
					1: userId, 
					2: name
					3: login
					4: email
					5: accessLevel
					6: createdDate
					7: lastLoginDate
			-->
			<value>select userid, user_name, login, email, accesslevel, createddate, lastlogindate
				from users order by userid</value>
		</property>
	</bean>
	
</beans>
