package org.aktin.broker.query.sql;

import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.SQLException;
import java.time.Instant;
import java.util.Objects;
import java.util.function.Function;

import javax.sql.DataSource;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;

import org.aktin.broker.query.QueryHandlerFactory;
import org.w3c.dom.Element;

// TODO add qualifier annotation

public class SQLHandlerFactory implements QueryHandlerFactory{
	private DataSource ds;
	private Charset exportCharset;

	public SQLHandlerFactory() {
		this.exportCharset = StandardCharsets.UTF_8;
	}
	public SQLHandlerFactory(DataSource database) {
		this();
		this.ds = database;
	}
	

	public void setDataSource(DataSource database){
		this.ds = database;
	}
	public Charset getExportCharset(){
		return exportCharset;
	}

	Connection openConnection() throws SQLException{
		Objects.requireNonNull(ds, "datasource not set");
		return ds.getConnection();
	}
	@Override
	public String getElementName() {
		return SQLQuery.XML_ELEMENT;
	}

	@Override
	public String getNamespace() {
		return SQLQuery.XML_NAMESPACE;
	}

	@Override
	public SQLHandler parse(Element element, Function<String,String> propertyLookup) {
		SQLQuery q;
		try {
			JAXBContext c = JAXBContext.newInstance(SQLQuery.class);
			q = (SQLQuery)c.createUnmarshaller().unmarshal(element);
		} catch (JAXBException e) {
			throw new IllegalArgumentException("Unable to parse query XML", e);
		}
		return wrap(q, propertyLookup);
	}

	public SQLHandler wrap(SQLQuery query, Function<String,String> propertyLookup){
		return new SQLHandler(this, query, propertyLookup);
	}
	@Override
	public String formatTimestamp(Instant timestamp) {
		return timestamp.toString();
	}

}

@@ -189,16 +189,59 @@
 nstant;%0A
+import java.time.format.DateTimeFormatter;%0A
 import j
@@ -511,16 +511,73 @@
 tation%0A%0A
+/**%0A * SQL Handler factory.%0A * @author R.W.Majeed%0A *%0A */%0A
 public c
@@ -686,16 +686,56 @@
 Charset;
+%0A%09private DateTimeFormatter formatter;%0A%09
 %0A%0A%09publi
@@ -805,16 +805,66 @@
 .UTF_8;%0A
+%09%09this.formatter = DateTimeFormatter.ISO_INSTANT;%0A
 %09%7D%0A%09publ
@@ -942,18 +942,114 @@
 ase;%0A%09%7D%0A
-%09
 %0A
+%0A%09/**%0A%09 * Set the data source used for executing SQL queries%0A%09 * @param database data source%0A%09 */
 %0A%09public
@@ -1179,16 +1179,370 @@
 et;%0A%09%7D%0A%0A
+%09/**%0A%09 * Set the formatter used to format timestamps for the SQL execution. Some SQL%0A%09 * dialects require specific date time formats. Defaults to%0A%09 * %7B@code DateTimeFormatter.ISO_INSTANT%7D if this method is never called.%0A%09 * @param formatter formatter%0A%09 */%0A%09public void setDateTimeFormatter(DateTimeFormatter formatter) %7B%0A%09%09this.formatter = formatter;%0A%09%7D%0A
 %09Connect
@@ -2421,27 +2421,34 @@
 urn 
-timestamp.toString(
+formatter.format(timestamp
 );%0A%09

allow configuration of timestamp format, documentation