package org.callimachusproject.rewrite;

import junit.framework.TestCase;

import org.apache.http.HttpResponse;
import org.callimachusproject.annotations.alternate;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openrdf.annotations.Iri;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.RDFS;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.object.ObjectConnection;
import org.openrdf.repository.object.ObjectRepository;
import org.openrdf.repository.object.config.ObjectRepositoryConfig;
import org.openrdf.repository.object.config.ObjectRepositoryFactory;
import org.openrdf.repository.sail.SailRepository;
import org.openrdf.sail.memory.MemoryStore;

public class RedirectTest extends TestCase {

	@Iri("http://example.com/Concept")
	public interface Concept {
		@alternate("http://example.com/")
		HttpResponse literal();

		@alternate("^http://(.*).example.com/(.*) http://example.com/$1/$2")
		HttpResponse readDomain();

		@alternate("$0#{frag}")
		HttpResponse frag(@Iri("urn:test:frag") String frag);

		@alternate("$0?{query}")
		HttpResponse replaceQuery(@Iri("urn:test:query") String query);

		@alternate("$0?param={value}")
		HttpResponse param(@Iri("urn:test:value") String value);

		@alternate("$0?param=http%3A%2F%2Fexample.com%2Fq%3D{value}")
		HttpResponse doubleParam(@Iri("urn:test:value") String value);
	}

	private Repository repository;
	private ObjectRepositoryConfig config = new ObjectRepositoryConfig();
	private ObjectConnection con;
	private Concept concept;

	private Repository createRepository() throws Exception {
		return new SailRepository(new MemoryStore());
	}

	private ObjectRepository getRepository() throws Exception {
		Repository repository = createRepository();
		repository.initialize();
		RepositoryConnection con = repository.getConnection();
		try {
			con.setAutoCommit(false);
			con.clear();
			con.clearNamespaces();
			con.setNamespace("test", "urn:test:");
			con.setAutoCommit(true);
		} finally {
			con.close();
		}
		ObjectRepositoryFactory factory = new ObjectRepositoryFactory();
		return factory.createRepository(config, repository);
	}

	@Before
	public void setUp() throws Exception {
		config.addConcept(Concept.class);
		repository = getRepository();
		con = (ObjectConnection) repository.getConnection();
		con.setAutoCommit(false);
		con.setNamespace("rdf", RDF.NAMESPACE);
		con.setNamespace("rdfs", RDFS.NAMESPACE);
		con.setAutoCommit(true);
	}

	@After
	public void tearDown() throws Exception {
		try {
			if (con.isOpen()) {
				con.close();
			}
			repository.shutDown();
		} catch (Exception e) {
		}
	}

	@Test
	public void testLiteral() throws Exception {
		concept = con.addDesignation(con.getObject("urn:test:concept"),
				Concept.class);
		assertEquals("http://example.com/", concept.literal().getFirstHeader("Location").getValue());
	}

	@Test
	public void testSubsitution() throws Exception {
		concept = con.addDesignation(con.getObject("http://www.example.com/pathinfo"),
				Concept.class);
		assertEquals("http://www.example.com/pathinfo#sub", concept.frag("sub").getFirstHeader("Location").getValue());
	}

	@Test
	public void testDomain() throws Exception {
		concept = con.addDesignation(con.getObject("http://www.example.com/pathinfo"),
				Concept.class);
		assertEquals("http://example.com/www/pathinfo", concept.readDomain().getFirstHeader("Location").getValue());
	}

	@Test
	public void testQueryString() throws Exception {
		concept = con.addDesignation(con.getObject("http://www.example.com/pathinfo"),
				Concept.class);
		assertEquals("http://www.example.com/pathinfo?qs", concept.replaceQuery("qs").getFirstHeader("Location").getValue());
	}

	@Test
	public void testQueryParameter() throws Exception {
		concept = con.addDesignation(con.getObject("http://www.example.com/pathinfo"),
				Concept.class);
		assertEquals("http://www.example.com/pathinfo?param=foo+bar", concept.param("foo bar").getFirstHeader("Location").getValue());
	}

	@Test
	public void testDoubleQueryParameter() throws Exception {
		concept = con.addDesignation(con.getObject("http://www.example.com/pathinfo"),
				Concept.class);
		assertEquals("http://www.example.com/pathinfo?param=http%3A%2F%2Fexample.com%2Fq%3Dfoo%2Bbar", concept.doubleParam("foo bar").getFirstHeader("Location").getValue());
	}

}

@@ -30,24 +30,46 @@
 t.rewrite;%0A%0A
+import java.net.URI;%0A%0A
 import junit
@@ -1476,24 +1476,116 @@
 ring value);
+%0A%0A%09%09@alternate(%22%7Bvalue%7D%22)%0A%09%09HttpResponse resolve(@Iri(%22urn:test:value%22) java.net.URI value);
 %0A%09%7D%0A%0A%09privat
@@ -4527,10 +4527,325 @@
 ));%0A%09%7D%0A%0A
+%09@Test%0A%09public void testQueryParameterURIEncoding() throws Exception %7B%0A%09%09concept = con.addDesignation(con.getObject(%22http://www.example.com/pathinfo%22),%0A%09%09%09%09Concept.class);%0A%09%09assertEquals(%22http://example.com/%25E2%259C%2593%22, concept.resolve(URI.create(%22http://example.com/%E2%9C%93%22)).getFirstHeader(%22Location%22).getValue());%0A%09%7D%0A%0A
 %7D%0A

Test that URI query string parameters are encoded correctly