From 60c76b51af9143d95ea51fb3ce596430e04fcd3c Mon Sep 17 00:00:00 2001
From: Constantin Jucovschi <jucovschi@gmail.com>
Date: Mon, 8 Jun 2015 19:16:31 +0200
Subject: [PATCH] pom.xml

---
 pom.xml                                       |  23 +--
 .../kwarc/sally4/client/EventHandler.java     |   5 +
 .../kwarc/sally4/client/EventListener.java    |  28 +++
 .../sally4/client/EventListenerFactory.java   |  41 ++++
 .../sally4/client/EventListenerList.java      |  26 +++
 .../kwarc/sally4/client/IActionAcceptor.java  |  10 +
 .../info/kwarc/sally4/client/SallyClient.java |   3 +-
 .../info/kwarc/sally4/client/SallyDoc.java    | 154 ++++++++++++++
 .../kwarc/sally4/client/TypedCallback.java    |   5 +
 .../sally4/client/impl/MessageParser.java     | 146 ++++++++++++++
 .../sally4/client/impl/SallyClientImpl.java   |  49 +++--
 .../kwarc/sally4/client/utils/CommUtils.java  |  55 -----
 .../ProducerConsumerSplitterComponent.java    | 190 ------------------
 ...onsumerSplitterComponentConfiguration.java |   5 -
 .../ProducerConsumerSplitterEndpoint.java     | 118 -----------
 .../sally4/client/utils/XMLMessageType.java   |  33 ---
 16 files changed, 454 insertions(+), 437 deletions(-)
 create mode 100644 src/main/java/info/kwarc/sally4/client/EventHandler.java
 create mode 100644 src/main/java/info/kwarc/sally4/client/EventListener.java
 create mode 100644 src/main/java/info/kwarc/sally4/client/EventListenerFactory.java
 create mode 100644 src/main/java/info/kwarc/sally4/client/EventListenerList.java
 create mode 100644 src/main/java/info/kwarc/sally4/client/IActionAcceptor.java
 create mode 100644 src/main/java/info/kwarc/sally4/client/SallyDoc.java
 create mode 100644 src/main/java/info/kwarc/sally4/client/TypedCallback.java
 create mode 100644 src/main/java/info/kwarc/sally4/client/impl/MessageParser.java
 delete mode 100644 src/main/java/info/kwarc/sally4/client/utils/CommUtils.java
 delete mode 100644 src/main/java/info/kwarc/sally4/client/utils/ProducerConsumerSplitterComponent.java
 delete mode 100644 src/main/java/info/kwarc/sally4/client/utils/ProducerConsumerSplitterComponentConfiguration.java
 delete mode 100644 src/main/java/info/kwarc/sally4/client/utils/ProducerConsumerSplitterEndpoint.java
 delete mode 100644 src/main/java/info/kwarc/sally4/client/utils/XMLMessageType.java

diff --git a/pom.xml b/pom.xml
index 5332ad6..eb87794 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,21 +17,22 @@
 
 	<packaging>bundle</packaging>
 
-	<artifactId>client-java-camel</artifactId>
+	<properties>
+		<bundle.private-package>info.kwarc.sally4.client.impl</bundle.private-package>
+		<bundle.export-package>info.kwarc.sally4.client*</bundle.export-package>
+	</properties>
 
 	<parent>
 		<groupId>info.kwarc.sally4</groupId>
 		<artifactId>sally4</artifactId>
-		<version>0.0.6</version>
+		<version>1.0.1-SNAPSHOT</version>
 		<relativePath>..</relativePath>
 	</parent>
 
-	<properties>
-		<bundle.private-package>info.kwarc.sally4.client.impl</bundle.private-package>
-		<bundle.export-package>info.kwarc.sally4.client*</bundle.export-package>
-	</properties>
+	<artifactId>client-java-camel</artifactId>
 
 	<dependencies>
+
 		<dependency>
 			<groupId>info.kwarc.sally4.comm</groupId>
 			<artifactId>comm-core</artifactId>
@@ -41,7 +42,7 @@
 		<dependency>
 			<groupId>org.apache.activemq</groupId>
 			<artifactId>activemq-camel</artifactId>
-			<version>5.9.0</version>
+			<version>${activemq.version}</version>
 		</dependency>
 
 		<dependency>
@@ -49,13 +50,5 @@
 			<artifactId>camel-jaxb</artifactId>
 			<version>${camel.version}</version>
 		</dependency>
-
-
-		<dependency>
-			<groupId>org.slf4j</groupId>
-			<artifactId>slf4j-simple</artifactId>
-			<version>1.7.7</version>
-		</dependency>
-
 	</dependencies>
 </project>
diff --git a/src/main/java/info/kwarc/sally4/client/EventHandler.java b/src/main/java/info/kwarc/sally4/client/EventHandler.java
new file mode 100644
index 0000000..bdd4540
--- /dev/null
+++ b/src/main/java/info/kwarc/sally4/client/EventHandler.java
@@ -0,0 +1,5 @@
+package info.kwarc.sally4.client;
+
+public interface EventHandler<EvtType> {
+	void run(EvtType evtData);
+}
diff --git a/src/main/java/info/kwarc/sally4/client/EventListener.java b/src/main/java/info/kwarc/sally4/client/EventListener.java
new file mode 100644
index 0000000..772ce11
--- /dev/null
+++ b/src/main/java/info/kwarc/sally4/client/EventListener.java
@@ -0,0 +1,28 @@
+package info.kwarc.sally4.client;
+
+public class EventListener <EvtType> {
+	public enum Status {
+		Active,
+		Suspended
+	};
+	
+	Status status;
+	
+	EventHandler<EvtType> runner;
+	
+	public EventHandler<EvtType> getRunner() {
+		return runner;
+	}
+	
+	public void setRunner(EventHandler<EvtType> runner) {
+		this.runner = runner;
+	}
+
+	public Status getStatus() {
+		return status;
+	}
+	
+	public void setStatus(Status status) {
+		this.status = status;
+	}
+}
diff --git a/src/main/java/info/kwarc/sally4/client/EventListenerFactory.java b/src/main/java/info/kwarc/sally4/client/EventListenerFactory.java
new file mode 100644
index 0000000..d8158cf
--- /dev/null
+++ b/src/main/java/info/kwarc/sally4/client/EventListenerFactory.java
@@ -0,0 +1,41 @@
+package info.kwarc.sally4.client;
+
+import info.kwarc.sally4.client.EventListener.Status;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class EventListenerFactory<EventType> {
+	Set<EventListener<EventType>> listeners;
+	
+	public EventListenerFactory() {
+		listeners = new HashSet<EventListener<EventType>>();
+	}
+	
+	public void emit(EventType t) {
+		for (EventListener<EventType> listener : listeners) {
+			if (listener.getStatus() == Status.Active) {
+				listener.getRunner().run(t);
+			}
+		}
+	}
+	
+	void suspendAll() {
+		for (EventListener<EventType> listener : listeners) {
+			listener.setStatus(Status.Suspended);
+		}
+	}
+	
+	public EventListener<EventType> create(EventHandler<EventType> runner) {		
+		EventListener<EventType> result = create();
+		result.setRunner(runner);
+		return result;
+	}
+	
+	public EventListener<EventType> create() {
+		EventListener<EventType>  result = new EventListener<EventType>();
+		result.setStatus(Status.Active);
+		listeners.add(result);
+		return result;
+	}
+}
diff --git a/src/main/java/info/kwarc/sally4/client/EventListenerList.java b/src/main/java/info/kwarc/sally4/client/EventListenerList.java
new file mode 100644
index 0000000..1d878f6
--- /dev/null
+++ b/src/main/java/info/kwarc/sally4/client/EventListenerList.java
@@ -0,0 +1,26 @@
+package info.kwarc.sally4.client;
+
+import info.kwarc.sally4.client.EventListener.Status;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class EventListenerList {
+	List<EventListener<?>> list;
+	
+	public EventListenerList() {
+		list = new ArrayList<EventListener<?>>();
+	}
+	
+	public <T> void addEventHandler(EventListener<T> evt) {
+		list.add(evt);
+	}
+	
+	public void suspendAll() {
+		for (EventListener<?> listener : list) {
+			listener.setStatus(Status.Suspended);
+		}
+	}
+	
+}
diff --git a/src/main/java/info/kwarc/sally4/client/IActionAcceptor.java b/src/main/java/info/kwarc/sally4/client/IActionAcceptor.java
new file mode 100644
index 0000000..9c131b2
--- /dev/null
+++ b/src/main/java/info/kwarc/sally4/client/IActionAcceptor.java
@@ -0,0 +1,10 @@
+package info.kwarc.sally4.client;
+
+import org.apache.camel.Exchange;
+
+public interface IActionAcceptor <T> {
+	T getEventData();
+	
+	Exchange cloneExchange();
+	void sendBack(Object obj);
+}
diff --git a/src/main/java/info/kwarc/sally4/client/SallyClient.java b/src/main/java/info/kwarc/sally4/client/SallyClient.java
index e11a70d..5ac06ac 100644
--- a/src/main/java/info/kwarc/sally4/client/SallyClient.java
+++ b/src/main/java/info/kwarc/sally4/client/SallyClient.java
@@ -1,8 +1,7 @@
 package info.kwarc.sally4.client;
 
-import org.apache.camel.RoutesBuilder;
 
 
 public interface SallyClient {
-	void registerDocument(String docName, String[] interfaces, RoutesBuilder builder);
+	void registerDocument(String docName, String[] interfaces, TypedCallback<SallyDoc> docCallback);
 }
diff --git a/src/main/java/info/kwarc/sally4/client/SallyDoc.java b/src/main/java/info/kwarc/sally4/client/SallyDoc.java
new file mode 100644
index 0000000..58d65a4
--- /dev/null
+++ b/src/main/java/info/kwarc/sally4/client/SallyDoc.java
@@ -0,0 +1,154 @@
+package info.kwarc.sally4.client;
+
+import info.kwarc.sally.comm.core.HeartbeatRequest;
+import info.kwarc.sally.comm.core.HeartbeatResponse;
+import info.kwarc.sally4.client.impl.MessageParser;
+
+import java.io.StringReader;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.Processor;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+
+public class SallyDoc extends RouteBuilder {
+
+	MessageParser parser;
+	HashSet<String> schemaSet;
+	ProducerTemplate producerTemplate;
+	String inputQueue;
+	String outputQueue;
+
+	EventHandler<IActionAcceptor<HeartbeatRequest>> heartbeatRequestHandler = new EventHandler<IActionAcceptor<HeartbeatRequest>>() {
+		
+		@Override
+		public void run(IActionAcceptor<HeartbeatRequest> evtData) {
+			evtData.sendBack(new HeartbeatResponse());
+		}
+	};
+	
+	public SallyDoc(MessageParser parser, List<String> schemas, String inputQueue, String outputQueue) {
+		this.parser = parser;
+		schemaSet = new HashSet<String>(schemas);
+		messageHandlers = new HashMap<Class<? extends Object>, SallyDoc.EventMessageHandler<?>>();
+		this.inputQueue = inputQueue;
+		this.outputQueue = outputQueue;
+		schemaSet.add("core");
+		addMessageHandler(HeartbeatRequest.class, heartbeatRequestHandler);
+	}
+
+	HashMap<Class<? extends Object>, EventMessageHandler<?>> messageHandlers ;
+
+	public class EventMessageHandler <T> extends EventListenerFactory<IActionAcceptor<T>>{
+	}
+
+	@SuppressWarnings("unchecked")
+	public <T> EventListener<IActionAcceptor<T>> addMessageHandler(Class<T> messageClass, EventHandler<IActionAcceptor<T>> eventRunner) {	
+		EventMessageHandler<T> factory = null;
+
+		if (!messageHandlers.containsKey(messageClass)) {
+			factory = new EventMessageHandler<T>();
+			messageHandlers.put(messageClass, factory);
+		} else {
+			factory =  (EventMessageHandler<T>) messageHandlers.get(messageClass);
+		}
+		return factory.create(eventRunner);
+	}
+
+	Processor unMarshalMessage = new Processor() {
+
+		@Override
+		public void process(Exchange exchange) throws Exception {
+			String xmlMessage = exchange.getIn().getBody(String.class);
+			String msgSchema = MessageParser.getMessageSchema(xmlMessage);
+			if (!schemaSet.contains(msgSchema)) {
+				log.info("Message schema does not match any schema at registration. Ignoring."+msgSchema);
+				return;
+			}
+			Unmarshaller unmarshaller = parser.getUnmarshaller(msgSchema);
+			if (unmarshaller == null) {
+				throw new Exception("No unmarshaller found for schema "+msgSchema);
+			}
+			exchange.getIn().setBody(unmarshaller.unmarshal(new StringReader(xmlMessage)));
+		}
+	};
+
+	Processor marshalMessage = new Processor() {
+
+		@Override
+		public void process(Exchange exchange) throws Exception {
+			exchange.getIn().setBody(parser.marshall(exchange.getIn().getBody()));
+		}
+	};
+	
+	public void sendEvent(Object obj) {
+		producerTemplate.sendBody("direct:sendAlexInOnly",obj);
+	}
+	
+	public <T> T sendRequest(Object obj, Class<T> type) {
+		return producerTemplate.requestBody("direct:sendAlexInOut", obj, type);
+	}
+
+
+	Processor triggerOnMessageHandlers = new Processor() {
+
+		@Override
+		public void process(final Exchange exchange) throws Exception {
+			final Object obj = exchange.getIn().getBody();
+
+			EventMessageHandler<?> evtMsgHandler = messageHandlers.get(obj.getClass());
+			if (evtMsgHandler == null)
+				return;
+
+			Method m = evtMsgHandler.getClass().getMethod("emit", Object.class);
+			m.invoke(evtMsgHandler, new IActionAcceptor<Object>() {
+
+				@Override
+				public Object getEventData() {
+					return obj;
+				}
+
+				@Override
+				public Exchange cloneExchange() {
+					return exchange.copy();
+				}
+
+				@Override
+				public void sendBack(Object obj) {
+					exchange.getIn().setBody(obj);
+				}
+
+			});
+		}
+	};
+
+	@Override
+	public void configure() throws Exception {
+		producerTemplate = getContext().createProducerTemplate();
+		
+		from(inputQueue)
+			.to("log:SallyDocImpl?showHeaders=true")
+			.convertBodyTo(String.class)
+			.process(unMarshalMessage)
+			.process(triggerOnMessageHandlers)
+			.process(marshalMessage)
+			.to("log:SallyDocImpl?showHeaders=true");
+		
+		from("direct:sendAlexInOut")
+			.process(marshalMessage)
+			.inOut(outputQueue)
+			.process(unMarshalMessage);
+
+		from("direct:sendAlexInOnly")
+			.process(marshalMessage)
+			.inOnly(outputQueue);
+
+	}
+
+}
diff --git a/src/main/java/info/kwarc/sally4/client/TypedCallback.java b/src/main/java/info/kwarc/sally4/client/TypedCallback.java
new file mode 100644
index 0000000..299f113
--- /dev/null
+++ b/src/main/java/info/kwarc/sally4/client/TypedCallback.java
@@ -0,0 +1,5 @@
+package info.kwarc.sally4.client;
+
+public interface TypedCallback <T> {
+	void run(T object);
+}
diff --git a/src/main/java/info/kwarc/sally4/client/impl/MessageParser.java b/src/main/java/info/kwarc/sally4/client/impl/MessageParser.java
new file mode 100644
index 0000000..c4b1c21
--- /dev/null
+++ b/src/main/java/info/kwarc/sally4/client/impl/MessageParser.java
@@ -0,0 +1,146 @@
+package info.kwarc.sally4.client.impl;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.camel.converter.jaxb.JaxbDataFormat;
+import org.apache.felix.ipojo.annotations.Validate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MessageParser {
+	public final static Pattern xmlNamespace = Pattern.compile("xmlns(:(\\w+))?=\"http://kwarc.info/sally/comm/([\\w/:.]+)\"");
+	final String packagePrefix = "info.kwarc.sally.comm";
+
+	class MessageMarshallers {
+		JAXBContext context;
+		Marshaller marshaller;
+		Unmarshaller unmarshaller;
+
+		public MessageMarshallers(JAXBContext context) {
+			this.context = context;
+			try {
+				marshaller = context.createMarshaller();
+				unmarshaller  = context.createUnmarshaller();
+			} catch (JAXBException e) {
+				e.printStackTrace();
+			}
+		}
+
+		public JAXBContext getContext() {
+			return context;
+		}
+
+		public Marshaller getMarshaller() {
+			return marshaller;
+		}
+
+		public Unmarshaller getUnmarshaller() {
+			return unmarshaller;
+		}
+	}
+
+	Logger log;
+
+	HashMap<String, MessageMarshallers > bundleMappings = new HashMap<String, MessageMarshallers>();
+
+	public JaxbDataFormat getFormat(String commType) {
+		return new JaxbDataFormat(bundleMappings.get(commType).getContext());
+	}
+
+	public Unmarshaller getUnmarshaller(String schemaType) {
+		if (!bundleMappings.containsKey(schemaType))
+			return null;
+		return bundleMappings.get(schemaType).getUnmarshaller();
+	}
+
+	public Marshaller getMarshaller(String schemaType) {
+		if (!bundleMappings.containsKey(schemaType))
+			return null;
+		return bundleMappings.get(schemaType).getMarshaller();
+	}
+
+	public static String getMessageSchema(String xmlMessage) {
+		Matcher m = xmlNamespace.matcher(xmlMessage);
+		if (m.find()) {
+			return m.group(3);
+		} else
+			return null;
+	}
+
+	/* (non-Javadoc)
+	 * @see info.kwarc.sally4.docmanager.impl.MessageParser1#validMessageSchemaDefinition(java.lang.String)
+	 */
+	public boolean validMessageSchemaDefinition(String iface) {
+		return bundleMappings.containsKey(iface);
+	}
+
+	public <T> T parseAs(String xmlMessage, Class<? extends T> resultClass) {
+		String msgType = getMessageSchema(xmlMessage);
+		if (!bundleMappings.containsKey(msgType))
+			return null;
+		StringReader r = new StringReader(xmlMessage);
+		try {
+			Object o = bundleMappings.get(msgType).getUnmarshaller().unmarshal(r);
+			if (resultClass.isAssignableFrom(o.getClass())) {
+				return (T) o;
+			} 
+		} catch (JAXBException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	public MessageParser() {
+		log = LoggerFactory.getLogger(getClass());	
+		addCommLibrary("core");
+	}
+
+	@Validate
+	void start() {
+		try {
+			// Make sure core is always there
+			bundleMappings.put("core", new MessageMarshallers(JAXBContext.newInstance("info.kwarc.sally.comm.core", getClass().getClassLoader())));
+		} catch (JAXBException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}		
+	}
+
+	public void addCommLibrary(String iFace) {
+		JAXBContext context;
+		try {
+			context = JAXBContext.newInstance(packagePrefix+"."+iFace, getClass().getClassLoader());
+			bundleMappings.put(iFace, new MessageMarshallers(context));
+		} catch (JAXBException e) {
+			e.printStackTrace();
+		}
+	}
+
+	public String marshall(Object obj) {
+		String pkg = obj.getClass().getPackage().getName();
+		if (!pkg.startsWith(packagePrefix))
+			return null;
+		String schema = pkg.substring(packagePrefix.length()+1);
+		Marshaller marshaller = getMarshaller(schema);
+		if (marshaller == null)
+			return null;
+		StringWriter output = new StringWriter();
+		try {
+			marshaller.marshal(obj, output);
+		} catch (JAXBException e) {
+			e.printStackTrace();
+			return null;
+		}
+		return output.toString();
+	}
+
+}
diff --git a/src/main/java/info/kwarc/sally4/client/impl/SallyClientImpl.java b/src/main/java/info/kwarc/sally4/client/impl/SallyClientImpl.java
index 1487455..8e31bb5 100644
--- a/src/main/java/info/kwarc/sally4/client/impl/SallyClientImpl.java
+++ b/src/main/java/info/kwarc/sally4/client/impl/SallyClientImpl.java
@@ -3,9 +3,11 @@ package info.kwarc.sally4.client.impl;
 import info.kwarc.sally.comm.core.RegisterClientRequest;
 import info.kwarc.sally.comm.core.RegisterClientResponse;
 import info.kwarc.sally4.client.SallyClient;
-import info.kwarc.sally4.client.utils.ProducerConsumerSplitterComponent;
+import info.kwarc.sally4.client.SallyDoc;
+import info.kwarc.sally4.client.TypedCallback;
 
 import java.util.Arrays;
+import java.util.List;
 import java.util.UUID;
 
 import javax.xml.bind.JAXBContext;
@@ -13,7 +15,7 @@ import javax.xml.bind.JAXBContext;
 import org.apache.activemq.ActiveMQConnectionFactory;
 import org.apache.camel.CamelContext;
 import org.apache.camel.Exchange;
-import org.apache.camel.RoutesBuilder;
+import org.apache.camel.builder.ExchangeBuilder;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.jms.JmsComponent;
 import org.apache.camel.converter.jaxb.JaxbDataFormat;
@@ -36,9 +38,12 @@ public class SallyClientImpl extends RouteBuilder implements SallyClient {
 
 	org.apache.camel.Component sallyConn;
 
+	MessageParser parser;
+	
 	CamelContext context;
 
-	public SallyClientImpl(String host, String user, String password) {
+	public SallyClientImpl(String host, String user, String password, MessageParser parser) {
+		this.parser = parser;
 		this.host = host;
 		this.user = user;
 		this.password = password;
@@ -91,6 +96,8 @@ public class SallyClientImpl extends RouteBuilder implements SallyClient {
 		sallyConn = JmsComponent.jmsComponent(connectionFactory);
 		context.addComponent("activemq", sallyConn);
 		context.addRoutes(this);
+
+		context.start();
 	}
 
 	@Invalidate
@@ -105,28 +112,29 @@ public class SallyClientImpl extends RouteBuilder implements SallyClient {
 		DataFormat core = new JaxbDataFormat(context);
 
 		from("direct:sally_register")
-		.setProperty("origRequest", body())
 		.marshal(core)
-		.to("log:foo?showHeaders=true&showProperties=true")
+		.to("log:foo?showHeaders=true")
 		.inOut("activemq:queue:sally_register")
-		.to("log:foo?showHeaders=true&showProperties=true")
+		.to("log:foo?showHeaders=true")
 		.unmarshal(core)
 		.bean(method(this, "registerResponse"));
 	}
-
-	public void registerResponse(Exchange e)  throws Exception {
-		RegisterClientResponse response = e.getIn().getBody(RegisterClientResponse.class);
-		RegisterClientRequest req = e.getProperty("origRequest", RegisterClientRequest.class);
-		RoutesBuilder builder = e.getProperty("builder", RoutesBuilder.class);
-
+	
+	public SallyDoc registerResponse(RegisterClientResponse response, 
+				@org.apache.camel.Property("schemas") List<String> schemas, 
+				@org.apache.camel.Property("inputQueue") String inputQueue, 
+				@org.apache.camel.Property("callback") TypedCallback<SallyDoc> callback)  throws Exception {
+		String outputQueue = "sallyclient:queue:"+response.getSendQueue();
+
+		SallyDoc newDoc = new SallyDoc(parser, schemas, "sallyclient:queue:"+inputQueue, outputQueue);
+		callback.run(newDoc);
+		
 		CamelContext docContext = new DefaultCamelContext();
 		docContext.addComponent("sallyclient", sallyConn);
 		
-		ProducerConsumerSplitterComponent comp = new ProducerConsumerSplitterComponent("sallyclient:queue:"+req.getListenQueue(), "sallyclient:queue:"+response.getSendQueue());
-		comp.setCamelContext(docContext);
-		docContext.addComponent("sally", comp);
-		docContext.addRoutes(builder);
+		docContext.addRoutes(newDoc);
 		docContext.start();
+		return newDoc;
 	}
 
 	String genUUID(String name) {
@@ -139,21 +147,24 @@ public class SallyClientImpl extends RouteBuilder implements SallyClient {
 	}
 
 	@Override
-	public void registerDocument(String docName, String[] schemas, RoutesBuilder builder) {
+	public void registerDocument(String docName, String[] schemas, TypedCallback<SallyDoc> callback) {
 		if (!started) {
 			try {
 				context.start();
 				started = true;
 			} catch (Exception e) {
 				e.printStackTrace();
-				return;
 			}
 		}
 		RegisterClientRequest regDoc  = new RegisterClientRequest();
 		regDoc.setListenQueue(genUUID(docName));
 		regDoc.setEnvironmentID(System.getenv("SALLYENVID"));
 		regDoc.getSchemas().addAll(Arrays.asList(schemas));
-		getContext().createProducerTemplate().sendBodyAndProperty("direct:sally_register", regDoc, "builder", builder);
+		Exchange e = ExchangeBuilder.anExchange(context)
+				.withBody(regDoc).withProperty("schemas", regDoc.getSchemas()).withProperty("callback", callback)
+				.withProperty("inputQueue", regDoc.getListenQueue())
+				.build();
+		getContext().createProducerTemplate().send("direct:sally_register", e);
 	}
 
 }
diff --git a/src/main/java/info/kwarc/sally4/client/utils/CommUtils.java b/src/main/java/info/kwarc/sally4/client/utils/CommUtils.java
deleted file mode 100644
index f47c9f9..0000000
--- a/src/main/java/info/kwarc/sally4/client/utils/CommUtils.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package info.kwarc.sally4.client.utils;
-
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.util.Map;
-
-import javax.xml.bind.JAXBContext;
-import javax.xml.bind.JAXBException;
-
-import org.apache.camel.converter.jaxb.JaxbDataFormat;
-import org.apache.camel.spi.DataFormat;
-
-public class CommUtils {
-	public final static String iFacePrefix = "info.kwarc.sally.comm.";
-	public final static String xmlFacePrefix = "http://kwarc.info/sally/comm/";
-
-	public static DataFormat getDataFormat(String iFace) {
-		try {
-			JAXBContext context = JAXBContext.newInstance(iFacePrefix+iFace, CommUtils.class.getClassLoader());
-			return new JaxbDataFormat(context);
-		} catch (JAXBException e) {
-			return null;
-		}
-	}
-
-
-	public static DataFormat getDataFormat(String iFace, ClassLoader loader) {
-		try {
-			JAXBContext context = JAXBContext.newInstance(iFacePrefix+iFace, loader);
-			return new JaxbDataFormat(context);
-		} catch (JAXBException e) {
-			return null;
-		}
-	}
-	
-	public static String SerializeToQuery(Map<String, String> props) {
-		StringBuilder builder = new StringBuilder();
-		boolean first = true;
-		for (String key : props.keySet()) {
-			if (first) {
-				first = false;
-			} else {
-				builder.append("&");
-			}
-			builder.append(key);
-			builder.append("=");			
-			try {
-				builder.append(URLEncoder.encode(props.get(key), "UTF-8"));
-			} catch (UnsupportedEncodingException e) {
-			}
-		}
-		return builder.toString();
-	}
-
-}
diff --git a/src/main/java/info/kwarc/sally4/client/utils/ProducerConsumerSplitterComponent.java b/src/main/java/info/kwarc/sally4/client/utils/ProducerConsumerSplitterComponent.java
deleted file mode 100644
index 47d017b..0000000
--- a/src/main/java/info/kwarc/sally4/client/utils/ProducerConsumerSplitterComponent.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package info.kwarc.sally4.client.utils;
-
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.Component;
-import org.apache.camel.ComponentConfiguration;
-import org.apache.camel.Endpoint;
-import org.apache.camel.EndpointConfiguration;
-import org.apache.camel.RuntimeCamelException;
-import org.apache.camel.impl.ParameterConfiguration;
-
-/**
- * 
- * @author Constantin Jucovschi
- *
- * This component allows to write Camel routes like from("alex") or to("alex") 
- * and these will be resolved to the necessary 
- */
-public class ProducerConsumerSplitterComponent implements Component{
-	String consumerEndpoint, producerEndpoint;
-	CamelContext context;
-
-	public ProducerConsumerSplitterComponent(String consumerEndpoint, String producerEndpoint) {
-		this.consumerEndpoint = consumerEndpoint;
-		this.producerEndpoint = producerEndpoint;
-	}
-
-	@Override
-	public void setCamelContext(CamelContext camelContext) {
-		this.context = camelContext;
-	}
-
-	@Override
-	public CamelContext getCamelContext() {
-		return context;
-	}
-
-	@Override
-	public Endpoint createEndpoint(String uri) throws Exception {
-		return new ProducerConsumerSplitterEndpoint(uri, this, producerEndpoint, consumerEndpoint);
-	}
-
-	@Override
-	public boolean useRawUri() {
-		return true;
-	}
-
-	@Override
-	public EndpointConfiguration createConfiguration(String uri)
-			throws Exception {
-		return new ProducerConsumerSplitterEndpointConfig(uri);
-	}
-
-	@Override
-	public ComponentConfiguration createComponentConfiguration() {
-		return new ProducerConsumerSplitterComponentConfig();
-	}
-	
-
-	class ProducerConsumerSplitterComponentConfig implements ComponentConfiguration {
-
-		String baseURI;
-		Map<String, Object> propertyValues = new HashMap<String, Object>();
-		
-		@Override
-		public String getBaseUri() {
-			return baseURI;
-		}
-
-		@Override
-		public void setBaseUri(String baseUri) {
-			this.baseURI = baseUri;
-		}
-
-		@Override
-		public Map<String, Object> getParameters() {
-			return propertyValues;
-		}
-
-		@Override
-		public void setParameters(Map<String, Object> propertyValues) {
-			this.propertyValues = propertyValues;
-		}
-
-		@Override
-		public Object getParameter(String name) {
-			return propertyValues.get("name");
-		}
-
-		@Override
-		public void setParameter(String name, Object value) {
-			propertyValues.put(name, value);
-		}
-
-		@Override
-		public String getUriString() {
-			return "";
-		}
-
-		@Override
-		public void setUriString(String newValue) throws URISyntaxException {
-			
-		}
-
-		@Override
-		public ParameterConfiguration getParameterConfiguration(String name) {
-			return new ParameterConfiguration(name, String.class);
-		}
-
-		@Override
-		public SortedMap<String, ParameterConfiguration> getParameterConfigurationMap() {
-			return new TreeMap<String, ParameterConfiguration> ();
-		}
-
-		@Override
-		public Endpoint createEndpoint() throws Exception {
-			return null;
-		}
-
-		@Override
-		public void configureEndpoint(Endpoint endpoint) {
-			
-		}
-
-		@Override
-		public Object getEndpointParameter(Endpoint endpoint, String name)
-				throws RuntimeCamelException {
-			return null;
-		}
-
-		@Override
-		public void setEndpointParameter(Endpoint endpoint, String name,
-				Object value) throws RuntimeCamelException {
-			// TODO Auto-generated method stub
-			
-		}
-
-		@Override
-		public List<String> completeEndpointPath(String completionText) {
-			// TODO Auto-generated method stub
-			return null;
-		}
-
-		@Override
-		public String createParameterJsonSchema() {
-			// TODO Auto-generated method stub
-			return null;
-		}
-	}
-	
-	class ProducerConsumerSplitterEndpointConfig implements EndpointConfiguration{
-
-		HashMap<String, Object> params = new HashMap<String, Object>();
-		String uri;
-		
-		public ProducerConsumerSplitterEndpointConfig(String uri) {
-			this.uri = uri;
-		}
-		
-		@Override
-		public URI getURI() {
-			return URI.create(uri);
-		}
-
-		@Override
-		public <T> T getParameter(String name) throws RuntimeCamelException {
-			return (T) params.get(name);
-		}
-
-		@Override
-		public <T> void setParameter(String name, T value)
-				throws RuntimeCamelException {
-			params.put(name, value);
-		}
-
-		@Override
-		public String toUriString(UriFormat format) {
-			return null;
-		}
-		
-	}
-
-}
diff --git a/src/main/java/info/kwarc/sally4/client/utils/ProducerConsumerSplitterComponentConfiguration.java b/src/main/java/info/kwarc/sally4/client/utils/ProducerConsumerSplitterComponentConfiguration.java
deleted file mode 100644
index e524aae..0000000
--- a/src/main/java/info/kwarc/sally4/client/utils/ProducerConsumerSplitterComponentConfiguration.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package info.kwarc.sally4.client.utils;
-
-public class ProducerConsumerSplitterComponentConfiguration {
-
-}
diff --git a/src/main/java/info/kwarc/sally4/client/utils/ProducerConsumerSplitterEndpoint.java b/src/main/java/info/kwarc/sally4/client/utils/ProducerConsumerSplitterEndpoint.java
deleted file mode 100644
index 2600a8d..0000000
--- a/src/main/java/info/kwarc/sally4/client/utils/ProducerConsumerSplitterEndpoint.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package info.kwarc.sally4.client.utils;
-
-import java.net.URI;
-import java.util.Map;
-
-import org.apache.camel.CamelContext;
-import org.apache.camel.Component;
-import org.apache.camel.Consumer;
-import org.apache.camel.Endpoint;
-import org.apache.camel.EndpointConfiguration;
-import org.apache.camel.Exchange;
-import org.apache.camel.ExchangePattern;
-import org.apache.camel.PollingConsumer;
-import org.apache.camel.Processor;
-import org.apache.camel.Producer;
-import org.apache.camel.util.URISupport;
-
-public class ProducerConsumerSplitterEndpoint  implements Endpoint {
-	String endPoint;
-	Component comp;
-	CamelContext context;
-	Endpoint alexProducer;
-	Endpoint alexConsumer;
-	
-	String producerPrefix;
-	String consumerPrefix;
-
-	ProducerConsumerSplitterEndpoint(String endPoint, Component comp, String producerPrefix, String consumerPrefix) {
-		this.endPoint = endPoint;
-		this.comp = comp;
-		this.context = comp.getCamelContext();
-		
-		this.producerPrefix = producerPrefix;
-		this.consumerPrefix = consumerPrefix;
-	}
-
-	public boolean isSingleton() {
-		return false;
-	}
-
-	public void start() throws Exception {
-		Map<String, Object> defaultConsumer = URISupport.parseParameters(URI.create(consumerPrefix));
-		Map<String, Object> defaultProducer = URISupport.parseParameters(URI.create(producerPrefix));
-		
-		Map<String, Object> params = URISupport.parseParameters(URI.create(endPoint));
-		
-		defaultConsumer.putAll(params);
-		defaultProducer.putAll(params);
-		
-		URI consumerURI = URISupport.createRemainingURI(URI.create(consumerPrefix), defaultConsumer);
-		URI producerURI = URISupport.createRemainingURI(URI.create(producerPrefix), defaultProducer);
-		
-		alexConsumer = getCamelContext().getEndpoint(consumerURI.toString());
-		alexProducer = getCamelContext().getEndpoint(producerURI.toString());
-		alexConsumer.start();
-		alexProducer.start();
-	}
-
-	public void stop() throws Exception {
-		alexConsumer.stop();
-		alexProducer.stop();
-	}
-
-	public String getEndpointUri() {
-		return endPoint;
-	}
-
-	public EndpointConfiguration getEndpointConfiguration() {
-		return null;
-	}
-
-	public String getEndpointKey() {
-		return "alex";
-	}
-
-	public Exchange createExchange() {
-		return alexConsumer.createExchange();
-	}
-
-	public Exchange createExchange(ExchangePattern pattern) {
-		return alexConsumer.createExchange(pattern);
-	}
-
-	@Deprecated
-	public Exchange createExchange(Exchange exchange) {
-		return alexConsumer.createExchange(exchange);
-	}
-
-	public CamelContext getCamelContext() {
-		return comp.getCamelContext();
-	}
-
-	public Producer createProducer() throws Exception {
-		return alexProducer.createProducer();
-	}
-
-	public Consumer createConsumer(Processor processor) throws Exception {
-		return alexConsumer.createConsumer(processor);
-	}
-
-	public PollingConsumer createPollingConsumer() throws Exception {
-		return alexConsumer.createPollingConsumer();
-	}
-
-	public void configureProperties(Map<String, Object> options) {
-
-	}
-
-	public void setCamelContext(CamelContext context) {
-		this.context = context;
-	}
-
-	public boolean isLenientProperties() {
-		return false;
-	}
-
-
-}
diff --git a/src/main/java/info/kwarc/sally4/client/utils/XMLMessageType.java b/src/main/java/info/kwarc/sally4/client/utils/XMLMessageType.java
deleted file mode 100644
index 2939dd8..0000000
--- a/src/main/java/info/kwarc/sally4/client/utils/XMLMessageType.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package info.kwarc.sally4.client.utils;
-
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.camel.Exchange;
-import org.apache.camel.Predicate;
-
-public class XMLMessageType implements Predicate {
-	String msgName;
-	public final static Pattern xmlNamespace = Pattern.compile("<((\\w+):)?(\\w+)\\s+xmlns(:(\\w+))?=\"([\\w/:.]+)\"/?>");
-
-	public XMLMessageType(String msgName) {
-		this.msgName = msgName;
-	}
-	
-	public boolean matches(String body) {
-		Matcher m = xmlNamespace.matcher(body);
-		if (m.find()) {
-			String msgType = m.group(3);
-			return msgName.equals(msgType);
-		}
-		return false;		
-	}
-	
-	public boolean matches(Exchange exchange) {
-		String msg = exchange.getIn().getBody(String.class);
-		return matches(msg);
-	}
-	
-
-	
-}
-- 
GitLab