<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html> <head profile="http://internetalchemy.org/2003/02/profile"> <link rel="foaf" type="application/rdf+xml" title="FOAF" href="http://www.openlinksw.com/dataspace/uda/about.rdf" /> <link rel="schema.dc" href="http://purl.org/dc/elements/1.1/" /> <meta name="dc.title" content="2. Installation Guide" /> <meta name="dc.subject" content="2. Installation Guide" /> <meta name="dc.creator" content="OpenLink Software Documentation Team ; " /> <meta name="dc.copyright" content="OpenLink Software, 1999 - 2009" /> <link rel="top" href="index.html" title="OpenLink Virtuoso Universal Server: Documentation" /> <link rel="search" href="/doc/adv_search.vspx" title="Search OpenLink Virtuoso Universal Server: Documentation" /> <link rel="parent" href="installation.html" title="Chapter Contents" /> <link rel="prev" href="installusado.html" title="Using Visual Studio 2008 to Build an ADO.NET Data Services based Application" /> <link rel="next" href="installcrweb.html" title="Creating a Web Browser Application to Access RDF Data Using The Virtuoso ADO.Net Provider" /> <link rel="shortcut icon" href="../images/misc/favicon.ico" type="image/x-icon" /> <link rel="stylesheet" type="text/css" href="doc.css" /> <link rel="stylesheet" type="text/css" href="/doc/translation.css" /> <title>2. Installation Guide</title> <meta http-equiv="Content-Type" content="text/xhtml; charset=UTF-8" /> <meta name="author" content="OpenLink Software Documentation Team ; " /> <meta name="copyright" content="OpenLink Software, 1999 - 2009" /> <meta name="keywords" content="" /> <meta name="GENERATOR" content="OpenLink XSLT Team" /> </head> <body> <div id="header"> <a name="installwfas" /> <img src="../images/misc/logo.jpg" alt="" /> <h1>2. Installation Guide</h1> </div> <div id="navbartop"> <div> <a class="link" href="installation.html">Chapter Contents</a> | <a class="link" href="installusado.html" title="Using Visual Studio 2008 to Build an ADO.NET Data Services based Application">Prev</a> | <a class="link" href="installcrweb.html" title="Creating a Web Browser Application to Access RDF Data Using The Virtuoso ADO.Net Provider">Next</a> </div> </div> <div id="currenttoc"> <form method="post" action="/doc/adv_search.vspx"> <div class="search">Keyword Search: <br /> <input type="text" name="q" /> <input type="submit" name="go" value="Go" /> </div> </form> <div> <a href="http://www.openlinksw.com/">www.openlinksw.com</a> </div> <div> <a href="http://docs.openlinksw.com/">docs.openlinksw.com</a> </div> <br /> <div> <a href="index.html">Book Home</a> </div> <br /> <div> <a href="contents.html">Contents</a> </div> <div> <a href="preface.html">Preface</a> </div> <br /> <div class="selected"> <a href="installation.html">Installation Guide</a> </div> <br /> <div> <a href="installwin32.html">Virtuoso for Windows</a> </div> <div> <a href="linuxinstall.html">Virtuoso for Linux (Enterprise Edition)</a> </div> <div> <a href="unxinstvirt.html">Virtuoso for Unix (Enterprise Edition)</a> </div> <div> <a href="unixpersonainstall.html">Virtuoso for Unix (Personal Edition)</a> </div> <div> <a href="installmacosx.html">Virtuoso for Mac OS X</a> </div> <div> <a href="installvsgrid.html">Virtuoso ADO.Net Data Grid Form Application</a> </div> <div> <a href="installvsent.html">Using Visual Studio 2008 to Build an Entity Frameworks based Windows Form Application</a> </div> <div> <a href="installusado.html">Using Visual Studio 2008 to Build an ADO.NET Data Services based Application</a> </div> <div class="selected"> <a href="installwfas.html">Windows Form Application for accessing Virtuoso RDF data via SPASQL using the Virtuoso ADO.Net Provider</a> <div> <a href="#installwfasintro" title="Pre-requisites">Pre-requisites</a> <a href="#installwfasgetstart" title="Creating the Application">Creating the Application</a> <a href="#installwfasxtendcomlab" title="Extending RDFDemo to Allow Dereferencing of External IRIs">Extending RDFDemo to Allow Dereferencing of External IRIs</a> <a href="#installwfasxtendcomplab" title="Extending RDFDemo to Display More Compact Labels">Extending RDFDemo to Display More Compact Labels</a> <a href="#installwfasmodify" title="Modifying the Northwind Ontology to Add Labels">Modifying the Northwind Ontology to Add Labels</a> <a href="#installwfasxtendlongtext" title="Extending RDFDemo to Display Images and Longer Text Fields.">Extending RDFDemo to Display Images and Longer Text Fields.</a> <a href="#installwfasxtendproplab" title="Extending RDFDemo To Make The Property Labels Clickable">Extending RDFDemo To Make The Property Labels Clickable</a> </div> </div> <div> <a href="installcrweb.html">Creating a Web Browser Application to Access RDF Data Using The Virtuoso ADO.Net Provider</a> </div> <div> <a href="installsilver.html">Creating a Silverlight Application to consume the service</a> </div> <div> <a href="installnetriadd.html">Creating A Simple .NET RIA Services Application To Display Data From Virtuoso</a> </div> <div> <a href="installnetriavd.html">Creating a .Net RIA Services Application That Will Update Virtuoso Data</a> </div> <div> <a href="clusterstcnf.html">Cluster Installation and Config</a> </div> <br /> </div> <div id="text"> <a name="installwfas" /> <h2>2.9. Windows Form Application for accessing Virtuoso RDF data via SPASQL using the Virtuoso ADO.Net Provider</h2> <p>This section will guide you through creating a simple application that allows you to access RDF data in a Virtuoso database as an Entity DataSet and explore that RDF data in an intuitive way by clicking on dereferenceable <a href="rdfdatarepresentation.html#rdfiriidtype">IRIs</a>.</p> <a name="installwfasintro" /> <h3>2.9.1. Pre-requisites</h3> <ol> <li>Microsoft Visual Studio 2008</li> <li>The Virtuoso ADO.Net provider for .Net 3.5 and the Entity Framework.</li> <li>The example assumes that you have a local Virtuoso server with the Northwind demo database installed. If the demo database is not already installed then download the <a href="http://download.openlinksw.com/packages/5.0/virtuoso/demo_dav.vad">demo database VAD package</a> (demo_dav.vad) and install it. The VAD package will create a new database in Virtuoso called demo containing the familiar Northwind tables. It will also creates <a href="http://docs.openlinksw.com/virtuoso/rdfsparqlintegrationmiddleware.html#rdfviews">RDF views</a> of the Northwind tables. In the example we assume the database is accessible on a hostname of "demo.openlinksw.com" on the default port 80, where an actually live instance of the Virtuoso Demo database is hosted. Users would use the appropriate hostname and port number of their Virtuoso installation to create the sample application, and would be would be localhost:8890 for a default installation or whatever the <a href="sect5_ini_URIQA.html">URIQA DefaultHost</a> Virtuoso configuration parameter is set to when the demo database VAD package is installed. </li> </ol> <br /> <a name="installwfasgetstart" /> <h3>2.9.2. Creating the Application</h3> <p> <strong>Step 1 - Create a view of the RDF data.</strong> </p> <p>We want to be able to access the RDF data in Visual Studio and the easiest way to do this is to create a view of the data that we are interested in and bind that view to a DataSet. This can be considered as using server side <a href="rdfsparql.html">SPARQL</a>. Virtuoso supports an <a href="rdfsparql.html#rdfsparqlinline">extension to standard SQL that allows</a> execution of SPARQL. If a SQL query begins with the keyword SPARQL then the rest of the query is interpreted by as SPARQL. If a SPARQL query is used as the definition of a view then that view can be manipulated using SQL like any other view. In this way the result set from a SPARQL query can be easily accessed from Visual Studio using ADO.Net and the Entity Framework. </p> <p> To create a view of the customers in the Northwind first open the Virtuoso Conductor and log in as dba. Then open iSQL from the menu on the left and execute the following statement. </p> <div> <pre class="programlisting"> CREATE VIEW Demo.demo.sparqlview as SPARQL PREFIX nwind: <http://demo.openlinksw.com/schemas/northwind#> SELECT DISTINCT ?s FROM <http://demo.openlinksw.com/Northwind> WHERE {?s a nwind:Customer} </pre> </div> <p> <strong>Note:</strong> If the view is added to the Visual Studio project as user "demo" (or any other than "dba'), then it must be ensured that the "SPARQL_SELECT" and "SPARQL_SPONGE" roles are assigned to this user, which can be done via the Virtuoso Conductor in the "System Admin" -> "User Accounts" tab. </p> <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="SPARQL_SPONGE" src="../images/ui/sparqlwinf1.png" /> </td> </tr> <tr> <td>Figure: 2.9.2.1. SPARQL_SPONGE</td> </tr> </table> <p> <strong>Step 2 - Create a simple grid form in Visual Studio</strong> </p> <ol> <li>Open <strong>Visual Studio</strong> and create a new <strong>Windows Forms Application</strong> called RDFDemo.</li> <li>In the <strong>Form Designer</strong> drag a <strong>DataGridView</strong> on to the form.</li> <li>Click the <strong>Choose Data Source</strong> drop down and select <strong>Add Project Data Source</strong>. <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Data Source" src="../images/ui/sparqlwinf2.png" /> </td> </tr> <tr> <td>Figure: 2.9.2.1. Data Source</td> </tr> </table> </li> <li>In the <strong>Data Source Configuration Wizard</strong> choose Database and then set up a connection to the demo database on your local Virtuoso server. </li> <li>On the <strong>Choose Your Data Objects</strong> page expand the <strong>Views</strong> and select sparqlview. <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Data Source Configuration Wizard" src="../images/ui/sparqlwinf3.png" /> </td> </tr> <tr> <td>Figure: 2.9.2.1. Data Source Configuration Wizard</td> </tr> </table> </li> <li>Click <strong>Finish</strong>.</li> <li>In the <strong>Form Designer</strong> select dataGridView1 and change the <strong>AutoSizeColumnsMode</strong> to AllCellsExceptHeader.</li> <li>Select the <strong>DefaultCellStyle</strong> and click on the ellipsis. This will open the <strong>CellStyleBuilder</strong>. Change the <strong>ForeColor</strong> to Blue. <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="CellStyleBuilder" src="../images/ui/sparqlwinf4.png" /> </td> </tr> <tr> <td>Figure: 2.9.2.1. CellStyleBuilder</td> </tr> </table> </li> <li>Expand <strong>Font</strong> and change <strong>Underline</strong> to True. Click <strong>OK</strong>.</li> </ol> <p> <strong>Step 3 - Change the mapping of the DataSet.</strong> </p> <p>In the Solution Explorer you will now have a DataSet called DemoDataSet.xsd. If you double click on this it opens the DataSet Designer. Select the column called s in the sparqlview table and in the Properties pane change the DataType from System.String to System.Object.</p> <p>The data returned by a SPARQL query can either be an <a href="rdfdatarepresentation.html#rdfiriidtype">IRI</a> or a literal value. In order to distinguish between the two the Virtuoso ADO.Net provider defines an additional data type, SQLExtendedString. By setting the column type to System.Object we can cast the fetched data back to SQLExtendedString and find out if an individual value is an IRI or a literal and handle it appropriately. </p> <p> <strong>Step 4 - Create the on_click event handler for the cells in the DataGridView.</strong> </p> <p>Return to the <strong>Form Designer</strong> and double click on the cell of the <strong>DataGridView</strong>. This creates the <strong>dataGridView1_CellContentClick</strong> method in Form1.cs. This is the method that handles clicking on IRI objects in the grid. </p> <p>Paste in the following block of code into the body of the <strong>dataGridView1_CellContentClick</strong> method. </p> <div> <pre class="programlisting"> int column = e.ColumnIndex; object o = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].Value; Type t = dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex].ValueType; if (o is SqlExtendedString) { SqlExtendedString se = (SqlExtendedString) o; ExtendedStringHandler seHandler = new ExtendedStringHandler(se, this.sparqlviewTableAdapter.Connection); seHandler.displayData(); } else if (o is SqlRdfBox) { //doesn't do anything at the moment } </pre> </div> <p> As we are using the SQLExtendedString extension from the Virtuoso ADO.Net provider you will also need to add </p> <div> <pre class="programlisting"> using OpenLink.Data.Virtuoso; </pre> </div> <p> at the top of the file. </p> <p> <strong>Step 5 - Create a class to handle exploring the RDF data.</strong> </p> <ul> <li>Add a new C# class to the project called ExtendedStringHandler, by Right clicking on RDFDemo in the <strong>Solution Explorer</strong> and <strong>Add</strong> a <strong>Class</strong>.</li> <li>Add the following using statements to the top of the file <div> <pre class="programlisting"> using OpenLink.Data.Virtuoso; using System.Data; using System.Windows.Forms; using System.Drawing; using System.Data.Mapping; using System.Data.Common; </pre> </div> </li> <li>Paste the following block of code into the class definition. <div> <pre class="programlisting"> StringBuilder DescribeCommand; VirtuosoConnection ParentConnection; List<Label> labelList = new List<Label>(); List<TextBox> textBoxList = new List<TextBox>(); DescribeDataSet describeDataSet = new DescribeDataSet(); Boolean isIRI = false; public ExtendedStringHandler(SqlExtendedString iri, VirtuosoConnection parentConnection) { ParentConnection = parentConnection; if (iri.IriType == SqlExtendedStringType.IRI) { isIRI = true; DescribeCommand = new StringBuilder("sparql select * from <http://demo.openlinksw.com/Northwind> where {<" + iri.ToString() + "> ?p ?o}"); // Replace demo.openlinksw.com with your URIQA DefaultHost setting } } public string describeCommandText { get { return DescribeCommand.ToString(); } } public void getDescribeData() { VirtuosoCommand myCommand = new VirtuosoCommand(this.describeCommandText, this.ParentConnection); VirtuosoDataAdapter myAdapter = new VirtuosoDataAdapter(); myAdapter.SelectCommand = myCommand; myAdapter.Fill(describeDataSet.DataTable1); } public void displayData() { if (isIRI) { getDescribeData(); Form describeForm = new Form(); describeForm.AutoScroll = true; describeForm.Width = 840; Label label1 = new Label(); label1.AutoSize = true; label1.Font = new Font(label1.Font.FontFamily, label1.Font.Size + 3.0F, label1.Font.Style | FontStyle.Bold, label1.Font.Unit); describeForm.Controls.Add(label1); DataTable table1 = describeDataSet.Tables[0]; if (table1.Rows.Count == 0) label1.Text = "No Details Available"; else { foreach (DataRow row in table1.Rows) if (row[0].ToString() == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") { StringBuilder title = new StringBuilder(row[1].ToString() + " details"); label1.Text = title.ToString(); break; } foreach (DataRow row in table1.Rows) { Label propertyLabel = new Label(); TextBox valueBox = new TextBox(); valueBox.Width = 400; object property = row[0]; object value = row[1]; if (value is SqlExtendedString) { valueBox.ForeColor = Color.Blue; valueBox.Font = new Font(valueBox.Font.FontFamily, valueBox.Font.Size, valueBox.Font.Style | FontStyle.Underline, valueBox.Font.Unit); } propertyLabel.Text = row[0].ToString(); propertyLabel.AutoEllipsis = true; propertyLabel.AutoSize = false; propertyLabel.Width = propertyLabel.PreferredWidth > 380 ? 380 : propertyLabel.PreferredWidth; Binding bind = new Binding("Text", row[1], ""); valueBox.DataBindings.Add(bind); labelList.Add(propertyLabel); textBoxList.Add(valueBox); } for (int i = 0; i < table1.Rows.Count; i++) { textBoxList[i].Click += new EventHandler(this.iri_Click); labelList[i].Location = new Point(10, i * 20 + 50); textBoxList[i].Location = new Point(400, i * 20 + 50); describeForm.Controls.Add(labelList[i]); describeForm.Controls.Add(textBoxList[i]); } describeForm.Height = labelList.Count * 20 + 100 > 500 ? 500 : labelList.Count * 20 + 100; } describeForm.ShowDialog(); } else { Form blankForm = new Form(); Label label1 = new Label(); label1.Text = "Blank Node"; label1.Font = new Font(label1.Font.FontFamily, label1.Font.Size + 3.0F, label1.Font.Style | FontStyle.Bold, label1.Font.Unit); blankForm.ShowDialog(); } } public void iri_Click(object sender, EventArgs e) { int boxNum = 0; for (int i = 0; i < textBoxList.Count; i++) { if (sender == textBoxList[i]) { boxNum = i; break; } } Object o = describeDataSet.DataTable1.Rows[boxNum][1]; if (o is SqlExtendedString) { SqlExtendedString se = (SqlExtendedString)o; ExtendedStringHandler seHandler = new ExtendedStringHandler(se, ParentConnection); seHandler.displayData(); } else if (o is SqlRdfBox) { //doesn't do anything at the moment } } </pre> </div> </li> </ul> <p> The ExtendedStringHandler class creates a new SPARQL query based on the IRI that was clicked. This query is executed against Virtuoso using the ADO.Net connection in the same way that any SQL statement would be executed across an ADO.Net connection. This can be considered as Client Side SPARQL. The result set from the query describes the selected object and is returned as an ADO.Net DataAdapter. The DataAdapter is used to fill a DataTable which is displayed on a new form. We now need to add the new DataSet to the project and define the DataTable that will hold the query results. </p> <p> <strong>Step 6 - Add a new DataSet to hold the query results.</strong> </p> <ol> <li>Right click RDFDemo in the <strong>Solution Explorer</strong> and add a new <strong>DataSet</strong>. Call the new <strong>DataSet</strong> DescribeDataSet. <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Add a new DataSet" src="../images/ui/sparqlwinf5.png" /> </td> </tr> <tr> <td>Figure: 2.9.2.1. Add a new DataSet</td> </tr> </table> </li> <li>Double click on DescribeDataSet in the <strong>Solution Explorer</strong> to open the <strong>DataSet</strong> Designer and drag a <strong>DataTable</strong> from the <strong>Toolbox</strong> into it.</li> <li>Add two columns, p and o, to the <strong>DataTable</strong> and set the <strong>DataType</strong> of each column to System.Object. <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Add two columns" src="../images/ui/sparqlwinf6.png" /> </td> </tr> <tr> <td>Figure: 2.9.2.1. Add two columns</td> </tr> </table> </li> </ol> <p> <strong>Step 7 - Build and run the application.</strong> </p> <p>You should see a form displaying all the Northwind customers, like this. </p> <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Northwind customers" src="../images/ui/sparqlwinf7.png" /> </td> </tr> <tr> <td>Figure: 2.9.2.2. Northwind customers</td> </tr> </table> <p>When any customer is clicked it opens a new form showing customer details. </p> <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Customer details" src="../images/ui/sparqlwinf8.png" /> </td> </tr> <tr> <td>Figure: 2.9.2.3. Customer details</td> </tr> </table> <p>Clicking on the links in the new form allows you to drill down further to get order, product, location details etc. </p> <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Order, product, location details" src="../images/ui/sparqlwinf9.png" /> </td> </tr> <tr> <td>Figure: 2.9.2.4. Order, product, location details</td> </tr> </table> <p>and</p> <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Order, product, location details" src="../images/ui/sparqlwinf10.png" /> </td> </tr> <tr> <td>Figure: 2.9.2.5. Order, product, location details</td> </tr> </table> <p> <strong>Next Steps</strong> </p> <p> You will notice if you keep clicking on the links that this application will only display data that is held in the Northwind graph. Clicking on an external link, for example the link to Berlin in dbpedia, http://dbpedia.org/resource/Berlin, results in a empty window and an error message. The next step is to extend this application so that it can handle dereferencing external IRIs. </p> <br /> <a name="installwfasxtendcomlab" /> <h3>2.9.3. Extending RDFDemo to Allow Dereferencing of External IRIs</h3> <p> This section will guide you through extending the application created in <a href="installwfas.html#installwfasgetstart">Creating a Windows Forms Application To Access RDF Data Using The Virtuoso ADO.Net Provider</a> so that it will dereference external IRIs. </p> <p> <strong>Pre-requisites</strong> </p> <ol> <li>A working copy of the RDFDemo application created in <a href="installwfas.html#installwfasgetstart">Creating a Windows Forms Application To Access RDF Data Using The Virtuoso ADO.Net Provider.</a> </li> </ol> <a name="installwfasxtendcomlabextappl" /> <h4>2.9.3.1. Extending the Application</h4> <p>In RDFDemo when the sparql endpoint is queried to get the description of the selected item it executes a query that is restricted to the local Northwind dataset. The query is something like </p> <div> <pre class="programlisting"> SPARQL PREFIX nwind: <http://demo.openlinksw.com/schemas/northwind#> SELECT DISTINCT ?s FROM <http://demo.openlinksw.com/Northwind> WHERE {?s a nwind:Customer} </pre> </div> <p>If you examine the ExtendedStringHandler class you will see that the dataset clause, from <http://localhost:8890/Northwind>, is hard coded. This means that when when the selected IRI is a link to an external data store, such as dbpedia, there is no matching data and an error is displayed. If the application is to be able to dereference external IRIs then the hard coded dataset clause needs to be removed and then we can use a Virtuoso extension to SPARQL, get:soft, that tells Virtuoso that it needs to go and look elsewhere for the graph. However, this will result in a loss of performance when exploring the local Northwind dataset. To minimize the impact on performance we will first query the local Northwind dataset and if there are no matching triples returned then we will use a more generic query that will look elsewhere for matching data. </p> <p> <strong>Step 1 - Add the alternative query to the ExtendedString Class.</strong> </p> <ul> <li>Open the RDFDemo project in Visual Studio </li> <li>Open the ExtendedStringHandler class.</li> <li>Remove DescribeCommand by removing the line <div> <pre class="programlisting"> StringBuilder DescribeCommand; </pre> </div> <p> and substitute the following: </p> <div> <pre class="programlisting"> StringBuilder DescribeCommandSimple, DescribeCommandGeneral; </pre> </div> </li> <li>In the ExtendedStringHandler constructor the sparql query that was DescribeCommand becomes DescribeCommandSimple and we define a new query for DescribeCommandGeneral. <div> <pre class="programlisting"> DescribeCommandSimple = new StringBuilder("sparql select * from <http://demo.openlinksw.com/Northwind> where {<" + iri.ToString() + "> ?p ?o}"); // Replace demo.openlinksw.com with your URIQA DefaultHost setting DescribeCommandGeneral = new StringBuilder("sparql define get:soft " + '"'.ToString() + "soft" + '"'.ToString() + " select * from <" + iri.ToString() + "> where { <" + iri.ToString() + "> ?p ?o }"); </pre> </div> </li> <li>The single describeCommand property needs to be replaced with the two new properties, DescribeCommandSimple and DescribeCommandGeneral <div> <pre class="programlisting"> public string describeCommandSimpleText { get { return DescribeCommandSimple.ToString(); } } public string describeCommandGeneralText { get { return DescribeCommandGeneral.ToString(); } } </pre> </div> </li> <li>Finally, the getDescribeData method needs changing to: <div> <pre class="programlisting"> public void getDescribeData() { VirtuosoCommand myCommand = new VirtuosoCommand(this.describeCommandSimpleText, this.ParentConnection); VirtuosoDataAdapter myAdapter = new VirtuosoDataAdapter(); myAdapter.SelectCommand = myCommand; myAdapter.Fill(describeDataSet.DataTable1); // Tried the simple version if fails to get the data try // to look elsewhere. if (describeDataSet.DataTable1.Rows.Count == 0) { myCommand.CommandText = describeCommandGeneralText; myAdapter.Fill(describeDataSet.DataTable1); } } </pre> </div> </li> </ul> <p> <strong>Step 2 - Build and Run the Application</strong> </p> <p> You will see the same starting form: </p> <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Build and Run the Application" src="../images/ui/sparqlwinf11.png" /> </td> </tr> <tr> <td>Figure: 2.9.3.1.1. Build and Run the Application</td> </tr> </table> <p> Select a Customer and then select the link to the City in dbpedia. This will now open up another window displaying information about the city from dbpedia. Be patient as it may take a little while to open. </p> <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Customer" src="../images/ui/sparqlwinf12.png" /> </td> </tr> <tr> <td>Figure: 2.9.3.1.2. Customer</td> </tr> </table> <p> <strong>Step 3 - Changing the Form Title</strong> </p> <p> Notice that in displayData method that we look for a http://www.w3.org/1999/02/22-rdf-syntax-ns#type and create a title for the form from it. </p> <div> <pre class="programlisting"> foreach (DataRow row in table1.Rows) if (row[0].ToString() == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type") { StringBuilder title = new StringBuilder(row[1].ToString() + " details"); label1.Text = title.ToString(); break; } </pre> </div> <p> This worked well for the Northwind subjects but less well now we are getting data from other graphs. To change the title of the forms used to display the data: </p> <ul> <li>Add an new member variable to hold the IRI that we exploring to the bock of member variables <div> <pre class="programlisting"> StringBuilder DescribeCommandSimple, DescribeCommandGeneral; VirtuosoConnection ParentConnection; List<Label> labelList = new List<Label>(); List<TextBox> textBoxList = new List<TextBox>(); DescribeDataSet describeDataSet = new DescribeDataSet(); Boolean isIRI = false; SqlExtendedString ParentIRI; </pre> </div> </li> <li>Assign a value to ParentIRI in the constructor: <div> <pre class="programlisting"> public ExtendedStringHandler(SqlExtendedString iri, VirtuosoConnection parentConnection) { ParentConnection = parentConnection; if (iri.IriType == SqlExtendedStringType.IRI) { ParentIRI = iri; isIRI = true; DescribeCommandSimple = new StringBuilder("sparql select * from <http://demo.openlinksw.com/Northwind> where {<" + iri.ToString() + "> ?p ?o}"); // Replace demo.openlinksw.com with your URIQA DefaultHost setting DescribeCommandGeneral = new StringBuilder("sparql define get:soft " + '"'.ToString() + "soft" + '"'.ToString() + " select * from <" + iri.ToString() + "> where { <" + iri.ToString() + "> ?p ?o }"); } } </pre> </div> </li> <li>Remove the existing foreach block that sets the form title and replace with the following lines: <div> <pre class="programlisting"> StringBuilder title = new StringBuilder(ParentIRI.ToString() + " details"); label1.Text = title.ToString(); </pre> </div> </li> <li>Build and run the application. <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Build and run the application" src="../images/ui/sparqlwinf13.png" /> </td> </tr> <tr> <td>Figure: 2.9.3.1.1. Build and run the application</td> </tr> </table> </li> </ul> <p> <strong>Next Steps</strong> </p> <p>The application now allows you to explore data and follow links from your locally held data into the external web of data. Looking at the data displayed in the form it would be nice to make the labels for the properties more compact. The label http://dbpedia.org/property/population is a very precise definition but for our purposes it would be clearer to label the property just population. In the next step will be to modify the application so that it displays more readable labels. </p> <br /> <br /> <a name="installwfasxtendcomplab" /> <h3>2.9.4. Extending RDFDemo to Display More Compact Labels</h3> <p> This section will guide you through extending the application created in <a href="installwfas.html#installwfasxtendcomlab">Extending RDFDemo to Allow Dereferencing of External IRIs</a> so that the data is displayed in a more readable form. </p> <p> <strong>Pre-requisites</strong> </p> <ol> <li>A working copy of the RDFDemo application created in <a href="installwfas.html#installwfasxtendcomlab">Extending RDFDemo to Allow Dereferencing of External IRIs</a> </li> </ol> <a name="installwfasxtendcomplabextapp" /> <h4>2.9.4.1. Extending the Application</h4> <p>The RDF demo application presents the user with a list of Customers from the Northwind database in the form of dereferenceable IRIs. When a customer is selected from the list the application uses a sparql query to describe that customer and the results are displayed in a form as rows of labels and data. The labels correspond to RDF predicates and the data corresponds to RDF objects while the subject is the customer initially selected. In many cases the objects are dereferencable IRIs which are then used as the subject when the 'drilling down' into the data. However, the predicates are also IRIs so it is possible to gain more information about these as well. </p> <p>The RDF Schema defines a property http://www.w3.org/2000/01/rdf-schema#label that may be used to provide a human-readable version of a resource's name. We can obtain further details of each of the predicates in a resultset and check to see if one of the properties is an http://www.w3.org/2000/01/rdf-schema#label. If it is we can use the associated text as the label in our form instead of the the predicate IRI. The benefit should be a more human readable form. </p> <p> <strong>Step 1 - Add a New Method to Get the Label Text</strong> </p> <p>This method takes the predicate IRI and issues a sparql query to get its description. It then cycles through the returned dataset to find a http://www.w3.org/2000/01/rdf-schema#label. If there is one then the associated text is returned by the method. Otherwise the method returns the IRI string. </p> <ul> <li>Add the following method to the ExtendedStringHandlerClass <div> <pre class="programlisting"> private string getLabelText(Object label) { string labelText = label.ToString(); if (label is SqlExtendedString) { SqlExtendedString se = (SqlExtendedString)label; StringBuilder getLabelCommandText = new StringBuilder("sparql define get:soft \"soft\" select * from <" + se.ToString() + "> where {<" + se.ToString() + "> ?p ?o}"); VirtuosoCommand getLabelCommand = new VirtuosoCommand(getLabelCommandText.ToString(), ParentConnection); VirtuosoDataAdapter getLabelAdapter = new VirtuosoDataAdapter(); getLabelAdapter.SelectCommand = getLabelCommand; DataSet getLabelDataSet = new DataSet(); try { getLabelAdapter.Fill(getLabelDataSet); foreach (DataRow getLabelRow in getLabelDataSet.Tables[0].Rows) { if (getLabelRow[0].ToString() == "http://www.w3.org/2000/01/rdf-schema#label") { labelText = getLabelRow[1].ToString(); break; } } } catch { } } return labelText; } </pre> </div> </li> <li>Change the line in displayData from <div> <pre class="programlisting"> propertyLabel.Text = row[0].ToString(); </pre> </div> </li> <li>to <div> <pre class="programlisting"> propertyLabel.Text = getLabelText(row[0]); </pre> </div> </li> </ul> <p> <strong>Step 1 - Add a New Method to Get the Label Text</strong> </p> <p>When you run the application you will see that the initial form is the same. In fact, when you select the Customer you will also see that the customer details are also the same. It is only when you start exploring data outside the Northwind graph that you will see the labels in the form change. </p> <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Northwind graph" src="../images/ui/sparqlwinf14.png" /> </td> </tr> <tr> <td>Figure: 2.9.4.1.1. Northwind graph</td> </tr> </table> <p> <strong>Next Steps</strong> </p> <p>It is clear from running the application that the Northwind ontology does not define an http://www.w3.org/2000/01/rdf-schema#label for its members. In order to benefit from this modified version of RDFDemo we need to update our Northwind ontology so that http://www.w3.org/2000/01/rdf-schema#label is defined for each resource. The next step will be to modify our Northwind ontology. </p> <br /> <br /> <a name="installwfasmodify" /> <h3>2.9.5. Modifying the Northwind Ontology to Add Labels</h3> <p>This section will guide you through modifying the Northwind Ontology created when you installed the <a href="http://download.openlinksw.com/packages/5.0/virtuoso/demo_dav.vad">demo database VAD package</a> so that each resources is identified by an http://www.w3.org/2000/01/rdf-schema#label. This will improve the readability of the information displayed by the application created in <a href="installwfas.html#installwfasxtendcomplab">Extending RDFDemo to Display More Compact Labels</a>. </p> <p> <strong>Pre-requisites</strong> </p> <ol> <li>A working copy of the RDFDemo application created in <a href="installwfas.html#installwfasxtendcomplab">Extending RDFDemo to Display More Compact Labels</a> </li> </ol> <a name="installwfasmodifyeditont" /> <h4>2.9.5.1. Editing the Ontology</h4> <p> <strong>Get a Working Copy of the Northwind Ontology</strong> </p> <p>The the file describing the Northwind Ontology, nw.owl, is installed in the DAV when the demo vad is loaded. To get a working copy open the Virtuoso Conductor and log in as dba. Select WebDAV Browser in the navigation panel on the left. This will open a window that allows you to browse the WebDAV Repository. The Northwind Ontology file can be found in DAV/VAD/demo/sql. Take a copy of the file. </p> <p> <strong>Editing nw.owl</strong> </p> <p>In the first instance is edited nw.owl so that the property name consistently begin with a lower case letter. This matches the results for describing resources held in the Northwind database. Also are added missing properties so that there should be a label in all cases. </p> <p> <strong>Registering the Changes in Virtuoso</strong> </p> <p>There are two methods for registering the changes in Virtuoso: </p> <ol> <li>Method I: <ul> <li>Copy the edited version of nw.owl back into the DAV.</li> <li>In isql, load the script load_ontology_dav.sql and execute it. The new version of nw.owl will then be used</li> </ul> </li> <li> <ul> <li>Ensure that your new version of nw.owl is in a folder accessible by Virtuoso. You may need to edit your virtuoso.ini file and restart the server.</li> <li>In isql, load the script load_ontology_file.sql and edit it so that it has the full path to the new version of nw.owl</li> <li>Run the script. The new version of nw.owl will then be used.</li> </ul> </li> </ol> <p>Modify RDFDemo so that it looks for the graph used to describe the Northwind data and searches that graph for the predicate details:</p> <ol> <li>Add a new member variable to the ExtendedStringHandler class to hold the graphs that we need to search for the predicate information. <div> <pre class="programlisting"> StringBuilder DescribeCommandSimple, DescribeCommandGeneral; VirtuosoConnection ParentConnection; List<Label> labelList = new List<Label>(); List<TextBox> textBoxList = new List<TextBox>(); List<String> graphList = new List<String>(); DescribeDataSet describeDataSet = new DescribeDataSet(); Boolean isIRI = false; SqlExtendedString ParentIRI; </pre> </div> </li> <li>In displayData, after we have set the title of the form, add the following block of code: <div> <pre class="programlisting"> // Later we will want to get property labels and for that // we will need the graph where the resource is defined. foreach (DataRow row in table1.Rows) if (row[0].ToString() == "http://www.openarchives.org/ore/terms/isDescribedBy" && row[1].ToString() != ParentIRI.ToString()) { String graph = row[1].ToString(); graphList.Add(graph); } </pre> </div> </li> <li>Replace the existing getLabelText method with an extended version <div> <pre class="programlisting"> private string getLabelText(Object label) { string labelText = label.ToString(); if (label is SqlExtendedString) { Boolean foundLabel = false; SqlExtendedString se = (SqlExtendedString)label; VirtuosoDataAdapter getLabelAdapter = new VirtuosoDataAdapter(); DataSet getLabelDataSet = new DataSet(); //Try finding it in resources graph first foreach (String graph in graphList) { StringBuilder getLabelCommandText = new StringBuilder("sparql select * from <" + graph + "> where {<" + se.ToString() + "> ?p ?o}"); VirtuosoCommand getLabelCommand = new VirtuosoCommand(getLabelCommandText.ToString(), ParentConnection); getLabelAdapter.SelectCommand = getLabelCommand; try { getLabelAdapter.Fill(getLabelDataSet); foreach (DataRow getLabelRow in getLabelDataSet.Tables[0].Rows) { if (getLabelRow[0].ToString() == "http://www.w3.org/2000/01/rdf-schema#label") { labelText = getLabelRow[1].ToString(); foundLabel = true; break; } } } catch { } if (foundLabel) break; } // If we still have no label try the predicate itself as the graph if (!foundLabel) { StringBuilder getLabelCommandText = new StringBuilder("sparql define get:soft \"soft\" select * from <" + se.ToString() + "> where {<" + se.ToString() + "> ?p ?o}"); VirtuosoCommand getLabelCommand = new VirtuosoCommand(getLabelCommandText.ToString(), ParentConnection); getLabelAdapter.SelectCommand = getLabelCommand; try { getLabelAdapter.Fill(getLabelDataSet); foreach (DataRow getLabelRow in getLabelDataSet.Tables[0].Rows) { if (getLabelRow[0].ToString() == "http://www.w3.org/2000/01/rdf-schema#label") { labelText = getLabelRow[1].ToString(); break; } } } catch { } } } return labelText; } </pre> </div> <p>This extended method first checks the graphs in the graph list for the predicate information then if no label has been found tries the predicate itself as the graph. </p> </li> <li>Build and run, the Northwind resources should now be correctly and concisely labeled <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Northwind resources" src="../images/ui/sparqlwinf15.png" /> </td> </tr> <tr> <td>Figure: 2.9.5.1.1. Northwind resources</td> </tr> </table> </li> </ol> <p> </p> <p> <strong>Improving The Appearance of the Form</strong> </p> <p>The following changes are not strictly necessary but improve the appearance of the form: </p> <ul> <li>Line up the right hand edge of the labels with the text boxes by setting TextAlign to MiddleRight and reduce the width of the labels. <div> <pre class="programlisting"> propertyLabel.Text = getLabelText(row[0]); propertyLabel.AutoEllipsis = true; propertyLabel.AutoSize = false; propertyLabel.Width = 130; propertyLabel.TextAlign = ContentAlignment.MiddleRight; </pre> </div> </li> <li>Make the form narrower: <div> <pre class="programlisting"> describeForm.Width = 660; </pre> </div> </li> <li>Alter the positioning of the labels and TextBoxes on the form: <div> <pre class="programlisting"> textBoxList[i].Click += new EventHandler(this.iri_Click); labelList[i].Location = new Point(10, i * 22 + 50); textBoxList[i].Location = new Point(150, i * 22 + 50); describeForm.Controls.Add(labelList[i]); describeForm.Controls.Add(textBoxList[i]); </pre> </div> <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Alter the positioning" src="../images/ui/sparqlwinf16.png" /> </td> </tr> <tr> <td>Figure: 2.9.5.1.1. Alter the positioning</td> </tr> </table> </li> </ul> <p> <strong>Next Steps</strong> </p> <p>The image below shows some of the information about an employee in the Northwind dataset. </p> <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="employee" src="../images/ui/sparqlwinf17.png" /> </td> </tr> <tr> <td>Figure: 2.9.5.1.1. employee</td> </tr> </table> <p>In the next step we will extend the application so the images and web pages can be viewed and long text fields are displayed in full. </p> <br /> <br /> <a name="installwfasxtendlongtext" /> <h3>2.9.6. Extending RDFDemo to Display Images and Longer Text Fields.</h3> <p>This section will guide you through extending RDFDemo so that longer text fields can be displayed as a block of text and so that links to images and web pages can be viewed in a browser window. </p> <p> <strong>Pre-requisites</strong> </p> <ol> <li>A working copy of the RDFDemo application created in <a href="installwfas.html#installwfasmodify">Modifying the Northwind Ontology to Add Labels</a> </li> </ol> <a name="installwfasxtendlongtextmodf" /> <h4>2.9.6.1. Modifying the Application</h4> <p> <strong>Displaying Text</strong> </p> <p>We will modify the form that show the details of the selected item so that when the text in the boxes is too long to be seen in full a button will appear beside the box on the form and if you click the button the complete text will be displayed in a separate window. </p> <ol> <li>Add a new class, MoreButton that extends System.Windows.Forms.Button. <ul> <li>In the <strong>Solution Explorer</strong> right click on the RDFDemo project and select <strong>Add</strong> then <strong>New Item</strong>.</li> <li>Add a new class called MoreButton.cs. <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Add a new class" src="../images/ui/sparqlwinf18.png" /> </td> </tr> <tr> <td>Figure: 2.9.6.1.1. Add a new class</td> </tr> </table> </li> <li>The following using statement goes at the top of the file: <div> <pre class="programlisting"> using System.Windows.Forms; </pre> </div> </li> <li>The MoreButton class must inherit from System.Windows.Forms.Button so the class definition line should look like this: <div> <pre class="programlisting"> class MoreButton : Button </pre> </div> </li> <li>Add the following code to the body of the MoreButton class: <div> <pre class="programlisting"> String longText; public MoreButton(String text) { longText = text; this.Text = "More"; } protected override void OnClick(EventArgs e) { Form moreForm = new Form(); TextBox moreBox = new TextBox(); moreBox.Text = longText; moreBox.Width = 300; moreBox.Height = 250; moreBox.ScrollBars = ScrollBars.Vertical; moreBox.Multiline = true; moreBox.WordWrap = true; moreBox.Select(0, 0); moreBox.ReadOnly = true; moreForm.Controls.Add(moreBox); moreForm.Width = 320; moreForm.Height = 280; moreForm.ShowDialog(); } </pre> </div> </li> </ul> </li> <li>In displayData in the ExtendedStringHandler class, when the labels and TextBoxes are added to the form check if the text is too big for the box. If it is then add a MoreButton that will display all the text in a separate window. <div> <pre class="programlisting"> if (textBoxList[i].DataBindings[0].DataSource.ToString().Length > 80 && !(textBoxList[i].DataBindings[0].DataSource is SqlExtendedString)) { moreButtonList.Add(new MoreButton(textBoxList[i].DataBindings[0].DataSource.ToString())); moreButtonList[moreButtonList.Count - 1].Location = new Point(550, i * 22 + 50); describeForm.Controls.Add(moreButtonList[moreButtonList.Count -1]); } </pre> </div> </li> <li>We will also need a list to hold the buttons as they are created so the following needs to be added to the member variables at the top of the ExtendedStringHandler class. <div> <pre class="programlisting"> List<MoreButton> moreButtonList = new List<MoreButton>(); </pre> </div> </li> <li>Build and run the application. If you click through to an Employee page you will see the Notes field now has a button labeled More next to it. If you click on that button the text from the Notes field is displayed in a new window. <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Notes" src="../images/ui/sparqlwinf19.png" /> </td> </tr> <tr> <td>Figure: 2.9.6.1.1. Notes</td> </tr> </table> </li> </ol> <p> <strong>Displaying Images and Web Pages</strong> </p> <p>Next we will modify the form so that item identified as images or web pages will be opened in a browser window. Again we will do this by adding a button beside the box on the form that will open the browser window. </p> <ol> <li>Add a new class, OpenButton that extends System.Windows.Forms.Button. <ul> <li>In the <strong>Solution Explorer</strong> right click on the RDFDemo project and select <strong>Add</strong> then <strong>New Item</strong> </li> <li>Add a new class called OpenButton.cs. </li> <li>The following using statement goes at the top of the file: <div> <pre class="programlisting"> using System.Windows.Forms; </pre> </div> </li> <li>The OpenButton class must inherit from System.Windows.Forms.Button so the class definition line should look like this: <div> <pre class="programlisting"> class OpenButton : Button </pre> </div> </li> <li>Add the following code to the body of the OpenButton class: <div> <pre class="programlisting"> String urlText; public OpenButton(String text) { urlText = text; this.Text = "Open"; } protected override void OnClick(EventArgs e) { System.Diagnostics.Process.Start(urlText); } </pre> </div> </li> </ul> </li> <li>In displayData in the ExtendedStringHandler class, where we added the code to check for long text fields we now need to check for IRIs that identify images and web pages. As a simple first attempt we will check for matching labels. So for example, if a property label is 'image' or 'webpage', we will assume it can be opened in a browser window and put an OpenButton beside it. <div> <pre class="programlisting"> if (labelList[i].Text == "website" || labelList[i].Text == "image" || labelList[i].Text == "depiction" || labelList[i].Text == "page" || labelList[i].Text == "url" || labelList[i].Text == "image skyline") { openButtonList.Add(new OpenButton(textBoxList[i].DataBindings[0].DataSource.ToString())); openButtonList[openButtonList.Count - 1].Location = new Point (550, i * 22 + 50); describeForm.Controls.Add(openButtonList[openButtonList.Count - 1]); } </pre> </div> </li> <li>We will also need a list to hold the buttons as they are created so the following needs to be added to the member variables at the top of the ExtendedStringHandler class. <div> <pre class="programlisting"> List<OpenButton> openButtonList = new List<OpenButton>(); </pre> </div> </li> <li>Build and run the application. If you click through to an Employee page now you will see that the Image field now has a button labeled Open next to it. If you click on that button the image is opened in your default browser. <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Image" src="../images/ui/sparqlwinf20.png" /> </td> </tr> <tr> <td>Figure: 2.9.6.1.1. Image</td> </tr> </table> </li> </ol> <p> <strong>Next Steps</strong> </p> <p>It has already been mentioned that the property labels are also dereferenceable IRIs. We used this feature to find a short name to display rather that the complete IRI. The next step is to make the labels clickable so the ontology itself can also be explored. </p> <br /> <br /> <a name="installwfasxtendproplab" /> <h3>2.9.7. Extending RDFDemo To Make The Property Labels Clickable</h3> <p>This section will guide you through extending RDFDemo to make the property labels clickable. Clicking on the property label will take you to a page describing that property. </p> <p> <strong>Pre-requisites</strong> </p> <ol> <li>A working copy of the RDFDemo application created in <a href="installwfas.html#installwfasxtendlongtext">Extending RDFDemo to Display Images and Longer Text Fields</a> </li> </ol> <a name="installwfasxtendproplabmod" /> <h4>2.9.7.1. Modifying the Application</h4> <p> <strong>Making the Labels Clickable</strong> </p> <p>Making the property labels clickable is fairly straight forward. We will use basically the same code as is used to make the values clickable. </p> <ol> <li>First we need to add a new event handler. In the ExtendedStringHandler class modify displayData to add an event handler for each of the property labels. <div> <pre class="programlisting"> for (int i = 0; i < table1.Rows.Count; i++) { textBoxList[i].Click += new EventHandler(this.iri_Click); labelList[i].Location = new Point(10, i * 22 + 50); textBoxList[i].Location = new Point(150, i * 22 + 50); describeForm.Controls.Add(labelList[i]); describeForm.Controls.Add(textBoxList[i]); </pre> </div> <p>becomes </p> <div> <pre class="programlisting"> for (int i = 0; i < table1.Rows.Count; i++) { textBoxList[i].Click += new EventHandler(this.iri_Click); labelList[i].Location = new Point(10, i * 22 + 50); labelList[i].Click += new EventHandler(this.label_Click); textBoxList[i].Location = new Point(150, i * 22 + 50); describeForm.Controls.Add(labelList[i]); describeForm.Controls.Add(textBoxList[i]); </pre> </div> </li> <li>Then we need to add the EventHandler method. Add the following to the ExtendedStringHandler Class: <div> <pre class="programlisting"> public void label_Click(object sender, EventArgs e) { int labelNum = 0; for (int i = 0; i < labelList.Count; i++) { if (sender == labelList[i]) { labelNum = i; break; } } Object o = describeDataSet.DataTable1.Rows[labelNum][0]; if (o is SqlExtendedString) { SqlExtendedString se = (SqlExtendedString)o; ExtendedStringHandler seHandler = new ExtendedStringHandler(se, ParentConnection); seHandler.displayData(); } else if (o is SqlRdfBox) { //doesn't do anything at the moment } } </pre> </div> <p> If you compare this method to the EventHandler for the values, iri_Click, you will see that it is basically the same. The only difference is that it uses the property element from the data table rather than value. </p> </li> <li>Finally, to make it clear that the labels are now active links, we will change the label colour to blue and underline them. <div> <pre class="programlisting"> propertyLabel.Text = getLabelText(row[0]); propertyLabel.AutoEllipsis = true; propertyLabel.AutoSize = false; propertyLabel.Width = 130; propertyLabel.TextAlign = ContentAlignment.MiddleRight; </pre> </div> <p>becomes: </p> <div> <pre class="programlisting"> propertyLabel.Text = getLabelText(row[0]); propertyLabel.ForeColor = Color.Blue; propertyLabel.Font = new Font(propertyLabel.Font.FontFamily, propertyLabel.Font.Size, propertyLabel.Font.Style | FontStyle.Underline, propertyLabel.Font.Unit); propertyLabel.AutoEllipsis = true; propertyLabel.AutoSize = false; propertyLabel.Width = 130; propertyLabel.TextAlign = ContentAlignment.MiddleRight; </pre> </div> </li> <li>Build and run the application. You will see the familiar starting page. If you then select one of the Customers you will notice the property labels now look like hyperlinks. <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="hyperlinks" src="../images/ui/sparqlwinf21.png" /> </td> </tr> <tr> <td>Figure: 2.9.7.1.1. hyperlinks</td> </tr> </table> <p>If you click on one of the label hyperlinks you will see a new form showing detailed information about the property which can itself be explored further by clicking on labels and values. <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="labels and values" src="../images/ui/sparqlwinf22.png" /> </td> </tr> <tr> <td>Figure: 2.9.7.1.1. labels and values</td> </tr> </table> </p> </li> </ol> <p>These simple changes work up to a point but are not robust. If you explore the properties used by the local Northwind graph you quickly find that the property details are not found. The application needs some further changes to work consistently. The problem is finding the graph where the property information is defined. The general handler for Extended Strings first checks the local Northwind graph, http://localhost:8890/Northwind, where the Northwind data is held, and then uses the IRI itself as the graph and tries to load that dynamically. This is not working for information about the Northwind properties. These properties are defined in the Northwind ontology, http://demo.openlinksw.com/schemas/northwind. We have already had to find this graph when getting the short label name. We need to be able to associate the property label with the graph where its definition is stored. Then we can search this graph for details about the property when the label is clicked. </p> <p> <strong>Using the Graph Where the Property Label was Found to Find the Property Details</strong> </p> <ol> <li>Create a new class, IRILabel, that inherits from System.Windows.Forms.Label. <ul> <li>In the <strong>Solution Explorer</strong> right click on the RDFDemo project and select <strong>Add</strong> then <strong>New Item</strong>.</li> <li>Add a new class called IRILabel.cs. <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Add a new class" src="../images/ui/sparqlwinf23.png" /> </td> </tr> <tr> <td>Figure: 2.9.7.1.1. Add a new class</td> </tr> </table> </li> </ul> </li> <li>We need to reference System.Windows.Forms, System.Data and OpenLink.Data.Virtuoso so add <div> <pre class="programlisting"> using System.Windows.Forms; using OpenLink.Data.Virtuoso; using System.Data; </pre> </div> <p>to the using block at the top of the class file. The class definition should look like this: </p> <div> <pre class="programlisting"> class IRILabel : Label </pre> </div> </li> <li>Paste the following code into the body of the class: <div> <pre class="programlisting"> SqlExtendedString SourceIRI; String GraphUsed; VirtuosoConnection ParentConnection; public IRILabel(Object iri, List<String> graphList, VirtuosoConnection parentConnection) { ParentConnection = parentConnection; if (iri is SqlExtendedString) { SourceIRI = (SqlExtendedString)iri; Text = this.getLabelText(graphList); } else Text = iri.ToString(); } public SqlExtendedString iri { get { return SourceIRI; } } public String graph { get { return GraphUsed; } } private string getLabelText(List<String> graphList) { string labelText = SourceIRI.ToString(); Boolean foundLabel = false; VirtuosoDataAdapter getLabelAdapter = new VirtuosoDataAdapter(); DataSet getLabelDataSet = new DataSet(); //Try finding it in resources graph first foreach (String graph in graphList) { StringBuilder getLabelCommandText = new StringBuilder("sparql select * from <" + graph + "> where {<" + SourceIRI.ToString() + "> ?p ?o}"); VirtuosoCommand getLabelCommand = new VirtuosoCommand(getLabelCommandText.ToString(), ParentConnection); getLabelAdapter.SelectCommand = getLabelCommand; try { getLabelAdapter.Fill(getLabelDataSet); foreach (DataRow getLabelRow in getLabelDataSet.Tables[0].Rows) { if (getLabelRow[0].ToString() == "http://www.w3.org/2000/01/rdf-schema#label") { labelText = getLabelRow[1].ToString(); foundLabel = true; break; } } } catch { } if (foundLabel) { GraphUsed = graph; break; } } // If we still have no label try the predicate itself as the graph if (!foundLabel) { GraphUsed = SourceIRI.ToString(); StringBuilder getLabelCommandText = new StringBuilder("sparql define get:soft \"soft\" select * from <" + GraphUsed + "> where {<" + SourceIRI.ToString() + "> ?p ?o}"); VirtuosoCommand getLabelCommand = new VirtuosoCommand(getLabelCommandText.ToString(), ParentConnection); getLabelAdapter.SelectCommand = getLabelCommand; try { getLabelAdapter.Fill(getLabelDataSet); foreach (DataRow getLabelRow in getLabelDataSet.Tables[0].Rows) { if (getLabelRow[0].ToString() == "http://www.w3.org/2000/01/rdf-schema#label") { labelText = getLabelRow[1].ToString(); break; } } } catch { } } return labelText; } </pre> </div> <p>Notice that the getLabelText method has been moved into this new class and is now called from the constructor. When the IRILabel is constructed the label text is found using the list of graphs provided to the constructor. The graph containing the label is noted. We need to alter ExtendedStringHandler so that the labels are the new IRILabel type and so that the correct information is supplied to the constructor. </p> </li> <li>Change the labelList member variable declaration so it looks like this: <div> <pre class="programlisting"> List<IRILabel> labelList = new List<IRILabel>(); </pre> </div> </li> <li>Each propertyLabel created must be the new IRILabel type so the line: <div> <pre class="programlisting"> Label propertyLabel = new Label(); </pre> </div> <p>becomes: </p> <div> <pre class="programlisting"> IRILabel propertyLabel = new IRILabel(row[0], graphList, ParentConnection); </pre> </div> </li> <li>As getLabelText is now called by the IRILabel constructor we can remove the line: <div> <pre class="programlisting"> propertyLabel.Text = getLabelText(row[0]); </pre> </div> <p>from describeData in ExtendedStringHandler. </p> </li> <li>Now we modify the label_Click EventHandler so that it uses the graph information. Replace the existing method with: <div> <pre class="programlisting"> public void label_Click(object sender, EventArgs e) { int labelNum = 0; for (int i = 0; i < labelList.Count; i++) { if (sender == labelList[i]) { labelNum = i; break; } } SqlExtendedString se = labelList[labelNum].iri; ExtendedStringHandler seHandler = new ExtendedStringHandler(se, ParentConnection, labelList[labelNum].graph); seHandler.displayData(); } </pre> </div> </li> <li>Note that this method uses a new constructor for the ExtendedStringHandler that takes the graph as an additional argument. We need to add this new constructor. <div> <pre class="programlisting"> public ExtendedStringHandler(SqlExtendedString iri, VirtuosoConnection parentConnection, String graph) { ParentConnection = parentConnection; if (iri.IriType == SqlExtendedStringType.IRI) { ParentIRI = iri; isIRI = true; DescribeCommandSimple = new StringBuilder("sparql select * from <http://localhost:8890/Northwind> where {<" + iri.ToString() + "> ?p ?o}"); DescribeCommandGeneral = new StringBuilder("sparql define get:soft " + '"'.ToString() + "soft" + '"'.ToString() + " select * from <" + graph + "> where { <" + iri.ToString() + "> ?p ?o }"); } } </pre> </div> <p>This new constructor uses the supplied graph to build the alternative sparql select statement that looks for the details about the supplied IRI. With these changes in place the application will find the description of the Northwind properties. </p> </li> <li>Build and run. As you explore the data you will see that you can find descriptions of the properties used to describe the entities in the Northwind dataset: <table class="figure" border="0" cellpadding="0" cellspacing="0"> <tr> <td> <img alt="Northwind dataset" src="../images/ui/sparqlwinf24.png" /> </td> </tr> <tr> <td>Figure: 2.9.7.1.1. Northwind dataset</td> </tr> </table> </li> </ol> <br /> <br /> <table border="0" width="90%" id="navbarbottom"> <tr> <td align="left" width="33%"> <a href="installusado.html" title="Using Visual Studio 2008 to Build an ADO.NET Data Services based Application">Previous</a> <br />Using Visual Studio 2008 to Build an ADO.NET Data Services based Application</td> <td align="center" width="34%"> <a href="installation.html">Chapter Contents</a> </td> <td align="right" width="33%"> <a href="installcrweb.html" title="Creating a Web Browser Application to Access RDF Data Using The Virtuoso ADO.Net Provider">Next</a> <br />Creating a Web Browser Application to Access RDF Data Using The Virtuoso ADO.Net Provider</td> </tr> </table> </div> <div id="footer"> <div>Copyright© 1999 - 2009 OpenLink Software All rights reserved.</div> <div id="validation"> <a href="http://validator.w3.org/check/referer"> <img src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /> </a> <a href="http://jigsaw.w3.org/css-validator/"> <img src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!" height="31" width="88" /> </a> </div> </div> </body> </html>