Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

/magnus/back_end/SessionManager/include/FEData.h

Go to the documentation of this file.
00001 /*
00002  *   $Id: FEData.h,v 1.5 1998/02/23 17:17:41 alex Exp $
00003  */
00004 
00005 // Copyright (C) 1995 The New York Group Theory Cooperative
00006 // See magnus/doc/COPYRIGHT for the full notice.
00007 
00008 // Contents: Declaration of mixin class FEData
00009 //
00010 // Principal Author: Roger Needham
00011 //
00012 // Status: in progress
00013 //
00014 // Revision History:
00015 //
00016 
00017 
00018 #ifndef _FEDATA_H_
00019 #define _FEDATA_H_
00020 
00021 
00022 #include <iostream.h>
00023 #include "Chars.h"
00024 #include "OID.h"
00025 #include "ARCSlotID.h"
00026 
00027 
00028 //   Introduction:
00029 //   ------------
00030 // 
00031 //   The following discussion is addressed to maintainers; users of class
00032 // FEData may wish to skip to the `Usage' section.
00033 // 
00034 //   Overview of Requirements:
00035 //   ------------------------
00036 // 
00037 //   The Magnus Front End (FE) must be able to reflect the state of the
00038 // Session Manager (SM). For modularity, the FE should know as little as
00039 // possible about the SM data it manipulates.
00040 // 
00041 //   Therefore, we predefine a small number of events, in response to
00042 // which the FE is to take some action which reflects the SM's state. The
00043 // SM describes to the FE what to do in each event, via a simple message
00044 // protocol.  The descriptions may refer to elements of a `blind'
00045 // database, which is stored by the FE and kept up to date by the SM.
00046 // 
00047 //   The FE must know nothing about the database except how to store and
00048 // extract data. Programmers in the SM layer should know nothing about
00049 // the database except its semantics in a given event.
00050 // 
00051 //   The classes wrapped in class FEData form the programmer's interface
00052 // between the SM and the database.
00053 // 
00054 //   Terminology:
00055 //   -----------
00056 // 
00057 //   The database is an associative array, where the keys and data can be
00058 // arbitrary strings. Exactly what strings are used is, of course,
00059 // hidden by the FEData classes.
00060 // 
00061 //   A `Key' may be constant or variable. When constant, it typically
00062 // consists of an object id supplied by the programmer, and a key
00063 // descriptor which is hidden from the programmer. When variable, it
00064 // typically consists of the index of a formal variable supplied by the
00065 // programmer, and the key descriptor. The latter allows database
00066 // references to be specified for events in advance, and later evaluated
00067 // in a context in which the formal variables have values. This is
00068 // tricky; see the discussion of menus, below.
00069 // 
00070 //   A `Datum' is the value returned by the database for a given key. It
00071 // is always constant, and is typically a boolean value, an object id, or
00072 // a string such as an object's name.  A Datum is represented only
00073 // conceptually by FEData (i.e., not as a class), since it exists only in
00074 // the FE. The programmer specifies a Datum via a Key.
00075 // 
00076 //   An `Expression' is built up from Keys via operators like `==', `&&',
00077 // and `!'. Thus an Expression may be variable or constant.
00078 // 
00079 //   A `Name' is an Expression which contains another Expression, where
00080 // the latter evaluates to an object id.
00081 // 
00082 //   Events:
00083 //   ------
00084 // 
00085 //   These are the events for which the FE must take action which depends
00086 // on the database:
00087 // 
00088 //   1) There is new data to be stored.
00089 // 
00090 //      The SM must supply a constant Key, and a constant Expression
00091 // (which may be a simple value) to become the Datum. For example, the SM
00092 // may announce that `the parent group of word <object-id> is
00093 // <object-id>'.  The `parent group' part is resolved as a key
00094 // descriptor, the first object id becomes part of the Key, and the
00095 // second object id is the Datum.
00096 // 
00097 //   2) The SM wishes to display textual data.
00098 // 
00099 //      In this case, the SM knows exactly which objects it wants to talk
00100 // about, so it can supply their object id's. SM programmers must be able
00101 // to embed constant Names in text.
00102 // 
00103 //   3) A new workspace object has been created.
00104 // 
00105 //      The view description for the object may contain text which refers
00106 // to various objects by name. These objects are known when the new one
00107 // is created, so the situation is as in 2).
00108 // 
00109 //   4) The workspace selection has changed.
00110 // 
00111 //      <To Appear>
00112 //
00113 //
00114 //   Usage:
00115 //   -----
00116 // 
00117 //      <To Appear>
00118 //
00119 
00120 
00121 //@rn  This stuff was too quickly hacked, and needs more thought. In
00122 //@rn  particular, the ! operator does not work properly; e.g., the
00123 //@rn  expression ( !  IsAuto(...) ) is spuriously false when there
00124 //@rn  is no `auto' key stored at all in the FE.
00125 
00126 
00127 
00128 //---------------------------------------------------------------------------//
00129 //----------------------------- FEData --------------------------------------//
00130 //---------------------------------------------------------------------------//
00131 
00132 class FEData
00133 {
00134 private:
00135 
00136   /////////////////////////////////////////////////////////////////////////
00137   //                                                                     //
00138   // Rep Classes:                                                        //
00139   //                                                                     //
00140   /////////////////////////////////////////////////////////////////////////
00141          
00142   struct ExpressionRep
00143   {
00144          ExpressionRep( ) : refs( 1 ) { }
00145 
00146          ExpressionRep* gimme( ) {
00147                 ++refs;
00148                 return this;
00149          }
00150 
00151          void getHence( ) {
00152                 if ( ! --refs ) { delete this; }
00153          }
00154 
00155          virtual ~ExpressionRep( ) { }
00156          
00157          virtual void printOn(ostream& ostr) const = 0;
00158 
00159          // Data Members:
00160 
00161          int refs;
00162   };
00163 
00164 
00165   struct KeyRep : public ExpressionRep
00166   {
00167          KeyRep(int i);  // Stupid special case
00168 
00169          KeyRep(int i, const char* t);
00170 
00171          KeyRep(OID oid, const char* t);
00172 
00173          KeyRep(ExpressionRep* se, const char* t);
00174 
00175          ~KeyRep( ) { if ( subExpression ) subExpression->getHence(); }
00176 
00177          void printOn(ostream& ostr) const;        // overrides ExpressionRep
00178 
00179          // Data Members:
00180 
00181          const int index;
00182          const char* text;
00183          bool isConstant;
00184          ExpressionRep* subExpression;
00185   };
00186 
00187   
00188   struct JoinRep : public ExpressionRep
00189   {
00190          JoinRep(ExpressionRep* a1, ExpressionRep* a2, const char* j);
00191 
00192          ~JoinRep( );
00193          
00194          void printOn(ostream& ostr) const;         // overrides ExpressionRep
00195 
00196          // Data Members:
00197 
00198          ExpressionRep* lhs;
00199          ExpressionRep* rhs;
00200          const char* junctor;  // Always static data
00201   };
00202 
00203 
00204   struct NotRep : public ExpressionRep
00205   {
00206          NotRep(ExpressionRep* a);
00207 
00208          ~NotRep( );
00209 
00210          void printOn(ostream& ostr) const;         // overrides ExpressionRep
00211 
00212          // Data Members:
00213 
00214          ExpressionRep* expr;
00215   };
00216 
00217 
00218   struct NameRep : public ExpressionRep
00219   {
00220          NameRep(ExpressionRep* a);
00221 
00222          ~NameRep( );
00223 
00224          void printOn(ostream& ostr) const;         // overrides ExpressionRep
00225 
00226          // Data Members:
00227 
00228          ExpressionRep* expr;
00229   };
00230 
00231 
00232 protected:
00233 
00234   //-------------------------------------------------------------------------//
00235   //---------------------------- Expression ---------------------------------//
00236   //-------------------------------------------------------------------------//
00237   
00238   class Expression
00239   {
00240   public:
00241          
00242          /////////////////////////////////////////////////////////////////////////
00243          //                                                                     //
00244          // Constructors:                                                       //
00245          //                                                                     //
00246          /////////////////////////////////////////////////////////////////////////
00247          
00248          Expression(int i) : theRep( new KeyRep( i ) ) { }
00249          // The hackery is getting rather thick; this is a quicky to allow storage
00250          // of, e.g., enum values as data.
00251          
00252          Expression( const Expression& E ) {
00253                 theRep = E.theRep->gimme();
00254          }
00255          
00256          ~Expression( ) { theRep->getHence(); }
00257  
00258          /////////////////////////////////////////////////////////////////////////
00259          //                                                                     //
00260          // Operators:                                                          //
00261          //                                                                     //
00262          /////////////////////////////////////////////////////////////////////////
00263          
00264          Expression operator == ( const Expression& E ) const {
00265                 return join( E, "==" );
00266          }
00267 
00268          Expression operator != ( const Expression& E ) const {
00269                 return join( E, "!=" );
00270          }
00271          
00272          Expression operator && ( const Expression& E ) const {
00273                 return join( E, "&&" );
00274          }
00275 
00276          Expression operator || ( const Expression& E ) const {
00277                 return join( E, "||" );
00278          }
00279 
00280          Expression operator ! ( ) const {
00281                 return Expression( new NotRep( theRep->gimme() ) );
00282          }
00283 
00284          Expression operator > ( const Expression& E ) const {
00285                 return join( E, ">" );
00286          }
00287 
00288          Expression operator >= ( const Expression& E ) const {
00289                 return join( E, ">=" );
00290          }
00291 
00292          Expression operator < ( const Expression& E ) const {
00293                 return join( E, "<" );
00294          }
00295 
00296          Expression operator <= ( const Expression& E ) const {
00297                 return join( E, "<=" );
00298          }
00299          
00300          /////////////////////////////////////////////////////////////////////////
00301          //                                                                     //
00302          // Output Methods:                                                     //
00303          //                                                                     //
00304          /////////////////////////////////////////////////////////////////////////
00305          
00306     friend ostream& operator << ( ostream& ostr, const Expression& E);
00307 
00308          /////////////////////////////////////////////////////////////////////////
00309          //                                                                     //
00310          // Protected Methods:                                                  //
00311          //                                                                     //
00312          /////////////////////////////////////////////////////////////////////////
00313          
00314          Expression( ExpressionRep* rep ) : theRep( rep ) { }
00315          // Call this ONLY when rep.refs already has the right value!
00316 
00317          /////////////////////////////////////////////////////////////////////////
00318          //                                                                     //
00319          // Data Members:                                                       //
00320          //                                                                     //
00321          /////////////////////////////////////////////////////////////////////////
00322 
00323          ExpressionRep* theRep;  // Public on purpose...
00324 
00325          /////////////////////////////////////////////////////////////////////////
00326          //                                                                     //
00327          // Private Methods:                                                    //
00328          //                                                                     //
00329          /////////////////////////////////////////////////////////////////////////
00330 
00331   private:
00332          
00333          Expression join( const Expression& E, const char* junctor ) const;
00334          
00335   };
00336 
00337 
00338   //-------------------------------------------------------------------------//
00339   //------------------------------- Key -------------------------------------//
00340   //-------------------------------------------------------------------------//
00341 
00342   class Key : public Expression
00343   {
00344   public:
00345 
00346          /////////////////////////////////////////////////////////////////////////
00347          //                                                                     //
00348          // Constructors:                                                       //
00349          //                                                                     //
00350          /////////////////////////////////////////////////////////////////////////
00351 
00352          Key( const Key& K ) : Expression( K.theRep->gimme() ) { }
00353 
00354          // Expression's dtor does the job
00355 
00356   protected:
00357 
00358          Key(int i) : Expression( new KeyRep( i ) ) { }  // Stupid special case
00359 
00360          Key(int i, const char* t) : Expression( new KeyRep( i, t ) ) { }
00361 
00362          Key(OID oid, const char* t) : Expression( new KeyRep( oid, t ) ) { }
00363 
00364          Key(const Key& K, const char* t)
00365            : Expression( new KeyRep( K.theRep->gimme(), t ) )
00366          { }
00367 
00368   };
00369 
00370 
00371   //-------------------------------------------------------------------------//
00372   //---------------------------- DataPair -----------------------------------//
00373   //-------------------------------------------------------------------------//
00374 
00375   struct DataPair
00376   {
00377          DataPair( const Key& key, const Expression& datum )
00378       : theKey( key ), theDatum( datum )
00379          { }
00380          
00381          // These are largely unneeded, but ListOf requires them:
00382 
00383          bool operator == (const DataPair& dp) const { return false; }
00384          DataPair& operator = (const DataPair& dp);
00385     friend ostream& operator << ( ostream& ostr, const DataPair& dp);
00386 
00387   private:
00388 
00389          Key theKey;
00390          Expression theDatum;
00391   };
00392 
00393 
00394   //-------------------------------------------------------------------------//
00395   //------------------------------ Text -------------------------------------//
00396   //-------------------------------------------------------------------------//
00397 
00398   struct Text
00399   {
00400          Text(const char* t = "");
00401          Text(const Expression& E);
00402          operator Chars( ) const;
00403          Text& operator + (const Text& t);
00404          Text& operator + (const Expression& E);
00405     friend ostream& operator << (ostream& ostr, const Text& t);
00406   private:
00407          Text(const Text&);
00408          // A Text is to be passed only by reference, so this is hidden and
00409          // not to be implemented. Also, unnecessary parenthesizing results
00410          // in a `passing reference to temp' warning which must not be
00411          // ignored.
00412          ostrstream ostrstr;
00413   };
00414 
00415 
00416   //-------------------------------------------------------------------------//
00417   //------------------------- Key Derivatives -------------------------------//
00418   //-------------------------------------------------------------------------//
00419   
00420   struct True : public Key
00421   {
00422          True( ) : Key( 1 ) { }
00423   };
00424 
00425 
00426   struct False : public Key
00427   {
00428          False( ) : Key( 0 ) { }
00429   };
00430 
00431 
00432   struct Object : public Key
00433   {
00434          Object(int i) : Key( i, 0 ) { }
00435          Object(OID o) : Key( o, 0 ) { }
00436          // Semantic pact with KeyRep: text == 0 => not a real key
00437   };
00438 
00439 
00440   struct CheckinType : public Key
00441   {
00442          CheckinType(int i) : Key( i, "checkin_type" ) { }
00443          CheckinType(OID o) : Key( o, "checkin_type" ) { }
00444          CheckinType(const Key& K) : Key( K, "checkin_type" ) { }
00445   };
00446   // Many menus and ARC slots are conditional, based purely on how the
00447   // selected objects were checked in (e.g., a group checked in as an
00448   // abelian group, not an FP group which is discovered to be
00449   // abelian).  Thus, this allows for associating, e.g., an enum
00450   // (type) value with an object, when and only when it is created,
00451   // and for subsequently using the value to choose the right menu item.
00452 
00453 
00454   // However, some menu items cannot make sense unless some piece of
00455   // information is known. For example, `Extend <a free group> by <a map>'
00456   // must not be posted unless the map is known to be an automorphism of
00457   // the group. Thus, in as few cases as we can get away with (to
00458   // stave off utter insanity), we dynamically update the FE database
00459   // with such crucial information when it is discovered. The following
00460   // provide the interface:
00461   
00462   
00463   struct IsHomo : public Key
00464   {
00465          IsHomo(int i) : Key( i, "homo" ) { }
00466          IsHomo(OID o) : Key( o, "homo" ) { }
00467   };
00468   
00469   
00470   struct IsIso : public Key
00471   {
00472          IsIso(int i) : Key( i, "iso" ) { }
00473          IsIso(OID o) : Key( o, "iso" ) { }
00474   };
00475   
00476   
00477   struct IsAuto : public Key
00478   {
00479          IsAuto(int i) : Key( i, "auto" ) { }
00480          IsAuto(OID o) : Key( o, "auto" ) { }
00481   };
00482 
00483 
00484   // The following are for static properties of algebraic objects which
00485   // are needed to determine whether a menu item, etc., should be posted.
00486 
00487   struct Parent : public Key
00488   {
00489          Parent(int i) : Key( i, "parent" ) { }
00490          Parent(OID o) : Key( o, "parent" ) { }
00491   };
00492 
00493   struct ParentGroup : public Key
00494   {
00495          ParentGroup(int i) : Key( Parent(i), "parent" ) { }
00496          ParentGroup(OID o) : Key( Parent(o), "parent" ) { }
00497   };
00498   
00499   struct Domain : public Key
00500   {
00501          Domain(int i) : Key( i, "domain" ) { }
00502          Domain(OID o) : Key( o, "domain" ) { }
00503   };
00504 
00505   
00506   struct Range : public Key
00507   {
00508          Range(int i) : Key( i, "range" ) { }
00509          Range(OID o) : Key( o, "range" ) { }
00510   };
00511   
00512 
00513   struct Oid : public Key
00514   {
00515          Oid(int i) : Key( i, "oid" ) { }
00516          Oid(OID o) : Key( o, "oid" ) { }
00517   };
00518 
00519 
00520   //-------------------------------------------------------------------------//
00521   //------------------------------ Name -------------------------------------//
00522   //-------------------------------------------------------------------------//
00523 
00524   struct Name : public Expression
00525   {
00526          Name(int i);
00527          Name(OID o);
00528          Name(const Expression& E);
00529   };
00530 
00531 
00532   // ----------------------------- Link ------------------------------------ //
00533 
00534   struct Link : public Text
00535   {
00536     Link( const Chars& text, const Chars& problemName,
00537           const Chars& fileName, bool isDynamic = false );
00538   };
00539 
00540 
00541   // ------------------------ SubProblemName ------------------------------- //
00542 
00543   struct SubProblemName
00544   {
00545     SubProblemName( OID oid, ARCSlotID asi ) 
00546       : theOid( oid.unwrap() ), theAsi( asi.unwrap() ) 
00547     { }
00548     
00549     friend ostream& operator << ( ostream& ostr, const SubProblemName& n ) {
00550       ostr << "[get_subProblemName " << n.theOid << " " << n.theAsi << "]";
00551       return ostr;
00552     }
00553  
00554   private:
00555     
00556     int theOid;
00557     int theAsi;
00558   };
00559 
00560   // ---------------------------- Banner ----------------------------------- //
00561 
00562   struct Banner
00563   {
00564     Banner( OID oid ) 
00565       : theOid( oid.unwrap() )
00566     { }
00567     
00568     friend ostream& operator << ( ostream& ostr, const Banner& b ) {
00569       ostr << "[get_viewBanner " << b.theOid << " " << "]";
00570       return ostr;
00571     }
00572  
00573   private:
00574     
00575     int theOid;
00576   };
00577 
00578 };
00579 
00580 #endif

Generated at Tue Jun 19 09:49:37 2001 for Magnus Classes by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001