Extending ORM Attributes


ORM attributes are important feature of Skipper which allows edit all ORM-specific values. It is a common practice that users extend common set of ORM attributes by their own definitions and attributes. To accomodate this Skipper supports such extensions. All posibble types of attributes are defined in the <attribute-types> section of Skipper configuration file.

<attribute-types>
  <struct name="Module">
    <attribute name="Any name" type="string" />
  </struct>
  <struct name="Entity">
    <indexed name="Example of container">...</indexed>
  </struct>
</attribute-types>

Attributes are of two types: scalar and containers. Scalar attributes are defined in XML tag <attribute> with type attribute to configure specific scalar type. Container attributes have their own XML tag based on their type.

Scalars

Basic scalar types are: string, integer, float, bool.

<attribute name="name" type="string" />
<attribute name="age" type="integer" />

Enumerations

Special scalar types are enumerations of various types: enum, enumEditable, entity, field (check section Enumerations for more info). In Skipper, graphic editor enumeration types are edited via a drop-down list.

<attribute name="file-suffix" type="enum" enum-values=".dcm|.orm|without-suffix"/>

Containers

There are five types of container types, each with different XML tag:

Container Description
<struct> Basic structure, can contain any other attributes or containers.
<group> Similar to the struct but group is not visible in the property editor.
<unordered> Multi-item container. Items in this container are not ordered by any criteria.
<ordered> Same as <unordered> but items are ordered by position.
<indexed> Multi-item container holding a pair key-value. Container is ordered by key.

Example of ordered list of fields:

<ordered name="fields" type="field"/>

Example of ordered container with a single inner type lifecycle-callback:

<ordered name="lifecycle-callbacks">
  <struct name="lifecycle-callback">
    <attribute name="type" type="enum" enum-values="..."/>
    <attribute name="method" type="string"/>
  </struct>
</ordered>

Another example of ordered container with multiple item types (Versionable,Timestampable):

<ordered name="actAs">
  <struct name="Versionable">...</struct>
  <struct name="Timestampable">...</struct>
</ordered>

Attribute types description

Simple scalars

Basic scalar attributes are trivial. Following code shows definitions for the Trivial Module and the picture shows how it looks in the property editor. XML attributes help-text and help-url can be assigned to any scalar or container and are shown in the lower half of Properties window.

<struct name="Module">
  <attribute name="String of Characters" type="string"
             help-text="This is help for string attribute."
 			 help-url="http://www.google.com" />
  <attribute name="Integer Number" type="integer" />
  <attribute name="Floating Number" type="float" />
  <attribute name="Boolean Expression" type="bool" />
</struct>

Scalar ORM attributes

Enumerations

Enumerations are of two types: simple and callback. Simple enumeration has the list of posible values in its XML tag. Callback enumerations are filled automatically, based on the context. Here is an example attribute definition of all available enum types:

<struct name="Entity">
  <attribute name="Basic Enumeration" type="enum" enum-values="value1|value2|value3" />
  <attribute name="Editable Enumeration" type="enumEditable" enum-values="val1|val2" />
  <attribute name="Entity Callback" type="entity" />
  <attribute name="Field Callback" type="field" />
  <attribute name="This Entity Child Callback" type="entity" enum-values="child" />
  <attribute name="This Entity Parent Callback" type="entity" enum-values="parent" />
</struct>    

Note: Attribute enum-values is used only by the enum and the enumEditable type.

Here is a table explaining each attribute definition one-by-one:

Property Type Possible values
Basic Enumeration enum value1, value2 or value3
Editable Enumeration enumEditable val1, val2 or anything
Entity Callback entity any entity in the model
Field Callback field any field in this entity
Field Callback fieldOrAlias field or association alias of current entity

Sometime it’s usefull to show also filtered entities or fields from remote entity. For such situation there is enum-values attribute which for entity and field servers as destination descriptor.

Property Type Enum-values Possible values
Entity Child Callback entity child any child entity (associations,inheritance,…)
Entity Parent Callback entity parent any parent entity (associations,inheritance,…)
Entity fields callback field owner fields from owner entity (associations,embedded,…)
Entity fields callback field inverse fields from inverse entity (associations,embedded,…)
Entity fields callback field foreign fields from opposite entity (associations,embedded,…)
Entity fields callback field local fields from local entity (associations,embedded,…)

Note: Selectors are currently supported for following objects: ManyToManyEntity,Association.

And this is how it looks in the Skipper model and the property editor when you choose Sample entity:

Enumeration ORM attribute
Callback attribute example


Structure

Structure (with xml tag struct) is a container attribute. It serves for encapsuling multiple child attributes to a single structure. When it is created, each structure automatically contains all of the child attributes defined inside it (with NULL values).

<struct name="Project">
  <struct name="Structure">
    <attribute name="stAttr" type="string"/>
    <attribute name="stAttrInt" type="integer"/>
  </struct>
  <unordered name="Unordered">
    <attribute name="uAttr" type="string"/>
    <attribute name="uAttrInt" type="integer"/>
  </unordered>
  <ordered name="Ordered">
    <attribute name="oAttr" type="string"/>
    <attribute name="oAttrInt" type="integer"/>
  </ordered>
  <indexed name="Indexed">
    <attribute name="iAttr" type="string"/>
    <attribute name="iAttrInt" type="integer"/>
  </indexed>
</struct>

<img title=”Structure ORM attribute” alt=”Structure ORM attribute” src=”title=”/images/expert-usage/extending-orm-attributes/4_ormd-structure-attr.png” />

External type definition

External type definition serves for declaring complex attribute structs externaly, and including the external structs from several locations. External structures are referred by their path and name.

<attribute-types>
  <struct name='Module'>
	<ordered name='ordered-struct' type='/external-struct'/>
	<struct name='struct-struct' type='/external-struct'/>
    <indexed name="indexed-struct" type='/external-struct' />
  </struct>

  <struct name='external-struct'>
	<attribute name='Description' type='string'/>
	<attribute name='Number' type='integer'/>
  </struct>
</attribute-types>

External structure ORM attribute

Group

Group container is very similar to the structure container. Group container also serves as the child encapsuler. Only difference from the struct is that the group container is not visually represented. This means that whenever you refer to this attribute, only the child elements will be used and displayed. Group container is mostly used when refering to an external group of attributes.

<attribute-types>
  <struct name='Module'>
	<ordered name='ordered-group' type='/external-group'/>
	<struct name='struct-group' type='/external-group'/>
	<indexed name="indexed-group" type='/external-group' />
  </struct>

  <group name='external-group'>
	<attribute name='Description' type='string'/>
	<attribute name='Number' type='integer'/>
  </group>
</attribute-types>

External group ORM attribute

Inherited Attribute

Next useful feature is attribute type inheriting. It is common that some group of attributes contains the same set of the child attributes. Instead of repetitive declaring the same child elements you can define base attribute and derive all the other attributes from it. In next example you can see how alphaNumberic and equalTo attributes derive from the ValidatorBase attribute.

<skipper-configuration>
  <orm-configuration name="CakePHP2">
    <attribute-types>
      <struct name="Field">
        <ordered name="validator" type="/Validators"/>
      </struct>

      <group name="Validators">
        <struct name="alphaNumeric" inherit="../../struct[@name='ValidatorBase']" >
          <attribute name="value" type="integer"/>
        </struct>
        <struct name="equalTo" inherit="../../struct[@name='ValidatorBase']" />
      </group>

      <struct name="ValidatorBase">
        <attribute name="name" type="string"/>
        <attribute name="required" type="bool"/>
      </struct>
    </attribute-types>
  </orm-configuration>

  <mvc-support-orm mvc-name="Without MVC" orm-name="CakePHP2" />
</skipper-configuration>

Note: Attribute type inheritance is evaluated during the XML configuration loading. This means that the inherit attribute has to be xpath.

CakePHP validators