Fork me on GitHub

Contributors guide Edit on GitHub


Building Pomona

You can build Pomona using Visual Studio 2015 or Mono (4.2.3+).

Only standard .NET 4.5.1 assemblies need to be installed, all other assemblies is included in the repository or will be restored by nuget.

Design

Pomona was built from the bottom up. If some architectural decisions might seem arbitrary, it's probably because they are.

Architecture

Pomona architecture diagram

Request lifecycle

Code path of request

Routing

During early stages of Pomona development the intention was to let Nancy handle the routing. Unfortunately we ran into some corner cases related to child resource sets which was hard to fix.

As a result Pomona now has its own routing logic, inside the Pomona.Routing namespace. The routes are organized as a tree with the Route class as the base node type.

Route node types

  • DataSourceRootRoute - Default root / route, listing all root resources
  • DataSourceCollectionRoute - Route to collection of a root resource type, like /customers
  • GetByIdRoute - Route to an identified item in a collection, like /customers/{id}
  • ResourcePropertyRoute - Route to a child resource collection bound to a property of another resource, like /customers/{id}/contacts

Queries

Expression parsing

QueryExpressionParser will orchestrate the conversion of an expression as a string to a LINQ expression tree in the following way:

The lexing and parsing of an expression is performed using an ANTLR 3 compatible grammar named PomonaQueryParser. This grammar will create an initial abstract syntax tree .

The tree will then be transformed in PomonaQueryTreeParser to an intermediate form, with more semantic information and error checking.

Finally NodeTreeToExpressionConverter will convert the intermediate tree to a LINQ Expression.

Type mapping

Pomona has its own type system, which mirrors the CLR types combined with Pomona-specific mapping details and metadata.

Here's some different types of type specs (...)

  • RuntimeTypeSpec: For shared and primitive types, also the base class for other type specs
  • ResourceType: For structured types exposed at an URI as a resource
  • ComplexType: For structured types with no URI, can be inlined in other objects
  • EnumerableTypeSpec: Sequences and collections
  • AnonymousType: For anonymous types generated by C# compiler

By default most primitive types maps to RuntimeTypeSpec, and types implementing the IEnumerable interface maps to EnumerableTypeSpec.

All types specified in SourceTypes property of the PomonaConfigurationBase will be mapped to ResourceType by default.

This behavior can be changed through either Changing conventions or Fluent rules.

Querying the type system

Usually an end-user application will not need to touch the Pomona type system, so the information below is mostly for corner cases and contributors.

Converting from and to System.Type

A TypeSpec can be converted to its wrapped System.Type by either explicit or implicit casting.

To get a TypeSpec from a System.Type we need to use the FromType method of the ITypeResolver interface.

Ideas for future changes

Root resource

For a long time the plan has been to abandon the IPomonaDataSource interface, and instead rely on having a root resource with navigation properties to all root resources.