Universidad Carlos III de Madrid

Ingeniería de Telecomunicación

Enero-Mayo 2010 / January-May 2010

Object-Orientation & Inheritance

Lab Section1.  Session 4 (lab): Object-Orientation & Inheritance (II)

Exercise Section1.1.  Multimedia files

Exercise

The objective is to create an application to manage a set of multimedia files in our computer. With this application, we will be able to store different information about those files. As we are focusing on audio and video files, there will be some features that are common to both file types, but there will also be some features that are specific of each type (such as, for instance, the size of the video screen).

Section 1. Base exception

A MultimediaObjectException class is going to be used to handle errors. Whenever a MultimediaObjectException happens, the program must display the following message in the screen (when it is caught):

Incorrect value
  

Section 2. MultimediaObject class

Considering that there is a series of common features to all multimedia files, a parent class, called MultimediaObject, is going to be defined, containing the following items:

  • Definition of the following attributes: name, to store the name of the file, and minutes and seconds, to hold the length of the multimedia file in minutes and seconds, respectively.

  • A constructor to be passed the necessary values to initialize those attributes. The constructor will check that the initialization value for seconds is greater or equal to 0 and lower than 60, and that the value for minutes is greater or equal to 0. Otherwise, a MultimediaObjectException exception must be thrown.

  • A printData() method to print on the screen all the attribute data:

    File: name_of_the_file
    Length: minutes:seconds
          

    For instance:

    File: Nothing else matters.mp3
    Length: 6:15
          

Section 3. Extending classes

Now we are going to define the classes to differentiate between audio and video files. These classes extend from MultimediaObject class.

The class in charge of modeling audio files, called AudioObject, must contain:

  • Definition of the bitRate, frequency and quality attributes. The first two store integer values, whereas the last one will be a String equal to Stereo or Mono.

  • Constructor to initialize all attributes that an AudioObject can hold and also checks that the bit rate and frequency are initialized to values greater or equal to 0 and the quality is equal to any of the two allowed values. Otherwise, the MultimediaObjectException exception must be thrown.

  • A printData() method that invokes the method in te parent class and also displays the values of the attributes of the child classed, in the format:

    Bit rate: value in kbps
    Frequency: value in Hz
    Quality:  value
          

At the end of Section 4, there is an example of the expected output in the screen after a call to this method.

In addition, the VideoObject class will include:

  • Definition of the width, height and fps (frames per second) attributes. The first two are integer and the last one is a float.

  • Constructor with the same functionality as the constructor of AudioObject.

  • Similarly, a printData() method that, after invoking the method in the parent class, shows the following data in the screen:

    Screen size: width x height
    Frames per second: value
          

Section 4. Main class

Finally you are going to implement a program that manipulates these elements. This program will be modeled by the MultimediaCollection class. This program must create two MultimediaObject objects: one AudioObject and one VideoObject. The values of these files are:

  • AudioObject:
    • Name: Nothing else matters.mp3
    • Minutes: 6
    • Seconds: 15
    • Bit rate: 192
    • Frequency: 44100
    • Calidad: Estéreo
  • VideoObject:
    • Name: Kill Bill Trailer.mpg
    • Minutes: 3
    • Seconds: 15
    • Width: 176
    • Height: 76
    • Fps: 30.0

Once created, their information must be displayed on the screen. The result will be similar to:

File: Nothing else matters.mp3
Length: 6:15
Bit rate: 192 kbps
Frequency: 44100 Hz
Quality: Estéreo

File: Kill Bill Trailer.mpg
Length: 3:15
Screen size: 176 x 76
Frames per second: 30.0
  

Your program must handle all the exception that can be thrown, showing the corresponding error message on the screen. The exception block must differentiate between MultimediaObjectException and the rest of exceptions.

Solution

The solution is included in the following listing:

public class MultimediaObjectException extends Exception {
  public MultimediaObjectException() {
    super("Incorrect value");
  }
}

          
public class MultimediaObject {
  String name;
  int minutes;
  int seconds;

  public MultimediaObject(String name, int minutes, int seconds)
      throws MultimediaObjectException {
    this.name = name;
    if (minutes >= 0) {
      this.minutes = minutes;
    } else {
      throw new MultimediaObjectException();
    }
    if (seconds >= 0 && seconds < 60) {
      this.seconds = seconds;
    } else {
      throw new MultimediaObjectException();
    }
  }

  public void printData() {
    System.out.println("File: " + name);
    System.out.println("Length: " + minutes + ":" + seconds);
  }
}

          
public class AudioObject extends MultimediaObject {
  int bitRate;
  int frequency;
  String quality;

  public AudioObject(String name, int minutes, int seconds, int bitRate,
      int frequency, String quality) throws MultimediaObjectException {
    super(name, minutes, seconds);
    if (bitRate >= 0) {
      this.bitRate = bitRate;
    } else {
      throw new MultimediaObjectException();
    }
    if (frequency >= 0) {
      this.frequency = frequency;
    } else {
      throw new MultimediaObjectException();
    }
    if (quality.equalsIgnoreCase("Stereo") || quality.equalsIgnoreCase("Mono")) {
      this.quality = quality;
    } else {
      throw new MultimediaObjectException();
    }
  }

  public void printData() {
    super.printData();
    System.out.println("Bit rate: " + bitRate + " kbps");
    System.out.println("Frequency: " + frequency + " Hz");
    System.out.println("Quality: " + quality);
  }
}

          
public class VideoObject extends MultimediaObject {
  int width;
  int height;
  float fps;

  public VideoObject(String name, int minutes, int seconds, int width,
      int height, float fps) throws MultimediaObjectException {
    super(name, minutes, seconds);
    if (width >= 0) {
      this.width = width;
    } else {
      throw new MultimediaObjectException();
    }
    if (height >= 0) {
      this.height = height;
    } else {
      throw new MultimediaObjectException();
    }
    if (fps >= 0) {
      this.fps = fps;
    } else {
      throw new MultimediaObjectException();
    }
  }

  public void printData() {
    super.printData();
    System.out.println("Screen size: " + width + " x " + height);
    System.out.println("Frames per second: " + fps);
  }
}

          
public class MultimediaCollection {
  public static void main(String args[]) {
    try {
      MultimediaObject audio = new AudioObject("Nothing else matters.mp3", 6,
          15, 128, 44100, "Stereo");
      MultimediaObject video = new VideoObject("Kill Bill Trailer.mpg", 3, 15,
          176, 76, 30.0f);
      audio.printData();
      video.printData();
    } catch (MultimediaObjectException moe) {
      System.err.println(moe.toString());
    } catch (Exception e) {
      System.err.println(e.toString());
    }
  }
}

          

Homework Section2.  Homework

Exercise Section2.1.  Operating systems

Exercise

Current multitask operating systems allow the concurrent execution (i.e., at the same time) of several programs. To do so, the operating system kernel has a module called "scheduler" that, according to a series of settings, selects which is the next program to be executed next.

All programs that can be run within a multitask operating system have the following features:

  • An identifier of String type that allows to differentiate among programs.

  • A priority value with which the scheduler will decide which is the program to be run next. The priority value can be 3, 2 or 1, being 3 the highest priority and 1 the lowest priority.

  • All of them have a method to show the information about their identifier and priority in the screen.

The class that models these object is called Program and stores the previous attributes, access methods for these attributes, a constructor that allows to initialize their values, and a void print() method to show the information in the screen.

In addition, there are two special type of programs: real time programs, which always have the highest priority (value of 4), and background programs, which have the lowest priority (0). Moreover, these programs specialize the behaviour of the print method, adding the type of program they are (real time or background).

Section 1. Class hierarchy

You are asked to implement the set of classes (Program, RealTimeProgram, BackgroundProgram) that model the previously described behaviour.

Section 2. Scheduler

You must implement a Scheduler class ("planificador" in Spanish) that is able to manage programs with different priorities. The class will have an attribute that stores an array of Program objects, which holds the programs to schedule. The constructor of the class receives the maximum number of programs that the scheduler will be able to manage.

You are also required to implement a method able to store programs sorted by ascending priority value: void add(Program program) throws Exception. This method must throw an exception if no more programs can be added (if the array is full).

Section 3. next() method

Implement a method in the scheduler that returns the next program to be run (the one with the highest priority among the stored programs): Program next() throws Exception. The method will throw an exception if there is no program (the array is empty).

Note: You are free to decide what to do when there are several programs with the same priority.

Solution

The solution is included in the following listing:

public class Program {
  private String id;
  private int priority;

  public Program(String id, int priority) {
    this.id = id;
    this.priority = priority;
  } // Program

  public int getPriority() {
    return priority;
  } // getPriority

  public void print() {
    System.out.println("Id: " + id);
    System.out.println("Priority: " + priority);
  } // print

} // Program

          
public class RealTimeProgram extends Program {
  final static int MAX_PRIORITY = 4;

  public RealTimeProgram(String id) {
    super(id, MAX_PRIORITY);
  } // RealTimeProgram

  public void print() {
    System.out.println("Real Time Program");
    super.print();
  } // print

} // RealTimeProgram

          
public class BackgroundProgram extends Program {
  final static int MIN_PRIORITY = 0;

  public BackgroundProgram(String id) {
    super(id, MIN_PRIORITY);
  } // BackgroundProgram

  public void print() {
    System.out.println("Background Program");
    super.print();
  } // print

} // BackgroundProgram

          
public class Scheduler {
  private Program programs[];

  public Scheduler(int size) {
    programs = new Program[size];
  } // Scheduler

  /** Adds a program, sorted from low to high priority */
  public void add(Program program) throws Exception {
    boolean found = false;
    int i = 0;
    int size = programs.length;
    int currentPriority = program.getPriority();
    // Find a place to insert into
    while ((!found) && (i < size)) {
      if (programs[i] == null) {
        found = true;
      } else if (currentPriority < programs[i].getPriority()) {
        found = true;
      } else {
        i++;
      }
    } // while
    if (found) {
      // Insert the program into the null position
      if (programs[i] == null) {
        programs[i] = program;
      } else {
        // Move the elements...
        // ...but what if it is full?
        if (programs[size - 1] != null) {
          throw new Exception("List is full (Cond 1)");
        } else {
          // Move from the end
          for (int j = size - 1; j > i; j--) {
            programs[j] = programs[j - 1];
          }
          // Then, asign the value
          programs[i] = program;
        }
      }
    } else {
      throw new Exception("List is full (Cond 2)");
    }
  } // add

  public Program next() throws Exception {
    boolean found = false;
    int size = programs.length;
    int i = size - 1;
    while ((!found) && (i >= 0)) {
      found = (programs[i] != null);
      i--;
    }
    if (!found) {
      throw new Exception("Empty list, no program to execute");
    } else {
      return programs[i + 1];
    }
  } // next

} // Scheduler

          
public class Programs {
  public static void main(String args[]) {
    Scheduler miScheduler = new Scheduler(6);
    try {
      Program program = new Program("1", 1);
      miScheduler.add(program);
      program = new Program("2", 2);
      miScheduler.add(program);
      program = new Program("3", 3);
      miScheduler.add(program);
      program = new Program("4", 2);
      miScheduler.add(program);
      RealTimeProgram realtimeProgram = new RealTimeProgram("5");
      miScheduler.add(realtimeProgram);
      BackgroundProgram backgroundProgram = new BackgroundProgram("6");
      miScheduler.add(backgroundProgram);

      // Test the full list (Cond 2)
      // miScheduler.add(new Program("7", 7));

      Program next = miScheduler.next();
      next.print();
    } catch (Exception ex) {
      System.out.println(ex.getMessage());
    }
    System.out.println("End");
  } // main
} // Programs