Vous êtes sur la page 1sur 8

CNAM NFP121

EXAMEN 1 29/01/2008 (Sance 14)

Examen (avec document) Corrig


Prambule : Rpondre de manire concise et prcise aux questions. Ne pas mettre de commentaires de documentation sauf sils sont ncessaires la comprhension. Barme indicatif : exercice 1 2 3 4 5 points 3 4 5 5 3 Lobjectif de ces exercices est de dnir des tches hirarchiques et de les exploiter de diffrentes manires. Exercice 1 : Comprhension de larchitecture des tches Larchitecture des tches est donne la gure 1 o le dtail des classes TacheElementaire et TacheComplexe nest pas donn. Une tche est caractrise par un nom et un cot. Une tche est soit une tche lmentaire, soit une tche complexe qui est alors compose de sous-tches. Il est ainsi possible dajouter une sous-tche une tche complexe, ajouter(Tache) ou de supprimer une sous-tche, supprimer(Tache). Le cot dune tche complexe est la somme des cots des tches qui la composent.
interface Tache getNom(): String getCout(): int 0..* sousTaches

TacheElementaire

TacheComplexe

F IG . 1 Architecture des tches hirarchiques 1.1 Indiquer le ou les patrons de conception utiliss dans cette architecture. Solution : Composite : La tche complexe est le composite, Tache est le composant et TacheElementaire est la feuille. Notons que les objets ajouter et supprimer ne sont ici que sur le composite et pas sur le composant. 1.2 Le listing 1 donne le code de linterface Tache. crire en Java la classe TacheElementaire qui est une ralisation de linterface Tache.

EXAMEN 1

1/8

NFP121

Examen (avec document)

Listing 1 Linterface Tache


1 2 3 4 5 6 7

public interface Tache { /** Obtenir le nom de la tche. */ String getNom(); /** Obtenir le cot de la tche. */ int getCout(); }

Solution :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18

public class TacheElementaire implements Tache { private String nom; private int cout; public TacheElementaire(String nom, int cout) { this.nom = nom; this.cout = cout; } public String getNom() { return this.nom; } public int getCout() { return this.cout; } }

Exercice 2 : Dnition dune tche complexe Nous nous intressons maintenant la classe TacheComplexe, en particulier sa relation avec linterface Tache. Une tche complexe est compose dun nombre quelconque de tches. On dcide dutiliser linterface java.util.Collection pour stocker les sous-tches. On lutilisera bien entendu dans sa version gnrique. Comme on souhaite pouvoir parcourir toutes les sous-tches dune tche complexe, la classe TacheComplexe ralise linterface java.lang.Iterable. 2.1 Indiquer quel est le principal intrt de la gnricit. Solution : Le contrle de type ralis par le compilateur. 2.2 Indiquer quel est le cot de la tche tA construite comme indiqu dans le listing 2. Listing 2 La classe TestTache1
1 2 3 4 5 6 7 8 9

public class TestTache1 { public static void main(String[] args) { TacheComplexe tA = new TacheComplexe("A"); tA.ajouter(new TacheElementaire("A1", 10)); tA.ajouter(new TacheElementaire("A2", 20)); System.out.println("Cout de tA = " + tA.getCout()); } }

EXAMEN 1

2/8

NFP121

Examen (avec document)

Solution : 30 2.3 crire en Java la classe TacheComplexe. Solution :


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38

import java.util.Collection; import java.util.ArrayList; import java.util.Iterator; public class TacheComplexe implements Tache, Iterable<Tache> { private Collection<Tache> sousTaches; private String nom; public TacheComplexe(String nom) { this.nom = nom; this.sousTaches = new ArrayList<Tache>(); } public void ajouter(Tache tache) { this.sousTaches.add(tache); } public void supprimer(Tache tache) { this.sousTaches.remove(tache); } public String getNom() { return this.nom; } public int getCout() { int result = 0; for (Tache t : sousTaches) { result += t.getCout(); } return result; } public Iterator<Tache> iterator() { return this.sousTaches.iterator(); } }

Exercice 3 : Interface graphique pour dnir une tche complexe Nous dnissons maintenant une interface graphique en Swing minimale qui permet dajouter de nouvelles sous-tches une tche complexe. Le code partiel de cette classe est donn au listing 3. 3.1 Dessiner la fentre (et les composants graphiques quelle contient) telle quelle est afche quand cette classe est excute. Solution :

EXAMEN 1

3/8

NFP121

Examen (avec document)

3.2 Complter cette classe pour que les boutons Ajouter et Quitter deviennent actifs. Le bouton Quitter ferme la fentre. Le bouton Ajouter ajoute une nouvelle sous-tche la tche complexe passe en paramtre du constructeur de cette classe. Le nom et le cot de cette soustche sont, bien entendu, saisis par lutilisateur dans les zones de saisie prvues, valeurNom et valeurCout. Dans le cas o lutilisateur saisit une information qui nest pas un entier pour saisir le cot, on signalera lerreur en mettant la couleur de fond de la zone de saisie correspondante en rouge (setBackground(Color.RED)). On rappelle que la mthode Integer.parseInt(String) renvoie lentier correspondant la chane de caractre pass en paramtre. Cette mthode lve lexception NumberFormatException si la chane ne correspond pas un entier. Remarque : On pourra mettre des numros sur le listing 3 pour indiquer o du code doit tre ajout, le code correspondant tant crit sur la copie, prcd du mme numro. Listing 3 La classe TacheComplexeSwing
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32

import javax.swing.*; import java.awt.*; import java.awt.event.*; public class TacheComplexeSwing { private TacheComplexe tache; final JFrame fenetre = new JFrame("Nouvelle tche"); final private JTextField valeurNom = new JTextField(10); final private JTextField valeurCout = new JTextField(10); final private JButton boutonAjouter = new JButton("Ajouter"); final private JButton boutonQuitter = new JButton("Quitter"); public TacheComplexeSwing(TacheComplexe tache) { this.tache = tache; Container c = fenetre.getContentPane(); c.setLayout(new BorderLayout()); JPanel informations = new JPanel(new GridLayout(2,2)); informations.add(new JLabel("Nom : ", SwingConstants.RIGHT)); informations.add(valeurNom); informations.add(new JLabel("Cot : ", SwingConstants.RIGHT)); informations.add(valeurCout); c.add(informations, BorderLayout.CENTER); JPanel boutons = new JPanel(new FlowLayout()); boutons.add(boutonAjouter); boutons.add(boutonQuitter); c.add(boutons, BorderLayout.SOUTH);

boutonQuitter.addActionListener(new ActionQuitter()); boutonAjouter.addActionListener(new ActionAjouter());

EXAMEN 1

4/8

NFP121

Examen (avec document)

33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

fenetre.pack(); fenetre.setVisible(true); }

private class ActionAjouter implements ActionListener { public void actionPerformed(ActionEvent ev) { try { String nom = valeurNom.getText(); int cout = Integer.parseInt(valeurCout.getText()); tache.ajouter(new TacheElementaire(nom, cout)); System.out.println("cout total = " + tache.getCout()); } catch (NumberFormatException e) { valeurCout.setBackground(Color.RED); } } } private class ActionQuitter implements ActionListener { public void actionPerformed(ActionEvent ev) { System.out.println("Appui sur Quitter..."); fenetre.dispose(); } } public static void main(String[] args) { new TacheComplexeSwing(new TacheComplexe("Test TacheComplexeSwing")); }

Exercice 4 : Sauvegarde dune tche en XML Intressons nous maintenant la sauvegarde dune tche sous la forme dun chier XML dont la DTD est donne au listing 4 Listing 4 La DTD pour reprsenter une tche
1 2 3 4 5 6 7 8

<?xml version="1.0" encoding="UTF-8"?> <!ELEMENT <!ELEMENT <!ELEMENT <!ATTLIST taches (tache*)> tache (attribut*, tache*)> attribut EMPTY> attribut nom CDATA #REQUIRED valeur CDATA #REQUIRED>

EXAMEN 1

5/8

NFP121

Examen (avec document)

4.1 Donner le contenu du chier XML qui correspond la tche tA construite dans le listing 2. Ne pas donner lentte de ce chier XML. Solution :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE taches SYSTEM "taches.dtd"> <taches> <tache> <attribut nom="nom" valeur="A" /> <attribut nom="cout" valeur="30" /> <tache> <attribut nom="nom" valeur="A1" /> <attribut nom="cout" valeur="10" /> </tache> <tache> <attribut nom="nom" valeur="A2" /> <attribut nom="cout" valeur="20" /> </tache> </tache> </taches>

4.2 Complter la classe TacheJDom pour engendrer le chier XML reprsentant une tche. Ce chier devra tre valide par rapport la DTD du listing 4. On ne modiera aucune des interfaces ou classes Tache, TacheElementaire et TacheComplexe. Listing 5 La classe TacheJDom
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

import import import import import import

org.jdom.*; org.jdom.output.*; java.io.OutputStream; java.io.PrintStream; java.io.IOException; java.io.FileWriter;

public class TacheJDom { private XMLOutputter sortie = new XMLOutputter(Format.getPrettyFormat()); public void printToXML(Tache t, String nomFichier) throws IOException { Element racine = new Element("taches"); racine.addContent(this.getElement(t)); Document d = new Document(racine, new DocType("taches", "taches.dtd")); sortie.output(d, new FileWriter(nomFichier)); }

public Element ajouterAttibut(Element e, String nom, String valeur) { return e.addContent( new Element("attribut") .setAttribute("nom", nom) .setAttribute("valeur", valeur)); }

EXAMEN 1

6/8

NFP121

Examen (avec document)

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62

/** Construire llment correspondant la tche complexe tc. */ public Element getElement(TacheComplexe tc) { Element elt = new Element("tache"); this.ajouterAttibut(elt, "nom", tc.getNom()); this.ajouterAttibut(elt, "cout", "" + tc.getCout()); for (Tache t: tc) { elt.addContent(getElement(t)); } return elt; } /** Construire llment correspondant la tche lmentaire te. */ public Element getElement(TacheElementaire te) { Element elt = new Element("tache"); this.ajouterAttibut(elt, "nom", te.getNom()); this.ajouterAttibut(elt, "cout", "" + te.getCout()); return elt; } /** Construire llment correspondant la tche t. */ public Element getElement(Tache t) { if (t instanceof TacheComplexe) { return getElement((TacheComplexe) t); } else { return getElement((TacheElementaire) t); } } }

4.3 Indiquer les patrons de conception qui auraient pu tre utiliss pour engendrer le chier XML. Il est possible de modier les interfaces ou classes Tache, TacheElementaire et TacheComplexe. Solution : Le visiteur. Le visiteur permettrait alors de visiter les classes TacheElementaire et TacheComplexe. Une autre solution consisterait dnir la mthode getElement() comme abstraite sur Tache et, bien sr, rednie sur les sous-classes. Exercice 5 : Utilisation de SaX tant donn, un chier XML valide vis--vis de la DTD du listing 4, crire un gestionnaire SaX (ContentHandler ou DefaultHandler) qui afche le niveau dimbrication de la tche la plus interne. Appliqu sur le chier correspondant la tche tA du listing 2, le rsultat doit tre 2. Indication : On pourra compter le nombre de balises ouvrantes <tache> non fermes. Solution :
1

import org.xml.sax.*;

EXAMEN 1

7/8

NFP121

Examen (avec document)

2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34

import org.xml.sax.helpers.*; class ProfondeurMaxHandler extends DefaultHandler { private int level, max; public void startDocument() { this.level = 0; this.max = 0; } public void startElement(String uriEspaceNom, String nom, String nomQualifie, Attributes attributs) throws SAXException { if (nomQualifie.equals("tache")) { this.level++; if (this.level > this.max) { this.max = this.level; } } } public void endElement(String uriEspaceNom, String nom, String nomQualifie) throws SAXException { if (nomQualifie.equals("tache")) { this.level--; } } public int getProfondeurMax() { return this.max; } }

EXAMEN 1

8/8