2ronwalf/*
2ronwalf * Created on Sep 9, 2005
2ronwalf */
2ronwalf
2ronwalfpackage examples;
2ronwalfimport java.net.URI;
2ronwalf
2ronwalfimport org.mindswap.owl.EntityFactory;
2ronwalfimport org.mindswap.owl.OWLClass;
2ronwalfimport org.mindswap.owl.OWLDataProperty;
2ronwalfimport org.mindswap.owl.OWLDataType;
2ronwalfimport org.mindswap.owl.OWLFactory;
2ronwalfimport org.mindswap.owl.OWLIndividual;
2ronwalfimport org.mindswap.owl.OWLKnowledgeBase;
2ronwalfimport org.mindswap.owl.OWLOntology;
2ronwalfimport org.mindswap.owl.vocabulary.XSD;
2ronwalfimport org.mindswap.owls.OWLSFactory;
2ronwalfimport org.mindswap.owls.grounding.Grounding;
2ronwalfimport org.mindswap.owls.process.AtomicProcess;
2ronwalfimport org.mindswap.owls.process.CompositeProcess;
2ronwalfimport org.mindswap.owls.process.Condition;
2ronwalfimport org.mindswap.owls.process.IfThenElse;
2ronwalfimport org.mindswap.owls.process.Input;
2ronwalfimport org.mindswap.owls.process.Local;
2ronwalfimport org.mindswap.owls.process.Output;
2ronwalfimport org.mindswap.owls.process.Perform;
2ronwalfimport org.mindswap.owls.process.Process;
2ronwalfimport org.mindswap.owls.process.ProcessList;
2ronwalfimport org.mindswap.owls.process.Produce;
2ronwalfimport org.mindswap.owls.process.Result;
2ronwalfimport org.mindswap.owls.process.Sequence;
2ronwalfimport org.mindswap.owls.process.SplitJoin;
2ronwalfimport org.mindswap.owls.process.ValueData;
2ronwalfimport org.mindswap.owls.process.execution.ProcessExecutionEngine;
2ronwalfimport org.mindswap.owls.process.execution.SimpleProcessMonitor;
2ronwalfimport org.mindswap.owls.profile.Profile;
2ronwalfimport org.mindswap.owls.service.Service;
2ronwalfimport org.mindswap.query.ValueMap;
2ronwalfimport org.mindswap.swrl.Atom;
2ronwalfimport org.mindswap.swrl.AtomList;
2ronwalfimport org.mindswap.swrl.SWRLDataObject;
2ronwalfimport org.mindswap.swrl.SWRLFactory;
2ronwalfimport org.mindswap.swrl.SWRLFactoryCreator;
2ronwalfimport org.mindswap.utils.URIUtils;
2ronwalf
2ronwalf/**
2ronwalf * <p>
2ronwalf * This example shows how to create a complex process model that is shown in the file
2ronwalf * <a href="http://www.mindswap.org/2004/owl-s/1.1/FindCheaperBook.owl">FindCheaperBook.owl
2ronwalf * </a>. The process model contains a sequence that starts with a service that gets the
2ronwalf * price for a given book title, then has a SplitJoin to get the book price from Amazon and
2ronwalf * Barnes&Nobles concurrently, and as a last step has an If-Then-Else construct to compare
2ronwalf * the prices and return the cheaper book price.
2ronwalf *
2ronwalf * @author Evren Sirin
2ronwalf *
2ronwalf */
2ronwalfpublic class CreateComplexProcess {
2ronwalf public static final URI baseURI = URI.create( "http://www.example.org/FindCheaperBook.owl#" );
2ronwalf public static final URI concepts = URI.create( "http://www.mindswap.org/2004/owl-s/concepts.owl#" );
2ronwalf
2ronwalf // knowledge base we are going to use
2ronwalf OWLKnowledgeBase kb;
2ronwalf
2ronwalf // ontology where service descirption is saved
2ronwalf OWLOntology ont;
2ronwalf
2ronwalf // swrl factory to create consitions and expressions
2ronwalf SWRLFactory swrl;
2ronwalf
2ronwalf // processes we will use
2ronwalf Process BookFinder;
2ronwalf Process BNPrice;
2ronwalf Process AmazonPrice;
2ronwalf
2ronwalf // commonly used classes, properties, datatypes
2ronwalf OWLDataType xsdString;
2ronwalf OWLDataType xsdFloat;
2ronwalf OWLClass Price;
2ronwalf OWLDataProperty amount;
2ronwalf
2ronwalf // the process we create to do the comparison
2ronwalf CompositeProcess ComparePricesProcess;
2ronwalf
2ronwalf // the inputs of the comparison process
2ronwalf Input CP_AmazonPrice;
2ronwalf Input CP_BNPrice;
2ronwalf
2ronwalf // the outputs of the comparison process
2ronwalf Output CP_Bookstore;
2ronwalf Output CP_OutputPrice;
2ronwalf
2ronwalf public CreateComplexProcess() {
2ronwalf }
2ronwalf
2ronwalf private URI uri( String localName ) {
2ronwalf return URIUtils.createURI( baseURI, localName );
2ronwalf }
2ronwalf
2ronwalf private Service createService() throws Exception {
2ronwalf Service service = ont.createService( uri( "TestService" ) );
2ronwalf
2ronwalf CompositeProcess process = createProcess();
2ronwalf Profile profile = createProfile( process );
2ronwalf Grounding grounding = createGrounding( process );
2ronwalf
2ronwalf service.setProfile( profile );
2ronwalf service.setProcess( process );
2ronwalf service.setGrounding( grounding );
2ronwalf
2ronwalf return service;
2ronwalf }
2ronwalf
2ronwalf private Profile createProfile( Process process ) {
2ronwalf Profile profile = ont.createProfile( uri( "TestProfile" ) );
2ronwalf
2ronwalf profile.setLabel( "Cheaper Book Finder" );
2ronwalf profile.setTextDescription(
2ronwalf "Find the price of book in Amazon and Barnes & Nobles " +
2ronwalf "and return the cheaper price" );
2ronwalf
2ronwalf for(int i = 0; i < process.getInputs().size(); i++) {
2ronwalf Input input = process.getInputs().inputAt( i );
2ronwalf
2ronwalf profile.addInput( input );
2ronwalf }
2ronwalf
2ronwalf for(int i = 0; i < process.getOutputs().size(); i++) {
2ronwalf Output output = process.getOutputs().outputAt( i );
2ronwalf
2ronwalf profile.addOutput( output );
2ronwalf }
2ronwalf
2ronwalf return profile;
2ronwalf }
2ronwalf
2ronwalf private Grounding createGrounding( CompositeProcess process ) {
2ronwalf Grounding grounding = ont.createGrounding( uri( "TestGrounding" ) );
2ronwalf
2ronwalf ProcessList list = process.getComposedOf().getAllProcesses();
2ronwalf for(int i = 0; i < list.size(); i++) {
2ronwalf Process pc = list.processAt( i );
2ronwalf if( pc instanceof AtomicProcess ) {
2ronwalf grounding.addGrounding( ((AtomicProcess) pc).getGrounding() );
2ronwalf }
2ronwalf }
2ronwalf
2ronwalf return grounding;
2ronwalf }
2ronwalf
2ronwalf private CompositeProcess createProcess() {
2ronwalf // create the composite process
2ronwalf CompositeProcess process = ont.createCompositeProcess( uri( "TestProcess") );
2ronwalf
2ronwalf // Create an input that has parameterType xsd:string
2ronwalf Input inputBookName = process.createInput( uri( "BookName" ), xsdString );
2ronwalf
2ronwalf // Create an output that has parameterType xsd:string
2ronwalf Output outputBookstore = process.createOutput( uri( "Bookstore" ), xsdString );
2ronwalf
2ronwalf // Create an output that has parameterType concepts:Price
2ronwalf Output outputBookPrice = process.createOutput( uri( "BookPrice" ), Price );
2ronwalf
2ronwalf // process is composed of a sequence
2ronwalf Sequence sequence = ont.createSequence();
2ronwalf process.setComposedOf(sequence);
2ronwalf
2ronwalf // first element of the sequence is a simple perform
2ronwalf Perform FindBookInfo = ont.createPerform( uri( "FindBookInfo" ) );
2ronwalf FindBookInfo.setProcess( BookFinder );
2ronwalf // the input of the perform is coming from the parent perform
2ronwalf FindBookInfo.addBinding( BookFinder.getInput(), Perform.TheParentPerform, inputBookName );
2ronwalf
2ronwalf // add thid perform as the first element of the sequence
2ronwalf sequence.addComponent( FindBookInfo );
2ronwalf
2ronwalf // second element of the sequence is a Split-Join that has to performs in it
2ronwalf SplitJoin split = ont.createSplitJoin();
2ronwalf
2ronwalf // first perform AmazonPrice
2ronwalf Perform FindAmazonPrice = ont.createPerform( uri( "FindAmazonPrice" ) );
2ronwalf FindAmazonPrice.setProcess( AmazonPrice );
2ronwalf // the input of the perform is coming from FindBookInfo perform
2ronwalf FindAmazonPrice.addBinding( AmazonPrice.getInput(), FindBookInfo, BookFinder.getOutput() );
2ronwalf // add it to the split-join
2ronwalf split.addComponent( FindAmazonPrice );
2ronwalf
2ronwalf // then similarly perform BNPrice
2ronwalf Perform FindBNPrice = ont.createPerform( uri( "FindBNPrice" ) );
2ronwalf FindBNPrice.setProcess( BNPrice );
2ronwalf // the input of the perform is coming from FindBookInfo perform
2ronwalf FindBNPrice.addBinding( BNPrice.getInput(), FindBookInfo, BookFinder.getOutput() );
2ronwalf // add it to the split-join
2ronwalf split.addComponent( FindBNPrice );
2ronwalf
2ronwalf // finally add the Split-Join to the sequence
2ronwalf sequence.addComponent( split );
2ronwalf
2ronwalf CompositeProcess ComparePricesProcess = createComparePricesProcess();
2ronwalf Perform ComparePrices = ont.createPerform( uri( "ComparePrices" ) );
2ronwalf ComparePrices.setProcess( ComparePricesProcess );
2ronwalf // feed the input from book previous performs to the comparison process
2ronwalf ComparePrices.addBinding( CP_AmazonPrice, FindAmazonPrice, AmazonPrice.getOutput() );
2ronwalf ComparePrices.addBinding( CP_BNPrice, FindBNPrice, BNPrice.getOutput() );
2ronwalf
2ronwalf // add the comparison step as the last construct in the sequence
2ronwalf sequence.addComponent( ComparePrices );
2ronwalf
2ronwalf Result result = process.createResult();
2ronwalf result.addBinding( outputBookstore, ComparePrices, CP_Bookstore );
2ronwalf result.addBinding( outputBookPrice, ComparePrices, CP_OutputPrice );
2ronwalf
2ronwalf return process;
2ronwalf }
2ronwalf
2ronwalf private CompositeProcess createComparePricesProcess() {
2ronwalf // we need a new composite process for the last step to do the
2ronwalf // comparison (we need local variables whihc can only be declared
2ronwalf // in conjunction with a process)
2ronwalf CompositeProcess ComparePricesProcess =
2ronwalf ont.createCompositeProcess( uri( "ComparePricesProcess" ) );
2ronwalf
2ronwalf // the price from two bookstores as input
2ronwalf CP_AmazonPrice = ComparePricesProcess.createInput( uri( "CP_AmazonPrice"), Price );
2ronwalf CP_BNPrice = ComparePricesProcess.createInput( uri( "CP_BNPrice"), Price );
2ronwalf
2ronwalf // the actual value for each price as locals
2ronwalf Local CP_AmazonPriceAmount = ComparePricesProcess.createLocal( uri( "CP_AmazonPriceAmount"), xsdFloat );
2ronwalf Local CP_BNPriceAmount = ComparePricesProcess.createLocal( uri( "CP_BNPriceAmount"), xsdFloat );
2ronwalf
2ronwalf // the minimum price and the associated bookstore as outputs
2ronwalf CP_OutputPrice = ComparePricesProcess.createOutput( uri( "CP_OutputPrice"), Price );
2ronwalf CP_Bookstore = ComparePricesProcess.createOutput( uri( "CP_Bookstore"), xsdString );
2ronwalf
2ronwalf // the first precondition is just to bind the value of concepts:amount property
2ronwalf // to the local variable for AmazonPrice
2ronwalf Condition precondition1 = ont.createSWRLCondition();
2ronwalf Atom atom1 = swrl.createDataPropertyAtom( amount, CP_AmazonPrice, CP_AmazonPriceAmount );
2ronwalf AtomList list1 = swrl.createList( atom1 );
2ronwalf precondition1.setBody( list1 );
2ronwalf ComparePricesProcess.addCondition( precondition1 );
2ronwalf
2ronwalf // exactly same as the previous one but for BNPrice. note that we could have
2ronwalf // equivalently create one precondition and add two atoms in it. the operational
2ronwalf // semantics would be same because multiple preconditions are simply conjuncted
2ronwalf Condition precondition2 = ont.createSWRLCondition();
2ronwalf Atom atom2 = swrl.createDataPropertyAtom( amount, CP_BNPrice, CP_BNPriceAmount );
2ronwalf AtomList list2 = swrl.createList( atom2 );
2ronwalf precondition2.setBody( list2 );
2ronwalf ComparePricesProcess.addCondition( precondition2 );
2ronwalf
2ronwalf // ComparePricesProcess is simply one If-Then-Else
2ronwalf IfThenElse ifThenElse = ont.createIfThenElse();
2ronwalf ComparePricesProcess.setComposedOf( ifThenElse );
2ronwalf
2ronwalf // now the condition for If-Then-Else to compare values
2ronwalf Condition condition = ont.createSWRLCondition();
2ronwalf Atom atom = swrl.createLessThan(
2ronwalf (SWRLDataObject) CP_BNPriceAmount.castTo(SWRLDataObject.class),
2ronwalf (SWRLDataObject) CP_AmazonPriceAmount.castTo(SWRLDataObject.class));
2ronwalf AtomList list = swrl.createList( atom );
2ronwalf condition.setBody( list );
2ronwalf
2ronwalf // set the condition
2ronwalf ifThenElse.setCondition( condition );
2ronwalf
2ronwalf // create two produce constructs to generate the results
2ronwalf ifThenElse.setThen( createProduceSequence( "BN", CP_BNPrice ) );
2ronwalf ifThenElse.setElse( createProduceSequence( "Amazon", CP_AmazonPrice ) );
2ronwalf
2ronwalf return ComparePricesProcess;
2ronwalf }
2ronwalf
2ronwalf private Sequence createProduceSequence( String bookstore, Input price ) {
2ronwalf // the produce construct to produce the price
2ronwalf Produce producePrice = ont.createProduce( uri( "Produce" + bookstore + "Price" ) );
2ronwalf // we directly pass the input value from the parent process as output to the parent process
2ronwalf producePrice.addBinding( CP_OutputPrice, Perform.TheParentPerform, price );
2ronwalf
2ronwalf // the produce construct to produce the name
2ronwalf Produce produceName = ont.createProduce( uri( "Produce" + bookstore + "Name" ) );
2ronwalf // we need a constant string value to produce so use process:ValueData
2ronwalf ValueData valueData = ont.createValueData( ont.createDataValue( bookstore ) );
2ronwalf // add the binding for this output
2ronwalf produceName.addBinding( CP_Bookstore, valueData);
2ronwalf
2ronwalf // now add both produce into this sequence
2ronwalf Sequence sequence = ont.createSequence();
2ronwalf sequence.addComponent( producePrice );
2ronwalf sequence.addComponent( produceName );
2ronwalf
2ronwalf return sequence;
2ronwalf }
2ronwalf
2ronwalf public void run() throws Exception {
2ronwalf // create an OWL-S knowledge base
2ronwalf kb = OWLFactory.createKB();
2ronwalf
2ronwalf // create an empty ontology in this KB
2ronwalf ont = kb.createOntology();
2ronwalf
2ronwalf // create SWRLFactory we will use for creating conditions and expressions
2ronwalf swrl = SWRLFactoryCreator.createFactory();
2ronwalf
2ronwalf // load three OWL-S files and directly get the processes we want
2ronwalf BookFinder = kb.readService("http://www.mindswap.org/2004/owl-s/1.1/BookFinder.owl#").getProcess();
2ronwalf BNPrice = kb.readService("http://www.mindswap.org/2004/owl-s/1.1/BNPrice.owl#").getProcess();
2ronwalf AmazonPrice = kb.readService("http://www.mindswap.org/2004/owl-s/1.1/AmazonBookPrice.owl#").getProcess();
2ronwalf
2ronwalf // also add the imports statement
2ronwalf ont.addImport( BookFinder.getOntology() );
2ronwalf ont.addImport( BNPrice.getOntology() );
2ronwalf ont.addImport( AmazonPrice.getOntology() );
2ronwalf
2ronwalf // get common classes, properties and datatypes we will need
2ronwalf xsdString = kb.getDataType( XSD.string );
2ronwalf xsdFloat = kb.getDataType( XSD.xsdFloat );
2ronwalf Price = kb.getClass( URIUtils.createURI( concepts, "Price" ) );
2ronwalf amount = kb.getDataProperty( URIUtils.createURI( concepts, "amount" ) );
2ronwalf
2ronwalf // create the service
2ronwalf Service s = createService();
2ronwalf
2ronwalf // print the description of new service to standard output
2ronwalf ont.write( System.out, baseURI );
2ronwalf System.out.println();
2ronwalf
2ronwalf // create an execution engine
2ronwalf ProcessExecutionEngine exec = OWLSFactory.createExecutionEngine();
2ronwalf
2ronwalf exec.addMonitor( new SimpleProcessMonitor() );
2ronwalf
2ronwalf // get the process of the new service
2ronwalf Process process = s.getProcess();
2ronwalf // initialize the input values to be empty
2ronwalf ValueMap values = new ValueMap();
2ronwalf // get the parameter using the local name
2ronwalf values.setValue( process.getInput(),
2ronwalf EntityFactory.createDataValue( "City of Glass" ) );
2ronwalf
2ronwalf // execute the service
2ronwalf values = exec.execute( process, values );
2ronwalf
2ronwalf // get the output param using the index
2ronwalf String bookstore = values.getStringValue( process.getOutput( "Bookstore" ) );
2ronwalf OWLIndividual price = values.getIndividualValue( process.getOutput( "BookPrice" ) );
2ronwalf
2ronwalf // display the result
2ronwalf System.out.println( "Cheaper price found in " + bookstore );
2ronwalf System.out.println( "Price is $" + price.getProperty( amount ));
2ronwalf System.out.println();
2ronwalf }
2ronwalf
2ronwalf public static void main( String[] args ) throws Exception {
2ronwalf CreateComplexProcess test = new CreateComplexProcess();
2ronwalf test.run();
2ronwalf }
2ronwalf}