11.3. Modification d'un slot

La modification d'un slot équivaut à modifier une ou plusieurs facettes du descripteur de slot et nécessite la création d'un modificateur de facette. Une facette est un objet qui représente l'état d'une des propriétés d'un slot, or la modification de la représentation d'une propriété ne se traduit pas par la modification de la propriété elle-même. C'est pourquoi lorsque l'on souhaite apporter une modification à l'une des facettes d'un slot, comme lorsque l'on souhaite définir une nouvelle facette, il faut appliquer un objet spécifique au slot, objet appelé modificateur de facette et qui décrit quels sont les changements désirés.

A chaque descripteur de slot est potentiellement associée une facette de type, une facette de documentation et une facette d'inférence. Plusieurs méthodes de lecture de l'état d'une facette pour un descripteur de slot donné sont proposés par l'API d'AROM :

Mais quelque soit la méthode choisie, et par conséquent l'objet obtenu en retour, il n'est pas autorisé de modifier directement cet objet. L'exemple qui suit illustre les deux cas de modification que sont la définition d'une nouvelle facette et la modification d'une facette existante.

Exemple 11-2. Modification de slots


import arom.AromSetUp;
import arom.kr.factory.AromSystem;
import arom.kr.factory.ModifierFactory;
import arom.kr.model.AMClass;
import arom.kr.model.KnowledgeBase;
import arom.kr.model.type.TypeSystem;
import arom.kr.model.type.CType;
import arom.kr.model.Variable;
import arom.kr.model.InvalidNameException;
import arom.kr.model.VariableDescriptor;
import arom.kr.model.EntityCreationException;
import arom.kr.model.NoSuchEntityException;
import arom.kr.model.modifiers.InvalidModifierException;
import arom.kr.model.modifiers.CTypeModifier;
import arom.kr.model.modifiers.FacetModifier;
import arom.kr.model.modifiers.InferenceModifier;
import java.util.Iterator;
import java.util.Vector;
import arom.kr.model.modifiers.DomainModifier;
import arom.kr.model.modifiers.DefaultValueModifier;
import arom.kr.model.modifiers.TypeModifier;

/**
 * ModifySlot.java
 *
 *
 * @author Veronique DUPIERRIS
 */

public class ModifySlot {

  /**
   * Cette methode cree une nouvelle base de connaissances nommee "BaseTest" et
   * cree un ensemble de classes dans cette base. Cet ensemble comprend : la
   * classe racine 'Personne' specialisee par les classes 'Homme'et 'Femme'.
   * La variable 'sexe' est associee a la classe 'Personne'.
   *
   * @return l'object KnowledgeBase representant la nouvelle base de 
   * connaissances.
   */
  public static KnowledgeBase createKb(){
    String kbName = "BaseTest";
    AromSystem kbFactory = AromSetUp.getAromSystem();

    // Recupere l'objet permettant de creer les modifieurs de facettes
    ModifierFactory modifierFactory = AromSetUp.getAromSystem().getModifierFactory();
    
    KnowledgeBase kb = null;
    try{
      kb = kbFactory.createKB(kbName, new Object[0]);
      AMClass personne = kb.createClass("Personne", null);
      AMClass femme = kb.createClass("Femme", personne);
      AMClass homme = kb.createClass("Homme", personne);	
      //Cree la variable sexe
      FacetModifier[] modifiers = new FacetModifier[1];
      modifiers[0] = modifierFactory.createCTypeModifier(kbFactory.getTypeSystem().getStringCType());
      personne.createVariable("sexe", modifiers);
    } catch(EntityCreationException ece){
      System.out.println("Une erreur est survenue lors de la creation de la base : ");
      System.out.println(ece.getMessage());
      //Arrete le System Arom proprement
      AromSetUp.getAromSystem().cleanup();
      System.exit(1);
    } catch(InvalidNameException ine) {
      System.out.println("Une erreur est survenue lors de la creation de la base: ");
      System.out.println(ine.getMessage());
      //Arrete le System Arom proprement
      AromSetUp.getAromSystem().cleanup();
      System.exit(1);
    }
    return kb;
  }
    
  /**
   * Cette modifie le domaine de la variable 'sexe' pour la classe 'Femme'
   * et une valeur par default est definie pour la classe 'Homme'.
   *
   * @param kb la base de connaissance contenant les classes 'Personne', 
   * 'Homme' et 'Femme'
   */
  public static void modifySlots(KnowledgeBase kb){
    
    AMClass homme = kb.lookupClass("Homme");
    AMClass femme = kb.lookupClass("Femme");
    Variable sexe = femme.lookupVariable("sexe");

    // Recupere l'objet permettant de creer les modifieurs de facettes
    ModifierFactory modifierFactory = AromSetUp.getAromSystem().getModifierFactory();
    
    // Modifie le domaine de la variable 'sexe':
    Vector newValues =  new Vector();
    newValues.add("f");

    // Cree un nouveau modificateur de domaine (definit un ensemble) pour la facettes
    // de type.
    Object[] args = { newValues }; 
    DomainModifier nvDomain = modifierFactory.createDomainModifier(ModifierFactory.SET_MODIFIER, args);
    
    //applique ce modificateur a la variable sexe pour la classe femme
    // ... donc au descripteur de la variable associe a la classe Femme.
    try {
      VariableDescriptor femmeSexe = sexe.getVariableDescriptionFor(femme);
      femmeSexe.applyTypeModifier(nvDomain);
    } catch(NoSuchEntityException nsee){
      System.out.println("La variable n'est pas defini pour la classe 'femme': ");
      System.out.println(nsee.getMessage());	    
      //Arrete le System Arom proprement
      AromSetUp.getAromSystem().cleanup();     
      System.exit(1);
    } catch(InvalidModifierException ime) {
      System.out.println("Une erreur est survenue lors de l'application du modifier: ");
      System.out.println(ime.getMessage()); 
      //Arrete le System Arom proprement
      AromSetUp.getAromSystem().cleanup();
      System.exit(1);
    }
    
    // definit une valeur par defaut pour la variable 'sexe' de la classe 'Homme' 
    // cree un nouveau modificateur de facettes
    args = new Object[1];
    args[0] = "h";
    InferenceModifier defaultValueModifier = modifierFactory.createInferenceModifier(ModifierFactory.DEFAULT_VALUE_MODIFIER, args);
    
    // applique ce modificateur au descripteur de la variable sexe
    // pour la classe Homme.
    try {
      VariableDescriptor hommeSexe = sexe.getVariableDescriptionFor(homme);
      hommeSexe.applyInferenceModifier(defaultValueModifier);
    } catch(NoSuchEntityException nsee){
      System.out.println("La variable n'est pas definie pour la classe 'homme': ");
      System.out.println(nsee.getMessage());
      //Arrete le System Arom proprement
      AromSetUp.getAromSystem().cleanup();
      System.exit(1);
    } catch(InvalidModifierException ime) {
      System.out.println("Une erreur est survenue lors de l'application du modifier: ");
      System.out.println(ime.getMessage());	    
      //Arrete le System Arom proprement
      AromSetUp.getAromSystem().cleanup();
      System.exit(1);
    }
    
  }
  
  public static void main(String[] args){
    
    KnowledgeBase kb = createKb();
    modifySlots(kb);
    AMClass homme = kb.lookupClass("Homme");
    Variable sexe = homme.lookupVariable("sexe");
    
    if(homme == null) {
      System.out.println("la classe Homme est introuvable !");
      //Arrete le System Arom proprement
      AromSetUp.getAromSystem().cleanup();
      System.exit(1);
    }

    VariableDescriptor hommeSexe = sexe.getVariableDescriptionFor(homme);
    InferenceModifier[] hommeDefault = hommeSexe.lookupInferenceModifier(DefaultValueModifier.class);
    if(hommeDefault==null || hommeDefault.length == 0){
      System.out.println("La valeur par defaut de la variable 'sexe' est inexistante pour la classe Homme");
    } else {
      String defVal = (String) ((DefaultValueModifier) hommeDefault[0]).getDefault();
      System.out.println("valeur par default = "+defVal);
    }	
    
    AMClass femme = kb.lookupClass("Femme");
    if(femme == null) {
      System.out.println("la classe Femme est introuvable !");
      //Arrete le System Arom proprement
      AromSetUp.getAromSystem().cleanup();
      System.exit(1);
    }

    VariableDescriptor femmeSexe = sexe.getVariableDescriptionFor(femme);
    TypeModifier[] femmeDomain = femmeSexe.lookupTypeModifier(DomainModifier.class);
    if(femmeDomain == null || femmeDomain.length == 0 ){
      System.out.println("Le domaine de la variable 'sexe' est inexistant pour la classe Femme");
      //Arrete le System Arom proprement
      AromSetUp.getAromSystem().cleanup();     
      System.exit(1);
    }

    System.out.println("valeur(s) du domaine :"+femmeDomain[0]);

    //Arrete le System Arom proprement
    AromSetUp.getAromSystem().cleanup();      
  }
  
}// ModifySlot

    

Dans cet exemple les deux méthodes utilisés, applyTypeModifier() et applyInferenceModifier(), permettent d'appliquer un modificateur de facette de type et d'inférence à un descripteur de slot donné. Il existe, de la même façon, une méthode permettant d'appliquer un modificateur de facette de documentation à un descripteur de slot.

Des méthodes similaires sont également définies afin de permettre d'annuler un modificateur qui a été précédemment appliqué, ce qui peut se traduire dans certain cas à supprimer une propriété donnée. Ces méthodes sont cancelTypeModifier(), cancelInferenceModifier() et cancelDocumentationModifier() pour les facettes de type, d'inference et de documentation respectivement.