import java.io.*;
import java.lang.reflect.*;

/** Classe abstraite fournissant les principaux mécanismes de gestion
    d'un Article : elle donne des accesseurs et des modifieurs sur les
    attributs communs à tous les articles (nom, référence, prix) 
    @author Michel Buffa
    @version 1.0 28/10/97
*/

public abstract class Article implements Dumpable {

  // Attributs de la classe. Privés si possible

  /** Nom de l'article */
  private String nom;
  /* reference de l'article */
  private String reference;
  /* prix unitaire de l'article */
  private double prixUnitaire;

  // Constructeurs. Rappel : pas de type de retour pour les constructeurs !
  
  /** Constructeur à utiliser normalement. */
  public Article(String nom, String reference, double prixUnitaire) {
    this.nom = nom;
    this.reference = reference;
    this.prixUnitaire = prixUnitaire;
  }

  /** Constructeur par défaut, ne devrait pas être appelé car tout
      article doit possèder une référence, un nom et un prix. Si
      toutefois ce constructeur est invoqué, il se contente
      d'initialiser le nom et la référence de l'article avec la valeur
      "-- non initialisé --" */

  public Article() {
    nom = new String("-- non initialisé --");
    reference = nom;
  }

  // Méthodes protégées
  
  /** Sert à positionner le prix. Etant donné que la visibilité de
      cette méthode est "protected", seule les classes dérivées ou les
      classes se trouvant dans même package que la classe Article
      pourront invoquer cette méthode sur un Article. */

  protected void setPrix(double nouveau_prix) {
    prixUnitaire = nouveau_prix;
  }

  /** Sert à positionner le nom. Etant donné que la visibilité de
      cette méthode est "protected", seule les classes dérivées ou les
      classes se trouvant dans même package que la classe Article
      pourront invoquer cette méthode sur un Article. */

  protected void setNom(String nouveau_nom) {
    nom = nouveau_nom;
  }

  /** Sert à positionner la référence. Etant donné que la visibilité
      de cette méthode est "protected", seule les classes dérivées ou
      les classes se trouvant dans même package que la classe Article
      pourront invoquer cette méthode sur un Article. */
  protected void setRef(String ref) {
    reference = ref;
  }

  // Méthodes publiques

    /** Cette méthode renvoie une chaîne de caractère décrivant
        l'article. Le résultat est de la forme : "Nom : nom de
        l'article (Ref : reference, Prix unitaire : prix)" */

  public String identifieToi() {
    String result;
    
    result = new String(" Nom : " + nom + " (Ref : " + reference + 
			", Prix unitaire : " + prixUnitaire + ")"); 
    return result;
  }

  /** Renvoie le prix de l'article.*/
  public double getPrix() {
    return prixUnitaire;
  }

  /** Renvoie la référence de l'article. */
  public String getRef() {
    return reference;
  }

  /** Renvoie le nom de l'article. */
  public String getNom() {
    return nom;
  }

  public void write(DataOutputStream dos) {
    String nomClasse = getClass().getName();
    
    try {
      System.out.println("J'écris le nom de la classe\n");
      dos.writeUTF(nomClasse); // type de l'article pour la lecture
      System.out.println("J'écris le nom de l'article\n");
      dos.writeUTF(nom);
      System.out.println("J'écris la reference de l'article\n");
      dos.writeUTF(reference);
      System.out.println("J'écris le prix de l'article " + prixUnitaire + "\n");
      dos.writeDouble(prixUnitaire);
    } catch(IOException e) {}
  }

  public Article  testeReflexivite() {
    Class classe = getClass();
    String nomClasse = classe.getName();
    Constructor[] constructeurs = classe.getDeclaredConstructors();
    System.out.println("Classe courante = " + nomClasse);
    System.out.println("Nombre de constructeurs  = " + constructeurs.length);

    for(int i = 0; i < constructeurs.length; i++) {
      Constructor c = constructeurs[i];
      Class[] paramTypes = c.getParameterTypes();
      
      for(int j = 0; j < paramTypes.length; j++) {
	System.out.println(paramTypes[j]);
      }
    }
    
    try {
      Constructor c = constructeurs[0];
      Class[] paramTypes = c.getParameterTypes();

      Object[] params= {"nom", "ref", new Double(1.11), "coul"};
      Article a = (Article) c.newInstance(params);
      return a;
    } catch(Exception e) {}
    
    return (Article) null;
  }

}
