<?xml version="1.0" encoding="UTF-8"?>

<!--
========================================================================================================================
beans-integration.xml

Copyright (c) 2013 Manning Publications Co.

Willie Wheeler (willie.wheeler@gmail.com)

Book: http://manning.com/wheeler/
Blog: http://springinpractice.com/
Code: https://github.com/springinpractice
========================================================================================================================
-->
<!-- http://www.rabbitmq.com/amqp-0-9-1-reference.html -->
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:int="http://www.springframework.org/schema/integration"
	xmlns:int-amqp="http://www.springframework.org/schema/integration/amqp"
	xmlns:int-mail="http://www.springframework.org/schema/integration/mail"
	xmlns:int-xml="http://www.springframework.org/schema/integration/xml"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:oxm="http://www.springframework.org/schema/oxm"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:rabbit="http://www.springframework.org/schema/rabbit"
	xmlns:util="http://www.springframework.org/schema/util"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.1.xsd
		http://www.springframework.org/schema/integration
		http://www.springframework.org/schema/integration/spring-integration-2.2.xsd
		http://www.springframework.org/schema/integration/amqp
		http://www.springframework.org/schema/integration/amqp/spring-integration-amqp-2.2.xsd
		http://www.springframework.org/schema/integration/mail
		http://www.springframework.org/schema/integration/mail/spring-integration-mail-2.2.xsd
		http://www.springframework.org/schema/integration/xml
		http://www.springframework.org/schema/integration/xml/spring-integration-xml-2.2.xsd
		http://www.springframework.org/schema/jee
		http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
		http://www.springframework.org/schema/oxm
		http://www.springframework.org/schema/oxm/spring-oxm-3.1.xsd
		http://www.springframework.org/schema/rabbit
		http://www.springframework.org/schema/rabbit/spring-rabbit-1.1.xsd
		http://www.springframework.org/schema/util
		http://www.springframework.org/schema/util/spring-util-3.1.xsd
		">
	
	<context:property-placeholder location="classpath:/spring/environment.properties" />
	
	<!-- Recipe 13.5 -->
	<jee:jndi-lookup id="mailSession" jndi-name="mail/Sip13HelpDeskMailSession" resource-ref="true" />
	
	<!-- Recipe 13.5 -->
	<bean id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl" p:session-ref="mailSession" />
	
	
	<!-- =========================================================================================================== -->
	<!-- Rabbit                                                                                                      -->
	<!-- =========================================================================================================== -->
	
	<rabbit:connection-factory
		id="rabbitConnectionFactory"
		username="${rabbitMq.username}"
		password="${rabbitMq.password}" />
	
	<!-- The <rabbit:admin/> declaration by default automatically looks for beans of type Queue, Exchange and Binding
	     and declares them to the broker on behalf of the user. -->
	<rabbit:admin connection-factory="rabbitConnectionFactory" />
	
	<rabbit:queue name="createTicketRequest.queue" />
	<rabbit:queue name="findTicketStatusRequest.queue" />
	<rabbit:queue name="findTicketCategoriesRequest.queue" />
	<rabbit:queue name="findTicketCategoryRequest.queue" />
	
	
	<!-- =========================================================================================================== -->
	<!-- OXM                                                                                                         -->
	<!-- =========================================================================================================== -->
	
	<!-- Set content type here or else it will be application/octet-stream -->
	<bean id="marshallingMessageConverter"
		class="org.springframework.amqp.support.converter.MarshallingMessageConverter"
		p:contentType="application/xml">
		
		<constructor-arg ref="marshaller" />
	</bean>
	
	<oxm:jaxb2-marshaller id="marshaller">
		<oxm:class-to-be-bound name="com.springinpractice.ch13.cdm.DummyPayload" />
		<oxm:class-to-be-bound name="com.springinpractice.ch13.cdm.Ticket" />
		<oxm:class-to-be-bound name="com.springinpractice.ch13.cdm.TicketCategory" />
		<oxm:class-to-be-bound name="com.springinpractice.ch13.cdm.TicketCategory$TicketCategoryList" />
		<oxm:class-to-be-bound name="com.springinpractice.ch13.cdm.TicketCategoryRequest" />
		<oxm:class-to-be-bound name="com.springinpractice.ch13.cdm.TicketStatus" />
		<oxm:class-to-be-bound name="com.springinpractice.ch13.cdm.TicketStatusRequest" />
	</oxm:jaxb2-marshaller>
	
	
	<!-- =========================================================================================================== -->
	<!-- Spring Integration                                                                                          -->
	<!-- =========================================================================================================== -->
	
	<context:component-scan base-package="com.springinpractice.ch13.helpdesk.integration.transformer" />
	
	<!-- Recipe 13.4 -->
	
	<!-- If you get PKIX errors, see this post: -->
	<!-- http://springinpractice.com/2012/04/29/fixing-pkix-path-building-issues-when-using-javamail-and-smtp/ -->
	
	<!-- You will need to adjust for IMAP though. E.g., for Gmail: -->
	<!-- openssl s_client -connect imap.gmail.com:993 > gmail-imap.cer -->
	
	<!-- Use this if your provider supports IMAP IDLE. -->
	<!-- DO NOT USE YOUR REAL E-MAIL ACCOUNT FOR THE STORE URI. USE A TEST ACCOUNT, OR YOU MAY END UP DELETING SEVERAL
	     YEARS WORTH OF E-MAIL AS I DID. [WLW] -->
	<!-- Set "should-delete-messages" to true. This channel adapter will delete messages from the IMAP mailbox as it
	     dequeues them. -->
	<int-mail:imap-idle-channel-adapter
		channel="newMailChannel"
		store-uri="${email.store.uri}"
		should-delete-messages="${email.shouldDeleteMessages}" />
	
	<!-- Recipe 13.4 -->
	<!-- Use this if your provider supports only plain IMAP. -->
	<!--
	<int-mail:inbound-channel-adapter
		channel="newMailChannel"
		store-uri="${email.store.uri}"
		should-delete-messages="${email.shouldDeleteMessages}">
		<int:poller max-messages-per-poll="3" fixed-rate="30000" />
	</int-mail:inbound-channel-adapter>
	-->
	
	<!-- Recipe 13.4 -->
	<int:channel id="newMailChannel" />
	
	<!-- Recipe 13.4 -->
	<int:transformer input-channel="newMailChannel"
		output-channel="createTicketRequestChannel"
		expression="@ticketTransformer.toDto(payload)" />
	
	<!-- From AMQP to SI -->
	<int-amqp:inbound-channel-adapter
		queue-names="createTicketRequest.queue"
		channel="createTicketRequestChannel"
		message-converter="marshallingMessageConverter" />
	
	<!-- Create ticket -->
	<!-- Modified for recipe 13.5 -->
<!-- 	<int:channel id="createTicketRequestChannel" /> -->
	<int:publish-subscribe-channel id="createTicketRequestChannel" />
	
	<int:chain input-channel="createTicketRequestChannel" output-channel="nullChannel">
		<int:transformer ref="ticketTransformer" method="toEntity" />
		<int:service-activator expression="@ticketRepository.save(payload)" />
	</int:chain>
	
	<!-- Recipe 13.5 -->
	<int:transformer input-channel="createTicketRequestChannel"
		output-channel="confirmationEmailChannel"
		expression="@ticketTransformer.toConfirmationEmail(payload)" />
	
	<int:channel id="confirmationEmailChannel" />
	
	<!-- Recipe 13.5 -->
	<int-mail:outbound-channel-adapter channel="confirmationEmailChannel" mail-sender="mailSender" />
	
	<!-- From AMQP to SI -->
	<!-- http://static.springsource.org/spring-integration/api/org/springframework/integration/amqp/inbound/AmqpInboundGateway.html -->
	<!-- mapped-request-headers="requestType" passes along our "requestType" AMQP custom message property as a custom SI message header -->
	<int-amqp:inbound-gateway
		queue-names="findTicketStatusRequest.queue,findTicketCategoriesRequest.queue,findTicketCategoryRequest.queue"
		request-channel="helpDeskRequestChannel"
		mapped-request-headers="requestType" 
		message-converter="marshallingMessageConverter" />
	
	<int:channel id="helpDeskRequestChannel">
		<int:interceptors>
			<int:wire-tap channel="logger" />
		</int:interceptors>
	</int:channel>
	
	<int:logging-channel-adapter id="logger" level="DEBUG" log-full-message="true" />
	
	<!-- http://forum.springsource.org/showthread.php?125777-keeping-default-headers-in-amqp-outbound-channel-adapters -->
	<int:header-value-router input-channel="helpDeskRequestChannel" header-name="requestType">
		<int:mapping value="findTicketStatusRequest" channel="findTicketStatusRequestChannel" />
		<int:mapping value="findTicketCategoriesRequest" channel="findTicketCategoriesRequestChannel" />
		<int:mapping value="findTicketCategoryRequest" channel="findTicketCategoryRequestChannel" />
	</int:header-value-router>
	
	<!-- Find ticket statuses -->
	<int:channel id="findTicketStatusRequestChannel" />
	
	<int:chain input-channel="findTicketStatusRequestChannel">
		<int:service-activator expression="@ticketStatusRepository.findByKey(payload.key)" />
		<int:transformer ref="ticketStatusTransformer" method="toDto" />
	</int:chain>
	
	<!-- Find ticket categories -->
	<int:channel id="findTicketCategoriesRequestChannel" />
	
	<int:chain input-channel="findTicketCategoriesRequestChannel">
		<int:service-activator expression="@ticketCategoryRepository.findAll()" />
		<int:transformer ref="ticketCategoryListTransformer" method="toDto" />
	</int:chain>
	
	<!-- Find ticket category -->
	<int:channel id="findTicketCategoryRequestChannel" />
	
	<int:chain input-channel="findTicketCategoryRequestChannel">
		<int:service-activator expression="@ticketCategoryRepository.findOne(payload.id)" />
		<int:transformer ref="ticketCategoryTransformer" method="toDto" />
	</int:chain>
	
	
	<!-- =========================================================================================================== -->
	<!-- FIXME: Replace this with AMQP-based integration                                                             -->
	<!-- =========================================================================================================== -->
	
	<bean id="restTemplate" class="org.springframework.web.client.RestTemplate" />
	
	<bean class="com.springinpractice.ch13.helpdesk.integration.gateway.impl.PortalGatewayImpl">
		<constructor-arg ref="restTemplate" />
		<constructor-arg value="http://localhost:8180/portal/api" />
	</bean>
</beans>
