JDF Blog

Tools, techniques and advice for real-world JDF integrations

First Look at Fluent JDF

with one comment

We have made quite a bit of progress implementing our vision for a truly fluent .NET library for authoring, navigating and transmitting JDF. Although we are not quite ready for an official release, the API is stable enough and functional enough to use.  The project is up at Codeplex and we’re also releasing stable builds on NuGet. It is open source under the commercial-friendly New BSD license.

Getting Started
The easiest way to get started is to head over to NuGet and download the current Fluent JDF package.   You can use it in a project or via LinqPad.

LinqPad is a cool .NET tool that, among other things, lets you write and execute C# code snippets.   As you will see here, it makes a great JDF tool when you hook it up with Fluent JDF.  If you do decide to use LinqPad, I highly recommend purchasing the Intellisense option for $39.  Make sure to download LinqPad for .NET 4.o because that’s the only framework Fluent JDF supports at the moment.  We are looking at adding support for .NET Framework 3.5 in the near future.

Anyway, once you add the NuGet package to a Visual Studio project, you will end up with a folder named packages/FluentJdf.[version number]/tools in the same directory as your project.  Use LinqPad to open FluentJdfSample.linq from there and press the run button.  You should see something like the following:

LinqPad Screenshot

Figure 1 -- LinqPad after running the basic sample. Click to enlarge.

Authoring JDF
Let’s start building a JDF intent ticket.  Replace the Main() function in the sample with the following code and run it:

void Main()
{
	InitializeFluentJdf();

	var ticket = Ticket.CreateIntent().WithInput().BindingIntent().Ticket;
	ticket.Dump();
}

InitializeFluentJdf() sets up everything the library needs. If you are writing your own application, make sure to run the initialization code only once at the beginning of your program. Dump() is provided by LinqPad to show the results in LinqPad’s lower pane. I’m not going to show the initialization code or the dump call after this, but you’ll want to leave them in place.

Dumping the ticket gives us the following xml:

<JDF Type="Product" xsi:type="Product" ID="R_0e748" Status="Waiting" JobID="J_bde70" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="1.4" xmlns="http://www.CIP4.org/JDFSchema_1_1">
  <AuditPool>
    <Created AgentName="Fluent JDF (Debug DB: 0)" AgentVersion="0.1.3.0" Author="Fluent JDF (Debug DB: 0)" TimeStamp="2011-07-20T18:27:53.8916546Z" />
  </AuditPool>
  <ResourcePool>
    <BindingIntent ID="R_c53c4" />
  </ResourcePool>
  <ResourceLinkPool>
    <BindingIntentLink rRef="R_c53c4" Usage="Input" />
  </ResourceLinkPool>
</JDF>

As you can see, Fluent JDF automatically handled quite a few details.  The namespace is set correctly, the Version attribute is set, the root JDF has a unique JobID, the binding intent resource is linked properly and placed in the resource pool and it even created a basic audit event.  Not bad for one short line of code.

Let’s add an output component.  The authoring code now looks like this:

var ticket = Ticket.CreateIntent().WithInput().BindingIntent()
  .WithOutput().Component()
  .Ticket;

And the JDF is pretty much what you’d expect:

<JDF Type="Product" xsi:type="Product" ID="R_3f9cc" Status="Waiting" JobID="J_b3991" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="1.4" xmlns="http://www.CIP4.org/JDFSchema_1_1">
  <AuditPool>
    <Created AgentName="Fluent JDF (Debug DB: 0)" AgentVersion="0.1.3.0" Author="Fluent JDF (Debug DB: 0)" TimeStamp="2011-07-20T18:29:18.7515083Z" />
  </AuditPool>
  <ResourcePool>
    <BindingIntent ID="R_7ca3d" />
    <Component ID="R_36136" />
  </ResourcePool>
  <ResourceLinkPool>
    <BindingIntentLink rRef="R_7ca3d" Usage="Input" />
    <ComponentLink rRef="R_36136" Usage="Output" />
  </ResourceLinkPool>
</JDF>

How about setting some attributes on the BindingIntent resource?

var ticket = Ticket.CreateIntent()
  .WithInput().BindingIntent().With().Id("myId").Attribute("BindingLength", "Short")
  .WithOutput().Component()
  .Ticket;

This code gives the BindingIntent node specific values for the Id and BindingLength attributes. By the time we release we’ll have attribute setters for all the key attributes. For now, you’ll have to use the Attribute function as shown here.

The JDF includes the attributes we set. Notice how FluentJdf automatically fixed the rRef in the BindingIntentLink to match the new ID value of the resource.

<JDF Type="Product" xsi:type="Product" ID="R_67f3e" Status="Waiting" JobID="J_4900f" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="1.4" xmlns="http://www.CIP4.org/JDFSchema_1_1">
  <AuditPool>
    <Created AgentName="Fluent JDF (Debug DB: 0)" AgentVersion="0.1.3.0" Author="Fluent JDF (Debug DB: 0)" TimeStamp="2011-07-20T18:29:56.8136853Z" />
  </AuditPool>
  <ResourcePool>
    <BindingIntent ID="myId" BindingLength="Short" />
    <Component ID="R_1d2fe" />
  </ResourcePool>
  <ResourceLinkPool>
    <BindingIntentLink rRef="myId" Usage="Input" />
    <ComponentLink rRef="R_1d2fe" Usage="Output" />
  </ResourceLinkPool>
</JDF>

It’s also easy to nest JDF elements. For example, consider the following code:

var ticket = Ticket.CreateIntent()
  .WithInput().BindingIntent().With().Id("myId").Attribute("BindingLength", "Short")
  .WithOutput().Component()
  .AddIntent()
    .WithInput().ArtDeliveryIntent()
  .Ticket;

That puts an intent node with an input ArtDeliveryIntent into the root JDF node:

<JDF Type="Product" xsi:type="Product" ID="R_485ee" Status="Waiting" JobID="J_fab72" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="1.4" xmlns="http://www.CIP4.org/JDFSchema_1_1">
  <AuditPool>
    <Created AgentName="Fluent JDF (Debug DB: 0)" AgentVersion="0.1.3.0" Author="Fluent JDF (Debug DB: 0)" TimeStamp="2011-07-20T18:30:22.0811305Z" />
  </AuditPool>
  <ResourcePool>
    <BindingIntent ID="myId" BindingLength="Short" />
    <Component ID="R_d0313" />
  </ResourcePool>
  <ResourceLinkPool>
    <BindingIntentLink rRef="myId" Usage="Input" />
    <ComponentLink rRef="R_d0313" Usage="Output" />
  </ResourceLinkPool>
  <JDF Type="Product" xsi:type="Product" ID="R_f2a94" Status="Waiting" JobPartID="JP_98ab0">
    <ResourcePool>
      <ArtDeliveryIntent ID="R_e1907" />
    </ResourcePool>
    <ResourceLinkPool>
      <ArtDeliveryIntentLink rRef="R_e1907" Usage="Input" />
    </ResourceLinkPool>
  </JDF>
</JDF>

The last thing I want to show you is how to add a sub-element to a resource. For example, let’s put an ArtDelivery inside the ArtDeliveryIntent:

var ticket = Ticket.CreateIntent()
  .WithInput().BindingIntent().With().Id("myId").Attribute("BindingLength", "Short")
  .WithOutput().Component()
  .AddIntent()
    .WithInput().ArtDeliveryIntent().AddNode(Element.ArtDelivery)
  .Ticket;

AddNode lets you add any node you want to another node. We plan to keep this method especially for custom elements. However, we will be adding specific add methods for legal child elements based on the standard. It produces exactly the kind of results you’d expect:

<JDF Type="Product" xsi:type="Product" ID="R_432fc" Status="Waiting" JobID="J_2b6da" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="1.4" xmlns="http://www.CIP4.org/JDFSchema_1_1">
  <AuditPool>
    <Created AgentName="Fluent JDF (Debug DB: 0)" AgentVersion="0.1.3.0" Author="Fluent JDF (Debug DB: 0)" TimeStamp="2011-07-20T18:31:08.6927966Z" />
  </AuditPool>
  <ResourcePool>
    <BindingIntent ID="myId" BindingLength="Short" />
    <Component ID="R_4fb0e" />
  </ResourcePool>
  <ResourceLinkPool>
    <BindingIntentLink rRef="myId" Usage="Input" />
    <ComponentLink rRef="R_4fb0e" Usage="Output" />
  </ResourceLinkPool>
  <JDF Type="Product" xsi:type="Product" ID="R_82204" Status="Waiting" JobPartID="JP_c98a4">
    <ResourcePool>
      <ArtDeliveryIntent ID="R_9ec11">
        <ArtDelivery />
      </ArtDeliveryIntent>
    </ResourcePool>
    <ResourceLinkPool>
      <ArtDeliveryIntentLink rRef="R_9ec11" Usage="Input" />
    </ResourceLinkPool>
  </JDF>
</JDF>

Getting Additional Help
We’re working on a set of getting started tutorials and screen casts. We’ll announce them here when they become available. If you have questions or ideas about what you’d like us to cover in the tutorials, post them on our discussion group.

Advertisements

Written by Tom Cabanski

July 20, 2011 at 6:45 pm

Posted in FluentJDF

One Response

Subscribe to comments with RSS.

  1. […] navigating and transmitting JDF, for the last several weeks.  I just posted an article on how to get started over at the JDF […]


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: