All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.pdx.cs.joy.rmi.MovieDatabaseImpl Maven / Gradle / Ivy

The newest version!
package edu.pdx.cs.joy.rmi;

import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.*;
import java.util.stream.Collectors;

/**
 * This class provides an implementation of the remote {@link
 * MovieDatabase} interface.  Note that this class does not extened
 * {@link UnicastRemoteObject}.  Therefore, we have to invoke {@link
 * UnicastRemoteObject#exportObject} in the constructor.
 */
public class MovieDatabaseImpl implements MovieDatabase {

  /** A map that maps id's to their movies.  This allows for a 
   * fast lookup of movies by their id. */
  private Map movies;

  ////////////////////////  Constructors  /////////////////////////

  /**
   * Creates a new MovieDatabaseImpl.
   */
  public MovieDatabaseImpl() {
    // Sort movies by their id, so the lookup is O(lg n)
    this.movies = new TreeMap<>(Long::compareTo);

    System.out.println("Starting Movie Database");
  }

  ///////////////////////  Remote Methods  ////////////////////////

  /**
   * Creates a new Movie object on the server.  It
   * returns the id of the movie that was created.
   *
   * @param title
   *        The title of the movie
   * @param year
   *        The year in which the movie was released
   */
  @Override
  public long createMovie(String title, int year) {
    Movie movie = new Movie(title, year);
    long id = movie.getId();
    this.movies.put(id, movie);
    System.out.println("Created a new movie " + movie);
    return id;
  }
  
  /**
   * Returns the Movie with the given id.
   */
  @Override
  public Movie getMovie(long id) {
    return this.movies.get(id);
  }

  /**
   * Makes note of a character in a given movie played by a given
   * actor.
   *
   * @throws IllegalArgumentException
   *         There is no movie with movieId or the
   *         character is already played by someone else
   */
  @Override
  public void noteCharacter(long movieId, String character, long actorId) {
    Movie movie = getExistingMovie(movieId);
    movie.addCharacter(character, actorId);
  }

  private Movie getExistingMovie(long movieId) {
    // Note local call of remote method
    Movie movie = this.getMovie(movieId);
    if (movie == null) {
      String s = "There is no movie with id " + movieId;
      throw new IllegalArgumentException(s);
    }
    return movie;
  }

  /**
   * Returns the movie in which a given actor acted.  The movies are
   * sorted by release date.
   */
  @Override
  public SortedSet getFilmography(final long actorId) {

    Query query = movie -> movie.getActors().contains(actorId);

    Comparator sorter = new SortMoviesByReleaseDate();

    return executeQuery(query, sorter);
  }

  /**
   * A comparator that sorts movies based on the year in which they
   * were released.  It must be serializable so that it may be sent to
   * the client.  It must be static so that it doesn't have a
   * reference to its outer class.
   */
  static class SortMoviesByReleaseDate 
    implements Comparator, java.io.Serializable {

    @Override
    public int compare(Movie movie1, Movie movie2) {
      int year1 = movie1.getYear();
      int year2 = movie2.getYear();
      return Integer.compare(year1, year2);
    }
  }

  /**
   * Performs a query on the database.  The movies that match the
   * query are sorted using the given comparator.
   */
  @Override
  public SortedSet executeQuery(Query query, Comparator sorter) {

    return this.movies.values().stream()
      .filter(query::satisfies)
      .collect(Collectors.toCollection(() -> new TreeSet<>(sorter)));
  }

  /**
   * Unregisters this MovieDatabaseImpl with the RMI
   * registry.
   */
  @Override
  public void shutdown() throws RemoteException {
    System.out.println("Shutting down Movie Database");
    UnicastRemoteObject.unexportObject(this, false /* force */);
    System.exit(0);
  }

  @Override
  public Collection getMovies() {
    return new HashSet<>(this.movies.values());
  }

  @Override
  public void deleteMovie(long movieId) {
    Movie movie = getExistingMovie(movieId);
    this.movies.remove(movie.getId());
  }

  ///////////////////////  Main Program  /////////////////////////

  /**
   * This main program registers an instance of MovieDatabaseImpl in
   * an RMI registry.
   */
  public static void main(String[] args) {
    int port = Integer.parseInt(args[0]);

    try {
      MovieDatabase database = (MovieDatabase) UnicastRemoteObject.exportObject(new MovieDatabaseImpl(), port);
      Registry registry = LocateRegistry.createRegistry(port);
      registry.bind(RMI_OBJECT_NAME, database);

    } catch (RemoteException | AlreadyBoundException ex) {
      ex.printStackTrace(System.err);
    }

  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy