[UMLV]

Introspection

Exercice - Affichage d'un graphe cyclique

Soit la classe suivante, représentant des graphes orientés avec un nœud initial :

public class Graph {
  private Node start;
  public void setStart(Node n) {
    start = n;
  }
  public class Node {
    private final String name;
    private final ArrayList<Node> transitions =
      new ArrayList<Node>();
    public Node(String name) {
      this.name=name;
    }
    public int hashCode() {
      return name.hashCode();
    }
    public boolean equals(Object o) {
      if (!(o instanceof Node))
        return false;
      return name.equals(((Node)o).name);
    }
    public void add(Node dest) {
      transitions.add(dest);
    }
    public Iterator<Node> transitions() {
      return transitions.iterator();
    }
    public String toString() {
      return name;
    }
  }
}

  1. Écrire une méthode toString() dans la classe Graph. L'affichage indique le nœud initial, puis une ligne par nœud du graphe, chaque ligne affichant le nœud suivi de deux points et des nœuds vers lesquels il possède un arc. L'affichage de chaque nœud comprend un identificateur du nœud et le nom du nœud entre parenthèses. Par exemple, voici un graphe et l'affichage souhaité :
    Exemple de graphe
    Noeud initial: n1(Bleu)
              n1(Bleu) : n2(Rouge) n3(Rouge)
              n2(Rouge) : n4(Vert)
              n3(Rouge) : n4(Vert)
              n4(Vert) : n1(Bleu) n5(Bleu)
              n5(Bleu) : n5(Bleu)
    
  2. Que se passe-t'il s'il y a un cycle ?
    Modifier le code sans changer le classe Node.
    Note: utiliser une HashMap ne marche pas !!!

Exercice - Bidouillage des itérateurs d'ArrayList

Les itérateurs obtenus à partir des collections du paquetage java.util sont dits fail-fast, ce qui signifie qu'une modification de la structure itérée entrelacée avec l'utilisation de l'itérateur provoque par cette dernière la levée d'une ConcurrentModificationException. Pour contrôler ces modifications, les itérateurs utilisent le champ modCount protégé de la classe abstraite AbstractList. Pour vous en convaincre, vous pouvez extraire le code source de ces classes de l'archive src.zip.

En utilisant les mécanismes de réflexion offerts par le paquetage java.lang.reflect, écrire une méthode bidouille() et faites en sorte que, dans le cas particulier l'exemple suivant, l'exception ConcurrentModificationException ne soit pas levée par l'itérateur d'un ArrayList, malgré la modification faite sur cette structure. Pour celà, vous devrez modifier par réflexion la valeur du champ modCount de la liste.

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list,args);
for(String s:list) {
  if (s.length()%2==0) {
    list.add(s+" stop");
    // bidouille(list); à écrire...
  }
}
System.out.println(list);

Exercice - Gestion récursive de l'état d'un objet

On souhaite maintenant avoir un algorithme qui affiche n'importe quel Object au format XML suivant :

  <instance class="java.awt.Point" id="1">
    <field name="x" value="10">
    <field name="y" value="20">
  </instance>
  
ou pour les nœuds du graphe, quelque chose dans ce genre :
    <instance class="Graphe" id="1">
      <field name="start" id-ref="2">
    </instance>
    <instance class="Graph.Node" id="2">
      <field name="name" value="root">
      <field name="transitions" id-ref="3">
    </instance>
    <instance class="java.util.ArrayList" id="3">
      <field name="modCount" value="3">
      <field name="size" value="2">
      <field name="elementData" id-ref="4">
    </instance>
    <instance class="java.lang.Object[]" id="4">
      <field name="length" value="11">
      <field id-ref="5">
      <field id-ref="6">
    </instance>
    <instance class="Graph.Node" id="5">
      <field name="name" value="node1">
      <field name="transitions" id-ref="7">
    </instance>
    ...
  
Vous veillerez à sauver les champs de type primitif et String suivant leurs valeurs, les objets sous la forme de leur référence d'identifiant et les tableaux d'une façon spéciale.
Il faut pour cela :
  1. Récupérer l'ensemble des champs d'un objet (y compris les privés) ;
  2. Trouver quelle est la valeur de chaque champ (toujours avec les champs privées) ;
  3. Étant donnée la référence à un objet, être capable d'associer un identificateur à chacune des références accessibles à partir de cet objet, à commencer par lui-même, et ce, récursivement.