/*
 * Copyright Aduna (http://www.aduna-software.com/) (c) 1997-2007.
 *
 * Licensed under the Aduna BSD-style license.
 */
package org.openrdf.sail.federation;

import java.io.IOException;
import java.util.Arrays;

import org.openrdf.model.Literal;
import org.openrdf.model.URI;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.RDFS;
import org.openrdf.query.BooleanQuery;
import org.openrdf.query.QueryLanguage;
import org.openrdf.repository.RDFSchemaRepositoryConnectionTest;
import org.openrdf.repository.Repository;
import org.openrdf.repository.RepositoryMetaData;
import org.openrdf.repository.base.RepositoryMetaDataWrapper;
import org.openrdf.repository.contextaware.ContextAwareConnection;
import org.openrdf.repository.sail.SailRepository;
import org.openrdf.sail.Sail;
import org.openrdf.sail.inferencer.fc.ForwardChainingRDFSInferencer;
import org.openrdf.sail.memory.MemoryStore;
import org.openrdf.store.StoreException;

public class RDFSchemaFederationRepositoryConnectionTest extends RDFSchemaRepositoryConnectionTest {

	protected URI[] writeContexts;

	protected URI[] readContexts;

	protected URI person;

	protected URI woman;

	protected URI man;

	protected URI tim;

	protected Literal nameTim;

	public RDFSchemaFederationRepositoryConnectionTest(String name) {
		super(name);
	}

	@Override
	public void setUp()
		throws Exception
	{
		super.setUp();

		person = vf.createURI(FOAF_NS + "Person");
		woman = vf.createURI("http://example.org/Woman");
		man = vf.createURI("http://example.org/Man");

		tim = vf.createURI("http://example.org/Tim");
		nameTim = vf.createLiteral("Tim");

		writeContexts = new URI[] { vf.createURI("http://example.org/") };
		readContexts = Arrays.copyOf(writeContexts, writeContexts.length + 1);
		// default context for inferred statements
		readContexts[readContexts.length - 1] = null;
	}

	public void testSubClassInferenceNegative()
		throws Exception
	{
		testCon.begin();
		testCon.add(woman, RDFS.SUBCLASSOF, person, writeContexts);
		testCon.add(man, RDFS.SUBCLASSOF, person, writeContexts);
		testCon.add(alice, RDF.TYPE, woman, writeContexts);
		testCon.commit();

		ContextAwareConnection contextConn = new ContextAwareConnection(testRepository, testCon);
		contextConn.setAddContexts(writeContexts);
		contextConn.setReadContexts(readContexts);

		BooleanQuery query = contextConn.prepareBooleanQuery(QueryLanguage.SPARQL, "ASK {?alice a ?person}");
		query.setBinding("alice", alice);
		query.setBinding("person", person);
		query.setIncludeInferred(false);

		assertFalse(query.evaluate().asBoolean());
	}

	@Override
	protected Repository createRepository()
		throws IOException
	{
		Federation sail = new Federation();
		sail.addMember(new SailRepository(new ForwardChainingRDFSInferencer(new MemoryStore())));
		sail.addMember(createReadOnlyRepository(new MemoryStore()));
		sail.addMember(createReadOnlyRepository(new MemoryStore()));
		return new SailRepository(sail);
	}

	private SailRepository createReadOnlyRepository(Sail sail) {
		return new SailRepository(sail) {

			RepositoryMetaData metaData;

			@Override
			public RepositoryMetaData getMetaData()
				throws StoreException
			{
				if (metaData == null) {
					metaData = new RepositoryMetaDataWrapper(super.getMetaData()) {

						@Override
						public boolean isReadOnly() {
							return true;
						}
					};
				}
				return metaData;
			}
		};
	}

	public void testInferencerTransactionIsolation()
		throws Exception
	{
		testCon.begin();
		testCon.add(tim, name, nameTim);

		assertTrue(testCon.hasMatch(tim, RDF.TYPE, RDFS.RESOURCE, true));
		assertFalse(testCon2.hasMatch(tim, RDF.TYPE, RDFS.RESOURCE, true));

		testCon.commit();

		assertTrue(testCon.hasMatch(tim, RDF.TYPE, RDFS.RESOURCE, true));
		assertTrue(testCon2.hasMatch(tim, RDF.TYPE, RDFS.RESOURCE, true));
	}
}

