Extension mechanisms

This topic presents an overview of extension mechanisms in the Spiralcraft Framework.

The framework imparts the property of extensibility on its applications in addition to being extensible itself via its API.

Because most of the forms of application code used with the framework have an extension mechanism, entire applications can be "subclassed" and specialized without duplication of code. This permits the development of maintainable domain specific sub-frameworks along with their own customized instances.

spiralcraft.builder

The spiralcraft.builder subsystem is a facility for defining an integration layer in an application or framework.

It assumes the role of a setter and constructor based dependency injection tool, with added extensibility features that go beyond the usual capabilites "configuration" tools.

While procedural programming code lives in Java classes, usually "parameterized" through the use of bean properties, declarative elements (eg. the initial values of the bean properties and interconnections between objects) tend to fall to a configuration mechanism.

Spiralcraft.builder was created out of the philosophy that declarative elements and the structural composition (ie. dependencies) of an application should be managed in their own flexible, extensible layer, in order to decouple Java classes from compositional specifics and thus maximize their re-use, and to enable the re-use of declarative and structural elements and thus remove complexity from the "configuration" layer.

Assembly extension

Assembly extension in spiralcraft.builder permits the creation of structural application building blocks which can be re-used by reference, customized, and combined to form ever-larger application components.

Assembly resolution is URI based as mapped by the VFS, so Assemblies can live anywhere inside or outside the VM classpath.

Assemblies can be constructed programmatically, or defined using a fluent XML syntax.

An Assembly can "extend" a basic POJO (Plain Old Java Object) to provide a pre-configured version.

 <!-- file <workspace>/myBuilder/MyWidget.assy.xml -->

 <myClasses:MyPOJO
   xmlns:myClasses="<workspace/myClasses/"
   >
    
   <!-- A simple, primitive bean property -->
   <durationMS>2000
   </durationMS>
 
   <!-- A bean property that references another Assembly. -->
   <!-- In this case, one that simple "extends" a POJO --> 
   <attachedWidget>
     <myClasses:MyOtherPOJO/>
   </attachedWidget>
 
 </myClasses:MyPOJO>

An Assembly can extend another to add further customization. The myBuilder:MyWidget tag name resolves to the declaration in the previous example via URI resolution and indicates that the Assembly being defined extends the myBuilder:MyWidget Assembly.

 <!-- file <workspace>/myBuilder/SpecificWidget.assy.xml -->
 
 <myBuilder:MyWidget
   xmlns:myBuilder="<workspace>/myBuilder/"
   >
   <name>CustomWidget
   </name>
 
   <durationMS>3000
   </durationMS>
 
   <!-- extend the inner Assembly defined in the super-Assembly 
        to provide a custom configuration within this Assembly 
   -->
   <attachedWidget.name>CustomAttachedWidget
   </attachedWidget.name>
 
   <attachedWidget.value>200
   </attachedWidget.value>
 
 </myBuilder:MyWidget> 

spiralcraft.lang

The spiralcraft.lang subsystem is an expression language system designed to bind application components together across multiple type systems.

The EL can navigate beans, static methods and metadata in the Java class namespace and data models exposed by spiralcraft.data, according to the contextual model provided by a container.

Containers, such as the built-in spiralcraft.builder and spiralcraft.webui and other special purpose and add-on implementations, define the set of objects reachable from the EL via the Focus chain.

The EL is compiled into a tree of Channels bound to points in one or more models or layers in the application (eg. the UI model, the data model, and the models provided by other integrated packages). The Channels comprise a data pathway that implements a computation or modifies the state of a referenced target based on a "current" model state.

Type Model Extension

The type system of spiralcraft.lang can be extended by implementing a Type Model- a set of Reflector implementations that supply type metadata and map names and method calls to appropriate implementation references.

This allows external type models to be integrated into applications, and allows spiralcraft.lang to provide EL capabilities to any application.

Channel Extension

Channels are data sources to the EL. A Channel provides a get() method, a set() method, and a reference to a Reflector that provides metadata. A Channel can be implemented to expose a custom data source to the EL, or to perform some generic transformation on the input or output of another Expression, in turn making the result available to the EL.

spiralcraft.data

Implements a Tuple based data engine with a an extensible type model. The spiralcraft.data subsystem is used for many purposes throughout the Spiralcraft Framework.

Type Definition

Primitive Types

These consist of letters, numbers, Strings, and other anonymous, immutable objects that are represented at runtime as Java objects.

New primitive types can be implemented by creating a Java class named <myFoo>Type that extends an element of the Type class hierarchy.

Primitive Domain Types

Primitive Domain types are extensions of Primitive types, where the natural range is further restricted by parameterization- eg. defining the maximum value, maximum size, set of allowed values, etc.,.

The parameters are applied either programmatically, or by using an XML type definition that defines a customized instance of the Java class of a Primitive type.

 <!-- defined in .../myMeta/Name.type.xml -->
 <String.type>
   <maxLength>128
   </maxLength>
 </String.type>

Complex Types

Complex types define Tuples (defined in the Spiralcraft framework as a set of named, typed values). They may be created programmatically by a TypeFactory implementation, or may be defined using an XML type definition that is comprised of a set of Fields, Keys, Methods and other definitions.

 <meta:Type
   xmlns:meta="class:/spiralcraft/data/types/meta/"
   xmlns:my="class:/org/myco/myapp/meta/"
   >
   <fields>
     <meta:Field>
         
       <name>firstName
       </name>
         
       <type><String.type/>
       </type>
 
     </meta:Field>
 
     <meta:Field>
         
       <name>lastName
       </name>
         
       <type><String.type/>
       </type>
 
     </meta:Field>
   </fields>
 </meta:Type>

Type Extension

Archetypes

A Type may have an optional Archetype, where the Type inherits the Archetype's member definitions and behavior by reference, and can add members and override behavior. This is roughly equivalent to OOP single inheritance.

Any instance of a Type derived from an Archetype is type compatible with the Archetype- ie. it can be passed to any component which expects the Archetype.

An Archetype is generally an anonymous type, and not an identified entity.

The Archetype itself is not instantiated, in this inheritance model.

An Archetype can be used as an interface, to allow components written to the Archetype to be bound to any data source implementing a subtype.

Base Types

A Type may have an optional Base Type, where the Type inherits the Base type's identity, member definitions, and behavior by delegation, and can add members and behavior. This is roughly equivalent to Single Table Inheritance in databases.

This type of data model inheritance is used when a set of items of different specific types share a common type, and are identified individually in a database, such as serialized parts tracked in a manufacturing operation.

A store can be queried for a base type, and may return multiple subtypes. The base type may enforce its own set of rules and relational integrity constraints.

A Base type typically has a primary key, which is shared by all its subtypes.

The base type and subtype are both instantiated. Their tuples are bound together as one in a delegation model and their life-cycle is synchronized.

spiralcraft.textgen

The textgen subsystem is a facility for generating streaming text, such as HTML, XML, data-merged e-mails, and a wide variety of other formats.

The markup language utilizes spiralcraft.builder to resolve and configure Element objects, which generate content and control processing, into an Element tree. The Element tree provides a hierarchical context reachable to the spiralcraft.lang expression language, which is used to bind Elements to points in the application model.

The textgen package can be extended by creating more complex Elements through spiralcraft.builder assemblies or by creating a new subclass of spiralcraft.textgen.Element.

Another means of achieving extensibility with textgen is to create a special purpose framework by using "wrapping includes" and content substitution to build a set of resources that can be customized by reference- ie. where customizations are set apart from the base resources.

spiralcraft.servlet.webui

The WebUI subsystem is driven by the textgen subsystem and adds a component model and a state management model for building server-side user interactivity into web applications.

WebUI can be extended by creating customizable application specific frameworks with Component assemblies, markup files and resources, and by creating new Components and Controls that expose server-side data models to end users and to client-side automation.