Angel \”Java\” Lopez on Blog

December 14, 2011

AjCoRe, A Simple Content Repository (2) Stores

Filed under: .NET, AjCoRe, Content Repository, Open Source Projects — ajlopez @ 10:04 am

Previous Post

I did some advances in my open source project AjCoRe, simple implementation of a content repository written in C#:

https://github.com/ajlopez/AjCoRe

If Content Repository is a new concept to you, check my links http://delicious.com/ajlopez/contentrepository and Roy Fielding’s JSR-170 overview .

Key concepts: there are Workspaces. Each workspace has a Root Node. Each Node can have Child Nodes, and Properties. A Property has a Name and a Value:

In the above diagram, nodes and workspaces are represented by interfaces. The idea is to have different implementations of that abstractions. In my previous post, I presented two such implementations: one representing a file system, allowing only read only operations. And another implementation, a more extensible one, using arbitrary nodes in memory. Since then, I added the support of saving and retrieving those arbitrary nodes using a store.

Now, the project looks:

where:

A: It is the concrete base implementation of workspace and nodes, based in memory, with the new support of having an optional store

B: The read-only implementation of workspace and nodes, representing an existing filesystem/directory

C: The new IStore (abstract) and the first concrete implementation, using a directory hierarchy and XML files to persists nodes in a workspace

D: The transaction support, during the lifetime of a session

Let’s see the new store capabilities. The Stores.IStore interface:

public interface IStore
{
    IEnumerable<string> GetChildNames(string path);
    PropertyList LoadProperties(string path);
    void SaveProperties(string path, PropertyList properties);
    void RemoveNode(string path);
}

Stores.Xml.Store is the first concrete implementation. Anyone could write another ones, using JSON, a relational database or a NoSQL backend. You can create, remove nodes, updated their properties, using a session, in the same way as in the previous post. BUT NOW, the workspace can be created injecting an IStore implementation in its constructor. Example (more details in the tests):

// Reference store in a directory
Store store = new Store("c:\\myworkspace");
// Workspace using that store to retrieve root node and their descendant
// (lazy loading)
Workspace workspace = new Workspace(store, "myws");
// Session accesing that workspace
Session session = new Session(workspace);
// You can use session to get the root node
// in case you have no direct workspace reference
INode root = session.Workspace.RootNode;
// Updates are made into a transaction
using (var tr = session.OpenTransaction())
{
    // Accessing a node
    INode node = root.ChildNodes["father"];
    // Changing a property
    session.SetPropertyValue(node, "Name", "Adam");
    
    // Creating a nodes    
    INode newnode = session.CreateNode(node, "newson", new Property[] {
                        new Property("Name", "Abel")
                    });
    
    // Removing a node
    session.RemoveNode(newson);
    tr.Complete();
}

The tr.Complete()  is in charge of updating the XML files where the properties of nodes are saved. An example file:

<?xml version="1.0" encoding="utf-8"?>
<Properties>
  <Name>John</Name>
  <Age type="int">35</Age>
  <Male type="bool">true</Male>
  <Hired type="datetime">2000-01-01T00:00:00</Hired>
  <Height type="double">167.2</Height>
  <Salary type="decimal">120000.5</Salary>
</Properties>

The key code in Transaction.Complete:

var nodestoupdate = 
    this.operations.Where(op => !(op is RemoveNodeOperation)).Select(op => op.Node).Distinct();
var nodestodelete = 
    this.operations.Where(op => op is RemoveNodeOperation).Select(op => op.Node).Distinct();
nodestoupdate = nodestoupdate.Except(nodestodelete);
foreach (var node in nodestoupdate)
    this.store.SaveProperties(node.Path, node.Properties);
foreach (var node in nodestodelete)
    this.store.RemoveNode(node.Path);

I could improve it, taken in account that some IStore implementation could prefer update each property, instead of a full node (I think in a database store).

I want to write another IStore implementation supporting JSON (I should design how to save the original type of each property). Other pending work: retrieve a node from a workspace using its full path, or query nodes (using XPath? Hmmm… I’m still in doubt).

Keep tuned!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

1 Comment »

  1. […] by AjCoRe, A Simple Content Repository (2) Stores « Angel “Java” Lopez on Blog — December 14, 2011 @ 10:04 am […]

    Pingback by AjCoRe, a simple Content Repository (1) First Steps « Angel “Java” Lopez on Blog — December 14, 2011 @ 10:05 am


RSS feed for comments on this post. TrackBack URI

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

Blog at WordPress.com.

%d bloggers like this: