/***
 * Excerpted from "Domain-Driven Design Using Naked Objects",
 * published by The Pragmatic Bookshelf.
 * Copyrights apply to this code. It may not be used to create training material, 
 * courses, books, articles, and the like. Contact us if you are in doubt.
 * We make no guarantees that this code is fit for any purpose. 
 * Visit http://www.pragmaticprogrammer.com/titles/dhnako for more book information.
***/
package com.pragprog.dhnako.carserv.camel.domainservices;

import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.builder.xml.Namespaces;
import org.apache.camel.impl.DefaultCamelContext;
import org.nakedobjects.applib.AbstractService;
import org.nakedobjects.runtime.snapshot.XmlSnapshot;
import org.w3c.dom.Document;

import com.pragprog.dhnako.carserv.dom.domainservices.MessagePublisher;
import com.pragprog.dhnako.carserv.dom.domainservices.Publishable;

public class MessagePublisherImpl extends AbstractService implements MessagePublisher {

	private DefaultCamelContext camelContext;
	private ProducerTemplate producerTemplate;

	public void publish(Publishable publishable) throws Exception {
		initializeIfRequired();

		XmlSnapshot xmlSnapshot = XmlSnapshot.create(publishable).build();
		Document xmlDocument = xmlSnapshot.getXmlDocument();
		producerTemplate.sendBody("direct:in", xmlDocument);
	}

	private synchronized void initializeIfRequired() throws Exception {
		if (camelContext == null) {
			camelContext = new DefaultCamelContext();
			camelContext.addRoutes(new ServiceMessageRoute());
			camelContext.start();

			producerTemplate = camelContext.createProducerTemplate();
		}
	}

	private final class ServiceMessageRoute extends RouteBuilder {
		@Override
		public void configure() throws Exception {
			from("direct:in")
			.choice()
				.when().xpath(
						"/app:RegularService/app:paymentMethod/app:CreditCard",
						regularServiceNamespaces())
					.to("xslt:RegularServiceToServiceMessage.xslt")
					.to("file:messages/service/creditcard")
				.otherwise()
					.convertBodyTo(String.class)
					.to("file:messages/unknown");
		}

		private Namespaces regularServiceNamespaces() {
			return new Namespaces("nof",
					"http://www.nakedobjects.org/ns/0.1/metamodel")
					.add("app", "http://www.nakedobjects.org/ns/app/com.pragprog.dhnako.carserv.dom.service/RegularService")
					.add("xsi", "http://www.w3.org/2001/XMLSchema-instance");
		}
	}

}
