home *** CD-ROM | disk | FTP | other *** search
/ The Net: Ultimate Internet Guide / WWLCD1.ISO / pc / java / un2maiq4 / pjjava / src / pj / io / paper.java < prev    next >
Encoding:
Java Source  |  1996-08-14  |  17.6 KB  |  513 lines

  1. /*---------------------------------------------------------------------------
  2.  
  3.     Written by the Personal Journal developers of Dow Jones & Company, Inc.
  4.  
  5.     Dow Jones makes no representations or warranties about 
  6.     the suitability of this software, either express or 
  7.     implied, including but not limited to the implied warranties 
  8.     of merchantability, fitness for a particular purpose, 
  9.     or non-infringement.  Dow Jones will not be liable for 
  10.     any damages suffered by a user as a result of using, 
  11.     modifying or distributing this software or its derivatives.
  12.  
  13.  
  14.  
  15.     @(#)Paper.java  0.00 20-Dec-95
  16.  
  17.  
  18.         A collection of stories, arranged into sections, transferred
  19.         from a Personal Journal server.
  20.  
  21.         A paper observes its subsections, which in turn observe it.
  22.         When a paper receives a StoryContainerNotification from one
  23.         of its subsections, it relays the message to its other subsections.
  24.  
  25.  
  26.     Authors:
  27.  
  28.         rphall      Rick Hall
  29.         jlee        James Lee
  30.  
  31.  
  32.     Version Ident:
  33.  
  34.         $Header$
  35.  
  36.  
  37.     History:
  38.  
  39.         20-Dec-95    rphall      Initial Creation
  40.         27-Dec-95    rphall      Observerable sections, observable paper
  41.         21-Mar-96    jlee        Added DownloadProgressNotification functionality
  42.  
  43. ---------------------------------------------------------------------------*/
  44.  
  45. package pj.io;
  46.  
  47. import pj.io.PaperStory;
  48. import pj.io.PaperSection;
  49.  
  50. import collections.Assertable;
  51. import collections.ImplementationCheckable;
  52. import collections.ImplementationError;
  53. import java.applet.Applet;
  54. import java.util.NoSuchElementException;
  55. import java.util.Observable;
  56. import java.util.Observer;
  57. import java.util.Vector;
  58.  
  59. /**
  60.  * A collection of stories, arranged into sections, transferred
  61.  * from a Personal Journal server.
  62.  * @version 0.00, 20-Dec-95
  63.  * @author      Rick Hall
  64.  */
  65. public class Paper extends Observable implements Assertable, StoryContainer, ImplementationCheckable, Observer
  66.     {
  67.     // --- Class variables
  68.  
  69.     /** Front page Business and Finance */
  70.     public static final String idFPBusFin = "101";
  71.     /** Front page World-Wide */
  72.     public static final String idFPWorld  = "102";
  73.     /** Front page Personal News */
  74.     public static final String idFPNews   = "103";
  75.     /** Front page News Flash */
  76.     public static final String idFPFlash  = "104";
  77.     /** TJI Business and Finance */
  78.     public static final String idTJIBusFin= "201";
  79.     /** TJI World-Wide */
  80.     public static final String idTJIWorld = "202";
  81.     /** TJI Personal News */
  82.     public static final String idTJINews  = "203";
  83.     /** Portfolio Stock Quote */
  84.     public static final String idPortQuote= "301";
  85.     /** Portfolio Advertisement */
  86.     public static final String idPortAd   = "302";
  87.     /** Markets Dow Jones IA */
  88.     public static final String idMrkDjia  = "401";
  89.     /** Markets Stock Indices */
  90.     public static final String idMrkStkIdx= "402";
  91.     /** Markets Exchange Rates */
  92.     public static final String idMrkExch  = "403";
  93.     /** Markets Treasuries */
  94.     public static final String idMrkTreas = "404";
  95.     /** Markets Wrapup */
  96.     public static final String idMrkWrap  = "405";
  97.     /** Sports Highlights */
  98.     public static final String idSpHilite = "501";
  99.     /** Sports Scores */
  100.     public static final String idSpScores = "502";
  101.     /** Sports Advertisement */
  102.     public static final String idSpAd     = "503";
  103.     /** Weather US Northeast */
  104.     public static final String idWthUSNE  = "601";
  105.     /** Weather US Southeast */
  106.     public static final String idWthUSSE  = "602";
  107.     /** Weather US Midwest */
  108.     public static final String idWthUSMW  = "603";
  109.     /** Weather US West */
  110.     public static final String idWthUSWest= "604";
  111.     /** Weather Canada */
  112.     public static final String idWthCanada= "605";
  113.     /** Weather South America */
  114.     public static final String idWthSouthA= "606";
  115.     /** Weather Europe */
  116.     public static final String idWthEurope= "607";
  117.     /** Weather Mid-East */
  118.     public static final String idWthMidE  = "608";
  119.     /** Weather Africa */
  120.     public static final String idWthAfrica= "609";
  121.     /** Weather Asia */
  122.     public static final String idWthAsia  = "610";
  123.     /** Weather Advertisement */
  124.     public static final String idWthAd    = "611";
  125.     /** Protocol Log (Obsolete) */
  126.     public static final String idPcolLog  = "701";
  127.     /** Protocol End of transmission */
  128.     public static final String idPcolEOT  = "702";
  129.     /** Protocol Error Message */
  130.     public static final String idPcolErr  = "703";
  131.     /** Protocol Timestamp */
  132.     public static final String idPcolTimes= "704";
  133.  
  134.  
  135.     // --- Instance variables
  136.  
  137.     private final int idxSubsect = 0;
  138.     private final int idxType = 1;
  139.  
  140.     private final String strSectionAttrib[][] =
  141.         { // Subsection  Type
  142.         { idFPBusFin  , PaperSection.typeArticle}, // Front page Business and Finance
  143.         { idFPWorld   , PaperSection.typeArticle}, // Front page World-Wide
  144.         { idFPNews    , PaperSection.typeArticle}, // Front page Personal News
  145.         { idFPFlash   , PaperSection.typeArticle}, // Front page News Flash
  146.         { idTJIBusFin , PaperSection.typeArticle}, // TJI Business and Finance
  147.         { idTJIWorld  , PaperSection.typeArticle}, // TJI World-Wide
  148.         { idTJINews   , PaperSection.typeArticle}, // TJI Personal News
  149.         { idPortQuote , PaperSection.typeArticle}, // Portfolio Stock Quote
  150.         { idPortAd    , PaperSection.typeArticle}, // Portfolio Advertisement
  151.         { idMrkDjia   , PaperSection.typeArticle}, // Markets Dow Jones IA
  152.         { idMrkStkIdx , PaperSection.typeArticle}, // Markets Stock Indices
  153.         { idMrkExch   , PaperSection.typeArticle}, // Markets Exchange Rates
  154.         { idMrkTreas  , PaperSection.typeArticle}, // Markets Treasuries
  155.         { idMrkWrap   , PaperSection.typeArticle}, // Markets Wrapup
  156.         { idSpHilite  , PaperSection.typeArticle}, // Sports Highlights
  157.         { idSpScores  , PaperSection.typeArticle}, // Sports Scores
  158.         { idSpAd      , PaperSection.typeArticle}, // Sports Advertisement
  159.         { idWthUSNE   , PaperSection.typeArticle}, // Weather US Northeast
  160.         { idWthUSSE   , PaperSection.typeArticle}, // Weather US Southeast
  161.         { idWthUSMW   , PaperSection.typeArticle}, // Weather US Midwest
  162.         { idWthUSWest , PaperSection.typeArticle}, // Weather US West
  163.         { idWthCanada , PaperSection.typeArticle}, // Weather Canada
  164.         { idWthSouthA , PaperSection.typeArticle}, // Weather South America
  165.         { idWthEurope , PaperSection.typeArticle}, // Weather Europe
  166.         { idWthMidE   , PaperSection.typeArticle}, // Weather Mid-East
  167.         { idWthAfrica , PaperSection.typeArticle}, // Weather Africa
  168.         { idWthAsia   , PaperSection.typeArticle}, // Weather Asia
  169.         { idWthAd     , PaperSection.typeArticle}, // Weather Advertisement
  170.         { idPcolLog   , PaperSection.typeArticle}, // Protocol Log (Obsolete)
  171.         { idPcolEOT   , PaperSection.typeArticle}, // Protocol End of transmission
  172.         { idPcolErr   , PaperSection.typeArticle}, // Protocol Error Message
  173.         { idPcolTimes , PaperSection.typeArticle}  // Protocol Timestamp
  174.         };
  175.  
  176.     private final int idxFirstEnumSection =  0; // Front page B&F
  177.     private final int idxLastEnumSection  = 27; // Last weather page
  178.     private Vector    vSection;                 // Implementation of this container
  179.     private       int idxCurrent;               // A cursor into sections
  180.  
  181.  
  182.  
  183.     // --- Public constructors
  184.  
  185.     public Paper() throws ImplementationError
  186.         {
  187.         vSection = new Vector();
  188.         for (int i=0; i<strSectionAttrib.length; i++)
  189.             {
  190.             PaperSection sec = new PaperSection (
  191.                     sectionString(strSectionAttrib[i][idxSubsect]),
  192.                     strSectionAttrib[i][idxSubsect],
  193.                     strSectionAttrib[i][idxType] );
  194.             sec.addObserver(this);
  195.             addObserver(sec);
  196.             vSection.addElement(sec);
  197.             }
  198.         idxCurrent = 0;
  199.         checkImplementation();
  200.         System.out.println("Debug-Paper:constructed");
  201.         }
  202.  
  203.     // --- Public operations
  204.  
  205.     public void assert(boolean predicate)
  206.         throws ImplementationError
  207.         { 
  208.         ImplementationError.assert(this, predicate); 
  209.         }
  210.  
  211.     public void checkImplementation()
  212.         throws ImplementationError
  213.         {
  214.         assert( vSection.size() == strSectionAttrib.length );
  215.         for (int i=0; i<strSectionAttrib.length; i++)
  216.             assert( vSection.elementAt(i) instanceof PaperSection );
  217.         assert( idxCurrent >= 0 );
  218.         assert( idxCurrent < vSection.size() );
  219.         }
  220.  
  221.     public synchronized void update(Observable o, Object arg)
  222.         {
  223.         if ( arg instanceof DownloadProgressNotification )
  224.             {
  225.             setChanged();
  226.             notifyObservers( arg );
  227.             }
  228.         else
  229.         if ( arg instanceof StoryContainerNotification )
  230.             {
  231.             setChanged();
  232.             notifyObservers(arg);
  233.  
  234.             if  ( !( ((StoryContainerNotification) arg).strSubsect.equals(idPcolEOT) ) )
  235.                 return;
  236.  
  237.             // HIDEOUS KLUDGE: define PaperEOTNotification instead of this PcolEOT
  238.             // crap
  239.  
  240.             // The Protocol EOT story requires special handling
  241.             if  ( ((StoryContainerNotification)arg).newState == PaperSection.stateAdding )
  242.                 {
  243.                 // Send a fake notification so that all subsections go to stateAdded
  244.                 PaperSection fake = new PaperSection( sectionString(idPcolEOT), idPcolEOT, PaperSection.typeArticle);
  245.                 StoryContainerNotification scn = new StoryContainerNotification( fake,idPcolEOT,PaperSection.stateAdding );
  246.                 setChanged();
  247.                 notifyObservers(scn);
  248.                 } // EOT adding
  249.             }
  250.         else
  251.             return;
  252.  
  253.         } // update
  254.  
  255.     
  256.  
  257.     public void addStory( PaperStory ps )
  258.         throws MalformedPaperStoryException, IncompatiblePaperStoryException,
  259.             IllegalArgumentException
  260.         {
  261.         if (ps == null)
  262.             throw new IllegalArgumentException();
  263.  
  264.         for (int i=0; i<strSectionAttrib.length; i++ )
  265.             {
  266.             if ( strSectionAttrib[i][idxSubsect].equals(ps.getSubsect()) )
  267.                 {
  268.                 ((PaperSection) vSection.elementAt(i)).addStory(ps);
  269.                 break;
  270.                 } // if
  271.             } // for
  272.         } // addStory
  273.  
  274.     public final int numStories()
  275.         {
  276.         int num = 0;
  277.         for (int i=0; i<strSectionAttrib.length; i++ )
  278.              num += ((PaperSection) vSection.elementAt(i)).numStories();
  279.         return num;
  280.         }
  281.  
  282.     public final synchronized void removeStories()
  283.         {
  284.         int num = 0;
  285.         for (int i=0; i<strSectionAttrib.length; i++ )
  286.              ((PaperSection) vSection.elementAt(i)).removeStories();
  287.         }
  288.  
  289.     public final synchronized PaperStory firstStory()
  290.         throws NoSuchElementException
  291.         { 
  292.         return ((PaperSection)
  293.                 vSection.elementAt(idxFirstEnumSection)).firstStory(); 
  294.         }
  295.  
  296.     public final synchronized PaperStory nextStory()
  297.         throws NoSuchElementException
  298.         {
  299.         int idxAttempt = idxCurrent;
  300.         PaperStory temp = null;
  301.  
  302.         // Pathologies
  303.         if ( numStories() == 0 )
  304.             throw new NoSuchElementException();
  305.  
  306.         if ( numStories() == 1 )
  307.             return ((PaperSection)
  308.                     vSection.elementAt(idxAttempt)).nextStory();
  309.  
  310.         // Typical case
  311.         try {
  312.             // Try the current section
  313.             temp= ((PaperSection)
  314.                     vSection.elementAt(idxAttempt)).nextStory();
  315.             }
  316.         catch (NoSuchElementException e)
  317.             {
  318.             // Bump to the next section
  319.             if (idxAttempt >= idxLastEnumSection)
  320.                 idxAttempt = idxFirstEnumSection;
  321.             else
  322.                 idxAttempt++;
  323.             }
  324.         if ( temp != null )
  325.             return temp;
  326.  
  327.         // Iterate over remaining sections to find next story
  328.         for (int i=0; i<vSection.size()-1; i++ )
  329.             {
  330.             try {
  331.                 // Try the current section
  332.                 temp= ((PaperSection)
  333.                         vSection.elementAt(idxAttempt)).firstStory();
  334.                 break;
  335.                 }
  336.             catch (NoSuchElementException e)
  337.                 {
  338.                 // Bump to the next section
  339.                 if (idxAttempt >= idxLastEnumSection)
  340.                     idxAttempt = idxFirstEnumSection;
  341.                 else
  342.                     idxAttempt++;
  343.                 }
  344.             } // for
  345.  
  346.         // Finish up
  347.         if (temp != null)
  348.             {
  349.             idxCurrent = idxAttempt;
  350.             return temp;
  351.             }
  352.         else
  353.             {
  354.             checkImplementation();
  355.             throw new NoSuchElementException();
  356.             }
  357.  
  358.         } // nextStory
  359.  
  360.     public final synchronized PaperStory lastStory()
  361.         throws NoSuchElementException
  362.         { 
  363.         return ((PaperSection)
  364.                 vSection.elementAt(idxLastEnumSection)).lastStory(); 
  365.         }
  366.  
  367.     public final synchronized PaperStory previousStory()
  368.         throws NoSuchElementException
  369.         {
  370.         int idxAttempt = idxCurrent;
  371.         PaperStory temp = null;
  372.  
  373.         // Pathologies
  374.         if ( numStories() == 0 )
  375.             throw new NoSuchElementException();
  376.  
  377.         if ( numStories() == 1 )
  378.             return ((PaperSection)
  379.                     vSection.elementAt(idxAttempt)).previousStory();
  380.  
  381.         // Typical case
  382.         try {
  383.             // Try the current section
  384.             temp= ((PaperSection)
  385.                     vSection.elementAt(idxAttempt)).previousStory();
  386.             }
  387.         catch (NoSuchElementException e)
  388.             {
  389.             // Decrement to the previous section
  390.             if (idxAttempt == idxFirstEnumSection)
  391.                 temp= ((PaperSection)
  392.                         vSection.elementAt(idxAttempt)).firstStory();
  393.             else
  394.                 idxAttempt--;
  395.             }
  396.  
  397.         if ( temp != null )
  398.             return temp;
  399.  
  400.         // Iterate over remaining sections to find previous story
  401.         for (int i=0; i<vSection.size()-1; i++ )
  402.             {
  403.             try {
  404.                 // Try the current section
  405.                 temp= ((PaperSection)
  406.                         vSection.elementAt(idxAttempt)).lastStory();
  407.                 break;
  408.                 }
  409.             catch (NoSuchElementException e)
  410.                 {
  411.                 // Decrement to the previous section
  412.                 if (idxAttempt == idxFirstEnumSection)
  413.                     {
  414.                     temp =((PaperSection)
  415.                             vSection.elementAt(idxAttempt)).lastStory();
  416.                     break;
  417.                     }
  418.                 else
  419.                     idxAttempt--;
  420.                 } // catch
  421.  
  422.             } // for
  423.  
  424.         // Finish up
  425.         if (temp != null)
  426.             {
  427.             idxCurrent = idxAttempt;
  428.             return temp;
  429.             }
  430.         else
  431.             {
  432.             checkImplementation();
  433.             throw new NoSuchElementException();
  434.             }
  435.  
  436.         } // previousStory
  437.  
  438.     public final synchronized PaperStory currentStory()
  439.         throws NoSuchElementException
  440.         { 
  441.         return ((PaperSection)
  442.                 vSection.elementAt(idxCurrent)).currentStory(); 
  443.         }
  444.  
  445.     /**
  446.      * Return a PaperSection matching the given section id.
  447.      * See the public variables of Paper for a list of valid id strings.
  448.      * @param name A section id.
  449.      * @return The section matching id.
  450.      * @exception NoSuchElementException thrown if no section exists
  451.      * with the given id.
  452.     */
  453.     public PaperSection section(String id) throws NoSuchElementException
  454.         {
  455.         PaperSection temp = null;
  456.         for (int i=0; i<vSection.size()-1; i++ )
  457.             {
  458.             PaperSection temp2 = (PaperSection) vSection.elementAt(i);
  459.             if ( temp2.getId().equals(id) )
  460.                 {
  461.                 temp = temp2;
  462.                 break;
  463.                 }
  464.             } // for
  465.  
  466.         if (temp == null) throw new NoSuchElementException();
  467.             return temp;
  468.  
  469.         } // section
  470.  
  471.     public String toString()
  472.         {
  473.         if (vSection.size() < 1 ) 
  474.             return "";
  475.  
  476.         String temp = ((PaperSection) vSection.elementAt(0)).toString();
  477.         for (int i=1; i<vSection.size(); i++)
  478.             temp += ((PaperSection) vSection.elementAt(i)).toString();
  479.  
  480.         return temp;
  481.         }
  482.  
  483.     /**
  484.      * A section string can be calculated from the subsection string.
  485.      * <pre>
  486.      * e.g.
  487.      *      Subsection "702" ==> Section "700"
  488.      * </pre>
  489.      * @param subsection A subsection string
  490.      * @return The corresponding section string
  491.      * @exception ImplementationError thrown if subsection string
  492.      * does not parse to an integer
  493.     */
  494.     public static String sectionString(String subsection)
  495.         throws ImplementationError
  496.         {
  497.         int i = 0;
  498.         try {
  499.             i = (new Integer(subsection)).intValue();
  500.             i = 100 * (i/100);
  501.             }
  502.         catch(NumberFormatException e)
  503.             { 
  504.             throw new ImplementationError(); 
  505.             }
  506.         return (new Integer(i)).toString();
  507.  
  508.         } // sectionString
  509.  
  510.     
  511.  
  512.     } // Paper
  513.