Excluding Facts

Most patterns will call for the specification to exclude facts that meet certain criteria. These criteria are expressed in terms of the existence of successors.

Not Any

Use !facts.Any<T> to write a condition based on existence. Pass in a predicate to trace a path to facts of type T. This will exclude the fact if any matching successor exists.

For example, the user might want to delete an album. This would be supported with the following model:

%0 Album.Delete Album.Delete Album Album Album.Delete->Album album Jinaga.User Jinaga.User Album->Jinaga.User creator

You can write a specification that excludes albums that have been deleted. Use a where clause to only include albums that do not have an AlbumDelete fact.

var albumsByUser = Given<User>.Match((user, facts) =>
    from album in facts.OfType<Album>()
    where album.creator == user &&
        !facts.Any<AlbumDelete>(delete => delete.album == album)
    select album);

Go one level deeper to implement the restore pattern. Add an AlbumRestore fact to the model.

%0 Album.Restore Album.Restore Album.Delete Album.Delete Album.Restore->Album.Delete delete Album Album Album.Delete->Album album Jinaga.User Jinaga.User Album->Jinaga.User creator

Then modify the specification to exclude albums that have been deleted but not restored.

var albumsByUser = Given<User>.Match((user, facts) =>
    from album in facts.OfType<Album>()
    where album.creator == user &&
        !facts.Any<AlbumDelete>(delete => delete.album == album &&
            !facts.Any<AlbumRestore>(restore => restore.delete == delete))
    select album);

Any

You can also go in the opposite direction. You can include only those facts that have a certain successor. For example, on the checkout screen, you might want to list only the carts that contain at least one item.

var cartsToCheckOut = Given<Environment, User>.Match((environment, user, facts) =>
    from customerBuyer in facts.OfType<CustomerBuyer>()
    where customerBuyer.buyer == user
    from customer in facts.OfType<Customer>()
    where customerBuyer.customer == customer
    where customer.environment == environment
    from cart in facts.OfType<Cart>()
    where cart.customer == customer &&
        facts.Any<CartItem>(cartItem => cartItem.cart == cart)
    select cart);

Continue With

Selecting Projections

Jinaga is a product of Jinaga LLC.

Michael L Perry, President