package owlapi;

import java.io.File;
import java.net.URI;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.LinkedList;
import java.util.Queue;

import javax.xml.bind.DatatypeConverter;

import org.junit.Before;
import org.junit.Test;
import org.semanticweb.owl.apibinding.OWLManager;
import org.semanticweb.owl.io.RDFXMLOntologyFormat;
import org.semanticweb.owl.model.AddAxiom;
import org.semanticweb.owl.model.OWLAxiom;
import org.semanticweb.owl.model.OWLClass;
import org.semanticweb.owl.model.OWLConstant;
import org.semanticweb.owl.model.OWLDataFactory;
import org.semanticweb.owl.model.OWLDataProperty;
import org.semanticweb.owl.model.OWLDataPropertyAssertionAxiom;
import org.semanticweb.owl.model.OWLDataType;
import org.semanticweb.owl.model.OWLIndividual;
import org.semanticweb.owl.model.OWLObjectProperty;
import org.semanticweb.owl.model.OWLObjectPropertyAssertionAxiom;
import org.semanticweb.owl.model.OWLOntology;
import org.semanticweb.owl.model.OWLOntologyManager;
import org.semanticweb.owl.util.SimpleURIMapper;



public class Test1OwlApi {
	
	private OWLOntologyManager manager = null;
	
	private OWLOntology ontology = null;
	
	final static int maxStones = 2000;
	
	final String ontoURI = "http://www.yoshtec.com/ontology/test/Bucket";
		
	private OWLDataFactory factory = null;
	
	
	private OWLDataType xsdString = null;
	private OWLDataType xsdDateTime = null;
	private OWLDataType xsdInt = null;
	
	
	@Before
	public void setUp() throws Exception {
		// get Singleton Manager
		manager = OWLManager.createOWLOntologyManager();
		
		// create physical URI to load the ontology from
		URI physicalURI = (new File("bucket.owl")).toURI();
		
		// Set up a mapping, which maps the ontology URI to the physical URI
		SimpleURIMapper mapper = new SimpleURIMapper(URI.create(ontoURI), physicalURI);
		manager.addURIMapper(mapper);
		
		// create Ontology
		ontology = manager.loadOntologyFromPhysicalURI(physicalURI);
		//ontology = manager.createOntology(URI.create(ontoURI));
		
		// create a Factory for our Datatypes
		factory = manager.getOWLDataFactory();
		
		// build some often needed Datatypes
		xsdString = factory.getOWLDataType(URI.create("http://www.w3.org/2001/XMLSchema#string"));
		xsdDateTime = factory.getOWLDataType(URI.create("http://www.w3.org/2001/XMLSchema#dateTime"));
		xsdInt = factory.getOWLDataType(URI.create("http://www.w3.org/2001/XMLSchema#int"));
		
	}
	
	
	@Test
	public void smallBucket() throws Exception {
		
		// hold changes in the Queue as they are done
		Queue<AddAxiom> changes = new LinkedList<AddAxiom>();
		
		OWLIndividual bucket = null;
		{
			// Creating Bucket Individual
			bucket = factory.getOWLIndividual(URI.create(ontoURI + "#MyPrecious"));
			OWLClass Class = factory.getOWLClass(URI.create(ontoURI + "#Bucket"));
			OWLAxiom bucketaxiom = factory.getOWLClassAssertionAxiom(bucket, Class);
			changes.add(new AddAxiom(ontology, bucketaxiom));
		}
		
		// creating Data property
		{
			OWLDataProperty owlp = factory.getOWLDataProperty(URI.create(ontoURI + "#Engraving"));
			OWLConstant owlc = factory.getOWLTypedConstant("One to hold them All", xsdString);
			OWLDataPropertyAssertionAxiom addProp = factory.getOWLDataPropertyAssertionAxiom(bucket, owlp, owlc);
			changes.add(new AddAxiom(ontology, addProp));
		}
		
		{ // create Material Property
			OWLDataProperty owlp = factory.getOWLDataProperty(URI.create(ontoURI + "#Material"));
			OWLConstant owlc = factory.getOWLTypedConstant("Plastik", xsdString);
			OWLDataPropertyAssertionAxiom addProp = factory.getOWLDataPropertyAssertionAxiom(bucket, owlp, owlc);
			changes.add(new AddAxiom(ontology, addProp));
		}
		
		// phew a lot of code for that
		
		// so no lets create a stone
		OWLIndividual stone1 = factory.getOWLIndividual(URI.create(ontoURI + "#Pebble"));
		OWLClass owlStone = factory.getOWLClass(URI.create(ontoURI + "#Stone"));
		{
			OWLAxiom axiom = factory.getOWLClassAssertionAxiom(stone1, owlStone);
			changes.add(new AddAxiom(ontology, axiom));
		}
		
		// fill its neccessary Props
		{ // create DateFound Property
			OWLDataProperty owlp = factory.getOWLDataProperty(URI.create(ontoURI + "#DateFound"));
			Calendar cal = new GregorianCalendar();
			OWLConstant owlc = factory.getOWLTypedConstant(DatatypeConverter.printDateTime(cal) , xsdDateTime);
			OWLDataPropertyAssertionAxiom addProp = factory.getOWLDataPropertyAssertionAxiom(stone1, owlp, owlc);
			changes.add(new AddAxiom(ontology, addProp));
		}
		
		{ // create Weight Property
			OWLDataProperty owlp = factory.getOWLDataProperty(URI.create(ontoURI + "#weight"));
			OWLConstant owlc = factory.getOWLTypedConstant("20", xsdInt);
			OWLDataPropertyAssertionAxiom addProp = factory.getOWLDataPropertyAssertionAxiom(stone1, owlp, owlc);
			changes.add(new AddAxiom(ontology, addProp));
		}
		
		// so no lets create the second stone
		OWLIndividual stone2 = factory.getOWLIndividual(URI.create(ontoURI + "#Suiseki"));
		{
			OWLAxiom axiom = factory.getOWLClassAssertionAxiom(stone2, owlStone);
			changes.add(new AddAxiom(ontology, axiom));
		}
		
		// fill its neccessary Props
		{ // create DateFound Property
			OWLDataProperty owlp = factory.getOWLDataProperty(URI.create(ontoURI + "#DateFound"));
			Calendar cal = new GregorianCalendar();
			OWLConstant owlc = factory.getOWLTypedConstant(DatatypeConverter.printDateTime(cal) , xsdDateTime);
			OWLDataPropertyAssertionAxiom addProp = factory.getOWLDataPropertyAssertionAxiom(stone2, owlp, owlc);
			changes.add(new AddAxiom(ontology, addProp));
		}
		
		{ // create Weight Property
			OWLDataProperty owlp = factory.getOWLDataProperty(URI.create(ontoURI + "#weight"));
			OWLConstant owlc = factory.getOWLTypedConstant("3000", xsdInt);
			OWLDataPropertyAssertionAxiom addProp = factory.getOWLDataPropertyAssertionAxiom(stone2, owlp, owlc);
			changes.add(new AddAxiom(ontology, addProp));
		}
		
		// lets put the stones into the bucket
		
		OWLObjectProperty containsProp = factory.getOWLObjectProperty(URI.create(ontoURI + "#Contains"));
		{ // first stone 
			OWLObjectPropertyAssertionAxiom addStone = factory.getOWLObjectPropertyAssertionAxiom(bucket, containsProp, stone1);
			changes.add(new AddAxiom(ontology, addStone));
		}
		{ //second stone 
			OWLObjectPropertyAssertionAxiom addStone = factory.getOWLObjectPropertyAssertionAxiom(bucket, containsProp, stone2);
			changes.add(new AddAxiom(ontology, addStone));
		}
		
				
		// dammit the inverse props have to be filled in manually (or using a reasoner..)
		OWLObjectProperty is_in_BucketProp = factory.getOWLObjectProperty(URI.create(ontoURI + "#is_in_Bucket"));
		{ // first stone 
			OWLObjectPropertyAssertionAxiom addStone = factory.getOWLObjectPropertyAssertionAxiom(stone1, is_in_BucketProp, bucket);
			changes.add(new AddAxiom(ontology, addStone));
		}
		{ //second stone 
			OWLObjectPropertyAssertionAxiom addStone = factory.getOWLObjectPropertyAssertionAxiom(stone2, is_in_BucketProp, bucket);
			changes.add(new AddAxiom(ontology, addStone));
		}
		
		
		// apply all changes to the Model
		for (AddAxiom addAxiom : changes) {
			manager.applyChange(addAxiom);
		}
		
		
		// save the Ontology to file
		manager.saveOntology(ontology, new RDFXMLOntologyFormat(), (new File("smallbucket.owl")).toURI() );

	}
	
	@Test
	public void bigBucket() throws Exception {
						
		OWLIndividual bucket = null;
		{
			// Creating Bucket Individual
			bucket = factory.getOWLIndividual(URI.create(ontoURI + "#MyPrecious"));
			OWLClass Class = factory.getOWLClass(URI.create(ontoURI + "#Bucket"));
			OWLAxiom bucketaxiom = factory.getOWLClassAssertionAxiom(bucket, Class);
			manager.applyChange(new AddAxiom(ontology, bucketaxiom));
		}
		
		// creating Data property
		{
			OWLDataProperty owlp = factory.getOWLDataProperty(URI.create(ontoURI + "#Engraving"));
			OWLConstant owlc = factory.getOWLTypedConstant("One to hold them All", xsdString);
			OWLDataPropertyAssertionAxiom addProp = factory.getOWLDataPropertyAssertionAxiom(bucket, owlp, owlc);
			manager.applyChange(new AddAxiom(ontology, addProp));
		}
		
		{ // create Material Property
			OWLDataProperty owlp = factory.getOWLDataProperty(URI.create(ontoURI + "#Material"));
			OWLConstant owlc = factory.getOWLTypedConstant("Plastik", xsdString);
			OWLDataPropertyAssertionAxiom addProp = factory.getOWLDataPropertyAssertionAxiom(bucket, owlp, owlc);
			manager.applyChange(new AddAxiom(ontology, addProp));
		}
		
		
		// so no lets create lots of stones
		OWLClass owlStone = factory.getOWLClass(URI.create(ontoURI + "#Stone"));
		OWLDataProperty owlDateFoundProp = factory.getOWLDataProperty(URI.create(ontoURI + "#DateFound"));
		OWLDataProperty owlWeightProp = factory.getOWLDataProperty(URI.create(ontoURI + "#weight"));
		OWLObjectProperty containsProp = factory.getOWLObjectProperty(URI.create(ontoURI + "#Contains"));
		OWLObjectProperty is_in_BucketProp = factory.getOWLObjectProperty(URI.create(ontoURI + "#is_in_Bucket"));
		
		for (int i = 0; i < maxStones; i++) {
			OWLIndividual stone1 = factory.getOWLIndividual(URI.create(ontoURI + "#Pebble" + i));

			// say its a stone
			manager.applyChange(new AddAxiom(ontology, factory.getOWLClassAssertionAxiom(stone1, owlStone)));
		
			{ // Found DateTime 
				OWLConstant owlc = factory.getOWLTypedConstant(DatatypeConverter.printDateTime(new GregorianCalendar()) , xsdDateTime);
				OWLDataPropertyAssertionAxiom addProp = factory.getOWLDataPropertyAssertionAxiom(stone1, owlDateFoundProp, owlc);
				manager.applyChange(new AddAxiom(ontology, addProp));
			}
			
			{ // create Weight Property
				OWLConstant owlc = factory.getOWLTypedConstant( Integer.toString(i), xsdInt);
				OWLDataPropertyAssertionAxiom addProp = factory.getOWLDataPropertyAssertionAxiom(stone1, owlWeightProp, owlc);
				manager.applyChange(new AddAxiom(ontology, addProp));
			}
			
			// lets put the stones into the bucket
			{  
				OWLObjectPropertyAssertionAxiom addStone = factory.getOWLObjectPropertyAssertionAxiom(bucket, containsProp, stone1);
				manager.applyChange(new AddAxiom(ontology, addStone));
			}
					
			// dammit the inverse props have to be filled in manually (or using a reasoner..)
			
			{ 
				OWLObjectPropertyAssertionAxiom addStone = factory.getOWLObjectPropertyAssertionAxiom(stone1, is_in_BucketProp, bucket);
				manager.applyChange(new AddAxiom(ontology, addStone));
			}

		}
	
		
		// save the Ontology to file
		manager.saveOntology(ontology, new RDFXMLOntologyFormat(), (new File("bigbucket.owl")).toURI() );

	}
	
}

