001package hirondelle.stocks.portfolio; 002 003import java.util.Observable; 004import java.util.*; 005import hirondelle.stocks.util.Args; 006import hirondelle.stocks.quotes.Stock; 007 008/** 009 * The central abstraction of this package, representing the current selection of 010 * stocks of interest to the end user 011 * (a {@link hirondelle.stocks.portfolio.Portfolio}). 012 * 013 * <P><tt>CurrentPortfolio</tt> may be used as an example implementation for any 014 * application which edits one item at a time. 015 * 016 * <p>The {@link #isUntitled} and {@link #getNeedsSave} properties are particularly 017 * significant. They influence the file menu actions. For example, a 018 * <tt>CurrentPortfolio</tt> for which {@link #isUntitled} is true cannot be deleted. 019 * 020 * <p><tt>CurrentPortfolio</tt> is an {@link java.util.Observable}. To minimize spurious 021 * updates, related {@link java.util.Observer} objects need to call 022 * {@link java.util.Observable#notifyObservers()} explicitly. This is important in this 023 * application, since quotes are fetched from the web each time the current portfolio is 024 * updated, and this is a relatively expensive operation. 025 */ 026public final class CurrentPortfolio extends Observable { 027 028 /** 029 * Constructor. 030 * 031 * @param aPortfolio is the set of stocks of current interest to the user; no 032 * defensive copy is made of <tt>aPortfolio</tt>. 033 * @param aNeedsSave is true only if this <tt>CurrentPortfolio</tt> 034 * has been edited by the end user, and these edits have not yet been saved. 035 */ 036 public CurrentPortfolio(Portfolio aPortfolio, NeedsSave aNeedsSave) { 037 Args.checkForNull(aPortfolio); 038 fPortfolio = aPortfolio; 039 fNeedsSave = aNeedsSave.getValue(); 040 // upon construction of the main window, an update is desired in order to 041 // synch the gui with the current portfolio. This update is called explicitly. 042 // Thus, setChanged needs to be set here, since it's default value is false. 043 setChanged(); 044 } 045 046 /** 047 * Enumeration for the two states of <tt>aNeedsSave</tt> passed to the constructor. 048 * Use of an enumeration forces the caller to create a constructor call which has 049 * high clarity. 050 */ 051 public enum NeedsSave { 052 TRUE(true), 053 FALSE(false); 054 boolean getValue() { 055 return fToggle; 056 } 057 private final boolean fToggle; 058 private NeedsSave(boolean aToggle) { 059 fToggle = aToggle; 060 } 061 } 062 063 /** 064 * Revert to an untitled <tt>Portfolio</tt> which does not need a save. 065 */ 066 public void clear() { 067 setPortfolio(Portfolio.getUntitledPortfolio()); 068 setNeedsSave(false); 069 } 070 071 /** 072 * Return <tt>true</tt> only if the current <tt>Portfolio</tt> has never been 073 * saved under a user-specified name, neither in this session, nor in any other. Such a 074 * <tt>Portfolio</tt> appears as untitled in the display. 075 */ 076 public boolean isUntitled() { 077 return fPortfolio.isUntitled(); 078 } 079 080 /** 081 * Return the {@link Portfolio} of current interest to the user. 082 */ 083 public Portfolio getPortfolio() { 084 return fPortfolio; 085 } 086 087 /** 088 * Change the {@link Portfolio} of current interest to the user. 089 */ 090 public void setPortfolio(Portfolio aPortfolio) { 091 Args.checkForNull(aPortfolio); 092 fPortfolio = aPortfolio; 093 setChanged(); 094 } 095 096 /** 097 * Return the name of this <tt>CurrentPortfolio</tt>. 098 */ 099 public String getName() { 100 return fPortfolio.getName(); 101 } 102 103 /** 104 * Change the name of this <tt>CurrentPortfolio</tt>. 105 * @param aName has the same conditions as 106 * {@link hirondelle.stocks.portfolio.Portfolio#setName(String)}. 107 */ 108 public void setName(String aName) { 109 fPortfolio.setName(aName); 110 setChanged(); 111 } 112 113 /** 114 * Return the {@link hirondelle.stocks.quotes.Stock} objects in this 115 * <tt>CurrentPortfolio</tt>. 116 */ 117 public Set<Stock> getStocks() { 118 return fPortfolio.getStocks(); 119 } 120 121 /** 122 * Change the stocks in this <tt>CurrentPortfolio</tt>. 123 * @param aStocks has the same conditions as 124 * {@link hirondelle.stocks.portfolio.Portfolio#setStocks(Set)} 125 */ 126 public void setStocks(Set<Stock> aStocks) { 127 fPortfolio.setStocks(aStocks); 128 setChanged(); 129 } 130 131 /** 132 * Return <tt>true</tt> only if this <tt>CurrentPortfolio</tt> has unsaved 133 * edits. 134 */ 135 public boolean getNeedsSave() { 136 return fNeedsSave; 137 } 138 139 /** 140 * Indicate that this <tt>CurrentPortfolio</tt> either does or does not have any 141 * unsaved edits. 142 */ 143 public void setNeedsSave(boolean aNeedsSave) { 144 fNeedsSave = aNeedsSave; 145 setChanged(); 146 } 147 148 // PRIVATE 149 private Portfolio fPortfolio; 150 private boolean fNeedsSave; 151}