JeeWiz Home  
The Model-Driven System Builder

JeeWiz Architect's Guide
 
Contents  >   9.  Patterns
 


9.2 Ways to specify patterns

There are three ways to signal that a pattern should be used.

  • The most common technique is to create a 'preIncludeSpec.vm', 'extraIncludeSpec.vm' or 'includeSpec.vm' file and put it in the template/pattern directory for the object and meta-model it applies to. This defines a default pattern to be applied to all objects of a class. It is therefore used to convert a specification object into something richer. The fact that a pattern is being applied is not visible in the specification itself: it is implied by the existence of an appropriate includeSpec.vm file.

    The difference between these types of files is
    • the 'preIncludeSpec.vm' file is processed first and is designed to make minor adjustments to a model object in isolation or to its environment, purely dependent on the values in the model object, not on the values in other model objects. For example, the preIncludeSpec is used to create extra objects, like jars/assemblies for the UI under an application, or default primary keys for an entity, or to slightly massage the name or type of a field, such as making it start with a lower-case character or converting primitive data-types into their wrapped/boxed versions.

    • the 'extraIncludeSpec.vm' file is used to create or amend model objects using
      • the current model object
      • any of its children
      • peer objects, and their children, that are processed before the current model object (after reordering).
      For example, an 'attribute group' in a data-view-field defines a naming pattern to create new data-view-fields from the underlying entity; this feature is implemented in an extraIncludeSpec on the affected data-view-field, because it depends on the entity, which is processed earlier than the data-view-field.

      Another example is the relation end, which has a pattern to create key-maps for the relation if none are specified: this is done as an extraIncludeSpec pattern because it depends on the keys of the related entities and the list of keys can be changed by patterns.

      This type of pattern should not be used when it references a peer object of the context object (that the pattern is being run on). This situation commonly arises when there are relationships between two objects, and one of the objects creates a related object, such as when as service transfer object (STO) creates a UiView object. Because the STOs have relationships between themselves and the pattern references peer objects, this pattern must be done as an 'includeSpec' pattern, as described next.
    • the 'includeSpec.vm' file is the main pattern. It is used for all manner of jobs. Here are just a few examples:
      • the jar creates an IChangeSummary interface class, which is used by all data-views
      • the java-bean creates <method> objects for its getter and setter methods based on the fields specified
      • the various types of classes create their dependent objects, such as proxies, delegates, service interfaces, factories, local and home interfaces
      • many methods change properties - e.g. is a field writeable - depending on properties of their environment.
      Unlike the other two standard pattern file types, the includeSpec for a model object is done after its children's includeSpec processing. This means it can depend on any necessary children having been created by patterns. For example, the jar can depend on all the extra classes and interfaces having been created. This file must be used if it makes use of lower objects. This is why this is the main type of pattern: it is the one to use if you need to process children (as most patterns do).
  • Any object can also have patterns added as properties in the specification using the 'jw-pattern' (e.g. jw-pattern="singleton"). This can equivalently be spelt 'jwPattern=...'. (The capital 'P' is important!) These are specified as a comma-separated list (or as a list of nested '<jw-pattern>' or '<jwPattern>' elements), which name files to be searched for in the context of the current object. If there is no extension, '.vm' is added. This approach is used when we want to embellish a fundamental rendering, without disturbing existing patterns. For example, this is how we would specify the singleton pattern. It can then be applied to normal classes, business objects etc.

    These patterns are applied after the lower object patterns are applied, so they are like the includeSpec style of pattern. If an object has both patterns in the specification and an 'includeSpec.vm' file, the patterns in the specification are actioned first.

    It turns out that this technique is not as important as you might think, because it fixes the order of patterns being called. In practice, the most effective technique for adding patterns is to use Velocity's #parse method, and include extra files in the pattern. The #parse technique is used extensively in the standard patterns because it gives the additional flexibility of being able to change which files are included via #parse by overriding the pattern. This is not possible with the 'jw-pattern=' property.
  • Sometimes it is convenient to express the pattern in stages. For example, in the J2EE system for entity EJBs, we create a boilerplate ejbCreate method that takes a value object. But then, the ejbCreate methods are handled specially in the entity EJB patterns. So it makes sense to use two stages to the pattern: first, define the ejbCreate; then, do the pattern that will further process this.

    This is an example driven by modularity - not absolute necessity. But there are cases where you must break a pattern into stages - when the objects you are creating have different parents. For example, the standard CRUD patterns for J2EE map data-view objects (children of the backend jar/assembly) into screen objects (children of the UI jar/assembly). In this case, you must break the overall pattern into stages so the different created objects can be correctly created.

    This is done using the 'next-pattern' attribute on the current object. The first-stage pattern sets the "next-pattern" attribute. JeeWiz then recognises this immediately after processing the previous pattern, and runs the next pattern. This is a 'one-shot' attribute: it is reset before the next pattern is run. However, the next-pattern attribute can be set in a next-pattern too, so in theory any number of stages can be added on to a first pattern.
In the general case, there can be many pattern attributes values in the specification, which could invoke their own 'next-pattern', followed by the includeSpec.vm, which may also have 'next-pattern's.

Regardless of how a pattern file is recognised, we will use the generic term 'pattern' for these files that will add onto the specification.

 


Copyright (c) 2001-2008 New Technology/enterprise Ltd.