Chapter 14. Dynamic Models

Jadex offers the possibility to change the underlying agent and capability models at runtime, i.e. it is e.g. easily possible to define new beliefs, goals and plans and the like at runtime. For this purpose every capability and agent instance owns it own copy of the underlying model. In this respect changes to a model remain local to the corresponding capability or agent instance, and the original model contained in the ADF will never be changed this way.

The process for creating model elements at runtime is very simple in principle. It consists of two steps:

Similarly, it is possible to delete elements from the model in two steps:

14.1. Adding/Removing Capabilities at Runtime

Using the model API (package jadex.model) plans can dynamically load and unload capabilities. To load a capability, you first have to create a so called capability reference in the agent (or capability) model. The createCapabilityReference() method works the same as the <capability> tag shown in Figure 5.3, “Including subcapabilities”, and therefore expects the local name of the subcapability and a filename. After creating the reference, which also loads the given XML file, you can register the new capability at runtime (this will initialize the capability by creating initial goals, plans, etc.). To use the features of the capability you can also dynamically add references to the exported beliefs and goals of the capability. Figure 14.1, “Adding a capability at runtime” shows how to include a capability at runtime.

public void body() {
    // Create reference in the model.
    IMCapability model = (IMCapability)getScope().getModelElement();
    IMCapabilityReference subcap = model.createCapabilityReference("dfcap",
        "jadex.planlib.DF");

    // Register capability at runtime.
    getScope().registerSubcapability(subcap);
    ...
}

Figure 14.1. Adding a capability at runtime

The removal of a capability can be done likewise. In Figure 14.2, “Removing a capability at runtime” an example code is depicted.

public void body() {
    ...
    IMCapabilityReference subcap = ((IMCapability)getScope().getModelElement())
        .getCapabilityReference("subcap_name");

    // Deregister subcapability at runtime.
    getScope().deregisterSubcapability(subcap);

    // Delete subcapability from the model.
    ((IMCapability)getScope().getModelElement()).deleteCapabilityReference(subcap);
    ...
}

Figure 14.2. Removing a capability at runtime

14.2. Creating/Deleting Beliefs at Runtime

Usually all agent beliefs are defined in the ADF. At runtime only the facts contained in the beliefs change, not the beliefs themselves. The model API (package jadex.model) allows to dynamically create new beliefs and belief sets at runtime, if this self-modifying functionality is required. To create a new belief, it first has to be defined in the agent or capability model. The createBelief...() methods of the IMBeliefbase work the same as the belief/set/reference tags shown in Figure 6.1, “The Jadex beliefs XML schema part”. For beliefs and belief sets a name, class, update rate and exported flag have to be specified. For belief(set) references instead of an update rate the path of the referenced belief(set) has to be provided.

After creating a belief(set) or reference in the model, you have to register the new element at runtime (this will also evaluate the initial facts, if you have supplied some in the model). Figure 14.3, “Creating a belief at runtime” shows how to create a belief at runtime.

public void body() {
    ...
    // Create belief in the model.
    IMBeliefbase model = (IMBeliefbase)getBeliefbase().getModelElement();
    IMBelief belief = model.createBelief("name", String.class, -1, false);

    // Register belief at runtime.
    getBeliefbase().registerBelief(belief);
    ...

    // Access the belief as usual.
    getBeliefbase().getBelief("name").setFact("Hugo");
    ...
}

Figure 14.3. Creating a belief at runtime

In Figure 14.4, “Deleting a belief at runtime” it is shown how a belief can be deleted at runtime.

public void body() {
    ...
    IBelief belief = getBeliefbase().getBelief("belief_name");
    IMBelief mbelief = (IMBelief)belief.getModelElement();

    // Deregister the belief at runtime.
    getBeliefbase().deregisterBelief(mbelief);

    // Delete the belief in the model.
    IMBeliefbase model = (IMBeliefbase)getBeliefbase().getModelElement();
    model.deleteBelief(mbelief);
    ...
}

Figure 14.4. Deleting a belief at runtime

14.3. Creating/Deleting Goal Types at Runtime

Usually all goal types (like, e.g., “performpatrol”) are defined in the ADF. At runtime instances of these types are created, but the set of available goal types remains the same. The model API (package jadex.model) allows to dynamically create new goal types and goal references at runtime, if this self-modifying functionality is required. To create a new goal type, it first has to be defined in the agent or capability model. The create...Goal() and create...GoalReference() methods of the IMGoalbase work the same as the tags shown in Figure 7.1, “The Jadex goals XML schema part”. For goals, a name, exported flag, retry, retry delay, and exclude mode are required. Maintain goals require in addition the specification of recur and recur delay. For references, the name, the exported flag, and the path to the referenced goal have to be specified.

After creating a goal or reference in the model, you have to register the new element at runtime (this will also activate the creation condition, if you have supplied one in the model). Figure 14.5, “Creating a new goal type at runtime” shows how to create a new goal type at runtime.

public void body() {
    ...
    // Create goal type in the model.
    IMGoalbase model = (IMGoalbase)getGoalbase().getModelElement();
    IMGoal goal = model.createPerformGoal("performpatrol", false, true, -1,
        IMGoal.EXCLUDE_NEVER);
    goal.createContextCondition("!$beliefbase.is_loading && !$beliefbase.daytime");

    // Register goal at runtime.
    getGoalbase().registerGoal(goal);
    ...
}

Figure 14.5. Creating a new goal type at runtime

An example for the deletion of a goal type at runtime is shown in Figure 14.6, “Deleting a goal type at runtime”.

public void body() {
    ...
	// Assuming that mgoal is the model of the element to be deleted

    // Deregister goal at runtime.
    getGoalbase().deregisterGoal(mgoal);

    // Delete goal type from the model.
    IMGoalbase model = (IMGoalbase)getGoalbase().getModelElement();
    model.deleteAchieveGoal((IMAchieveGoal)mgoal);
    ...
}

Figure 14.6. Deleting a goal type at runtime

14.4. Creating/Deleting Plan Types at Runtime

Adding new plan specifications to the agent or capability at runtime is similar to what has already been described for beliefs and goals. First the plan head has to be created using the API of the jadex.model package. Afterwards, the plan has to be registered at runtime, mainly for activating the plan trigger.

public void body() {
    ...
    // Create plan type in the model.
    IMPlanbase model = (IMPlanbase)getPlanbase().getModelElement();
    IMPlan plan = model.createPlan("ping", 0, "new PingPlan()", IMPlanBody.BODY_STANDARD);
    plan.createTrigger().createMessageEvent("query_ping");

    // Register plan at runtime.
    getPlanbase().registerPlan(plan);
    ...
}

Figure 14.7. Creating a new plan type at runtime

In the following the deletion of a plan type is sketched (see Figure 14.8, “Deleting a plan type at runtime”).

public void body() {
    ...
	// Assuming that mplan is the model of the element to be deleted

    // Deregister plan at runtime.
    getPlanbase().deregisterPlan(mplan);

    // Delete plan type in the model.
    IMPlanbase model = (IMPlanbase)getPlanbase().getModelElement();
    model.deletePlan(mplan);
    ...
}

Figure 14.8. Deleting a plan type at runtime

14.5. Creating/Deleting Event Types at Runtime

In general it is possible to create custom events at runtime. This applies for goal, message as well as internal events. Nevertheless, as goal events are used only internally creating message and internal events should be the only relevant use case.

In Figure 14.9, “Creating a new internal event type at runtime” an example is depicted how a new internal event can be created and registered.

public void body() {
    ...
    // Create event type in the model.
    IMEventbase model = (IMEventbase)getEventbase().getModelElement();
    IMInternalEvent ievent = model.createInternalEvent("new_ievent", false);
    ievent.createParameter("param1", String.class, IMParameter.DIRECTION_IN, 0, null, null);

    // Register event at runtime.
    getEventbase().registerEvent(ievent);
    ...
}

Figure 14.9. Creating a new internal event type at runtime

In Figure 14.10, “Deleting an internal event type at runtime” the removal of an internal event at runtime is outlined.

public void body() {
    ...
    // Assuming that imevent is the model of the event to be deleted

    // Deregister event at runtime.
    getEventbase().deregisterEvent(imevent);

    // Delete event type in the model.
    IMEventbase model = (IMEventbase)getEventbase().getModelElement();
    model.deleteInternalEvent(imevent);
    ...
}

Figure 14.10. Deleting an internal event type at runtime