#### Feature references

[[feature-refs]]There are cases when a value range of a parameter of one feature spec is defined by a set of existing in the configuration model values of an ID parameter of another feature spec. In other words, a feature spec may declare certain parameters as references to ID parameters of another feature spec. (In a relational database, this would be a foreign key reference).

In a feature spec a simple feature reference would look like this

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP"/>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p"/>
   </params>
 </feature-spec>
----

Attribute `feature` of element `ref` contains the name of the referenced feature-spec. Note that we have not provided which parameter of `featureC` references the ID parameter of `featureP`. This example also demonstrates the *default (implicit) reference parameter mapping*.

IMPORTANT: The default reference parameter mapping rule is based on the expectation that the feature spec declaring the reference includes parameters with the names matching the ID parameter names of the referenced feature spec.

So the example above will work if one of the following statements is true:

. `featureP` declares parameter `p` and it is its only feature-id parameter;

. `featureP` declares parameter `name` and it is its only feature-id parameter;

. `featureP` declares parameters `name` and `p` as its feature-id parameters and has not other feature-id parameters.


.The complete set of a feature reference declaration attributes
[options="autowidth"]
|===
|Attribute name |Required |Default |Description

|*dependency* |false |null (current feature-pack or its dependencies) |The feature-pack dependency name the referenced feature spec belongs to.

|*feature* |true |null |The name of the referenced feature spec.

|*name* |false |The value of the *feature* attribute |Unique feature reference name.

|*nillable* |false |false |Whether a reference is nillable or not.

|*include* |false |false |Whether the referenced feature should automatically be included into the config model if it was not explicitly configured.
|===


##### Non-default reference parameter mapping

Instead of relying on the default reference parameter mapping rule, it is also possible to map the parameters in the reference declaration explicitly. The example below will correspond to the statement 1. from the example above.

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP">
       <param name="p" maps-to="p"/>
     </ref>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p"/>
   </params>
 </feature-spec>
----

Now let's suppose that `featureP` ID parameter is in fact `name` but we still want to use parameter `p` as the reference to `featureP`.

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP">
       <param name="p" maps-to="name"/>
     </ref>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p"/>
   </params>
 </feature-spec>
----

If `featureP` had more than one ID parameter, e.g.

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
   <params>
     <param name="id1" feature-id="true"/>
     <param name="id2" feature-id="true"/>
   </params>
 </feature-spec>
----

Then the reference parameter mapping in `featureC` could look like:

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP">
       <param name="p1" maps-to="id1"/>
       <param name="p2" maps-to="id2"/>
     </ref>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p1"/>
     <param name="p2"/>
   </params>
 </feature-spec>
----

##### Nillable feature references

IMPORTANT: Feature reference resolves to null if one of the feature reference parameters is null.

IMPORTANT: If a reference resolves to null and its not marked as nillable in the feature spec, the provisioning will fail with an error. Here is an example of a nillable reference declaration:

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP" nillable="true">
       <param name="p1" maps-to="id1"/>
       <param name="p2" maps-to="id2"/>
     </ref>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p1" nillable="true"/>
     <param name="p2"/>
   </params>
 </feature-spec>
----


##### External feature references

A feature may reference a feature from another feature-pack. The other feature-pack must be a (direct or transitive) dependency of the feature-pack the referencing feature belongs to.

NOTE: Unless the feature-pack of the referenced feature has not been explicitly specified, the mechanism will navigate the dependency tree of the feature-pack of the referencing feature and the first feature-pack containing a feature spec with the referenced feature spec name will be selected as the target.

Otherwise, the target feature-pack can be specified using `dependency` attribute of the feature reference declaration. The value of `dependency` attribute must match the value of `origin` element of the feature-pack dependency (the referenced feature spec belongs to) declaration in the `feature-pack.xml` file of the referencing feature spec.

For example, suppose, feature-pack `fp1` depends on feature-pack `fp2`.

[source,xml]
----
 <feature-pack xmlns="urn:jboss:galleon:feature-pack:2.0"
                location="fp1@maven(org.jboss.universe:community-universe):1#1.0.0">
    <dependencies>
        <dependency location="fp2@maven(org.jboss.universe:community-universe):2#2.0.0">
            <origin>fp2-dep</origin>
        </dependency>
    </dependencies>
 </feature-pack>
----

`fp2` includes feature spec `featureP`.

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
   <params>
     <param name="p" feature-id="true"/>
   </params>
 </feature-spec>
----

And `fp1` includes feature spec `featureC` which declares a reference to `featureP`

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref dependency="fp2-dep" feature="featureP"/>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p"/>
   </params>
 </feature-spec>
----

NOTE: It is expected that in most cases `dependency` attribute of element `ref` will not have to be used.

##### Implicit feature reference parameter initialization

[[feature-fk-init]]Let's suppose we have a parent-child relationship between two feature specs, e.g.

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureP">
   <params>
     <param name="parentId" feature-id="true"/>
   </params>
 </feature-spec>
----

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP"/>
   </refs>
   <params>
     <param name="childId" feature-id="true"/>
     <param name="parentId"/>
   </params>
 </feature-spec>
----

If we were to add features of these specs to a config, it could look like this

[source,xml]
----
 <config name="main">
   <feature spec="featureP">
     <param name="parentId" value="parent1"/>
   </feature>
   <feature spec="featureC">
     <param name="childId" value="child1"/>
     <param name="parentId" value="parent1"/>
   </feature>
 </config>
----

This approach is very verbose, the value for `parentId` parameter is set on every feature. There is a more compact way of expressing the same configuration using nesting, e.g.

[source,xml]
----
 <config name="main">
   <feature spec="featureP">
     <param name="parentId" value="parent1"/>
     <feature spec="featureC">
       <param name="childId" value="child1"/>
     </feature>
   </feature>
 </config>
----

Here, `parentId` parameter is initialized only once for the parent feature. `parentId` of the child feature will be implicitly initialized to the value of `parentId` of the parent.

IMPORTANT: When a feature is nested, the tool will look in the feature spec of the nested feature for a reference declaration with the name matching the outer feature spec and, if it is found, the tool will resolve the reference parameter mappings and will initialize the parameters of the child feature referencing the parent.

In case the reference name is different from the referenced feature spec name, i.e. it was explicitly set in the reference spec, e.g.
[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref feature="featureP" name="parent"/>
   </refs>
   <params>
     <param name="childId" feature-id="true"/>
     <param name="parentId"/>
   </params>
 </feature-spec>
----

Then the name of the reference has to be explicitly specified when the child feature is nested using the `parent-ref` attribute, e.g.
[source,xml]
----
 <config name="main">
   <feature spec="featureP">
     <param name="parentId" value="parent1"/>
     <feature spec="featureC" parent-ref="parent">
       <param name="childId" value="child1"/>
     </feature>
   </feature>
 </config>
----

NOTE: it is also possible to <<fg-in-features,include a feature-group as a child of the feature>>.

##### Implicit inclusion of referenced features into the configuration

It is possible to configure feature references so that when the resolved referenced feature ID is not found in the configuration model, instead of failing with the referential integrity constraint error, implicitly include the referenced feature into the configuration model initializing it with its default values. This is done by simply setting `include` attribute of the feature reference declaration to `true`.

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="featureC">
   <refs>
     <ref dependency="fp2-dep" feature="featureP" include="true"/>
   </refs>
   <params>
     <param name="name" feature-id="true"/>
     <param name="p"/>
   </params>
 </feature-spec>
----

##### Multiple references to the same feature spec

Suppose a feature needs to declare more than one reference to the same feature spec. For example let's model a chain using a feature spec called `link`. `link` must have an ID parameter, let's call it `id`. Then it has to include a parameter to reference the previous link and another parameter to reference the next link in the chain. The following, although looking right from the parameter mapping perspective, will clearly not work

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="link">
   <refs>
     <ref feature="link">
       <param name="prev-id" maps-to="id"/>
     </ref>
     <ref feature="link">
       <param name="next-id" maps-to="id"/>
     </ref>
   </refs>
   <params>
     <param name="id" feature-id="true"/>
     <param name="prev-id" nillable="true"/>
     <param name="next-id" nillable="true"/>
   </params>
 </feature-spec>
----

Feature references must have a unique name. In this case, both reference names are set to *link* and the provisioning tool will fail to process this spec. To workaround the error explicit names have to be assigned to the reference declarations, e.g.

[source,xml]
----
 <feature-spec xmlns="urn:jboss:galleon:feature-spec:1.0" name="link">
   <refs>
     <ref name="prev" feature="link">
       <param name="prev-id" maps-to="id"/>
     </ref>
     <ref name="next" feature="link">
       <param name="next-id" maps-to="id"/>
     </ref>
   </refs>
   <params>
     <param name="id" feature-id="true"/>
     <param name="prev-id" nillable="true"/>
     <param name="next-id" nillable="true"/>
   </params>
 </feature-spec>
----

##### Processing of features with references

One of the responsibilities of the provisioning tool is to order the features from the resolved configuration model for processing by the provisioning plugins that generate the final installation configuration files. While the general rule is to preserve the order in which the features where added to the configuration model, when feature `A` references feature `B`, feature `B` will get the priority and will be processed by the provisioning plugins before feature `A` to not break the referential integrity of the generated model (if it is significant for the consuming plugin).

##### Circular feature references

The provisioning mechanism is capable of identifying circular references (circular reference graphs). It does not throw an error if a circular reference graphs is detected. The responsibility of the provisioning mechanism is to make sure the configuration model is valid and all the referential integrity constraints are satisfied. From this point of view circular references are not illegal.

The issue with circular references is the ordering of the features when configuration model is processed by the product specific plugins that generate the final configuration files. In some cases the order of the features will not be significant but in some cases it will be. So the rule is 

IMPORTANT: When a circular reference graph is identified, the feature that was added to the configuration model first will be processed by the provisioning plugins first, the rest of the features from the graph will be processed respecting the references as usual.
