Recently we discovered an issue in the installation guide’s import script that was causing the ontologies to be incorrectly imported. There was an extra call to DeleteResource that was resulting in previously imported ontologies to be removed.
Here is the updated script below. Remember to set your timeout really high as this takes several minutes to complete.
import "/imm/semanticmetadataservice/ontology.rql";
debug=true;
consoleOutput=true;
var ontologyUri = "http://purl.org/dc/elements/1.1/";
var tempOntologyDs = new datasource("inet?parsetype=rdf&context=" + server.urlencode(ontologyUri) + "&url=" + server.urlencode(ontologyUri));
InsertOntology(ontologyUri, tempOntologyDs);
var ontologyUri = "http://purl.org/dc/terms/";
var tempOntologyDs = new datasource("inet?parsetype=rdf&context=" + server.urlencode(ontologyUri) + "&url=" + server.urlencode(ontologyUri));
InsertOntology(ontologyUri, tempOntologyDs);
var ontologyUri = "http://purl.org/dc/dcmitype/";
var tempOntologyDs = new datasource("inet?parsetype=rdf&context=" + server.urlencode(ontologyUri) + "&url=" + server.urlencode(ontologyUri));
InsertOntology(ontologyUri, tempOntologyDs);
var ontologyUri = "http://schemas.microsoft.com/imm/2.0/core/";
var tempOntologyDs = new datasource("inet?parsetype=rdf&context=" + server.urlencode(ontologyUri) + "&url=" + server.urlencode(ontologyUri));
InsertOntology(ontologyUri, tempOntologyDs);
var ontologyPath = "C:\\Program Files\\Microsoft Interactive Media Manager\\Samples\\Data\\LitwareInc.owl";
var ontologyUri = "http://imm.litwareinc.com/samples/2.0/";
var tempOntologyDs = new datasource("inet?parsetype=rdf&context=" + server.urlencode(ontologyUri) + "&url=" + server.urlencode(ontologyPath));
InsertOntology(ontologyUri, tempOntologyDs);
After importing the Ontologies, you can run this SQL Script and you should see a row for each imported ontology.
exec sw_Sparql '
SELECT ?s ?o
FROM <http://schemas.microsoft.com/IMM/ontology>
WHERE { graph ?g { ?s <http://schemas.microsoft.com/imm/2.0/core/InferenceIndex> ?o }}',
1
It’s often very useful when creating custom SPARQL queries against the IMM Metadata Store using the sw_Sparql stored procedure to pull in some “inferred” metadata from the ontologies that you have imported. For example, you may have ingested a bunch of metadata into the IMM data table that stores the “facts” but you want to query back for information that is generated dynamically based on you ontology definitions.
One simple example of this is you may have saved a VideoItem in the database with it’s rdf:type set to imm:VideoItem, but you never provided the metadata to explain that this item is also derived from imm:MediaItem. That information is provided in the IMM core ontology. To write a query for that directly against the sw_sparql stored procedure in the database, you need to know two well known graph URI’s.
The first one is the URI to the IMM data graph which stores all of the known “facts". Note that the “IMM” in this URI is case sensitive!
http://schemas.microsoft.com/IMM/data
The next URI you will need is the one for the inferred metadata generated from your imported ontology.
If I execute the following query in SQL Server Management Studio against the IMMMetadata database, it will select all the VideoItems from the “facts” table as you can see in the FROM clause. If you have the Litware sample data installed, you should get some results back. If you look at the Litware rdf data, you will notice that we have set the type of these objects to VideoItem already, so the “facts” table contains their types.
exec sw_Sparql '
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dii: <urn:mpeg:mpeg21:2002:01-DII-NS#>
PREFIX did: <urn:mpeg:mpeg21:2002:02-DIDMODEL-NS#>
PREFIX imm: <http://schemas.microsoft.com/imm/2.0/core/>
SELECT ?s
FROM <http://schemas.microsoft.com/IMM/data>
WHERE {
?s rdf:type imm:VideoItem.
}',
1
If I execute this query, which is the same as above except now this time I am asking for a type that is in the IMM core Ontology, but not declared in the facts that I imported – it will return no results. Notice that the only change I made is the name of the type.
exec sw_Sparql '
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dii: <urn:mpeg:mpeg21:2002:01-DII-NS#>
PREFIX did: <urn:mpeg:mpeg21:2002:02-DIDMODEL-NS#>
PREFIX imm: <http://schemas.microsoft.com/imm/2.0/core/>
SELECT ?s
FROM <http://schemas.microsoft.com/IMM/data>
WHERE {
?s rdf:type imm:MediaItem.
}',
1
So, how do I get back these “inferred” types in a query. First we need to know the graph name that was generated for us when we imported our Ontology. IMM automatically creates an inference graph when you import the core and any custom ontology. We automatically add those inference graphs if you pass in the URI to to your ontology in the GetResource or Query methods on the web service.
In order to get back this information from the database you can execute the following SQL script which will return back a list of the known ontologies that are imported into IMM, as well as an ID that is used to identify their inference graph name.
exec sw_sparql '
SELECT ?s ?o
FROM <http://schemas.microsoft.com/IMM/ontology>
WHERE { graph ?g { ?s <http://schemas.microsoft.com/imm/2.0/core/InferenceIndex> ?o. }}
order by ?o',
1
Now, we can rewrite the script above to add a extra FROM clause that uses this inference index to point to the correct inference graph.
Look at the results of the above query and locate the Ontology that you are interested in using. Append the InferenceIndex that is returned in column 2 of the results to the following URI “http://schemas.microsoft.com/IMM/inference_” and you will get the URI for that inference graph.
For example the results from my database contains the index number “8” for the IMM Core ontology, so my resulting graph URI would be “http://schemas.microsoft.com/IMM/inference_8”.
My new query with ontology inferencing enabled would then look like this:
exec sw_Sparql '
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dii: <urn:mpeg:mpeg21:2002:01-DII-NS#>
PREFIX did: <urn:mpeg:mpeg21:2002:02-DIDMODEL-NS#>
PREFIX imm: <http://schemas.microsoft.com/imm/2.0/core/>
SELECT ?s
FROM <http://schemas.microsoft.com/IMM/data>
FROM <http://schemas.microsoft.com/IMM/inference_8>
WHERE {
?s rdf:type imm:MediaItem.
}',
1
If you execute this against the Litware sample metadata you will now get back the same (or more if you have other items that are derived from MediaItem) number of results as in the first query.
Ok, so I have been playing around with the ADO.NET DataServices to get something working for a REST based access to the RDF Store. My goal here was to create a simple REST based way to grab metadata out of the RDF store based on the ADO.NET DataServices model instead of relying on SOAP and SPARQL. I just wanted a simple way to get a specific object and some basic locked down values into a Silverlight application.
To create an ADO.NET DataService for use with IMM you need to follow these steps. Keep in mind that the DataService will need to be locked down to a specific Entity view of objects in the IMM Store, and is mostly meant to be read only for Silverlight applications or public sites.
- Fire up Visual Studio 2008 SP1. (has to be SP1)
- Create a new ASP.NET Web Application
- Add a new solution Folder and call it Views
- Add a New Item to the Views folder. Select Text item and call it
“CreateVideoItemsView.sql”
- We’ll use this SQL script to create a new View in the IMMMetadata database for us to expose via LINQ to SQL
- Copy and paste this CREATE View script into the new sql script file.
A few notes here. This creates a new View table based on a SPARQL query. You can edit this and create as many columns as you want bound to your SPARQL query.
In this case, I am creating a new row for every imm:VideoItem in the database and adding a column for the title, description, and proxy path.
ONE VERY IMPORTANT NOTE HERE – YOU MUST use the column name “ID” (in caps!) for the Entity framework and ADO.NET DataServices to work properly. That becomes the default primary key on the table and will be the value that you use to index into the REST service’s list of VideoItems. In this example below, I used a SUBSTRING on the value returned from IMM as the Subject. The reason I did this is because I wanted to use only the GUID at the end of the Subject URI as the method of indexing, so my URI looks like this -
http://localhost:29062/SemanticMetadata.svc/VideoItems('A8FC8F13-0A34-4446-B7E0-1AD8AF9E1A49').
Nice and simple to use instead of a full URL.
CREATE VIEW dbo.VideoItems
AS
SELECT SUBSTRING(c1.Value,50,37) AS ID,
c2.Value as Title,
c3.Value as [Description],
c4.Value as [Ref],
FROM dbo.sparql ('
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX imm: <http://schemas.microsoft.com/imm/2.0/core/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX did: <urn:mpeg:mpeg21:2002:02-DIDMODEL-NS#>
PREFIX dii: <urn:mpeg:mpeg21:2002:01-DII-NS#>
SELECT ?item ?title ?description ?ref
FROM <http://schemas.microsoft.com/IMM/data>
WHERE
{
?item rdf:type imm:VideoItem.
?item dc:title ?title.
?item dc:title ?description.
?item did:ResourceCollection ?resource.
?resource imm:ResourceType "Proxy"^^<http://www.w3.org/2001/XMLSchema#string>.
?resource did:Ref ?ref.
}
')
GO
- With the SQL script open hit F5 to execute it. You will need to connect to the database “IMMMetadata”.
- Once that is successful, we now have a View in our database that contains the VideoItem data that we wanted. You can repeat this process to add Views for other Ontology class types in the RDF Store.
- Next we are going to add our ADO.NET DataService. Add a New ADO.NET Data Service Item to the Project. If you don’t see that item, then you don’t have Visual Studio SP1 installed.
Call the item something like IMMDataService.svc
- Next we will add a LINQ to SQL class. Go to Add Item to Project and select the LINQ to SQL template. Name it IMMMetadata.dbml
- Now we need to make sure we have a connection to the SQL database in our Server Explorer. Should have this since we connected to the SQL to run the View Script.
Open it up and check to see if you View is in the IMMMetadata database.
- Next you will need to drag the View out onto the LINQ to SQL designer surface.
- Open the DataService class file – IMMDataService.svc. We need to make a few edits in this file to get stuff working.
- Edit the file by adding your DataContext to the base class type for the DataService. In my case below I added IMMMetadataDataContext which is the class that was generated by the LINQ to SQL tool.
In addition, I uncommented the Access Rule in the InitializeService method and changed the name of my Entity set to “VideoItems” to expose that collection. You can adjust the security settings as needed, but AllRead is fine for now. If you want to expose ALL entity sets that you may have views for, you can add more lines, or for testing you can set the value to “*” to expose everything.
/// <summary>
/// The IMM Data Service for use with ADO.NET
/// </summary>
public class IMMDataService : DataService<IMMMetadataDataContext>
{
// This method is called only once to initialize service-wide policies.
/// <summary>
/// Initializes the service.
/// </summary>
/// <param name="config">The config.</param>
public static void InitializeService(IDataServiceConfiguration config)
{
config.SetEntitySetAccessRule("VideoItems", EntitySetRights.AllRead);
// config.SetServiceOperationAccessRule("MyServiceOperation", ServiceOperationRights.All);
}
}
- Now, just Build your solution and browse to the IMMDataService.svc page. You should see the following.
If you cannot see the output in the above way, go to Tools->Internet Options-> Content Tab. Click the Settings button in the Feeds section, an uncheck the Turn on Feed Reading View option. You may need to restart IE for that setting to take. I had to on server but not on Vista.
- Notice that the collection is named VideoItems. It used the name of our View to create the collection name.
- We can now drill down into that collection. To view the whole list of items we could hit this URL. That could be really slow on a huge database, and you may want to disable that in production by setting the EntitySetRights in the InitializeService method to allow only single items.
http://localhost:33655/IMMDataService.svc/VideoItems
- Note that the format of the feed is AtomPub. You can also get a JSON feed if you like – just look at the docs on DataServices).
- Also notice that in the feed we now have an //entry/id element that contains the full URI to the details page for each asset.
I have the Litware RDF data loaded so I am seeing the Litware items. If you have this sample data loaded also, you should see the Billion Dollar Limited title asset as the first item.
If you don’t have anything listed at this point, you probably don’t have any items that match your SPARQL query loaded in the database. Load some data, or check to make sure the SPARQL query you used to create the view is correct.
- To drill down into the details, just use the URI in the ID element, or adjust your URI on the address bar to include the GUID of the item you want.
Notice that I now have just the single item’s details.
- We can even go further into the item by adding the Predicate name to the end of the URI. For example to get the Ref path for the proxy, I just add /Ref to the URL.
- I can now also use some queries to change the resultsets. Try out a few of these…
a.) Select the Top 3 Items
http://localhost:29062/SemanticMetadata.svc/VideoItems?$top=3
b.) Order by Title predicate
http://localhost:29062/SemanticMetadata.svc/VideoItems?$orderby=Title
c.) Skip ahead by 10 items in the results and limit to 10. Good for paging!
http://localhost:33655/IMMDataService.svc/VideoItems?$skip=10&$top=10
d.) Filter by the content of a predicate.
http://localhost:33655/IMMDataService.svc/VideoItems?$filter=Title eq 'Volcano'
e.) More query options and examples are here and here
- If you want to use the REST service in your .NET code or more importantly in a Silverlight application, you must deploy the DataService to the same Domain as you Silverlight application.
- To use the data service from the application for Silverlight:
a.) Generate data service classes from the running data service. These classes represent each of the entities that are defined in the data service. This step can be completed by using the Add Service Reference Dialog Box in Visual Studio. Make sure the data service is running, right-click the project, and then select Add Service Reference. Type the base URL of the data service, such as http://localhost:33655/IMMDataService.svc into the address text box and click Go.
The output from the command is a C# or Visual Basic file that contains a class for each entity type in the data service. For more information about the client classes, see .NET Client Library (ADO.NET Data Services Framework). The System.Data.Services.Client assembly is added to the project automatically when you generate the client classes by using Add Service Reference. This assembly comes with Silverlight and contains the classes needed by the client application to access ADO.NET Data Services.
b.) The classes that represent data service types can also be generated by using DataSvcUtil.exe. DataSvcUtil.exe is located in the directory \WINDOWS\Microsoft.NET\Framework\v3.5\. The command line takes two arguments: the name and path of an output file and the base URL to the data service for which types are to be generated.
c.) In the page.xaml.cs, add the following using directive: using System.Data.Services.Client.
- You can now create an instance of the DataServiceContext in your Silverlight client code and add data binding to you user interface elements
For more details on the ADO.NET Data Services Framework see http://msdn.microsoft.com/en-us/library/cc668792.aspx
- If you want to add relationships, say for example Resources under the VideoItems you just do the following.
- Add a new View for Resources. Here’s my sample view…
CREATE VIEW dbo.Resources
AS
SELECT SUBSTRING(c1.Value,50,37) AS ID,
c2.Value as Type,
c3.Value as [Size],
c4.Value as vFormat,
c5.Value as Mime,
c6.Value as Ref,
c7.Value As Lang,
SUBSTRING(c8.Value,50,37) As ParentID
FROM dbo.sparql ('
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX dii: <urn:mpeg:mpeg21:2002:01-DII-NS#>
PREFIX did: <urn:mpeg:mpeg21:2002:02-DIDMODEL-NS#>
PREFIX imm: <http://schemas.microsoft.com/imm/2.0/core/>
SELECT ?s ?type ?size ?vFormat ?mime ?ref ?lang ?parent
FROM <http://schemas.microsoft.com/IMM/data>
WHERE
{
?s rdf:type did:Resource.
?parent did:ResourceCollection ?s.
OPTIONAL{
?s imm:ResourceType ?type.
?s imm:SizeInBytes ?size.
?s imm:VideoFormat ?vFormat.
?s did:MimeType ?mime.
?s did:Ref ?ref.
?s dc:language ?lang.
}
}
')
- Next in the LINQ to SQL designer, drag the new Resources View table out.
- Right click on the design surface and Add an Association. Set it up like this.
- Set the Primary Key for both “ID” columns in the designer Property box.
- Rebuild your Solution and relaunch the DataService in the browser.
- You will now be able to drill down into your linked Resources from your VideoItems

Have Fun!
As an overview, the Interactive Media Manager (IMM) solution is a collection of managed Intellectual Property (IP) that extends Microsoft Office SharePoint 2007 and other Microsoft platform capabilities to enable the development and deployment of a collaborative asset management system. The solution addresses a variety of rich media management scenarios built on top of MOSS’07:
- Digital Asset Management
- Media Asset Management
- Enterprise Marketing Management
- Corporate Communications
- eLearning
- eLibrary
- Media Distribution
The solution builds on existing technology investments, and helps create an end-to-end content ingest, production, and delivery system. Here are the most pertinent Internet links for the IMM solution:
IMM Contracting / Pricing
IMM is provided as "pre-existing work," on a Services contract [work order (WO)/statement of work (SOW)], contributing to the overall value and deliverables of the MCS engagement. Microsoft Consulting Services (MCS) and customers will be able to access the source code with Microsoft retaining the IP ownership rights. MCS will advise and provide custom support as requested by customers, per individual engagement.
In addition to the IMM Solution, the following software and licensing is required to deploy the production IMM system (and if any/all are in place we look to take advantage of these investments):
- SQL Server 2005 Standard Edition (Enterprise Edition is required for 4+ node clustering).
- MOSS 2007 Standard Edition with CALs or External Connectors ( in case of availability outside intranet – now known as MOSS 2007 Internet)
- Windows Server 2003 Enterprise Edition with CALs/External Connector
- Intellidimension's Semantics.Server (Standard if deployed on SQL Standard, Enterprise if deployed on SQL Enterprise).
- Storage component (SAN)
- Visual Studio 2005 with .NET Framework v3.0 (for development only)
For more information on pricing, deal structure or positioning please reach directly to Mark Kashman, IMM Product Manager (mkashman@microsoft.com).
Deployment Services
The services to deploy and configure IMM are done through a Microsoft Consulting Services (MCS). Companies can leverage partner system integrators for direct engagements as long as Microsoft retains the ability to sub to the partner with appropriate architect resources.
The size and cost of the engagements are dependent on the complexity of the workflow(s), 3rd party integration, desired metadata migration, design for example. As a benchmark a bare minimum deployment would be approximately 2 resources for 12 weeks. For more information and detail about IMM deployment projects and how to engage and begin architecting/scoping the solution that's right for your company, please reach out to Randy Simmons (randy.simmons@microsoft.com).
Closing
If you have any general questions, technical or business oriented, please do not hesitate to contact the IMM Team via the IMMAsk@microsoft.com email address. We look forward to hearing what use cases and scenarios you have and how we can best offer a solution that is targeted, productive, flexible, extensible, well-connected, and provide you with the highest return on your investment.
A common question that comes up a lot on our IMMAsk@microsoft.com alias is how does one delete all of the RDF triples in the IMM database. Just follow these simple steps.
- Open up SQL Server Management Studio and connect to your SQL Server.
- Open up the IMMMetadata Database
- Right click on the IMMMetadata and select New Query
- Enter this SQL script and execute it.
exec sw_sparql '
DELETE FROM <http://schemas.microsoft.com/IMM/data> {?s ?p ?o}
FROM <http://schemas.microsoft.com/IMM/data>
WHERE { ?s ?p ?o }'
,0
That will delete all of the triples in the “data” graph for IMM. Note that there is a known bug in RTM of 2.0 where some triples of type “decimal” could be left behind. Just ignore those triples if there are just a few of them.
Today we posted an updated MetadataPolicy.xml configuration file to support more image metadata fields when using the IMM Media Services to extract metadata from a JPEG or TIFF image. Download the latest cersion of the file and replace the existing one in the folder:
%Program Files%/Microsoft Interactive Media Manager\Microsoft Interactive Media Manager\Media Services\Metadata
The updates include support for more EXIF, TIFF, and XMP metadata fields that are commonly found.
It’s very useful to spend a few moments to understand how the metadata policy file works, if you need to extend it to extract metadata fields that may not be standard. You can easily edit this file and just save it back and it will be used immediately on the next query to the Image endpoint’s GetMetadata method.
The MetadataPolicy.xml file is modeled after the default Vista metadata policy in how it chooses what metadata to parse from an image file. You will notice that it is grouped into Policy Groups. Each Group defines a prioritized list of metadata paths to attempt to extract metadata from a file. IMM MediaServices uses this policy file to determine which path to attempt first and once it gets a hit, it will stop processing that Policy Group and return the results in RDF format using the property name defined in the immPredicate attribute of the Policy element.
There are lots of tools out there to use to view the existing metadata on your image files and help determine which ones to add to the policy document. Here’s a couple of my favorite tools.
WIC EXPLORER
A great tool for helping out with image metadata and our MetadataPolicy file is the WIC Explorer which is in the Windows Imaging Component Code Samples and Tools. You can download it from here.
The WIC Explorer lets you view a tree of the metadata extracted in the files. You can use the “Metadata Values” decimal (in Green below) to extract the metadata by setting the appropriate path in MetadataPolicy.xml file.

EXIF TOOL
Another handy tool is ExifTool by Phil Harvey. It is great for getting a dump from a file of available metadata in XMP format. http://www.sno.phy.queensu.ca/~phil/exiftool/
Drop it in your Windows folder, rename it to just “exiftool.exe” and run it like this to get an .xmp file in RDF format. Great for debugging.
c:\Content>exiftool 068.JPG -o -s %d%f.xmp
Also, just run the console like this to get a dump of metadata and field names.
c:\Content>exiftool 068.JPG –s
Updating Ontology to Support New Properties
Once you have located and added the new properties to the MetadataPolicy.xml file you will need to update your Owl Ontology’s ImageEssenceFormat class to have the new property restrictions. In the current version of the IMM 2.0 Core Ontology, only the following properties are defined on the ImageEssenceFormat. If you want to use other properties in your code, you will need to add more property restrictions to this class and then regenerate your own custom ontology assemblies for use in .NET development.
Default Properties of ImageEssenceFormat on the IMM Core 2.0 Ontology.
- imm:ResolutionX
- imm:ResolutionY
- imm:Codec
- imm:BitDepth
- MicrosoftPhoto:CameraSerialNumber
- MicrosoftPhoto:DateAcquired
- MicrosoftPhoto:FlashManufacturer
- MicrosoftPhoto:FlashModel
- MicrosoftPhoto:LastKeywordIPTC
- MicrosoftPhoto:LastKeywordXMP
- MicrosoftPhoto:LensManufacturer
- MicrosoftPhoto:LensModel
- MicrosoftPhoto:Rating
- MicrosoftPhoto:RatingPercent
- dc:Subject
To extend the ImageEssenceFormat Class, you simply create a new custom ontology (or if you already defined one use that one), and then you add restrictions to the ImageEssenceFormat class.
First open or create a new OWL document. Define a new Ontology element and import the IMM Core 2.0 ontology from the web.
<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:owl=http://www.w3.org/2002/07/owl#
xmlns:rdf=http://www.w3.org/1999/02/22-rdf-syntax-ns#
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#">
<rdf:Description rdf:about="foo:MyCustomOntology">
<rdf:type>
<rdf:Description rdf:about="http://www.w3.org/2002/07/owl#
Ontology"/>
</rdf:type>
<rdfs:comment>My Custom Ontology example for extending
ImageEssenceFormat</rdfs:comment>
<owl:imports>
<rdf:Description rdf:about="http://schemas.microsoft.com/imm/2.0/core/"/>
</owl:imports>
<owl:versionInfo>1.0</owl:versionInfo>
</rdf:Description>
</rdf:RDF>
First you need to define the new property that you want to add. In this case, I am adding the XMP Rating property as a new DatatypeProperty of type integer.
<rdf:Description rdf:about="http://ns.adobe.com/xap/1.0/Rating">
<rdf:type rdf:resource="http://www.w3.org/2002/07/owl#
DatatypeProperty"/>
<rdfs:comment>A number that indicates a document’s status relative to
other documents, used to organize documents in a file
browser. Values are user-defined within an application defined
range.</rdfs:comment>
<rdfs:label>Rating</rdfs:label>
<rdfs:range rdf:resource="http://www.w3.org/2001/XMLSchema#integer"/>
</rdf:Description>
Next you need to add the property as a restriction on the ImageEssenceFormat class.
<rdf:Description rdf:about="http://schemas.microsoft.com/imm/2.0/core/
ImageEssenceFormat">
<rdfs:subClassOf>
<rdf:Description>
<owl:maxCardinality rdf:datatype="http://www.w3.org/
2001/XMLSchema#nonNegativeInteger">1</owl:maxCardinality>
<owl:onProperty>
<rdf:Description rdf:about="http://ns.adobe.com/
xap/1.0/Rating"/>
</owl:onProperty>
<rdf:type>
<rdf:Description rdf:about="http://www.w3.org/2002/
07/owl#Restriction"/>
</rdf:type>
</rdf:Description>
</rdfs:subClassOf>
</rdf:Description>
Now, if I regenerate my ontology class using the Visual Studio tools, I will have a new Rating property on my ImageEssenceFormat class. I can now deserialize the RDF/XML from the GetMetadata call to Media Services and it will populate this new Rating property if the image has an XMP Rating value stored on it.
Henry Stewart is a briefing and networking event focused on digital asset management. We will be attending the Los Angeles, CA briefing event, with a presentation focused on showing how companies can streamline the creation, management, and delivery of content, “Integrating DAM with Distribution Tools to Build and Effective Digital Supply Chain,” <Monday, Nov. 10th @ 4:30pm> by Jake Winett – M&E Global Industry Manager. And a session focused on the productive use of workflow to bridge process gaps, “How Our Workflow has Been Made More Productive,” <Monday, Nov. 10th @ 10am> presented by Mark Kashman -- IMM Product Manager. If you plan to be at the conference, or are in the area, come tap us on the shoulder. We are open to any side meetings/conversations you'd like to coordinate - send any requests to IMMAsk@microsoft.com. For more information on the Henry Stewart DAM LA conference, click here. And for the official brochure, click here.
Today I would like to profile an advanced SPARQL query, break it down, and explain how each part works.
The Query:
with (
select ?entityIdIn ?highestTypeOut
{
{ ?entityIdIn rdf:type ?highestTypeOut. }
not() {
?entityIdIn rdf:type ?hType.
?hType rdfs:subClassOf ?highestTypeOut.
}
} as :getMostSpecificType
)
SELECT ?title ?rdfType
WHERE
{
?entityId ?predicate ?title.
{ :getMostSpecificType(?entityId, ?rdfType) }
FILTER(:contains(?title, 'Superman'))
}
Overview
In essence, this query is searching every entity in the store and returns those entities where a property contains the word “Superman.” It also finds and returns the most specific type of each result. The purpose of this query is simple: to allow a user to search for a single term and find any resultant entities, regardless of their type or their schema.
In the results below, a number of different entities are returned: videos, clips, containers, and even resources.
Inference Rules
The “with” clause provides the ability to specify custom inference rules within a SPARQL query. In this case, we have a named rule that returns the most derivative (specific) type of the supplied entity. Since SPARQL variables either act as constraints or as variables depending on whether they are bound or unbound, I have suffixed “in” and “out” to make it clear how each is expected to be used. Calling the rule is simple. It is important to note that the results of this rule are not optional. Therefore, all returned entities must have at least one rdf:type.
{ :getMostSpecificType(?entityId, ?rdfType) }
Negation
The idea of negation is simple. The solution is the result of a graph pattern which is negatively constrained against the results of another graph pattern.
{ ?entityIdIn rdf:type ?highestTypeOut. }
not() {
?entityIdIn rdf:type ?hType.
?hType rdfs:subClassOf ?highestTypeOut.
}
Expressed in English: “Any triple where the subject is ?entityIdIn and the predicate is rdf:type EXCEPT where the same triple exists in the following graph pattern: any triple where the subject is ?entityIdIn and the predicate is rdf:type AND the resultant type is a subclass of another resultant type.” Whew. Put more simply: “Bind ?highestTypeOut to the rdf:type which has no derivative types.” This is an example of using negation to constrain the results of a graph pattern.
Full Text Search
The :contains function provides support for SQL full-text queries in a SPARQL filter. This is the most performant method of querying for specific text. In addition to simple word matching seen in the query above, advanced features of full-text can be used. For example, we can search for different inflections of the word “ship” by using the following:
FILTER(:contains(?title, 'FORMSOF(INFLECTIONAL, \"ship\")'))
This will return results with values such as “ships,” “shipped,” and “shipping.”
Other Thoughts
As mentioned in my previous post, the “rdf” and “rdfs” prefixes used in this query are handled automatically by IMM. Additionally, this query uses the ontology graph to determine class derivation. An enterprising developer could utilize more facts from the ontology to enhance the results of the query. For example, he/she could return the friendly name (rdfs:label) for a type instead of the type’s URI.
Many areas of the IMM SDK have been vastly improved in version 2. The most common operations have been streamlined and simplified.
The sample below demonstrates some differences in using the new IMM SDK, as well as highlights the improvements we have made in this release. The example scenario is a method that returns the title of every video in the Semantic Metadata Store by executing a SPARQL query.
In version 1:
(Contributed by MCS Architect extraordinaire, Jackie Nichols)
private static DataTable GetAllVideoes()
{
string strQuery = @"
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX imm: <http://schemas.microsoft.com/imm/core/1.0#>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
SELECT ?videoItem ?videoTitle WHERE {
?videoId rdf:type imm:VideoItem.
?videoId dc:title ?videoTitle.
}";
bool isSparqlXml;
XmlDocument resultXml = new XmlDocument();
DataTable returnTable = null;
using (Impersonator.ImpersonateAppPool())
{
using (DamServiceClient dsc = new DamServiceClient("DamEndpoint"))
{
QueryRequest request = new QueryRequest();
request.IsSparql = true;
request.Query = strQuery;
QueryResponse response = dsc.Query(request);
isSparqlXml = response.IsSparqlXml;
resultXml.LoadXml(response.Result);
}
}
if (isSparqlXml)
{
returnTable = SparqlResult.ToDataTable(resultXml.CreateNavigator());
}
else
{
TripleCollection trips = new TripleCollection();
trips.Load(resultXml.CreateNavigator(), null);
returnTable = trips.ToDataTable();
}
return returnTable;
}
Version 2:
private static DataTable GetAllVideoes()
{
string strQuery = @"
SELECT ?videoItem ?videoTitle WHERE {
?videoId rdf:type imm:VideoItem.
?videoId dc:title ?videoTitle.
}";
DataTable returnTable = null;
using (Impersonator.ImpersonateAppPool())
{
using (ReadClient dsc = new ReadClient("Read"))
{
Table response = dsc.Query(strQuery);
returnTable = response.ToDataTable();
}
}
return returnTable;
}
Let me highlight some of the differences:
· Prefixes - Many common namespaces are handled automatically. In this example, therefore, I can use the QNames for RDF, Dublin Core, and IMM without defining the full namespace in my query.
· Table - The Table class is an intermediary object that stores RDF values coming from the IMM Semantic Metadata Store. (Note: Powerful things can be done with a "Table." I will revisit Table soon.)
· QueryRequest - It still exists as SparqlQueryRequest. There is an overload on Query, however, that allows you to just specify the SPARQL command text.
A question that always comes up is how to bulk export and bulk import raw nTriples or RDF/XML into and out of the IMM Semantic Store.
Its actually quite simple. You should open up the RDFQA.exe application in the %Program Files%\Microsoft Interactive Media Manager\Semantic Metadata Store folder, connect to your database, and then execute the following commands.
USE IMM; Export data as [c:/backup/mydata.rdf];
var datas = new DataSource("inet?url=C:\\backup\\mydata.rdf.1&
parsetype=ntriples");
//insert {?p ?s ?o} into data using #datas where {?p ?s ?o};
LOAD {?p ?s ?o} INTO data USING #datas;
As you notice here I commented out the insert command. Insert can be used for small loads, but for larger bulk loads of nTriples or rdf/xml you should use the LOAD command. The LOAD command is targeted at bulk imports.
To parse ntriples, set the parsetype=ntriples. For Rdf/XML set the parsetype=rdf.
IMM is designed to enable users who work with rich media to ingest, manage, edit, and distribute content. While IMM is based on Office SharePoint Server 2007 and offers collaborative, enterprise content management, and search capabilities, IMM is designed specifically to work with media files, and has been modified to integrate with the wider media industry. Key to this is the addition of the IMM Semantic Metadata Store. IMM uses Semantic Web technologies to express, interchange, store and search media asset metadata. This is because RDF and OWL enable developers and users to add business specific and technical information to media assets. In the below vidcast, John Deutscher - Group Program Manager, spends a few minutes drilling into the IMM metadata model and reasons behind the decision to use the RDF standard:
We were recently in Las Vegas for the National Association of Broadcaster's (NAB) convention 2008 and produced a simple 19 minute video that shows the DEMO we presented. Eric Schoonover, Lead Solution Architect, takes you on the full tour of IMM v2.0 as it was shown at NAB 2008 (beta 1). This includes the IMM Silverlight-based Rough-Cut Editor, updated Media Library, project site creation, metadata management, Silverlight Inking, Media Services (based on WIC) and more.
Great conference, had a blast! Check it out:
Another NAB down, this has to be my 11th or 12th show and it's starting to feel a bit repetitive. One thing that did perk my interest at this year's show was a book. I always look forward to visiting the NAB book store to see what is new and pick up one of the latest broadcast reference compilations, but this time I spotted something different.
Since 2005, my team has been working to push web services standards into the broadcast and media industries on behalf of Microsoft. The first iteration of that was a project called Connected Services Framework for Media. My current project is an asset management system based on web services and Semantic Web standards called Interactive Media Manager. Throughout the journey I have met many smart people at NAB, but I have always looked forward to running into those who shared a similar, IT-based vision of the future for the M&E market.
I was so pleased when I saw John Footen's and Joey Faust's new book "The Service Oriented Media Enterprise". John is the Vice President of National TeleConsultants Software Solutions Group and high on my list of people that I wait to run into at NAB each year. We don't always agree on which technology stack to use, but that is beside the point. The point is that the industry should begin to adopt more open standards that enable interoperability and ease of integration between systems in complex workflows. This will lead to more manageable and reliable IT-based solutions in the broadcast industry. This is increasingly important as the whole industry moves to end-to-end file based workflows. John is a strong believer in this vision of Web Services and I was also excited to see that on page 493 he and Joey also recognize the need for Semantics in a media SOA.
"Semantic standards and technologies attempt to capture the true, human-understandable meaning behind all of those countless metadata standards and models."
"The Semantic Web is a powerful idea that is taking the IT industry by storm. The M&E industry, since it already deals so heavily in the creative expression of data and meaning, should take note and find ways to leverage the semantic technologies currently out there to develop enhanced library and asset management systems."
Thanks John for making my NAB a lot more interesting this year.
- John Deutscher (john.deutscher@microsoft.com)
Kirk Evans just put up an interview he did with Mark Kashman, IMM Product Manager, onto Channel9.
Check it out.
A continuation from the Part 1 article on how to define new custom Ontologies for use in IMM.
Once you have your properties and vocabulary defined, you now need to create classes to use those properties with. In IMM, there are a number of pre defined core classes that are used throughout the solution. Some examples of those include the VideoItem, AudioItem, and ImageItem classes. There are also some lower level base classes like MediaItem, Container, and Anchor that other classes can derive from. Most classes in IMM Core derive from the base IMM Object class.
To define your own classes, you have two choices, you can take an existing class such as VideoItem and add your own specific properties to it, or you can define your own custom class that is semantically different from the classes that IMM Core provides. Your custom classes should derive from one of the core types whenever possible.
Defining new custom Classes in OWL
To define a new class in SemanticWorks, just switch to the Classes tab and select the insert owl:Class button at the top of the tab page.
For this example, I am going to create a new Container type called Catalog. For sake of demonstration, I will define a Catalog as a virtual grouping of assets similar to a virtual folder in IMM, but in this case it may contain some more custom metadata and lets just say that it is semantically different than just a folder in the "Contoso" business rules.
So this new class would look like this in the Classes tab page.
Since our new Catalog can contain pointers to assets or other containers, we must set it to derive from the did:Container class in the IMM Core ontology.
To do so, click into the new cont:Catalog class and right click on the class. Select the add Subclass of menu option. Now, right click on the arrow subClassOf arrow and select add Class. From the drop down select the did:Container class.
You can now add custom properties and restrictions to this new class. I'll go back and create a new property called cont:ContainerName in the Contoso namespace, set it to type xsd:string, and then add it to the cont:Catalog class as a property restriction. The final class should look like this.
That's all there is to it. You can now get a lot fancier with defining more semantic information about your classes and their equivalents, etc...
Save the final OWL file for Contoso, and you should be able to generate .NET helper classes with the IMM 2.0 Visual Studio tools now. The tools will generate classes that derive from RdfObject tha can be used in IMM Workflows and your own custom web parts to create instances of RDF that will be valid within your custom ontology.