Commit 4a94eb5f authored by Jeannie Backer's avatar Jeannie Backer
Browse files

Added PvlFlatMap class to API. Fixes #2399

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/trunk@6577 41f8697f-d340-4b68-9986-7bafba869bb8
parent 5d21d60e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
ifeq ($(ISISROOT), $(BLANK))
.SILENT:
error:
	echo "Please set ISISROOT";
else
	include $(ISISROOT)/make/isismake.objs
endif
 No newline at end of file
+889 −0

File added.

Preview size limit exceeded, changes collapsed.

+283 −0
Original line number Diff line number Diff line
#ifndef PvlFlatMap_h
#define PvlFlatMap_h
/**
 * @file                                                                  
 * $Revision: 6187 $ 
 * $Date: 2015-05-11 17:31:51 -0700 (Mon, 11 May 2015) $ 
 * $Id: PvlFlatMap.h 6187 2015-05-12 00:31:51Z kbecker@GS.DOI.NET $
 *
 *   Unless noted otherwise, the portions of Isis written by the USGS are
 *   public domain. See individual third-party library and package descriptions
 *   for intellectual property information, user agreements, and related
 *   information.
 *
 *   Although Isis has been used by the USGS, no warranty, expressed or
 *   implied, is made by the USGS as to the accuracy and functioning of such
 *   software and related material nor shall the fact of distribution
 *   constitute any such warranty, and no responsibility is assumed by the
 *   USGS in connection therewith.
 *
 *   For additional information, launch
 *   $ISISROOT/doc//documents/Disclaimers/Disclaimers.html
 *   in a browser or see the Privacy & Disclaimers page on the Isis website,
 *   http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on
 *   http://www.usgs.gov/privacy.html.
 */

// Qt library
#include <QMap>
#include <QString>
#include <QStringList>

// PvlConstraints type
#include "PvlKeyword.h"

namespace Isis {

  class FileName;
  class PvlContainer;
  class PvlGroup;
  class PvlObject;

  /**
   * This class can be used to define import/export behavior of Pvl structures 
   * when used in the PvlFlatMap class. 
   *  
   * The include/exclude features are applied to PvlObject and PvlGroup 
   * structures. 
   *  
   * The keylists apply only to keywords. 
   *  
   * Behavior beyond what is provided here is the burden of the programmer.
   *  
   * A complete Pvl structure can be provided in the PvlFlatMap class along with a 
   * defined PvlConstraints class containing objects/groups that are included or 
   * excluded from import operations.  Additionally, users can restrict the 
   * contents of all keyword containers to a list of keywords as provided in the 
   * keylist in this class.  It applies to all PVL keyword containers so ensure 
   * the list is comprehensive to include all desired keywords from all 
   * containers. 
   *  
   * Note if any include containers names are specified, all others are excluded 
   * by definition.  Likewise, if any containers are excluded, all other keywords 
   * containers are included by definition.  This behavior is defined to be 
   * constrained to the PvlObject and/or PvlGroup levels. 
   *  
   * A special mode can be defined by using both the include and exclude feature 
   * in combination. Include names are preimenent in this mode including only 
   * those PVL structures in the include list and excluding PVL structures in the 
   * exclude list. If any keywords exist in the keylist, then they are the only 
   * keywords mapped from the  PVL stuctures in the include list. 
   *  
   * Note that if a PvlGroup/PvlObject is excluded, then every PvlGroup/PvlObject 
   * contained within it are also excluded. Similarly, in order for a 
   * PvlGroup/PvlObject to be included, then any PvlObject that it is contained in 
   * must also be included. 
   *  
   * Example PVL:
   *  
   * @code 
   * Object = IsisCube
   *   Object = Core
   *     StartByte   = 65537
   *     Format      = Tile
   *     TileSamples = 128
   *     TileLines   = 128
   * 
   *     Group = Dimensions
   *       Samples = 704
   *       Lines   = 3640
   *       Bands   = 5
   *     End_Group
   * 
   *     Group = Pixels
   *       Type       = Real
   *       ByteOrder  = Lsb
   *       Base       = 0.0
   *       Multiplier = 1.0
   *     End_Group
   *   End_Object
   * 
   *   Group = Instrument
   *     SpacecraftName            = "LUNAR RECONNAISSANCE ORBITER"
   *     InstrumentId              = WAC-VIS
   *     TargetName                = Moon
   *     StartTime                 = 2009-09-15T07:27:49.230
   *   End_Group
   * 
   *   Group = Archive
   *     DataSetId            = LRO-L-LROC-2-EDR-V1.0
   *     ProducerId           = LRO_LROC_TEAM
   *     ProductId            = M107638937CE
   *   End_Group
   * 
   *   Group = BandBin
   *     FilterNumber = (3, 4, 5, 6, 7)
   *     Center       = (415, 566, 604, 643, 689)
   *   End_Group
   * 
   * End_Object
   * @endcode 
   *  
   * For the example PVL above, we can do the following: 
   *  
   * 1) Exclude the Pixels group 
   *  
   * @code 
   * PvlConstraints constraints; 
   * constraints.addExclude("Pixels"); 
   * @endcode 
   *  
   * 2) Include the Pixels group. 
   *  
   * @code 
   * PvlConstraints constraints; 
   * constraints.addInclude("IsisCube"); 
   * constraints.addInclude("Core"); 
   * constraints.addInclude("Pixels"); 
   * @endcode 
   *  
   * 3) The following will include everything in the Core object (Pixels, 
   * Dimensions, and Core keywords). 
   *  
   * @code 
   * PvlConstraints constraints; 
   * constraints.addInclude("IsisCube"); 
   * constraints.addInclude("Core"); 
   * @endcode 
   *  
   * 4) In some cases we will have a mix of includes/excludes.
   *  
   * @code 
   * PvlConstraints constraints; 
   * constraints.addInclude("IsisCube"); 
   * constraints.addInclude("Core"); 
   * constraints.addExclude("Pixels"); 
   * @endcode 
  *  
   * @author 2012-07-15 Kris Becker 
   * @internal 
   *   @history 2012-07-15 Kris Becker - Original version.
   *   @history 2015-03-20 Ian Humphrey - Updated documentation. Added
   *                           loadContainer method as helper method to
   *                           loadContainers to make exluding groups function
   *                           correctly.
  *    @history 2016-02-24 Jeannie Backer - Added unit test. Updated
  *                            documentation. Fixes #2399
   */
  class PvlConstraints {
    public:
      PvlConstraints();
      PvlConstraints(const QString &keyListFile);
      virtual ~PvlConstraints();
  
      int excludeSize() const;
      int includeSize() const;
      int keyListSize() const;
  
      void addExclude(const QString &name);
      void addInclude(const QString &name);
      void addKeyToList(const QString &name);
  
      void addExclude(const QStringList &other);
      void addInclude(const QStringList &other);
      void addKeyToList(const QStringList &other);
  
      void addKeyToList(const FileName &fileName);

      bool isExcluded(const QString &name) const;
      bool isIncluded(const QString &name) const;
      bool isKeyInList(const QString &name) const;
  
      const QStringList &excludes() const;
      const QStringList &includes() const;
      const QStringList &keyList()  const;
      
      static PvlConstraints withExcludes(const QStringList &excludes);
      static PvlConstraints withIncludes(const QStringList &includes);
  
    private:
      void readKeyListFile(const FileName &fname);

      QStringList m_excludes; //!< The names of objects and groups excluded (Excludes keyword)
      QStringList m_includes; //!< The names of objects and groups included (Includes keyword)
      QStringList m_keylist;  //!< The names of keywords to exclusively include (KeyListFile)
  
  };


  /**
   * @brief Provides a flat map of PvlKeywords.
   *  
   * This class provides a very fast convenient way to store PVL keywords for 
   * applications that require extensive use of them.  It is intended to provide a 
   * much easier interface to ISIS Pvl structures that represents them as a single 
   * flat lookup table. 
   *  
   * Note that if you use the methods provided in this class, then the keywords 
   * names will be converted to lowercase to provide a consistent interface.  One 
   * could choose to use the Qt QMap interface directly (which is the base class 
   * of this class) to use a case sensitive map.  Restricting use to add() and 
   * get() methods provides the case insensitive representation. 
   *  
   * @author 2012-07-15 Kris Becker 
   * @internal 
   *   @history 2012-07-15 Kris Becker - Original version.
   *   @history 2015-03-18 Jeannie Backer - Brought class files closer to ISIS coding standards.
   *   @history 2015-03-20 Ian Humphrey - Updated documentation. Modified loadGroups() and added 
   *                           loadGroup() method to correctly load PvlGroups against 
   *                           PvlConstraints.
   *   @history 2016-02-28 Jeannie Backer - Moved from isisminer app to base class area.
   *                           Brought closer to ISIS coding standards. Improved documentation.
   *                           Created unit test. Fixes #2399
   */
  class PvlFlatMap : public QMap<QString, PvlKeyword> {
  
    public:
      //! A const iterator for the underling QMap that PvlFlatMap is built on.
      typedef QMap<QString,PvlKeyword>::const_iterator ConstPvlFlatMapIterator;
      //! An iterator for the underlying QMap that PvlFlatMap is built on.
      typedef QMap<QString,PvlKeyword>::iterator       PvlFlatMapIterator;
  
      PvlFlatMap();
      PvlFlatMap(const PvlFlatMap &other);
      PvlFlatMap(const PvlFlatMap &pmap1, const PvlFlatMap &pmap2);
      PvlFlatMap(const PvlObject &pvl, const PvlConstraints &constraints = PvlConstraints());
      PvlFlatMap(const PvlGroup &pvl, const PvlConstraints &constraints = PvlConstraints());
      virtual ~PvlFlatMap();
  
      bool exists(const QString &key) const;
      int  count(const QString &key) const;
      bool isNull(const QString &key, const int index = 0) const;
      void add(const QString &key, const QString &value);
      void add(const PvlKeyword &keyword);
  
      void append(const PvlKeyword &key);
      void append(const QString &key, const QString &value);
  
      bool erase(const QString &key);
  
      QString get(const QString &key, const int &index = 0) const;
      QString get(const QString &key, const QString &defValue, 
                  const int &index = 0) const;
  
      // QString value(const QString &key) const;
      QString operator()(const QString &name) const;
      QStringList allValues(const QString &key) const;
  
      PvlKeyword keyword(const QString &key) const;
  
      int merge(const PvlFlatMap &other);
      
      static QStringList keywordValues(const PvlKeyword &keyword);
  
    private:
      int loadObject(const PvlObject &object, const PvlConstraints &constraints);
      int loadGroups(const PvlObject &object, const PvlConstraints &constraints);
      int loadGroup(const PvlGroup &group, const PvlConstraints &constraints);
      int loadKeywords(const PvlContainer &pvl, const PvlConstraints &constraints);
  };

} // Namespace Isis

#endif
+209 −0
Original line number Diff line number Diff line
PvlFlatMap1 Source (PvlObject): 
Object = Beasts
  CAT     = Meow
  Cat     = Null
  cat     = Purr
  Eagle   = Swoop
  Rattler = coil

  Object = ExcludeObject
    Dog = Moo
  End_Object

  Group = Fish
    Trout = Brown
    Bass  = "Large mouth"
  End_Group

  Group = Birds
    Sparrow = House
    Crow    = Null
    EAGLE   = Claws
  End_Group

  Group = ExcludeGroup
    CAT = Woof
  End_Group
End_Object

Map1 - CAT and EAGLE values are overwritten. No Constraints: 
	Bass = "Large mouth"
	CAT = Woof
	Crow = Null
	Dog = Moo
	EAGLE = Claws
	Rattler = coil
	Sparrow = House
	Trout = Brown

Map1B Constraints: 
    excludes:  ("ExcludeGroup", "ExcludeObject") 
    includes:  () 
    key list:  () 

Map1B - ExcludeGroup and ExcludeObject are excluded: 
	Bass = "Large mouth"
	cat = Purr
	Crow = Null
	EAGLE = Claws
	Rattler = coil
	Sparrow = House
	Trout = Brown

    Map1C Constraints: 
    size of excludes:  2 
    size of includes:  1 
    excludes:  ("ExcludeGroup", "ExcludeObject") 
    includes:  ("Beasts") 
    key list:  () 
    cat is excluded?  false 
    ExcludeGroup is excluded?  true 
    cat is included?  false 
    Beasts is included?  true 

Map1C - ExcludeGroup and ExcludeObject are excluded.
        Beasts object is included: 
	Bass = "Large mouth"
	cat = Purr
	Crow = Null
	EAGLE = Claws
	Rattler = coil
	Sparrow = House
	Trout = Brown

Map1D Constraints: 
    excludes:  () 
    includes:  ("Fish", "Birds") 
    key list:  () 

Map1D - Fish group and Birds object are included.
        However, parent object Beasts is not included,
        so all subgroups/subobjects are skipped: 
	 <Empty Map>

Map1E Constraints: 
    size of key list:  7 
    excludes:  () 
    includes:  () 
    key list:  ("cat", "eagle", "rattler", "trout", "bass", "sparrow", "crow") 
    cat is in list?   true 
    dog is in list?   false 

Map1E - key list provided: 
	Bass = "Large mouth"
	CAT = Woof
	Crow = Null
	EAGLE = Claws
	Rattler = coil
	Sparrow = House
	Trout = Brown

Map1F Constraints: 
    size of key list:  7 
    excludes:  () 
    includes:  () 
    key list:  ("dog", "eagle", "rattler", "trout", "bass", "sparrow", "crow") 
    cat is in list?   false 
    dog is in list?   true 

Map1F - key list file provided: 
	Bass = "Large mouth"
	Crow = Null
	Dog = Moo
	EAGLE = Claws
	Rattler = coil
	Sparrow = House
	Trout = Brown

Map1 Copy: 
	Bass = "Large mouth"
	CAT = Woof
	Crow = Null
	Dog = Moo
	EAGLE = Claws
	Rattler = coil
	Sparrow = House
	Trout = Brown

PvlFlatMap2 Source (PvlGroup): 
# Are slimey
Group = Snake
  Rattler = DiamondBack
End_Group

Map2 - No constraints: 
	Rattler = DiamondBack

Map1 and Map2 combined - RATTLER is overwritten: 
	Bass = "Large mouth"
	CAT = Woof
	Crow = Null
	Dog = Moo
	EAGLE = Claws
	Rattler = DiamondBack
	Sparrow = House
	Trout = Brown

Map3 - CLIMB values are appended: 
	Climb = (Wall, Rock, Tree)
	Field = Run
	Fly = Sugar

Merging Map3 to Maps 1,2. Adding [ "3" ] new keywords. 
Map1, Map2, and Map3 merged: 
	Bass = "Large mouth"
	CAT = Woof
	Climb = (Wall, Rock, Tree)
	Crow = Null
	Dog = Moo
	EAGLE = Claws
	Field = Run
	Fly = Sugar
	Rattler = DiamondBack
	Sparrow = House
	Trout = Brown

Get map info for existing keys: 
    Map has keyword=crow? true 
    crow is Null?  true 
    Map has keyword=climb? true 
    All Values for climb: ("Wall", "Rock", "Tree") 
    climb count:  3 
    climb at index "0" is Null?  false 
    climb at index "1" is Null?  false 
    climb at index "2" is Null?  false 
    Get first value of climb:   "Wall" 
    Get second value of climb:  "Rock" 
    Get third value of climb:   "Tree" 
    Get fourth value of climb or return KingKong:  "KingKong" 
    Get climb as PvlKeyword: Climb = (Wall, Rock, Tree)

Get map info for non-existent keys: 
    Map has keyword=pencil? false 
    All Values for pencil: () 
    pencil count:  0 
    pencil is Null?  true 
    Get value of pencil or return Lucy:  "Lucy" 
    Get values for PvlKeyword('pencil', 'Linus'):  ("Linus") 

Erasing climb keyword:  true 
Reprint Map123 merged with CLIMB keyword erased: 
	Bass = "Large mouth"
	CAT = Woof
	Crow = Null
	Dog = Moo
	EAGLE = Claws
	Field = Run
	Fly = Sugar
	Rattler = DiamondBack
	Sparrow = House
	Trout = Brown

Try to get CLIMB keyword after erased... 
**PROGRAMMER ERROR** Keyword Climb does not exist!.

Try to get CAT keyword at non-existent index... 
**PROGRAMMER ERROR** Index 10 does not exist for keyword CAT!.

Try to get non-existent pencil keyword... 
**PROGRAMMER ERROR** Keyword pencil does not exist!.
+285 −0

File added.

Preview size limit exceeded, changes collapsed.