package model; import java.util.Collection; import java.util.LinkedList; import java.util.Map; import main.error.VideothekException; import model.data.exceptions.RecordNotFoundException; import model.events.EventManager; import model.events.VideoCreatedEvent; import model.events.VideoDeletedEvent; import model.events.VideoEditedEvent; import model.exceptions.CurrentDateException; import model.exceptions.EmptyFieldException; import model.exceptions.FalseFieldException; import model.exceptions.FalseIDException; /** * * Video.java * * @author Andie Hoffmann (andhoffm@uos.de) * @date 15.09.2008 */ public class Video implements Comparable<Video> { private int vID; private String title; private int releaseYear = Data.NOTSET; private PriceCategory priceCategory; private int priceCategoryID = Data.NOTSET; private int ratedAge = Data.NOTSET; private boolean deleted = false; private static Map<Integer, Video> videoList; private static int minvID; /** * public-Konstruktor zum Aufruf durch die GUI * * @param title Filmtitel * @param releaseYear Erscheinungsjahr * @param priceCategory Preiskategorie-ID * @param ratedAge Altersfreigabe * @param numberOfVideoUnits Anzahl VideoUnits, die für diesen Film erstellt * werden soll. * @throws FalseIDException , wenn eine falsche ID übergeben wird * @throws EmptyFieldException , wenn leere Felder übergeben werden * @throws FalseFieldException , wenn nicht reguläre Daten übergeben werden * @throws CurrentDateException , wenn ein noch nicht existentes * CurrentDate-Objekt abgefragt wird, oder das schon gesetzte CurrentDate * nachträglich verändert werden soll */ public Video(String title, int releaseYear, PriceCategory priceCategory, int ratedAge, int numberOfVideoUnits) throws FalseIDException, EmptyFieldException, FalseFieldException, CurrentDateException { this(minvID, title, releaseYear, priceCategory.getID(), ratedAge); this.priceCategory = priceCategory; if(containsEqualVideo(this)) { throw new FalseFieldException("Video mit gleichen Daten bereits vorhanden!"); } minvID++; if(numberOfVideoUnits <= 0) { throw new FalseFieldException("Anzahl Exemplare muss mindestens 1 sein!"); } this.addNewVideoUnits(numberOfVideoUnits); videoList.put(this.vID, this); // Event feuern EventManager.fireEvent(new VideoCreatedEvent(this)); } /** * private-Konstruktor, der durch die reCreate-Methode zur Erstellung von * {@link Video}-Objekten aus der xml-Datei aufgerufen wird * * @param vID für jedes {@link Video} einzigartige ID * @param title Filmtitel * @param releaseYear Erscheinungsjahr * @param priceCategoryID Preiskategorie-ID * @param ratedAge Altersfreigabe * @throws FalseIDException , wenn eine falsche ID übergeben wird * @throws EmptyFieldException , wenn leere Felder übergeben werden * @throws FalseFieldException , wenn nicht reguläre Daten übergeben werden * @throws CurrentDateException , wenn ein noch nicht existentes * {@link CurrentDate}-Objekt abgefragt wird, oder das schon gesetzte * {@link CurrentDate} nachträglich verändert werden soll */ private Video(int vID, String title, int releaseYear, int priceCategoryID, int ratedAge) throws FalseIDException, EmptyFieldException, FalseFieldException, CurrentDateException { if (correctIDs(vID, priceCategoryID) && noEmptyFields(title, releaseYear, ratedAge) && noFalseFields(ratedAge, releaseYear)) { this.vID = vID; this.title = title; this.releaseYear = releaseYear; this.priceCategoryID = priceCategoryID; this.ratedAge = ratedAge; } } /** * Erstellt {@link Video}-Objekte mit den Daten, die in der xml-Datei * gespeichert wurden. * * @param vID für jedes {@link Video} einzigartige ID * @param title Filmtitel * @param releaseYear Erscheinungsjahr * @param priceCategoryID Preiskategorie-ID * @param ratedAge Altersfreigabe * @return ein altes {@link Video}-Objekt * @throws FalseIDException , wenn eine falsche ID übergeben wird * @throws EmptyFieldException , wenn leere Felder übergeben werden * @throws FalseFieldException , wenn nicht reguläre Daten übergeben werden * @throws CurrentDateException , wenn ein noch nicht existentes * {@link CurrentDate}-Objekt abgefragt wird, oder das schon gesetzte * {@link CurrentDate} nachträglich verändert werden soll */ public static Video reCreate(int vID, String title, int releaseYear, int priceCategoryID, int ratedAge) throws FalseIDException, EmptyFieldException, FalseFieldException, CurrentDateException { Video video = new Video(vID, title, releaseYear, priceCategoryID, ratedAge); return video; } /** * Setzt die {@link Video} Liste, sodass sie global verfügbar wird. * * @param newVideoList Die Liste der geladenen Videos * @throws FalseFieldException , wenn Parameter null */ public static void setVideoList(Map<Integer, Video> newVideoList) throws FalseFieldException { if (newVideoList != null) { videoList = newVideoList; } else { throw new FalseFieldException("VideoList is null!"); } } /** * Liefert den Titel * @return den Filmtitel */ public String getTitle() { return this.title; } /** * Liefert das Erscheinungsjahr * @return das Erscheinungsjahr */ public int getReleaseYear() { return this.releaseYear; } /** * Liefert die Altersfreigabe * @return die Altersfreigabe */ public int getRatedAge() { return this.ratedAge; } /** * Liefert die Preiskategorie-ID * @return die Preiskategorie-ID */ public int getPriceCategoryID() { return this.priceCategoryID; } /** * Liefert die zum {@link Video} gehörende Preiskategorie * @return die Preiskategorie * @throws RecordNotFoundException , wenn das {@link Video} keine * {@link PriceCategory} enthält */ public PriceCategory getPriceCategory() throws RecordNotFoundException { if (this.priceCategory == null) { this.priceCategory = PriceCategory.findByID(this.priceCategoryID); } return this.priceCategory; } /** * Liefert eine Liste aller VideoUnits (Exemplare), die mit diesem * {@link Video} verknüpft sind * @return eine Liste von VideoUnits */ public Collection<VideoUnit> getVideoUnits() { return VideoUnit.findByVideo(this); } /** * Liefert Liste aller VideoUnits (Exemplare), die mit diesem * {@link Video} verknüpften, sortiert nach Ausgeliehen-Status (Zuerst nicht * ausgeliehene, danach ausgeliehene) * @return eine Liste von VideoUnits */ public Collection<VideoUnit> getSortedVideoUnits() { Collection<VideoUnit> availableVideoUnits = new LinkedList<VideoUnit>(); Collection<VideoUnit> rentedVideoUnits = new LinkedList<VideoUnit>(); Collection<VideoUnit> sortedVideoUnits = new LinkedList<VideoUnit>(); for (VideoUnit unit : getVideoUnits()) { if (unit.isRented()) { rentedVideoUnits.add(unit); } else { availableVideoUnits.add(unit); } } sortedVideoUnits.addAll(availableVideoUnits); sortedVideoUnits.addAll(rentedVideoUnits); return sortedVideoUnits; } /** * Entfernt Video aus globaler Video-Liste. Wird beim nächsten Speichern * nicht mehr mitgespeichert und geht somit verloren. * * @throws VideothekException */ public void delete() throws VideothekException { Collection<VideoUnit> videoUnits = this.getVideoUnits(); for (VideoUnit unit : new LinkedList<VideoUnit>(videoUnits)) { if (unit.getInRent() != null && !unit.isRented()) { throw new VideothekException( "Exemplare dieses Videos noch in Ausleihe. Löschen nicht möglich!"); } else { unit.delete(); } } videoList.remove(this.getID()); this.deleted = true; // Event feuern EventManager.fireEvent(new VideoDeletedEvent(this)); } /** * Gibt an, ob das Video gelöscht wurde (via delete()) * * @return True, falls gelöscht, False sonst. */ public boolean isDeleted() { return this.deleted; } /** * Informiert alle anderen Teilsysteme, dass dieses Video evtl. geändert * wurde. Feuert ein {@link VideoEditedEvent} und sollte einmal nach einem * Bearbeitungsvorgang aufgerufen werden. */ public void save() { // Event feuern EventManager.fireEvent(new VideoEditedEvent(this)); } /** * Setzt den Wert der statischen Variable MinvID * * @param newMinvID die neue MinID der {@link Video}s * @throws FalseIDException */ public static void setMinID(int newMinvID) throws FalseIDException { if (newMinvID > 0) { minvID = newMinvID; } else { throw new FalseIDException( "Übergebene MinID für Video ist kleiner 0!!!"); } } /** * Überprüft die übergebenen IDs * * @param newvID neue ID des {@link Video} * @param newPriceCategoryID neue Preiskategorie-ID das {@link Video}s * @return true, wenn die beiden IDs größer 0 * @throws FalseIDException , wenn eine der beiden IDs kleiner 1 */ private boolean correctIDs(int newvID, int newPriceCategoryID) throws FalseIDException { if (newvID < 1) throw new FalseIDException("vID kleiner 1!"); if (newPriceCategoryID < 1) throw new FalseIDException("pID kleiner 1!"); else return true; } /** * Überprüft die übergebenen Felder auf Inhalt * * @param newTitle Filmtitel * @param newReleaseYear Erscheinungsjahr * @param newRatedAge Altersfreigabe * @return true, wenn kein Parameter leer ist * @throws EmptyFieldException , wenn ein oder mehrere Parameter leer sind */ private boolean noEmptyFields(String newTitle, int newReleaseYear, int newRatedAge) throws EmptyFieldException { if (newTitle == null || newTitle.equals("") || newReleaseYear == Data.NOTSET || newRatedAge == Data.NOTSET) throw new EmptyFieldException("Titel, Erscheinungsjahr oder Altersbeschränkung ungültig."); else return true; } /** * Überprüft die Parameter auf Plausibilität * * @param newRatedAge Altersfreigabe * @param newReleaseYear Erscheinungsjahr * @return true, wenn alle Parameter logisch korrekt * @throws FalseFieldException , wenn FSK falsch, oder wenn Erscheinungsjahr * vor 1900 oder in Zukunft * @throws CurrentDateException wird geworfen, wenn ein noch nicht * existentes CurrentDate-Objekt abgefragt wird, oder das schon gesetzte * CurrentDate nachträglich verändert werden soll */ private boolean noFalseFields(int newRatedAge, int newReleaseYear) throws FalseFieldException, CurrentDateException { if (newRatedAge != 0 && newRatedAge != 6 && newRatedAge != 12 && newRatedAge != 16 && newRatedAge != 18) throw new FalseFieldException("Bitte FSK überprüfen"); if (newReleaseYear > CurrentDate.get().getYear() || newReleaseYear < 1900) throw new FalseFieldException("Bitte Erscheinungsjahr überprüfen"); return true; } /** * Liefert die Filmnummer * @return die Filmnummer */ public int getID() { return this.vID; } /** * Setzt den Titel des Films * @param newTitle neuer Titel * @throws EmptyFieldException */ public void setTitle(String newTitle) throws EmptyFieldException { if (newTitle != null && !newTitle.equals("")) { this.title = newTitle; } else throw new EmptyFieldException(); } /** * Setzt das Erscheinungsjahr des Films * @param newReleaseYear neues Erscheinungsjahr * @throws CurrentDateException * @throws FalseFieldException * @throws EmptyFieldException */ public void setReleaseYear(int newReleaseYear) throws CurrentDateException, FalseFieldException, EmptyFieldException { if (newReleaseYear == 0) throw new EmptyFieldException(); if (newReleaseYear < 1900 || newReleaseYear > CurrentDate.get().getYear()) throw new FalseFieldException(); else { releaseYear = newReleaseYear; } } /** * Setzt die Preiskategorie des Films * @param newPriceCategory neue Preiskategorie * @throws EmptyFieldException */ public void setPriceCategory(PriceCategory newPriceCategory) throws EmptyFieldException { if (newPriceCategory != null) { this.priceCategory = newPriceCategory; } else throw new EmptyFieldException(); } /** * Setzt die Altersfreigabe eines Films * @param newRatedAge neue Altersfreigabe * @throws FalseFieldException */ public void setRatedAge(int newRatedAge) throws FalseFieldException { if (newRatedAge == 0 || newRatedAge == 6 || newRatedAge == 12 || newRatedAge == 16 || newRatedAge == 18) { this.ratedAge = newRatedAge; } else throw new FalseFieldException("Bitte FSK überprüfen"); } /** * Fügt einem Film neue Exemplare hinzu und liefert eine Liste der neuen Exemplare zurück * @param numberOfNewUnits Anzahl der neuen Exemplare * @return Liste der neuen Exemplare * @throws FalseFieldException */ public Collection<VideoUnit> addNewVideoUnits(int numberOfNewUnits) throws FalseFieldException { Collection<VideoUnit> newVideoUnits = new LinkedList<VideoUnit>(); for(int i = 0; i < numberOfNewUnits; i++) { newVideoUnits.add(new VideoUnit(this)); } return newVideoUnits; } /** * Liefert die Anzahl der Filmexemplare * @return die Anzahl der Filmexemplare */ public int getNumberOfVideoUnits() { return this.getVideoUnits().size(); } /** * Gibt die Menge aller Videos in der Datenbasis zurück. * * @return Die Menge aller Videos in der Datenbasis. */ public static Collection<Video> findAll() { return videoList.values(); } /** * Gibt das Video mit einer bestimmten VideoID zurück. * * @param vID Die ID des Videos. * @return Das Video mit der angegebenen ID. * @throws RecordNotFoundException , falls kein Video mit dieser ID gefunden * wurde. */ public static Video findByID(int vID) throws RecordNotFoundException { if (videoList.containsKey(vID)) { return videoList.get(vID); } else { throw new RecordNotFoundException("Video", "VideoNr", vID); } } /** * Gibt eine Menge von Videos zurück, deren Titel mit einem angegebenen * Titel anfangen. * * @param videoTitle Der Titel, nach dem gesucht wird. * @return Die Menge der Videos, deren Titel mit dem angegebenen anfangen. */ public static Collection<Video> findByTitle(String videoTitle) { Collection<Video> foundVideos = new LinkedList<Video>(); for (Video vid : videoList.values()) { if (vid.title.toLowerCase().contains(videoTitle.toLowerCase())) { foundVideos.add(vid); } } return foundVideos; } /** * Gibt eine Menge von Videos zurück, die ein angegebenes * Veröffentlichungsjahr haben. * * @param releaseYear Das Veröffentlichungsjahr, nach dem gesucht wird. * @return Die Menge der Videos, die das gleiche Veröffentlichungsjahr * haben. */ public static Collection<Video> findByReleaseYear(int releaseYear) { Collection<Video> foundVideos = new LinkedList<Video>(); for (Video vid : videoList.values()) { if (vid.releaseYear == releaseYear) { foundVideos.add(vid); } } return foundVideos; } /** * Gibt eine Menge von Videos zurück, die einer angegebenen Preiskategorie * angehören. * * @param priceCategory Die Preiskategorie, nach der gesucht wird. * @return Die Menge der Videos, die der gleiche Preiskategorie angehören. */ public static Collection<Video> findByPriceCategory( PriceCategory priceCategory) { Collection<Video> foundVideos = new LinkedList<Video>(); for (Video vid : videoList.values()) { if (vid.priceCategory == priceCategory) { foundVideos.add(vid); } } return foundVideos; } /** * Gibt eine Menge von Videos zurück, die die gleiche Altersbeschränkung * haben. * * @param ratedAge Die Alterbeschränkung, nach der gesucht wird. * @return Die Menge der Videos, die die gleiche Altersbeschränkung haben. */ public static Collection<Video> findByRatedAge(int ratedAge) { Collection<Video> foundVideos = new LinkedList<Video>(); for (Video vid : videoList.values()) { if (vid.ratedAge == ratedAge) { foundVideos.add(vid); } } return foundVideos; } /** * Gibt die derzeitige MinID für Videos zurück. * * @return die derzeitige MinID für Videos */ public static int getMinID() { return minvID; } /** * Gibt an, ob ein angegebener Film bereits vorhanden ist * (d.h. dass bereits ein anderer Film existiert, bei dem alle Datenfelder gleich sind). * @param video der zu vergleichende Film * @return True, wenn ein gleicher Film existiert, False sonst */ private static boolean containsEqualVideo(Video video) { for(Video v: videoList.values()) { if(v.equals(video)) { return true; } } return false; } @Override /** * */ public int compareTo(Video other) { if(this.priceCategoryID == other.priceCategoryID && this.ratedAge == other.ratedAge && this.releaseYear == other.releaseYear && this.title.equals(other.title)) { return 0; } return 1; } /** * Gibt an, ob dieses Video einem anderen gleicht. * @param other Das andere Video, mit dem verglichen werden soll. * @return True, falls gleich, False sonst. */ public boolean equals(Video other) { return this.compareTo(other) == 0; } }