lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [5019] Implement base class for MVC input sequences


From: Greg Chicares
Subject: [lmi-commits] [5019] Implement base class for MVC input sequences
Date: Sat, 03 Jul 2010 00:55:16 +0000

Revision: 5019
          http://svn.sv.gnu.org/viewvc/?view=rev&root=lmi&revision=5019
Author:   chicares
Date:     2010-07-03 00:55:15 +0000 (Sat, 03 Jul 2010)
Log Message:
-----------
Implement base class for MVC input sequences

Modified Paths:
--------------
    lmi/trunk/ChangeLog
    lmi/trunk/datum_sequence.cpp
    lmi/trunk/datum_sequence.hpp

Modified: lmi/trunk/ChangeLog
===================================================================
--- lmi/trunk/ChangeLog 2010-07-01 17:31:37 UTC (rev 5018)
+++ lmi/trunk/ChangeLog 2010-07-03 00:55:15 UTC (rev 5019)
@@ -26221,3 +26221,19 @@
   version.hpp
 Mark release candidate.
 
+20100701T1731Z <address@hidden> [697]
+
+  Makefile.am
+  datum_sequence.cpp       [new file]
+  datum_sequence.hpp       [new file]
+  input_sequence_entry.cpp [new file]
+  input_sequence_entry.hpp [new file]
+  objects.make
+Add embryonic input-sequence editor.
+
+20100703T0055Z <address@hidden> [697]
+
+  datum_sequence.cpp
+  datum_sequence.hpp
+Implement base class for MVC input sequences.
+

Modified: lmi/trunk/datum_sequence.cpp
===================================================================
--- lmi/trunk/datum_sequence.cpp        2010-07-01 17:31:37 UTC (rev 5018)
+++ lmi/trunk/datum_sequence.cpp        2010-07-03 00:55:15 UTC (rev 5019)
@@ -26,20 +26,29 @@
 #   pragma hdrstop
 #endif // __BORLANDC__
 
-// The remainder of this initial version is just a copy of
-// 'datum_string.cpp' with 's/datum_string/datum_sequence/g'.
-
 #include "datum_sequence.hpp"
 
-#include "facets.hpp"
+#include "assert_lmi.hpp"
 
+/// Default constructor.
+///
+/// Throws if insane.
+
 datum_sequence::datum_sequence()
+    :keyword_values_are_blocked_(false)
 {
+    assert_sanity();
 }
 
-datum_sequence::datum_sequence(std::string const& value)
-    :value_(value)
+/// Construct from string.
+///
+/// Throws if insane.
+
+datum_sequence::datum_sequence(std::string const& s)
+    :datum_string(s)
+    ,keyword_values_are_blocked_(false)
 {
+    assert_sanity();
 }
 
 datum_sequence::~datum_sequence()
@@ -48,30 +57,90 @@
 
 datum_sequence& datum_sequence::operator=(std::string const& s)
 {
-    value_ = s;
+    datum_string::operator=(s);
     return *this;
 }
 
-std::string const& datum_sequence::value() const
+/// Block or unblock keyword values.
+///
+/// This has no practical effect if keyword values are not allowable.
+///
+/// Throws if insane.
+
+void datum_sequence::block_keyword_values(bool z)
 {
-    return value_;
+    keyword_values_are_blocked_ = z;
+    assert_sanity();
 }
 
-std::istream& datum_sequence::read(std::istream& is)
+/// Declare whether numeric values are allowable.
+
+bool datum_sequence::numeric_values_are_allowable() const
 {
-    std::locale old_locale = is.imbue(blank_is_not_whitespace_locale());
-    is >> value_;
-    is.imbue(old_locale);
-    return is;
+    return true;
 }
 
-std::ostream& datum_sequence::write(std::ostream& os) const
+/// Declare whether keyword values are allowable.
+///
+/// Even if they are allowable, they may be blocked.
+
+bool datum_sequence::keyword_values_are_allowable() const
 {
-    return os << value();
+    return false;
 }
 
+/// Ascertain which keywords are allowed in the current context.
+///
+/// The return value is a map: keyword --> mc_enum string. Rationale:
+/// keywords are part of the user interface, and should be easy for
+/// users to write and remember; whereas mc_enum strings are internal,
+/// and should be easy for domain experts to read--thus, evocative and
+/// unambiguous more than terse. For example:
+///   - "glp" --> "PmtGLP" // for payments
+///   - "glp" --> "SAGLP"  // for specified amount
+/// Here, "PmtGLP" can mean only a guideline-level-premium payment
+/// strategy, but users wouldn't want to type it; "glp" is easy to
+/// type, but its meaning depends upon context. Furthermore, using a
+/// map makes it possible to change internal names without affecting
+/// the user interface.
+
+std::map<std::string,std::string> const datum_sequence::allowed_keywords() 
const
+{
+    return std::map<std::string,std::string>();
+}
+
+/// Determine whether two objects are equivalent.
+///
+/// Rationale: to support free function operator==(). See:
+///   http://lists.nongnu.org/archive/html/lmi/2010-07/msg00002.html
+/// It would be simpler to provide a trivial accessor for the member
+/// datum, but maintaining strong encapsulation reduces the temptation
+/// for one component of MVC to inspect another's internals.
+
+bool datum_sequence::equals(datum_sequence const& z) const
+{
+    return z.keyword_values_are_blocked_ == keyword_values_are_blocked_;
+}
+
+/// Ensure that input is possible; throw otherwise.
+///
+/// Input is possible iff either
+///   - keyword values are allowable and not blocked; or
+///   - numeric values are allowable.
+/// For the nonce at least, the first condition doesn't require
+/// allowed_keywords() to return a non-empty map; that can be
+/// considered as experience emerges with derived classes.
+
+void datum_sequence::assert_sanity() const
+{
+    LMI_ASSERT
+        (  (keyword_values_are_allowable() && !keyword_values_are_blocked_)
+        ||  numeric_values_are_allowable()
+        );
+}
+
 bool operator==(datum_sequence const& lhs, datum_sequence const& rhs)
 {
-    return lhs.value() == rhs.value();
+    return lhs.equals(rhs);
 }
 

Modified: lmi/trunk/datum_sequence.hpp
===================================================================
--- lmi/trunk/datum_sequence.hpp        2010-07-01 17:31:37 UTC (rev 5018)
+++ lmi/trunk/datum_sequence.hpp        2010-07-03 00:55:15 UTC (rev 5019)
@@ -21,26 +21,48 @@
 
 // $Id$
 
-// The remainder of this initial version is just a copy of
-// 'datum_string.hpp' with 's/datum_string/datum_sequence/g'.
-
 #ifndef datum_sequence_hpp
 #define datum_sequence_hpp
 
 #include "config.hpp"
 
-#include "datum_base.hpp"
+#include "datum_string.hpp"
 
 #include "value_cast.hpp"
 
 #include <boost/operators.hpp>
 
+#include <map>
 #include <string>
 
-// Implicitly-declared special member functions do the right thing.
+/// Base class for MVC input sequences.
+///
+/// Sequences are formed of values and intervals. Intervals may always
+/// be specified by numbers, keywords, or a combination of both. Each
+/// sequence's semantics determines whether its allowable values may
+/// be numbers, or keywords, or both; that's a fixed property of each
+/// derived class. Keyword values may be blocked in context even if
+/// they would be allowed in general; that's a runtime property of
+/// each derived-class instance.
+///
+/// For some sequences, no keywords are defined, and therefore none
+/// are ever permitted. It is difficult, e.g., to conceive of a
+/// keyword that would be useful for 7702A amounts-paid history.
+///
+/// For others, only keywords can be used, and numbers are never
+/// permitted. Payment mode, e.g., is chosen from an enumerated list,
+/// and numbers would at best be ambiguous synonyms:
+///  -  1=annual, 12=monthly // payments per least-frequent mode
+///  - 12=annual,  1=monthly // payments per  most-frequent mode
+///  -  1=A, 2=S, 3=Q, 4=M   // order in which they might be listed
+///
+/// Still others permit both numbers and keywords. Specified amount,
+/// e.g., must accommodate numeric entry.
+///
+/// Implicitly-declared special member functions do the right thing.
 
 class datum_sequence
-    :public datum_base
+    :public datum_string
     ,private boost::equality_comparable<datum_sequence,datum_sequence>
 {
   public:
@@ -50,14 +72,21 @@
 
     datum_sequence& operator=(std::string const&);
 
-    std::string const& value() const;
+    void block_keyword_values(bool);
 
-    // datum_base required implementation.
-    virtual std::istream& read (std::istream&);
-    virtual std::ostream& write(std::ostream&) const;
+    // For the nonce, this class is used concretely. These three
+    // functions will become pure virtual once a full complement of
+    // derived classes has been written.
+    //
+    virtual bool numeric_values_are_allowable() const;
+    virtual bool keyword_values_are_allowable() const;
+    virtual std::map<std::string,std::string> const allowed_keywords() const;
 
+    bool equals(datum_sequence const&) const;
+    void assert_sanity() const;
+
   private:
-    std::string value_;
+    bool keyword_values_are_blocked_;
 };
 
 bool operator==(datum_sequence const&, datum_sequence const&);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]